use GCD argument to fail early in positive boolean scalprod eq cst

This commit is contained in:
lperron@google.com
2014-06-26 12:47:09 +00:00
parent bee77f38af
commit ec712bc80e

View File

@@ -61,7 +61,8 @@ class TreeArrayConstraint : public CastConstraint {
target_var_->DebugString().c_str());
}
void AcceptInternal(const std::string& name, ModelVisitor* const visitor) const {
void AcceptInternal(const std::string& name,
ModelVisitor* const visitor) const {
visitor->BeginVisitConstraint(name, this);
visitor->VisitIntegerVariableArrayArgument(ModelVisitor::kVarsArgument,
vars_);
@@ -1155,7 +1156,8 @@ class SumBooleanLessOrEqualToOne : public BaseSumBooleanConstraint {
class SumBooleanGreaterOrEqualToOne : public BaseSumBooleanConstraint {
public:
SumBooleanGreaterOrEqualToOne(Solver* const s, const std::vector<IntVar*>& vars);
SumBooleanGreaterOrEqualToOne(Solver* const s,
const std::vector<IntVar*>& vars);
virtual ~SumBooleanGreaterOrEqualToOne() {}
virtual void Post();
@@ -1485,7 +1487,8 @@ struct Container {
// If keep_inside is true, the constant will be added back into the
// scalprod as IntConst(1) * constant.
int64 SortBothChangeConstant(std::vector<IntVar*>* const vars,
std::vector<int64>* const coefs, bool keep_inside) {
std::vector<int64>* const coefs,
bool keep_inside) {
CHECK(vars != nullptr);
CHECK(coefs != nullptr);
if (vars->empty()) {
@@ -1521,7 +1524,8 @@ int64 SortBothChangeConstant(std::vector<IntVar*>* const vars,
class BooleanScalProdLessConstant : public Constraint {
public:
BooleanScalProdLessConstant(Solver* const s, const std::vector<IntVar*>& vars,
const std::vector<int64>& coefs, int64 upper_bound)
const std::vector<int64>& coefs,
int64 upper_bound)
: Constraint(s),
vars_(vars),
coefs_(coefs),
@@ -1626,8 +1630,10 @@ class BooleanScalProdLessConstant : public Constraint {
class PositiveBooleanScalProdEqVar : public CastConstraint {
public:
PositiveBooleanScalProdEqVar(Solver* const s, const std::vector<IntVar*>& vars,
const std::vector<int64>& coefs, IntVar* const var)
PositiveBooleanScalProdEqVar(Solver* const s,
const std::vector<IntVar*>& vars,
const std::vector<int64>& coefs,
IntVar* const var)
: CastConstraint(s, var),
vars_(vars),
coefs_(coefs),
@@ -1870,7 +1876,8 @@ class PositiveBooleanScalProd : public BaseIntExpr {
class PositiveBooleanScalProdEqCst : public Constraint {
public:
PositiveBooleanScalProdEqCst(Solver* const s, const std::vector<IntVar*>& vars,
PositiveBooleanScalProdEqCst(Solver* const s,
const std::vector<IntVar*>& vars,
const std::vector<int64>& coefs, int64 constant)
: Constraint(s),
vars_(vars),
@@ -1922,6 +1929,7 @@ class PositiveBooleanScalProdEqCst : public Constraint {
}
first_unbound_backward_.SetValue(solver(), last_unbound);
}
CheckGcd();
}
virtual void InitialPropagate() {
@@ -1955,11 +1963,35 @@ class PositiveBooleanScalProdEqCst : public Constraint {
Propagate();
}
void CheckGcd() {
bool first = true;
int64 rhs = constant_;
int64 gcd = 0;
for (int i = 0; i < vars_.size(); ++i) {
const int64 coeff = coefs_[i];
if (coeff == 0) continue;
if (vars_[i]->Bound()) {
rhs -= vars_[i]->Min() * coefs_[i];
} else if (first) {
gcd = coeff;
first = false;
} else {
gcd = MathUtil::GCD64(gcd, coeff);
}
if (gcd == 1) {
return;
}
}
if (!first && rhs % gcd != 0) {
solver()->Fail();
}
}
virtual std::string DebugString() const {
return StringPrintf("PositiveBooleanScalProd([%s], [%s]) == %" GG_LL_FORMAT
"d",
JoinDebugStringPtr(vars_, ", ").c_str(),
strings::Join(coefs_, ", ").c_str(), constant_);
return StringPrintf(
"PositiveBooleanScalProd([%s], [%s]) == %" GG_LL_FORMAT "d",
JoinDebugStringPtr(vars_, ", ").c_str(),
strings::Join(coefs_, ", ").c_str(), constant_);
}
void Accept(ModelVisitor* const visitor) const {
@@ -2159,8 +2191,9 @@ class ExprLinearizer : public ModelParser {
const std::vector<IntVar*>& cp_vars =
Top()->FindIntegerVariableArrayArgumentOrDie(
ModelVisitor::kVarsArgument);
const std::vector<int64>& cp_coefficients = Top()->FindIntegerArrayArgumentOrDie(
ModelVisitor::kCoefficientsArgument);
const std::vector<int64>& cp_coefficients =
Top()->FindIntegerArrayArgumentOrDie(
ModelVisitor::kCoefficientsArgument);
CHECK_EQ(cp_vars.size(), cp_coefficients.size());
for (int i = 0; i < cp_vars.size(); ++i) {
const int64 coefficient = cp_coefficients[i];
@@ -2255,8 +2288,9 @@ class ExprLinearizer : public ModelParser {
// ----- Factory functions -----
void DeepLinearize(Solver* const solver, const std::vector<IntVar*>& pre_vars,
const std::vector<int64>& pre_coefs, std::vector<IntVar*>* vars,
std::vector<int64>* coefs, int64* constant) {
const std::vector<int64>& pre_coefs,
std::vector<IntVar*>* vars, std::vector<int64>* coefs,
int64* constant) {
CHECK(solver != nullptr);
CHECK(vars != nullptr);
CHECK(coefs != nullptr);
@@ -2300,7 +2334,8 @@ void DeepLinearize(Solver* const solver, const std::vector<IntVar*>& pre_vars,
Constraint* MakeScalProdEqualityFct(Solver* const solver,
const std::vector<IntVar*>& pre_vars,
const std::vector<int64>& pre_coefs, int64 cst) {
const std::vector<int64>& pre_coefs,
int64 cst) {
int64 constant = 0;
std::vector<IntVar*> vars;
std::vector<int64> coefs;
@@ -2665,8 +2700,8 @@ IntExpr* MakeSumArrayAux(Solver* const solver, const std::vector<IntVar*>& vars,
solver->AddConstraint(
solver->RevAlloc(new SumConstraint(solver, vars, sum_var)));
}
solver->Cache()->InsertVarArrayExpression(sum_var, vars,
ModelCache::VAR_ARRAY_SUM);
solver->Cache()
->InsertVarArrayExpression(sum_var, vars, ModelCache::VAR_ARRAY_SUM);
return solver->MakeSum(sum_var, constant);
}
}
@@ -2718,9 +2753,9 @@ IntExpr* MakeScalProdAux(Solver* solver, const std::vector<IntVar*>& vars,
if (AreAllPositive(coefs)) {
if (vars.size() > 8) {
return solver->MakeSum(
solver->RegisterIntExpr(
solver->RevAlloc(new PositiveBooleanScalProd(
solver, vars, coefs)))->Var(),
solver->RegisterIntExpr(solver->RevAlloc(
new PositiveBooleanScalProd(solver, vars, coefs)))
->Var(),
constant);
} else {
return solver->MakeSum(
@@ -2980,7 +3015,8 @@ Constraint* Solver::MakeMaxEquality(const std::vector<IntVar*>& vars,
}
}
Constraint* Solver::MakeSumLessOrEqual(const std::vector<IntVar*>& vars, int64 cst) {
Constraint* Solver::MakeSumLessOrEqual(const std::vector<IntVar*>& vars,
int64 cst) {
const int size = vars.size();
if (cst == 1LL && AreAllBooleans(vars) && size > 2) {
return RevAlloc(new SumBooleanLessOrEqualToOne(this, vars));
@@ -2999,7 +3035,8 @@ Constraint* Solver::MakeSumGreaterOrEqual(const std::vector<IntVar*>& vars,
}
}
Constraint* Solver::MakeSumEquality(const std::vector<IntVar*>& vars, int64 cst) {
Constraint* Solver::MakeSumEquality(const std::vector<IntVar*>& vars,
int64 cst) {
const int size = vars.size();
if (size == 0) {
return cst == 0 ? MakeTrueConstraint() : MakeFalseConstraint();
@@ -3092,16 +3129,16 @@ Constraint* Solver::MakeScalProdGreaterOrEqual(const std::vector<IntVar*>& vars,
return MakeScalProdGreaterOrEqualFct(this, vars, ToInt64Vector(coeffs), cst);
}
Constraint* Solver::MakeScalProdLessOrEqual(const std::vector<IntVar*>& vars,
const std::vector<int64>& coefficients,
int64 cst) {
Constraint* Solver::MakeScalProdLessOrEqual(
const std::vector<IntVar*>& vars, const std::vector<int64>& coefficients,
int64 cst) {
DCHECK_EQ(vars.size(), coefficients.size());
return MakeScalProdLessOrEqualFct(this, vars, coefficients, cst);
}
Constraint* Solver::MakeScalProdLessOrEqual(const std::vector<IntVar*>& vars,
const std::vector<int>& coefficients,
int64 cst) {
Constraint* Solver::MakeScalProdLessOrEqual(
const std::vector<IntVar*>& vars, const std::vector<int>& coefficients,
int64 cst) {
DCHECK_EQ(vars.size(), coefficients.size());
return MakeScalProdLessOrEqualFct(this, vars, ToInt64Vector(coefficients),
cst);