Skip to content

Commit

Permalink
SCIP::AddConstraint(NLConstraint&) #237
Browse files Browse the repository at this point in the history
  • Loading branch information
glebbelov committed Aug 20, 2024
1 parent 45b26ba commit 7edb0fa
Show file tree
Hide file tree
Showing 14 changed files with 393 additions and 39 deletions.
13 changes: 13 additions & 0 deletions include/mp/flat/constr_2_expr.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ class Constraints2Expr {
stage_cvt2expr_ = 2; // func cons -> explicifiers
MPD( GetModel() ).ConvertAllWithExpressions(*(Impl*)this);
MPD( EliminateExprResultVars() ); // In the very end
MPD( PassHooksToModelAPI() );
}

/// Mark which functional constraints to be used as expressions,
Expand Down Expand Up @@ -224,6 +225,18 @@ class Constraints2Expr {
MPD( MarkVarAsEliminated(i) );
}

/// Pass some infos and callbacks to the ModelAPI
void PassHooksToModelAPI() {
MPD( GetModelAPI() ).PassVarProperFlags(
MPCD( GetVarProperFlags() ));
MPD( GetModelAPI() ).PassInitExprGetter(
[this](int i_res_var, void* pexpr) {
assert( !MPCD( IsProperVar(i_res_var) ) ); // is an expression
MPD( GetInitExpression(i_res_var) ).StoreSolverExpression(
MPD(GetModelAPI()), i_res_var, pexpr);
});
}


protected:
/// Algebraic cons: no marking (when NLConstraint accepted?)
Expand Down
2 changes: 2 additions & 0 deletions include/mp/flat/constr_base.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ class ExprWrapper {
ExprWrapper(Con c) : con_flat_(std::move(c)) { }
/// Constraint type
using FlatConType = Con;
/// Type name
const char* GetTypeName() const { return con_flat_.GetTypeName(); }
/// Get const & (con)
const Con& GetFlatConstraint() const { return con_flat_; }
/// Get & (con)
Expand Down
22 changes: 22 additions & 0 deletions include/mp/flat/constr_keeper.h
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,10 @@ class ConstraintKeeper final
DoCvtWithExprs();
}

/// acc:_expr==1 ?
bool IfWantNLOutput() const override
{ return GetConverter().IfWantNLOutput(); }

/// Converter's ability to convert the constraint type
bool IfConverterConverts(
BasicFlatConverter& cvt ) const override {
Expand Down Expand Up @@ -206,6 +210,19 @@ class ConstraintKeeper final
}
}

/// Store the solver's native expression for constraint \a i.
/// Have to abandon type safety - an alternative would be to
/// parameterize BasicConstraintKeeper by ConverterType
/// and ModelAPI incl. ExprType.
void StoreSolverExpression(
BasicFlatModelAPI& be, int i, void* pexpr) override {
if constexpr (ExpressionAcceptanceLevel::NotAccepted
!= Backend::ExpressionInterfaceAcceptanceLevel()) {
*(typename Backend::Expr*)pexpr =
static_cast<Backend&>(be).AddExpression(cons_[i].GetExpr());
}
}

/// Log constraint group
void LogConstraintGroup(
BasicFlatModelAPI& be) override {
Expand Down Expand Up @@ -262,6 +279,11 @@ class ConstraintKeeper final
/// Get the flat constraint &
Constraint& GetCon() { return con_.GetFlatConstraint(); }

/// Get the expression, const &
const FlatExprType& GetExpr() const { return con_; }
/// Get the expression &
FlatExprType& GetExpr() { return con_; }

private:
// Storing in the ExprWrapper,
// so we can send (wrapper &) to ModelAPI::AddExpression().
Expand Down
2 changes: 1 addition & 1 deletion include/mp/flat/converter.h
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,7 @@ class FlatConverter :
int AcceptanceLevelCommon() const { return options_.accAll_; }

/// Option to actually use expressions if available
bool IfWantNLOutput() const { return options_.accExpr_; }
bool IfWantNLOutput() const { return options_.accExpr_==1; }

/// Whether solver CAN accept expressions
static constexpr bool IfAcceptingNLOutput()
Expand Down
4 changes: 4 additions & 0 deletions include/mp/flat/converter_model.h
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,10 @@ class FlatModel
return !VarHasMarking(v) || var_result_[v];
}

/// Get var proper flags
const std::vector<bool>& GetVarProperFlags() const
{ return var_result_; }

