use GCD argument to fail early in positive boolean scalprod eq cst
This commit is contained in:
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user