Skip to content

Commit

Permalink
Presolve div by const
Browse files Browse the repository at this point in the history
  • Loading branch information
glebbelov committed Jun 3, 2024
1 parent 7a7b928 commit b6c299a
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 1 deletion.
6 changes: 6 additions & 0 deletions include/mp/flat/expr_quadratic.h
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,12 @@ class QuadAndLinTerms :
QuadTerms::add(qlt.GetQPTerms());
}

/// Multiply by const
void operator*=(double n) {
GetLinTerms() *= n;
GetQPTerms() *= n;
}

/// Value at given variable vector
template <class VarInfo>
long double ComputeValue(const VarInfo& x) const {
Expand Down
21 changes: 20 additions & 1 deletion include/mp/flat/problem_flattener.h
Original file line number Diff line number Diff line change
Expand Up @@ -497,6 +497,25 @@ class ProblemFlattener :
return AssignResult2Args( std::move(fc) );
}

/// Specialize for Div:
/// For constant divisor, return linear expression.
/// Why we need this: AMPL 20240331 does not preprocess this.
template <class ExprArray=std::initializer_list<Expr> >
EExpr VisitDivExpression(ExprArray ea) {
auto dividend = Convert2EExpr(*ea.begin());
auto it = ea.begin();
auto divisor = Convert2EExpr(*(++it));
if (divisor.is_constant()) {
if (!divisor.constant_term())
MP_RAISE("Division by 0 in the model.");
dividend *= (1.0 / divisor.constant_term());
return dividend;
}
DivConstraint fc
{{ Convert2Var(std::move(dividend)), Convert2Var(std::move(divisor)) }};
return AssignResult2Args( std::move(fc) );
}

template <class ExprArray>
void Exprs2Vars(const ExprArray& ea, std::vector<int>& result) {
assert(result.empty());
Expand Down Expand Up @@ -666,7 +685,7 @@ class ProblemFlattener :
}

EExpr VisitDiv(BinaryExpr e) {
return VisitFunctionalExpression<DivConstraint>(
return VisitDivExpression(
{ e.lhs(), e.rhs() });
}

Expand Down
15 changes: 15 additions & 0 deletions test/end2end/cases/categorized/fast/nonlinear/div_by_const.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#### See if Div/const is well presolved
#### MP does this because AMPL 20240331 does not
#### See if abs() is well redefined (or used well natively)
###################################################

var x {1..3} >=-200, <=200;

minimize Unbalance:
sum {i in 1..3} abs(x[i] - sum {i1 in 1..3} x[i1] / 3);

## Some extra constraints
s.t. C1: sum {I in 1..3} x[I] == 15;

s.t. C2: x[1] + 2*x[2] + 4*x[3] == 18;

5 changes: 5 additions & 0 deletions test/end2end/cases/categorized/fast/nonlinear/modellist.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
[
{
"name" : "div_by_const",
"tags" : ["linear"],
"objective": 11.33333333333333
},
{
"name" : "expA_1",
"tags" : ["nonlinear"],
Expand Down

0 comments on commit b6c299a

Please sign in to comment.