/// Mark var as eliminated.
void MarkVarAsEliminated(int v) {
AutoExpand(var_elim_, v) = true;
Expand Down
17 changes: 17 additions & 0 deletions include/mp/flat/item_keeper.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@ class BasicConstraintKeeper {
/// Convert to use expressions
virtual void ConvertAllWithExpressions(BasicFlatConverter& cvt) = 0;

/// acc:_expr==1 ?
virtual bool IfWantNLOutput() const = 0;

/// Query (user-chosen) acceptance level.
/// This is "combined" for constraint or expression
ConstraintAcceptanceLevel GetChosenAcceptanceLevel() const {
Expand All @@ -70,6 +73,8 @@ class BasicConstraintKeeper {
al = acc_level_item_;
std::array<int, 5> alv = {0, 1, 2, 1, 2};
acceptance_level_ = alv.at(al);
if (al>2 && !IfWantNLOutput()) // expression accepted but NL format not chosen
acceptance_level_ = 0;
}
return ConstraintAcceptanceLevel(acceptance_level_);
}
Expand Down Expand Up @@ -122,6 +127,13 @@ class BasicConstraintKeeper {
virtual void AddUnbridgedToBackend(
BasicFlatModelAPI& be, const std::vector<std::string>* vnames) = 0;

/// Store the solver's native expression for constraint \a i.
/// Have to abandon type safety - an alternative would be to
/// parameterize BasicConstraintKeeper by ConverterType
/// and ModelAPI incl. ExprType.
virtual void StoreSolverExpression(
BasicFlatModelAPI& be, int i, void* pexpr) = 0;

/// This logs the constraint group
virtual void LogConstraintGroup(BasicFlatModelAPI& be) = 0;

Expand Down Expand Up @@ -243,6 +255,11 @@ struct ConstraintLocationHelper {
typename ConstraintKeeper::ConstraintType&
GetConstraint() { return GetCK()->GetConstraint(GetIndex()); }

/// Store native expression for result index \a i.
void StoreSolverExpression(
BasicFlatModelAPI& be, int i, void* pexpr) const
{ GetCK()->StoreSolverExpression(be, i, pexpr); }

/// Get Keeper
ConstraintKeeper* GetCK() const { assert(HasId()); return pck_; }
/// Get index
Expand Down
1 change: 1 addition & 0 deletions include/mp/flat/model_api_base.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ enum ConstraintGroup {
CG_Quadratic,
CG_Conic,
CG_General,
CG_Nonlinear,
CG_Piecewiselinear,
CG_SOS,
CG_SOS1,
Expand Down
5 changes: 5 additions & 0 deletions include/mp/flat/nl_expr/constr_nl.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,11 @@ inline void WriteModelItem(Writer& wrt,
}


/// NLComplementarity
/// TODO extra class, to enable ACCEPT_CONSTRAINT
using NLComplementarity = ComplementarityConstraint<AffineExpr>;


/// NL logical constraint: expr(resvar) == true
class NLLogical
: public BasicConstraint, public LogicalFunctionalConstraintTraits {
Expand Down
114 changes: 112 additions & 2 deletions include/mp/flat/nl_expr/model_api_base.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,20 @@
#ifndef MODEL_API_BASE_H
#define MODEL_API_BASE_H

#include <utility>

#include "mp/flat/model_api_base.h"
#include "mp/flat/nl_expr/constr_nl.h"

namespace mp {

/// ModelAPIs handling expression trees should derive from
template <class ExprType=void*>
/// BasicExprModelAPI<Impl, Expr>,
/// with Impl the final implementation class (CRTP)
/// and Expr default-constructible.
template <class Impl, class ExprType=void*>
class BasicExprModelAPI
:public BasicFlatModelAPI {
: public BasicFlatModelAPI {
public:
using Expr = ExprType;
/// Placeholder for GetTypeName()
Expand All @@ -52,6 +57,111 @@ class BasicExprModelAPI
/// Reuse inherited names
USE_BASE_CONSTRAINT_HANDLERS(BasicFlatModelAPI)


/// Placeholder for AddExpression<>()
template <class Expression>
Expr AddExpression(const Expression& e) {
MP_RAISE(
std::string("Not handling expression type '") +
e.GetTypeName() +
"'. Provide a handler or a converter method");
}

/// Derived backends have to tell C++ to use default handlers if they are needed
/// when they overload AddExpression(), due to C++ name hiding
#define USE_BASE_EXPRESSION_HANDLERS(BaseBackend) \
using BaseBackend::Expr; \
using BaseBackend::AddExpression;


/// NL model item accessors

/// Get num linear terms
int GetLinSize(const NLConstraint& nlc) const {
return nlc.GetMainCon().size();
}

/// Get linear coef \a i.
double GetLinCoef(const NLConstraint& nlc, int i) const {
return nlc.GetMainCon().coef(i);
}

/// Get linear part var \a i.
int GetLinVar(const NLConstraint& nlc, int i) const {
assert(IsVarProper(i));
return nlc.GetMainCon().var(i);
}

/// Get the expression term of an \a NLConstraint.
/// @note Can return the dummy expression
/// via Impl::GetZeroExpression().
ExprType GetExpression(const NLConstraint& nlc) {
const auto i_expr = nlc.HasExpr()
? nlc.ExprIndex() : -1;
if (i_expr<0)
return MPD( GetZeroExpression() );
return GetInitExpression(i_expr);
}

/// Get NLConstraint's lower bound
double GetLower(const NLConstraint& nlc) const {
return nlc.GetMainCon().lb();
}

/// Get NLConstraint's upper bound
double GetUpper(const NLConstraint& nlc) const {
return nlc.GetMainCon().ub();
}

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

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

/// Get InitExpression()
Expr GetInitExpression(int i_expr) {
assert(i_expr < is_expr_stored_.size());
assert(i_expr < expr_stored_.size());
if (!is_expr_stored_[i_expr]) {
is_expr_stored_[i_expr] = true;
if (IsVarProper(i_expr)) {
expr_stored_[i_expr] = MPD( GetVarExpression(i_expr) );
} else {
get_init_expr_(i_expr, &expr_stored_[i_expr]);
}
}
return expr_stored_[i_expr]; // ...............
}

/// Pass vector of var proper flags
void PassVarProperFlags(std::vector<bool> isvp) {
is_var_proper_ = std::move(isvp);
is_expr_stored_.resize(is_var_proper_.size()); // allocate
expr_stored_.resize(is_var_proper_.size());
}

/// Is var proper?
bool IsVarProper(int i) const {
assert(i>=0 && i<(int)is_var_proper_.size());
return is_var_proper_[i];
}

/// Init expr getter type
using InitExprGetterType = std::function<void(int i_expr, void* pexpr)>;

/// Provide init expr getter
void PassInitExprGetter(InitExprGetterType gt)
{ get_init_expr_ = gt; }


private:
std::vector<bool> is_var_proper_;
std::vector<bool> is_expr_stored_;
std::vector<ExprType> expr_stored_;
InitExprGetterType get_init_expr_;
};

} // namespace mp
Expand Down
9 changes: 9 additions & 0 deletions solvers/scipmp/scipmpcommon.cc
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,19 @@ SCIP_DECL_PROBDELORIG(probdataDelOrigNl)
SCIP_CALL( SCIPreleaseCons(scip, &(*probdata)->linconss[i]) );
}

for (auto& pnlc: (*probdata)->nlconss)
SCIP_CALL( SCIPreleaseCons(scip, &pnlc) );

for( i = 0; i < (*probdata)->nvars; ++i )
{
SCIP_CCALL( SCIPreleaseVar(scip, &(*probdata)->vars[i]) );
if ((*probdata)->var_exprs[i])
SCIP_CALL( SCIPreleaseExpr(scip, &(*probdata)->var_exprs[i]) );
}

if ((*probdata)->dummyexpr)
SCIP_CALL( SCIPreleaseExpr(scip, &(*probdata)->dummyexpr) );

SCIPfreeBlockMemoryArray(scip, &(*probdata)->vars, (*probdata)->nvars);

SCIPfreeMemory(scip, probdata);
Expand Down
15 changes: 10 additions & 5 deletions solvers/scipmp/scipmpcommon.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,17 @@
/// problem data stored in SCIP
struct SCIP_ProbData
{
SCIP_VAR** vars; /**< variables in the order given by AMPL */
int nvars; /**< number of variables */
SCIP_VAR** vars; /**< variables in the order given by AMPL */
std::vector<SCIP_EXPR*> var_exprs; /**< expressions for the variables, when non-zero */
int nvars; /**< number of variables */

std::vector<SCIP_CONS*> linconss; /**< linear constraints in the order given by AMPL */
int i = 0; /**< shows free slot of linear constraints */
int nlinconss = 0; /**< number of linear constraints */
std::vector<SCIP_CONS*> linconss; /**< linear constraints in the order given by AMPL */
int i = 0; /**< shows free slot of linear constraints */
int nlinconss = 0; /**< number of linear constraints */

std::vector<SCIP_CONS*> nlconss; /**< NL linear constraints in the order given by AMPL */

SCIP_EXPR* dummyexpr {nullptr};
};

namespace mp {
Expand Down
Loading

0 comments on commit 7edb0fa

Please sign in to comment.