Skip to content

Commit

Permalink
Preprocess And/Or constraints
Browse files Browse the repository at this point in the history
Required for XPRESS (does not like fixed arguments)
  • Loading branch information
glebbelov committed Aug 31, 2023
1 parent 668134f commit 54450d4
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 6 deletions.
5 changes: 5 additions & 0 deletions CHANGES.mp.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
Summary of recent updates to the AMPL MP Library
================================================

## unreleased
- Check solutions, options sol:chk:*.
- Preprocess And/Or constraints.


## 20230817
- Alternative solutions: solve status equal to that
of the final solution.
Expand Down
59 changes: 56 additions & 3 deletions include/mp/flat/constr_prepro.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ namespace mp {

/// A mix-in base class
/// providing preprocessors of flat constraints.
/// Currently used before adding a constraint (if not simplified to nothing).
/// Currently used before adding a constraint
/// (if not simplified to nothing).
template <class Impl>
class ConstraintPreprocessors {
public:
Expand Down Expand Up @@ -271,16 +272,68 @@ class ConstraintPreprocessors {

template <class PreprocessInfo>
void PreprocessConstraint(
AndConstraint& , PreprocessInfo& prepro) {
AndConstraint& con, PreprocessInfo& prepro) {
prepro.narrow_result_bounds(0.0, 1.0);
prepro.set_result_type( var::INTEGER );
// Remove fixed variables for XPRESS (solvers/#61).
auto n01 = count_fixed_01(con.GetArguments());
if (n01.first) { // AND = false
prepro.narrow_result_bounds(0.0, 0.0);
return;
}
if (con.GetArguments().size() == n01.second) {
prepro.narrow_result_bounds(1.0, 1.0);
return;
}
if (n01.second) {
std::vector<int> arg1;
arg1.reserve(con.GetArguments().size() - n01.second);
for (auto x: con.GetArguments()) {
if (MPCD( lb(x) ) <= 0.0) // not fixed
arg1.push_back(x);
}
con.GetArguments() = arg1;
}
}

template <class PreprocessInfo>
void PreprocessConstraint(
OrConstraint& , PreprocessInfo& prepro) {
OrConstraint& con, PreprocessInfo& prepro) {
prepro.narrow_result_bounds(0.0, 1.0);
prepro.set_result_type( var::INTEGER );
// Remove fixed variables for XPRESS (solvers/#61).
auto n01 = count_fixed_01(con.GetArguments());
if (n01.second) { // OR = true
prepro.narrow_result_bounds(1.0, 1.0);
return;
}
if (con.GetArguments().size() == n01.first) {
prepro.narrow_result_bounds(0.0, 0.0);
return;
}
if (n01.first) {
std::vector<int> arg1;
arg1.reserve(con.GetArguments().size() - n01.first);
for (auto x: con.GetArguments()) {
if (MPCD( ub(x) ) >= 1.0) // not fixed
arg1.push_back(x);
}
con.GetArguments() = arg1;
}
}

/// Count N fixed binary vars
template <class Vec>
std::pair<int, int> count_fixed_01(const Vec& vec) const {
std::pair<int, int> result {0, 0};
for (auto x: vec) {
assert(MPCD( is_binary_var(x) ));
if (MPCD( ub(x) ) <= 0.0)
++ result.first;
if (MPCD( lb(x) ) >= 1.0)
++ result.second;
}
return result;
}

template <class PreprocessInfo>
Expand Down
5 changes: 4 additions & 1 deletion include/mp/flat/converter_model.h
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,10 @@ class FlatModel

/// Returns true also when fixed
bool is_binary_var(int v) const {
return 0.0<=lb(v) && 1.0>=ub(v) && is_integer_var(v);
return
(0.0==lb(v) && 1.0==ub(v) && is_integer_var(v))
|| (is_fixed(v)
&& (0.0==fixed_value(v) || 1.0==fixed_value(v)));
}

template <class VarArray=std::initializer_list<int> >
Expand Down
6 changes: 4 additions & 2 deletions solvers/xpress/xpressmodelapi.cc
Original file line number Diff line number Diff line change
Expand Up @@ -184,8 +184,10 @@ void XpressmpModelAPI::AddConstraint(const SOS2Constraint& sos) {
(double*)sos.get_weights().data()));
}

template <class Args, class Params, class NumOrLogic, class Id> void XpressmpModelAPI::addGenCon(
const CustomFunctionalConstraint<Args, Params, NumOrLogic, Id>& c, int xpressConType)
template <class Args, class Params, class NumOrLogic, class Id>
void XpressmpModelAPI::addGenCon(
const CustomFunctionalConstraint<Args, Params, NumOrLogic, Id>& c,
int xpressConType)
{
int type[] = { xpressConType };
int resultant[] = { c.GetResultVar() };
Expand Down

0 comments on commit 54450d4

Please sign in to comment.