Skip to content

Commit

Permalink
Fix init expr, NLObj, NLCon #237
Browse files Browse the repository at this point in the history
  • Loading branch information
glebbelov committed Aug 21, 2024
1 parent 76d8b3e commit 567fd67
Show file tree
Hide file tree
Showing 9 changed files with 91 additions and 44 deletions.
53 changes: 27 additions & 26 deletions include/mp/flat/constr_2_expr.h
Original file line number Diff line number Diff line change
Expand Up @@ -231,9 +231,9 @@ class Constraints2Expr {
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);
auto cloc = MPD( GetInitExpression(i_res_var) );
cloc.StoreSolverExpression(
MPD(GetModelAPI()), pexpr);
});
}

Expand Down Expand Up @@ -298,23 +298,23 @@ class Constraints2Expr {
int exprResVar = -1;
if (exprTerm.GetArguments().is_variable()) {
exprResVar = exprTerm.GetArguments().get_representing_variable();
assert( !MPCD( IsProperVar(exprResVar) ) ); // is an expr
// assert( !MPCD( IsProperVar(exprResVar) ) ); // is an expr
} else {
assert( !exprTerm.GetArguments().empty() ); // has more terms, or coef != 1.0
exprTerm.SetContext( // Context is compulsory
exprTerm.AddContext( // Context is compulsory
rng.lb() > MPCD( PracticallyMinusInf() ) // Should not need to propagate
? (rng.ub() < MPCD( PracticallyInf() )
? Context::CTX_MIX : Context::CTX_POS)
: Context::CTX_NEG);
exprResVar = MPD( AssignResultVar2Args(std::move(exprTerm)) );
if (!MPCD(VarHasMarking(exprResVar))) // mark as expr if new
MPD( MarkAsExpression(exprResVar) );
/// Exists and marked a variable
else if (MPCD( IsProperVar(exprResVar) )) { // Not an expression after all
lt.add_term(1.0, exprResVar);
exprResVar = -1; // no expression
lt.sort_terms();
}
}
if (!MPCD(VarHasMarking(exprResVar))) // mark as expr if new
MPD( MarkAsExpression(exprResVar) );
/// Exists and marked a variable
else if (MPCD( IsProperVar(exprResVar) )) { // Not an expression after all
lt.add_term(1.0, exprResVar);
exprResVar = -1; // no expression
lt.sort_terms();
} // else, stays as -1
NLConstraint nlc{lt, exprResVar, rng, false}; // no sorting
MPD( AddConstraint( std::move(nlc) ) );
Expand All @@ -330,7 +330,7 @@ class Constraints2Expr {
int exprResVar = -1;
if (lt_in_expr.is_variable() && qobj.GetQPTerms().empty()) {
exprResVar = lt_in_expr.get_representing_variable();
assert( !MPCD( IsProperVar(exprResVar) ) ); // is an expr
// assert( !MPCD( IsProperVar(exprResVar) ) ); // is an expr
} else { // We need a new expression
// Set up AutoLink
auto obj_src = // source value node for this obj
Expand All @@ -343,18 +343,18 @@ class Constraints2Expr {
exprResVar = MPD( AssignResultVar2Args(
QuadraticFunctionalConstraint
{ {{lt_in_expr, std::move(qobj.GetQPTerms())}, 1.0} } ) );
MPD( SetInitExprContext(exprResVar, // Context is compulsory
MPD( AddInitExprContext(exprResVar, // Context is compulsory
obj::MAX==qobj.obj_sense_true() // no need to propagate
? Context::CTX_POS : Context::CTX_NEG) );
if ( !MPCD(VarHasMarking(exprResVar) )) // mark as expr if new
MPD( MarkAsExpression(exprResVar) );
if ( !MPCD( GetModelAPI() ).AcceptsNLObj() ) // But as var if NLObj not accepted
MPD( MarkAsResultVar(exprResVar) );
if ( MPCD( IsProperVar(exprResVar) ) ) { // Not an expression after all
lt_varsonly.add_term(1.0, exprResVar);
exprResVar = -1; // no expression
lt_varsonly.sort_terms();
}
}
if ( !MPCD(VarHasMarking(exprResVar) )) // mark as expr if new
MPD( MarkAsExpression(exprResVar) );
if ( !MPCD( GetModelAPI() ).AcceptsNLObj() ) // But as var if NLObj not accepted
MPD( MarkAsResultVar(exprResVar) );
if ( MPCD( IsProperVar(exprResVar) ) ) { // Not an expression after all
lt_varsonly.add_term(1.0, exprResVar);
exprResVar = -1; // no expression
lt_varsonly.sort_terms();
}
qobj.GetLinTerms() = lt_varsonly;
if (exprResVar>=0)
Expand Down Expand Up @@ -391,7 +391,7 @@ class Constraints2Expr {

/// Split linterms into pure-var and expressions
/// @return the expressions part
LinTerms SplitLinTerms(const LinTerms& ltin, LinTerms lt_out_vars) {
LinTerms SplitLinTerms(const LinTerms& ltin, LinTerms& lt_out_vars) {
LinTerms result;
int nvars=0;
for (int v: ltin.vars())
Expand Down Expand Up @@ -481,7 +481,8 @@ class Constraints2Expr {
auto alscope = MPD( MakeAutoLinker( con, i ) ); // link from \a con
auto resvar = con.GetResultVar();
if (MPCD( is_fixed(resvar) ) // "root" context
&& MPCD( fixed_value(resvar) )) { // static logical constraint
&& MPCD( fixed_value(resvar) )
&& con.GetContext().HasPositive()) { // static logical constraint
MPD( AddConstraint(NLLogical(resvar)) );
}
else { // A (half-)reified function constraint
Expand Down
2 changes: 1 addition & 1 deletion include/mp/flat/constr_base.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ class BasicConstraint {
/// Set context, if meaningful
void SetContext(Context ) const { MP_RAISE("Setting context for static constraint"); }
/// Add (merge) context, if meaningful
void AddContext(Context ) const { MP_RAISE("Setting context for static constraint"); }
void AddContext(Context ) const { MP_RAISE("Adding context for static constraint"); }
/// Has result var (is functional)?
bool HasResultVar() const { return false; }
/// For functional constraints, result variable index
Expand Down
4 changes: 4 additions & 0 deletions include/mp/flat/constr_keeper.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,10 @@ class ConstraintKeeper final
Context GetContext(int i) const override
{ assert(check_index(i)); return cons_[i].GetCon().GetContext(); }

/// Add context of contraint \a i
void AddContext(int i, Context ctx) override
{ assert(check_index(i)); cons_[i].GetCon().AddContext(ctx); }

/// Set context of contraint \a i
void SetContext(int i, Context ctx) override
{ assert(check_index(i)); cons_[i].GetCon().SetContext(ctx); }
Expand Down
8 changes: 7 additions & 1 deletion include/mp/flat/converter.h
Original file line number Diff line number Diff line change
Expand Up @@ -897,7 +897,13 @@ class FlatConverter :
ie.GetCK()->SetContext(ie.GetIndex(), ctx);
}

/// Get the init expression pointer.
/// Add func expr context
void AddInitExprContext(int var, Context ctx) {
auto ie = GetInitExpression(var);
ie.GetCK()->AddContext(ie.GetIndex(), ctx);
}

/// Get the init expression pointer.
/// @return nullptr if no init expr or not this type
template <class ConType>
const ConType* GetInitExpressionOfType(int var) {
Expand Down
6 changes: 3 additions & 3 deletions include/mp/flat/converter_model.h
Original file line number Diff line number Diff line change
Expand Up @@ -399,11 +399,11 @@ class FlatModel
// Convert names to c-str if needed
for (const std::string& s : var_names_storage_)
var_names_.push_back(s.c_str());
backend.AddVariables({ var_lb_, var_ub_, var_type_, var_names_ });
backend.AddVariables({ var_lb_subm_, var_ub_subm_, var_type_, var_names_ });
} else {
backend.AddVariables({ var_lb_, var_ub_, var_type_ });
backend.AddVariables({ var_lb_subm_, var_ub_subm_, var_type_ });
}
ExportVars(0, var_lb_, var_ub_, var_type_,
ExportVars(0, var_lb_subm_, var_ub_subm_, var_type_,
"Updated model information.");
}

Expand Down
7 changes: 5 additions & 2 deletions include/mp/flat/item_keeper.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ class BasicConstraintKeeper {
/// Get context of contraint \a i
virtual Context GetContext(int i) const = 0;

/// Add context of contraint \a i
virtual void AddContext(int i, Context ctx) = 0;

/// Set context of contraint \a i
virtual void SetContext(int i, Context ctx) = 0;

Expand Down Expand Up @@ -255,8 +258,8 @@ struct ConstraintLocationHelper {

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

/// Get Keeper
ConstraintKeeper* GetCK() const { assert(HasId()); return pck_; }
Expand Down
39 changes: 33 additions & 6 deletions include/mp/flat/nl_expr/model_api_base.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ class BasicExprModelAPI
? nlc.ExprIndex() : -1;
if (i_expr<0)
return MPD( GetZeroExpression() );
return GetInitExpression(i_expr);
return GetPureInitExpression(i_expr);
}

/// Get NLConstraint's lower bound
Expand All @@ -123,7 +123,7 @@ class BasicExprModelAPI
template <int sense>
ExprType GetExpression(const NLReification<sense>& nll) {
assert( nll.GetResultVar()>=0 );
return GetInitExpression(nll.GetResultVar());
return GetPureInitExpression(nll.GetResultVar());
}

/// Get the variable of an \a NLReification.
Expand Down Expand Up @@ -185,9 +185,9 @@ class BasicExprModelAPI

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

/// Get InitExpression().
/// Solver expression for the given implicit variable,
/// or for the given independent variable.
private:
/// Get Expr for a variable, if proper/explicit,
/// or for the InitExpression().
Expr GetInitExpression(int i_expr) {
assert(i_expr < is_expr_stored_.size());
assert(i_expr < expr_stored_.size());
Expand All @@ -202,11 +202,37 @@ class BasicExprModelAPI
return expr_stored_[i_expr]; // ...............
}

/// Get Expr for the InitExpression().
/// Solver expression for the given variable's init expression.
/// This is called for NLConstraint
/// and for NLReification. For them, during result explicification,
/// the result is marked as variable,
/// but we still need the expression.
/// We have to trust that the init expression is accepted.
/// @note GetInitExpression(\a i_expr) might still return
/// the Expr for the result variable \a i_expr.
Expr GetPureInitExpression(int i_expr) {
assert(i_expr < is_expr_stored_.size());
assert(i_expr < expr_stored_.size());
assert(i_expr < is_init_expr_retrieved_.size());
assert(!is_init_expr_retrieved_[i_expr]); // not twice explicified
if (IsVarProper(i_expr)) {
is_init_expr_retrieved_[i_expr] = true; // is being explicified
Expr result;
get_init_expr_(i_expr, &result);
return result;
}
return GetInitExpression(i_expr); // standard case
}


public:
/// 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_init_expr_retrieved_.resize(is_var_proper_.size());
}

/// Is var proper?
Expand All @@ -225,8 +251,9 @@ class BasicExprModelAPI

private:
std::vector<bool> is_var_proper_;
std::vector<bool> is_expr_stored_;
std::vector<bool> is_expr_stored_; // actual Expr's of the result var or the init expressions
std::vector<ExprType> expr_stored_;
std::vector<bool> is_init_expr_retrieved_;
InitExprGetterType get_init_expr_;
};

Expand Down
12 changes: 7 additions & 5 deletions solvers/scipmp/scipmpcommon.cc
Original file line number Diff line number Diff line change
Expand Up @@ -11,24 +11,26 @@ SCIP_DECL_PROBDELORIG(probdataDelOrigNl)

for( i = 0; i < (*probdata)->nlinconss; ++i )
{
SCIP_CALL( SCIPreleaseCons(scip, &(*probdata)->linconss[i]) );
SCIP_CCALL( SCIPreleaseCons(scip, &(*probdata)->linconss[i]) );
}

for (auto& pnlc: (*probdata)->nlconss)
SCIP_CALL( SCIPreleaseCons(scip, &pnlc) );
SCIP_CCALL( 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]) );
SCIP_CCALL( SCIPreleaseExpr(scip, &(*probdata)->var_exprs[i]) );
SCIP_CCALL( SCIPreleaseVar(scip, &(*probdata)->vars[i]) );
}

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

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

SCIPsetMessagehdlrQuiet(scip, true); // Spurious warnings and failure in Debug build

SCIPfreeMemory(scip, probdata);

return SCIP_OKAY;
Expand Down
4 changes: 4 additions & 0 deletions solvers/scipmp/scipmpmodelapi.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,10 @@ class ScipModelAPI :
/// NLLogical, NLEquivalence, NLImpl, NLRimpl, and NLObjective.
ACCEPT_EXPRESSION_INTERFACE(AcceptedButNotRecommended);

/// Whether accepts NLObjective.
/// No, as of SCIP 9.1.
static int AcceptsNLObj() { return 0; }

/// Once expressions are supported, need the following
/// helper methods.
///
Expand Down

0 comments on commit 567fd67

Please sign in to comment.