diff --git a/src/flatzinc/parser.cc b/src/flatzinc/parser.cc index a5d34b9b07..33fce9d80d 100644 --- a/src/flatzinc/parser.cc +++ b/src/flatzinc/parser.cc @@ -18,6 +18,28 @@ extern void yyset_extra (void* user_defined ,void* yyscanner ); extern void yyerror(void* parm, const char *str); namespace operations_research { +// ----- Misc ----- +bool HasDomainAnnotation(AST::Node* const annotations) { + if (annotations != NULL) { + return annotations->hasAtom("domain"); + } + return false; +} + +bool HasDefineAnnotation(AST::Node* const annotations) { + if (annotations != NULL) { + if (annotations->isArray()) { + AST::Array* const ann_array = annotations->getArray(); + if (ann_array->a[0]->isCall("defines_var")) { + return true; + } + } + } + return false; +} + +// ----- Parser State ----- + ParserState::~ParserState() { STLDeleteElements(&int_variables_); STLDeleteElements(&bool_variables_); @@ -79,13 +101,6 @@ AST::Node* ParserState::FindTarget(AST::Node* const annotations) const { return NULL; } -bool HasDomainAnnotation(AST::Node* const annotations) { - if (annotations != NULL) { - return annotations->hasAtom("domain"); - } - return false; -} - void ParserState::CollectRequired(AST::Array* const args, const NodeSet& candidates, NodeSet* const require) const { @@ -1040,7 +1055,7 @@ bool ParserState::PresolveOneConstraint(CtSpec* const spec) { break; } } - if (!one_positive) { + if (!one_positive && !HasDefineAnnotation(spec->annotations())) { VLOG(1) << " - presolve: transform all negative int_lin_eq into " << "int_lin_eq in " << spec->DebugString(); diff --git a/src/flatzinc/registry.cc b/src/flatzinc/registry.cc index 244882b16f..994076a19f 100644 --- a/src/flatzinc/registry.cc +++ b/src/flatzinc/registry.cc @@ -433,7 +433,6 @@ void p_int_lin_eq_reif(FlatZincModel* const model, CtSpec* const spec) { const int size = array_coefficients->a.size(); CHECK_EQ(size, array_variables->a.size()); std::vector coefficients(size); - std::vector variables(size); int positive = 0; int negative = 0; @@ -466,12 +465,12 @@ void p_int_lin_eq_reif(FlatZincModel* const model, CtSpec* const spec) { std::vector neg_vars; std::vector neg_coeffs; for (int i = 0; i < size; ++i) { - variables[i] = model->GetIntExpr(array_variables->a[i])->Var(); + IntVar* const var = model->GetIntExpr(array_variables->a[i])->Var(); const int64 coeff = coefficients[i]; if (coeff > 0) { - pos = solver->MakeProd(variables[i], coeff); + pos = solver->MakeProd(var, coeff); } else if (coeff < 0) { - neg_vars.push_back(variables[i]); + neg_vars.push_back(var); neg_coeffs.push_back(-coeff); } } @@ -499,7 +498,7 @@ void p_int_lin_eq_reif(FlatZincModel* const model, CtSpec* const spec) { const int64 coeff = coefficients[i]; IntExpr* const expr = model->GetIntExpr(array_variables->a[i]); if (coeff < 0) { - neg = solver->MakeProd(variables[i], -coeff); + neg = solver->MakeProd(expr, -coeff); } else if (coeff > 0) { pos_exprs.push_back(solver->MakeProd(expr, coeff)); } @@ -510,11 +509,11 @@ void p_int_lin_eq_reif(FlatZincModel* const model, CtSpec* const spec) { std::vector pos_coeffs; for (int i = 0; i < size; ++i) { const int64 coeff = coefficients[i]; - variables[i] = model->GetIntExpr(array_variables->a[i])->Var(); + IntVar* const var = model->GetIntExpr(array_variables->a[i])->Var(); if (coeff < 0) { - neg = solver->MakeProd(variables[i], -coeff); + neg = solver->MakeProd(var, -coeff); } else if (coeff > 0) { - pos_vars.push_back(variables[i]); + pos_vars.push_back(var); pos_coeffs.push_back(coeff); } } @@ -534,6 +533,7 @@ void p_int_lin_eq_reif(FlatZincModel* const model, CtSpec* const spec) { solver->AddConstraint(ct); } } else { + std::vector variables(size); for (int i = 0; i < size; ++i) { coefficients[i] = array_coefficients->a[i]->getInt(); variables[i] = model->GetIntExpr(array_variables->a[i])->Var();