git-subtree-dir: software/gecode_base git-subtree-split: bbefcea214fec798a0f5acc442581984555acd21
2327 lines
86 KiB
C++
Executable File
2327 lines
86 KiB
C++
Executable File
/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
|
|
/*
|
|
* Main authors:
|
|
* Guido Tack <tack@gecode.org>
|
|
*
|
|
* Contributing authors:
|
|
* Mikael Lagerkvist <lagerkvist@gmail.com>
|
|
*
|
|
* Copyright:
|
|
* Guido Tack, 2007
|
|
* Mikael Lagerkvist, 2009
|
|
*
|
|
* This file is part of Gecode, the generic constraint
|
|
* development environment:
|
|
* http://www.gecode.org
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining
|
|
* a copy of this software and associated documentation files (the
|
|
* "Software"), to deal in the Software without restriction, including
|
|
* without limitation the rights to use, copy, modify, merge, publish,
|
|
* distribute, sublicense, and/or sell copies of the Software, and to
|
|
* permit persons to whom the Software is furnished to do so, subject to
|
|
* the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be
|
|
* included in all copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
*
|
|
*/
|
|
|
|
#include <gecode/flatzinc/registry.hh>
|
|
#include <gecode/kernel.hh>
|
|
#include <gecode/int.hh>
|
|
#include <gecode/minimodel.hh>
|
|
|
|
#ifdef GECODE_HAS_SET_VARS
|
|
#include <gecode/set.hh>
|
|
#endif
|
|
#ifdef GECODE_HAS_FLOAT_VARS
|
|
#include <gecode/float.hh>
|
|
#endif
|
|
#include <gecode/flatzinc.hh>
|
|
|
|
namespace Gecode { namespace FlatZinc {
|
|
|
|
Registry& registry(void) {
|
|
static Registry r;
|
|
return r;
|
|
}
|
|
|
|
void
|
|
Registry::post(FlatZincSpace& s, const ConExpr& ce) {
|
|
std::map<std::string,poster>::iterator i = r.find(ce.id);
|
|
if (i == r.end()) {
|
|
throw FlatZinc::Error("Registry",
|
|
std::string("Constraint ")+ce.id+" not found", ce.ann);
|
|
}
|
|
i->second(s, ce, ce.ann);
|
|
}
|
|
|
|
void
|
|
Registry::add(const std::string& id, poster p) {
|
|
r[id] = p;
|
|
r["gecode_" + id] = p;
|
|
r["fzn_" + id] = p;
|
|
}
|
|
|
|
namespace {
|
|
|
|
void p_distinct(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
IntVarArgs va = s.arg2intvarargs(ce[0]);
|
|
IntPropLevel ipl = s.ann2ipl(ann);
|
|
unshare(s, va);
|
|
distinct(s, va, ipl == IPL_DEF ? IPL_BND : ipl);
|
|
}
|
|
|
|
void p_distinctOffset(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
IntVarArgs va = s.arg2intvarargs(ce[1]);
|
|
unshare(s, va);
|
|
AST::Array* offs = ce.args->a[0]->getArray();
|
|
IntArgs oa(offs->a.size());
|
|
for (int i=offs->a.size(); i--; ) {
|
|
oa[i] = offs->a[i]->getInt();
|
|
}
|
|
IntPropLevel ipl = s.ann2ipl(ann);
|
|
distinct(s, oa, va, ipl == IPL_DEF ? IPL_BND : ipl);
|
|
}
|
|
|
|
void p_all_equal(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
IntVarArgs va = s.arg2intvarargs(ce[0]);
|
|
rel(s, va, IRT_EQ, s.ann2ipl(ann));
|
|
}
|
|
|
|
void p_int_CMP(FlatZincSpace& s, IntRelType irt, const ConExpr& ce,
|
|
AST::Node* ann) {
|
|
if (ce[0]->isIntVar()) {
|
|
if (ce[1]->isIntVar()) {
|
|
rel(s, s.arg2IntVar(ce[0]), irt, s.arg2IntVar(ce[1]),
|
|
s.ann2ipl(ann));
|
|
} else {
|
|
rel(s, s.arg2IntVar(ce[0]), irt, ce[1]->getInt(), s.ann2ipl(ann));
|
|
}
|
|
} else {
|
|
rel(s, s.arg2IntVar(ce[1]), swap(irt), ce[0]->getInt(),
|
|
s.ann2ipl(ann));
|
|
}
|
|
}
|
|
void p_int_eq(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
p_int_CMP(s, IRT_EQ, ce, ann);
|
|
}
|
|
void p_int_ne(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
p_int_CMP(s, IRT_NQ, ce, ann);
|
|
}
|
|
void p_int_ge(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
p_int_CMP(s, IRT_GQ, ce, ann);
|
|
}
|
|
void p_int_gt(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
p_int_CMP(s, IRT_GR, ce, ann);
|
|
}
|
|
void p_int_le(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
p_int_CMP(s, IRT_LQ, ce, ann);
|
|
}
|
|
void p_int_lt(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
p_int_CMP(s, IRT_LE, ce, ann);
|
|
}
|
|
void p_int_CMP_reif(FlatZincSpace& s, IntRelType irt, ReifyMode rm,
|
|
const ConExpr& ce, AST::Node* ann) {
|
|
if (rm == RM_EQV && ce[2]->isBool()) {
|
|
if (ce[2]->getBool()) {
|
|
p_int_CMP(s, irt, ce, ann);
|
|
} else {
|
|
p_int_CMP(s, neg(irt), ce, ann);
|
|
}
|
|
return;
|
|
}
|
|
if (ce[0]->isIntVar()) {
|
|
if (ce[1]->isIntVar()) {
|
|
rel(s, s.arg2IntVar(ce[0]), irt, s.arg2IntVar(ce[1]),
|
|
Reify(s.arg2BoolVar(ce[2]), rm), s.ann2ipl(ann));
|
|
} else {
|
|
rel(s, s.arg2IntVar(ce[0]), irt, ce[1]->getInt(),
|
|
Reify(s.arg2BoolVar(ce[2]), rm), s.ann2ipl(ann));
|
|
}
|
|
} else {
|
|
rel(s, s.arg2IntVar(ce[1]), swap(irt), ce[0]->getInt(),
|
|
Reify(s.arg2BoolVar(ce[2]), rm), s.ann2ipl(ann));
|
|
}
|
|
}
|
|
|
|
/* Comparisons */
|
|
void p_int_eq_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
p_int_CMP_reif(s, IRT_EQ, RM_EQV, ce, ann);
|
|
}
|
|
void p_int_ne_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
p_int_CMP_reif(s, IRT_NQ, RM_EQV, ce, ann);
|
|
}
|
|
void p_int_ge_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
p_int_CMP_reif(s, IRT_GQ, RM_EQV, ce, ann);
|
|
}
|
|
void p_int_gt_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
p_int_CMP_reif(s, IRT_GR, RM_EQV, ce, ann);
|
|
}
|
|
void p_int_le_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
p_int_CMP_reif(s, IRT_LQ, RM_EQV, ce, ann);
|
|
}
|
|
void p_int_lt_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
p_int_CMP_reif(s, IRT_LE, RM_EQV, ce, ann);
|
|
}
|
|
|
|
void p_int_eq_imp(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
p_int_CMP_reif(s, IRT_EQ, RM_IMP, ce, ann);
|
|
}
|
|
void p_int_ne_imp(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
p_int_CMP_reif(s, IRT_NQ, RM_IMP, ce, ann);
|
|
}
|
|
void p_int_ge_imp(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
p_int_CMP_reif(s, IRT_GQ, RM_IMP, ce, ann);
|
|
}
|
|
void p_int_gt_imp(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
p_int_CMP_reif(s, IRT_GR, RM_IMP, ce, ann);
|
|
}
|
|
void p_int_le_imp(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
p_int_CMP_reif(s, IRT_LQ, RM_IMP, ce, ann);
|
|
}
|
|
void p_int_lt_imp(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
p_int_CMP_reif(s, IRT_LE, RM_IMP, ce, ann);
|
|
}
|
|
|
|
/* linear (in-)equations */
|
|
void p_int_lin_CMP(FlatZincSpace& s, IntRelType irt, const ConExpr& ce,
|
|
AST::Node* ann) {
|
|
IntArgs ia = s.arg2intargs(ce[0]);
|
|
int singleIntVar;
|
|
if (s.isBoolArray(ce[1],singleIntVar)) {
|
|
if (singleIntVar != -1) {
|
|
if (std::abs(ia[singleIntVar]) == 1 && ce[2]->getInt() == 0) {
|
|
IntVar siv = s.arg2IntVar(ce[1]->getArray()->a[singleIntVar]);
|
|
BoolVarArgs iv = s.arg2boolvarargs(ce[1], 0, singleIntVar);
|
|
IntArgs ia_tmp(ia.size()-1);
|
|
int count = 0;
|
|
for (int i=0; i<ia.size(); i++) {
|
|
if (i != singleIntVar)
|
|
ia_tmp[count++] = ia[singleIntVar] == -1 ? ia[i] : -ia[i];
|
|
}
|
|
IntRelType t = (ia[singleIntVar] == -1 ? irt : swap(irt));
|
|
linear(s, ia_tmp, iv, t, siv, s.ann2ipl(ann));
|
|
} else {
|
|
IntVarArgs iv = s.arg2intvarargs(ce[1]);
|
|
linear(s, ia, iv, irt, ce[2]->getInt(), s.ann2ipl(ann));
|
|
}
|
|
} else {
|
|
BoolVarArgs iv = s.arg2boolvarargs(ce[1]);
|
|
linear(s, ia, iv, irt, ce[2]->getInt(), s.ann2ipl(ann));
|
|
}
|
|
} else {
|
|
IntVarArgs iv = s.arg2intvarargs(ce[1]);
|
|
linear(s, ia, iv, irt, ce[2]->getInt(), s.ann2ipl(ann));
|
|
}
|
|
}
|
|
void p_int_lin_CMP_reif(FlatZincSpace& s, IntRelType irt, ReifyMode rm,
|
|
const ConExpr& ce, AST::Node* ann) {
|
|
if (rm == RM_EQV && ce[2]->isBool()) {
|
|
if (ce[2]->getBool()) {
|
|
p_int_lin_CMP(s, irt, ce, ann);
|
|
} else {
|
|
p_int_lin_CMP(s, neg(irt), ce, ann);
|
|
}
|
|
return;
|
|
}
|
|
IntArgs ia = s.arg2intargs(ce[0]);
|
|
int singleIntVar;
|
|
if (s.isBoolArray(ce[1],singleIntVar)) {
|
|
if (singleIntVar != -1) {
|
|
if (std::abs(ia[singleIntVar]) == 1 && ce[2]->getInt() == 0) {
|
|
IntVar siv = s.arg2IntVar(ce[1]->getArray()->a[singleIntVar]);
|
|
BoolVarArgs iv = s.arg2boolvarargs(ce[1], 0, singleIntVar);
|
|
IntArgs ia_tmp(ia.size()-1);
|
|
int count = 0;
|
|
for (int i=0; i<ia.size(); i++) {
|
|
if (i != singleIntVar)
|
|
ia_tmp[count++] = ia[singleIntVar] == -1 ? ia[i] : -ia[i];
|
|
}
|
|
IntRelType t = (ia[singleIntVar] == -1 ? irt : swap(irt));
|
|
linear(s, ia_tmp, iv, t, siv, Reify(s.arg2BoolVar(ce[3]), rm),
|
|
s.ann2ipl(ann));
|
|
} else {
|
|
IntVarArgs iv = s.arg2intvarargs(ce[1]);
|
|
linear(s, ia, iv, irt, ce[2]->getInt(),
|
|
Reify(s.arg2BoolVar(ce[3]), rm), s.ann2ipl(ann));
|
|
}
|
|
} else {
|
|
BoolVarArgs iv = s.arg2boolvarargs(ce[1]);
|
|
linear(s, ia, iv, irt, ce[2]->getInt(),
|
|
Reify(s.arg2BoolVar(ce[3]), rm), s.ann2ipl(ann));
|
|
}
|
|
} else {
|
|
IntVarArgs iv = s.arg2intvarargs(ce[1]);
|
|
linear(s, ia, iv, irt, ce[2]->getInt(),
|
|
Reify(s.arg2BoolVar(ce[3]), rm),
|
|
s.ann2ipl(ann));
|
|
}
|
|
}
|
|
void p_int_lin_eq(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
p_int_lin_CMP(s, IRT_EQ, ce, ann);
|
|
}
|
|
void p_int_lin_eq_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
p_int_lin_CMP_reif(s, IRT_EQ, RM_EQV, ce, ann);
|
|
}
|
|
void p_int_lin_eq_imp(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
p_int_lin_CMP_reif(s, IRT_EQ, RM_IMP, ce, ann);
|
|
}
|
|
void p_int_lin_ne(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
p_int_lin_CMP(s, IRT_NQ, ce, ann);
|
|
}
|
|
void p_int_lin_ne_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
p_int_lin_CMP_reif(s, IRT_NQ, RM_EQV, ce, ann);
|
|
}
|
|
void p_int_lin_ne_imp(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
p_int_lin_CMP_reif(s, IRT_NQ, RM_IMP, ce, ann);
|
|
}
|
|
void p_int_lin_le(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
p_int_lin_CMP(s, IRT_LQ, ce, ann);
|
|
}
|
|
void p_int_lin_le_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
p_int_lin_CMP_reif(s, IRT_LQ, RM_EQV, ce, ann);
|
|
}
|
|
void p_int_lin_le_imp(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
p_int_lin_CMP_reif(s, IRT_LQ, RM_IMP, ce, ann);
|
|
}
|
|
void p_int_lin_lt(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
p_int_lin_CMP(s, IRT_LE, ce, ann);
|
|
}
|
|
void p_int_lin_lt_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
p_int_lin_CMP_reif(s, IRT_LE, RM_EQV, ce, ann);
|
|
}
|
|
void p_int_lin_lt_imp(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
p_int_lin_CMP_reif(s, IRT_LE, RM_IMP, ce, ann);
|
|
}
|
|
void p_int_lin_ge(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
p_int_lin_CMP(s, IRT_GQ, ce, ann);
|
|
}
|
|
void p_int_lin_ge_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
p_int_lin_CMP_reif(s, IRT_GQ, RM_EQV, ce, ann);
|
|
}
|
|
void p_int_lin_ge_imp(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
p_int_lin_CMP_reif(s, IRT_GQ, RM_IMP, ce, ann);
|
|
}
|
|
void p_int_lin_gt(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
p_int_lin_CMP(s, IRT_GR, ce, ann);
|
|
}
|
|
void p_int_lin_gt_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
p_int_lin_CMP_reif(s, IRT_GR, RM_EQV, ce, ann);
|
|
}
|
|
void p_int_lin_gt_imp(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
p_int_lin_CMP_reif(s, IRT_GR, RM_IMP, ce, ann);
|
|
}
|
|
|
|
void p_bool_lin_CMP(FlatZincSpace& s, IntRelType irt, const ConExpr& ce,
|
|
AST::Node* ann) {
|
|
IntArgs ia = s.arg2intargs(ce[0]);
|
|
BoolVarArgs iv = s.arg2boolvarargs(ce[1]);
|
|
if (ce[2]->isIntVar())
|
|
linear(s, ia, iv, irt, s.iv[ce[2]->getIntVar()], s.ann2ipl(ann));
|
|
else
|
|
linear(s, ia, iv, irt, ce[2]->getInt(), s.ann2ipl(ann));
|
|
}
|
|
void p_bool_lin_CMP_reif(FlatZincSpace& s, IntRelType irt, ReifyMode rm,
|
|
const ConExpr& ce, AST::Node* ann) {
|
|
if (rm == RM_EQV && ce[2]->isBool()) {
|
|
if (ce[2]->getBool()) {
|
|
p_bool_lin_CMP(s, irt, ce, ann);
|
|
} else {
|
|
p_bool_lin_CMP(s, neg(irt), ce, ann);
|
|
}
|
|
return;
|
|
}
|
|
IntArgs ia = s.arg2intargs(ce[0]);
|
|
BoolVarArgs iv = s.arg2boolvarargs(ce[1]);
|
|
if (ce[2]->isIntVar())
|
|
linear(s, ia, iv, irt, s.iv[ce[2]->getIntVar()],
|
|
Reify(s.arg2BoolVar(ce[3]), rm),
|
|
s.ann2ipl(ann));
|
|
else
|
|
linear(s, ia, iv, irt, ce[2]->getInt(),
|
|
Reify(s.arg2BoolVar(ce[3]), rm),
|
|
s.ann2ipl(ann));
|
|
}
|
|
void p_bool_lin_eq(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
p_bool_lin_CMP(s, IRT_EQ, ce, ann);
|
|
}
|
|
void p_bool_lin_eq_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann)
|
|
{
|
|
p_bool_lin_CMP_reif(s, IRT_EQ, RM_EQV, ce, ann);
|
|
}
|
|
void p_bool_lin_eq_imp(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann)
|
|
{
|
|
p_bool_lin_CMP_reif(s, IRT_EQ, RM_IMP, ce, ann);
|
|
}
|
|
void p_bool_lin_ne(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
p_bool_lin_CMP(s, IRT_NQ, ce, ann);
|
|
}
|
|
void p_bool_lin_ne_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann)
|
|
{
|
|
p_bool_lin_CMP_reif(s, IRT_NQ, RM_EQV, ce, ann);
|
|
}
|
|
void p_bool_lin_ne_imp(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann)
|
|
{
|
|
p_bool_lin_CMP_reif(s, IRT_NQ, RM_IMP, ce, ann);
|
|
}
|
|
void p_bool_lin_le(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
p_bool_lin_CMP(s, IRT_LQ, ce, ann);
|
|
}
|
|
void p_bool_lin_le_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann)
|
|
{
|
|
p_bool_lin_CMP_reif(s, IRT_LQ, RM_EQV, ce, ann);
|
|
}
|
|
void p_bool_lin_le_imp(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann)
|
|
{
|
|
p_bool_lin_CMP_reif(s, IRT_LQ, RM_IMP, ce, ann);
|
|
}
|
|
void p_bool_lin_lt(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann)
|
|
{
|
|
p_bool_lin_CMP(s, IRT_LE, ce, ann);
|
|
}
|
|
void p_bool_lin_lt_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann)
|
|
{
|
|
p_bool_lin_CMP_reif(s, IRT_LE, RM_EQV, ce, ann);
|
|
}
|
|
void p_bool_lin_lt_imp(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann)
|
|
{
|
|
p_bool_lin_CMP_reif(s, IRT_LE, RM_IMP, ce, ann);
|
|
}
|
|
void p_bool_lin_ge(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
p_bool_lin_CMP(s, IRT_GQ, ce, ann);
|
|
}
|
|
void p_bool_lin_ge_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann)
|
|
{
|
|
p_bool_lin_CMP_reif(s, IRT_GQ, RM_EQV, ce, ann);
|
|
}
|
|
void p_bool_lin_ge_imp(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann)
|
|
{
|
|
p_bool_lin_CMP_reif(s, IRT_GQ, RM_IMP, ce, ann);
|
|
}
|
|
void p_bool_lin_gt(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
p_bool_lin_CMP(s, IRT_GR, ce, ann);
|
|
}
|
|
void p_bool_lin_gt_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann)
|
|
{
|
|
p_bool_lin_CMP_reif(s, IRT_GR, RM_EQV, ce, ann);
|
|
}
|
|
void p_bool_lin_gt_imp(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann)
|
|
{
|
|
p_bool_lin_CMP_reif(s, IRT_GR, RM_IMP, ce, ann);
|
|
}
|
|
|
|
/* arithmetic constraints */
|
|
|
|
void p_int_plus(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
if (!ce[0]->isIntVar()) {
|
|
rel(s, ce[0]->getInt() + s.arg2IntVar(ce[1])
|
|
== s.arg2IntVar(ce[2]), s.ann2ipl(ann));
|
|
} else if (!ce[1]->isIntVar()) {
|
|
rel(s, s.arg2IntVar(ce[0]) + ce[1]->getInt()
|
|
== s.arg2IntVar(ce[2]), s.ann2ipl(ann));
|
|
} else if (!ce[2]->isIntVar()) {
|
|
rel(s, s.arg2IntVar(ce[0]) + s.arg2IntVar(ce[1])
|
|
== ce[2]->getInt(), s.ann2ipl(ann));
|
|
} else {
|
|
rel(s, s.arg2IntVar(ce[0]) + s.arg2IntVar(ce[1])
|
|
== s.arg2IntVar(ce[2]), s.ann2ipl(ann));
|
|
}
|
|
}
|
|
|
|
void p_int_minus(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
if (!ce[0]->isIntVar()) {
|
|
rel(s, ce[0]->getInt() - s.arg2IntVar(ce[1])
|
|
== s.arg2IntVar(ce[2]), s.ann2ipl(ann));
|
|
} else if (!ce[1]->isIntVar()) {
|
|
rel(s, s.arg2IntVar(ce[0]) - ce[1]->getInt()
|
|
== s.arg2IntVar(ce[2]), s.ann2ipl(ann));
|
|
} else if (!ce[2]->isIntVar()) {
|
|
rel(s, s.arg2IntVar(ce[0]) - s.arg2IntVar(ce[1])
|
|
== ce[2]->getInt(), s.ann2ipl(ann));
|
|
} else {
|
|
rel(s, s.arg2IntVar(ce[0]) - s.arg2IntVar(ce[1])
|
|
== s.arg2IntVar(ce[2]), s.ann2ipl(ann));
|
|
}
|
|
}
|
|
|
|
void p_int_times(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
IntVar x0 = s.arg2IntVar(ce[0]);
|
|
IntVar x1 = s.arg2IntVar(ce[1]);
|
|
IntVar x2 = s.arg2IntVar(ce[2]);
|
|
mult(s, x0, x1, x2, s.ann2ipl(ann));
|
|
}
|
|
void p_int_pow(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
IntVar x0 = s.arg2IntVar(ce[0]);
|
|
IntVar x2 = s.arg2IntVar(ce[2]);
|
|
pow(s, x0, ce[1]->getInt(), x2, s.ann2ipl(ann));
|
|
}
|
|
void p_int_div(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
IntVar x0 = s.arg2IntVar(ce[0]);
|
|
IntVar x1 = s.arg2IntVar(ce[1]);
|
|
IntVar x2 = s.arg2IntVar(ce[2]);
|
|
div(s,x0,x1,x2, s.ann2ipl(ann));
|
|
}
|
|
void p_int_mod(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
IntVar x0 = s.arg2IntVar(ce[0]);
|
|
IntVar x1 = s.arg2IntVar(ce[1]);
|
|
IntVar x2 = s.arg2IntVar(ce[2]);
|
|
mod(s,x0,x1,x2, s.ann2ipl(ann));
|
|
}
|
|
|
|
void p_int_min(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
IntVar x0 = s.arg2IntVar(ce[0]);
|
|
IntVar x1 = s.arg2IntVar(ce[1]);
|
|
IntVar x2 = s.arg2IntVar(ce[2]);
|
|
min(s, x0, x1, x2, s.ann2ipl(ann));
|
|
}
|
|
void p_int_max(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
IntVar x0 = s.arg2IntVar(ce[0]);
|
|
IntVar x1 = s.arg2IntVar(ce[1]);
|
|
IntVar x2 = s.arg2IntVar(ce[2]);
|
|
max(s, x0, x1, x2, s.ann2ipl(ann));
|
|
}
|
|
void p_int_negate(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
IntVar x0 = s.arg2IntVar(ce[0]);
|
|
IntVar x1 = s.arg2IntVar(ce[1]);
|
|
rel(s, x0 == -x1, s.ann2ipl(ann));
|
|
}
|
|
|
|
/* Boolean constraints */
|
|
void p_bool_CMP(FlatZincSpace& s, IntRelType irt, const ConExpr& ce,
|
|
AST::Node* ann) {
|
|
rel(s, s.arg2BoolVar(ce[0]), irt, s.arg2BoolVar(ce[1]),
|
|
s.ann2ipl(ann));
|
|
}
|
|
void p_bool_CMP_reif(FlatZincSpace& s, IntRelType irt, ReifyMode rm,
|
|
const ConExpr& ce, AST::Node* ann) {
|
|
rel(s, s.arg2BoolVar(ce[0]), irt, s.arg2BoolVar(ce[1]),
|
|
Reify(s.arg2BoolVar(ce[2]), rm), s.ann2ipl(ann));
|
|
}
|
|
void p_bool_eq(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
p_bool_CMP(s, IRT_EQ, ce, ann);
|
|
}
|
|
void p_bool_eq_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
p_bool_CMP_reif(s, IRT_EQ, RM_EQV, ce, ann);
|
|
}
|
|
void p_bool_eq_imp(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
p_bool_CMP_reif(s, IRT_EQ, RM_IMP, ce, ann);
|
|
}
|
|
void p_bool_ne(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
p_bool_CMP(s, IRT_NQ, ce, ann);
|
|
}
|
|
void p_bool_ne_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
p_bool_CMP_reif(s, IRT_NQ, RM_EQV, ce, ann);
|
|
}
|
|
void p_bool_ne_imp(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
p_bool_CMP_reif(s, IRT_NQ, RM_IMP, ce, ann);
|
|
}
|
|
void p_bool_ge(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
p_bool_CMP(s, IRT_GQ, ce, ann);
|
|
}
|
|
void p_bool_ge_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
p_bool_CMP_reif(s, IRT_GQ, RM_EQV, ce, ann);
|
|
}
|
|
void p_bool_ge_imp(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
p_bool_CMP_reif(s, IRT_GQ, RM_IMP, ce, ann);
|
|
}
|
|
void p_bool_le(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
p_bool_CMP(s, IRT_LQ, ce, ann);
|
|
}
|
|
void p_bool_le_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
p_bool_CMP_reif(s, IRT_LQ, RM_EQV, ce, ann);
|
|
}
|
|
void p_bool_le_imp(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
p_bool_CMP_reif(s, IRT_LQ, RM_IMP, ce, ann);
|
|
}
|
|
void p_bool_gt(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
p_bool_CMP(s, IRT_GR, ce, ann);
|
|
}
|
|
void p_bool_gt_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
p_bool_CMP_reif(s, IRT_GR, RM_EQV, ce, ann);
|
|
}
|
|
void p_bool_gt_imp(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
p_bool_CMP_reif(s, IRT_GR, RM_IMP, ce, ann);
|
|
}
|
|
void p_bool_lt(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
p_bool_CMP(s, IRT_LE, ce, ann);
|
|
}
|
|
void p_bool_lt_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
p_bool_CMP_reif(s, IRT_LE, RM_EQV, ce, ann);
|
|
}
|
|
void p_bool_lt_imp(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
p_bool_CMP_reif(s, IRT_LE, RM_IMP, ce, ann);
|
|
}
|
|
|
|
#define BOOL_OP(op) \
|
|
BoolVar b0 = s.arg2BoolVar(ce[0]); \
|
|
BoolVar b1 = s.arg2BoolVar(ce[1]); \
|
|
if (ce[2]->isBool()) { \
|
|
rel(s, b0, op, b1, ce[2]->getBool(), s.ann2ipl(ann)); \
|
|
} else { \
|
|
rel(s, b0, op, b1, s.bv[ce[2]->getBoolVar()], s.ann2ipl(ann)); \
|
|
}
|
|
|
|
#define BOOL_ARRAY_OP(op) \
|
|
BoolVarArgs bv = s.arg2boolvarargs(ce[0]); \
|
|
if (ce.size()==1) { \
|
|
rel(s, op, bv, 1, s.ann2ipl(ann)); \
|
|
} else if (ce[1]->isBool()) { \
|
|
rel(s, op, bv, ce[1]->getBool(), s.ann2ipl(ann)); \
|
|
} else { \
|
|
rel(s, op, bv, s.bv[ce[1]->getBoolVar()], s.ann2ipl(ann)); \
|
|
}
|
|
|
|
void p_bool_or(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
BOOL_OP(BOT_OR);
|
|
}
|
|
void p_bool_or_imp(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
BoolVar b0 = s.arg2BoolVar(ce[0]);
|
|
BoolVar b1 = s.arg2BoolVar(ce[1]);
|
|
BoolVar b2 = s.arg2BoolVar(ce[2]);
|
|
clause(s, BOT_OR, BoolVarArgs()<<b0<<b1, BoolVarArgs()<<b2, 1,
|
|
s.ann2ipl(ann));
|
|
}
|
|
void p_bool_and(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
BOOL_OP(BOT_AND);
|
|
}
|
|
void p_bool_and_imp(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
BoolVar b0 = s.arg2BoolVar(ce[0]);
|
|
BoolVar b1 = s.arg2BoolVar(ce[1]);
|
|
BoolVar b2 = s.arg2BoolVar(ce[2]);
|
|
rel(s, b2, BOT_IMP, b0, 1, s.ann2ipl(ann));
|
|
rel(s, b2, BOT_IMP, b1, 1, s.ann2ipl(ann));
|
|
}
|
|
void p_array_bool_and(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann)
|
|
{
|
|
BOOL_ARRAY_OP(BOT_AND);
|
|
}
|
|
void p_array_bool_and_imp(FlatZincSpace& s, const ConExpr& ce,
|
|
AST::Node* ann)
|
|
{
|
|
BoolVarArgs bv = s.arg2boolvarargs(ce[0]);
|
|
BoolVar b1 = s.arg2BoolVar(ce[1]);
|
|
for (unsigned int i=bv.size(); i--;)
|
|
rel(s, b1, BOT_IMP, bv[i], 1, s.ann2ipl(ann));
|
|
}
|
|
void p_array_bool_or(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann)
|
|
{
|
|
BOOL_ARRAY_OP(BOT_OR);
|
|
}
|
|
void p_array_bool_or_imp(FlatZincSpace& s, const ConExpr& ce,
|
|
AST::Node* ann)
|
|
{
|
|
BoolVarArgs bv = s.arg2boolvarargs(ce[0]);
|
|
BoolVar b1 = s.arg2BoolVar(ce[1]);
|
|
clause(s, BOT_OR, bv, BoolVarArgs()<<b1, 1, s.ann2ipl(ann));
|
|
}
|
|
void p_array_bool_xor(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann)
|
|
{
|
|
BOOL_ARRAY_OP(BOT_XOR);
|
|
}
|
|
void p_array_bool_xor_imp(FlatZincSpace& s, const ConExpr& ce,
|
|
AST::Node* ann)
|
|
{
|
|
BoolVarArgs bv = s.arg2boolvarargs(ce[0]);
|
|
BoolVar tmp(s,0,1);
|
|
rel(s, BOT_XOR, bv, tmp, s.ann2ipl(ann));
|
|
rel(s, s.arg2BoolVar(ce[1]), BOT_IMP, tmp, 1);
|
|
}
|
|
void p_array_bool_clause(FlatZincSpace& s, const ConExpr& ce,
|
|
AST::Node* ann) {
|
|
BoolVarArgs bvp = s.arg2boolvarargs(ce[0]);
|
|
BoolVarArgs bvn = s.arg2boolvarargs(ce[1]);
|
|
clause(s, BOT_OR, bvp, bvn, 1, s.ann2ipl(ann));
|
|
}
|
|
void p_array_bool_clause_reif(FlatZincSpace& s, const ConExpr& ce,
|
|
AST::Node* ann) {
|
|
BoolVarArgs bvp = s.arg2boolvarargs(ce[0]);
|
|
BoolVarArgs bvn = s.arg2boolvarargs(ce[1]);
|
|
BoolVar b0 = s.arg2BoolVar(ce[2]);
|
|
clause(s, BOT_OR, bvp, bvn, b0, s.ann2ipl(ann));
|
|
}
|
|
void p_array_bool_clause_imp(FlatZincSpace& s, const ConExpr& ce,
|
|
AST::Node* ann) {
|
|
BoolVarArgs bvp = s.arg2boolvarargs(ce[0]);
|
|
BoolVarArgs bvn = s.arg2boolvarargs(ce[1]);
|
|
BoolVar b0 = s.arg2BoolVar(ce[2]);
|
|
clause(s, BOT_OR, bvp, bvn, b0, s.ann2ipl(ann));
|
|
}
|
|
void p_bool_xor(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
BOOL_OP(BOT_XOR);
|
|
}
|
|
void p_bool_xor_imp(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
BoolVar b0 = s.arg2BoolVar(ce[0]);
|
|
BoolVar b1 = s.arg2BoolVar(ce[1]);
|
|
BoolVar b2 = s.arg2BoolVar(ce[2]);
|
|
clause(s, BOT_OR, BoolVarArgs()<<b0<<b1, BoolVarArgs()<<b2, 1,
|
|
s.ann2ipl(ann));
|
|
clause(s, BOT_OR, BoolVarArgs(), BoolVarArgs()<<b0<<b1<<b2, 1,
|
|
s.ann2ipl(ann));
|
|
}
|
|
void p_bool_l_imp(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
BoolVar b0 = s.arg2BoolVar(ce[0]);
|
|
BoolVar b1 = s.arg2BoolVar(ce[1]);
|
|
if (ce[2]->isBool()) {
|
|
rel(s, b1, BOT_IMP, b0, ce[2]->getBool(), s.ann2ipl(ann));
|
|
} else {
|
|
rel(s, b1, BOT_IMP, b0, s.bv[ce[2]->getBoolVar()], s.ann2ipl(ann));
|
|
}
|
|
}
|
|
void p_bool_r_imp(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
BOOL_OP(BOT_IMP);
|
|
}
|
|
void p_bool_not(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
BoolVar x0 = s.arg2BoolVar(ce[0]);
|
|
BoolVar x1 = s.arg2BoolVar(ce[1]);
|
|
rel(s, x0, BOT_XOR, x1, 1, s.ann2ipl(ann));
|
|
}
|
|
|
|
/* element constraints */
|
|
void p_array_int_element(FlatZincSpace& s, const ConExpr& ce,
|
|
AST::Node* ann) {
|
|
bool isConstant = true;
|
|
AST::Array* a = ce[1]->getArray();
|
|
for (int i=a->a.size(); i--;) {
|
|
if (!a->a[i]->isInt()) {
|
|
isConstant = false;
|
|
break;
|
|
}
|
|
}
|
|
IntVar selector = s.arg2IntVar(ce[0]);
|
|
rel(s, selector > 0);
|
|
if (isConstant) {
|
|
IntSharedArray sia = s.arg2intsharedarray(ce[1]);
|
|
element(s, sia, selector, -1, s.arg2IntVar(ce[2]), s.ann2ipl(ann));
|
|
} else {
|
|
IntVarArgs iv = s.arg2intvarargs(ce[1]);
|
|
element(s, iv, selector, -1, s.arg2IntVar(ce[2]), s.ann2ipl(ann));
|
|
}
|
|
}
|
|
void p_array_int_element_offset(FlatZincSpace& s, const ConExpr& ce,
|
|
AST::Node* ann) {
|
|
bool isConstant = true;
|
|
AST::Array* a = ce[2]->getArray();
|
|
for (int i=a->a.size(); i--;) {
|
|
if (!a->a[i]->isInt()) {
|
|
isConstant = false;
|
|
break;
|
|
}
|
|
}
|
|
IntVar selector = s.arg2IntVar(ce[0]);
|
|
int offset = ce[1]->getInt();
|
|
rel(s, selector >= offset);
|
|
if (isConstant) {
|
|
IntSharedArray sia = s.arg2intsharedarray(ce[2]);
|
|
element(s, sia, selector, -offset, s.arg2IntVar(ce[3]), s.ann2ipl(ann));
|
|
} else {
|
|
IntVarArgs iv = s.arg2intvarargs(ce[2]);
|
|
element(s, iv, selector, -offset, s.arg2IntVar(ce[3]), s.ann2ipl(ann));
|
|
}
|
|
}
|
|
void p_array_int_element2d(FlatZincSpace& s, const ConExpr& ce,
|
|
AST::Node* ann) {
|
|
bool isConstant = true;
|
|
AST::Array* a = ce[2]->getArray();
|
|
for (int i=a->a.size(); i--;) {
|
|
if (!a->a[i]->isInt()) {
|
|
isConstant = false;
|
|
break;
|
|
}
|
|
}
|
|
IntVar selector0 = s.arg2IntVar(ce[0]);
|
|
IntVar selector1 = s.arg2IntVar(ce[1]);
|
|
IntSet idxset0 = s.arg2intset(ce[3]);
|
|
IntSet idxset1 = s.arg2intset(ce[4]);
|
|
|
|
int w = idxset1.size();
|
|
int s1off = idxset1.min();
|
|
int h = idxset0.size();
|
|
int s0off = idxset0.min();
|
|
|
|
if (isConstant) {
|
|
IntSharedArray sia = s.arg2intsharedarray(ce[2], 0);
|
|
element(s, sia, selector1, -s1off, w, selector0, -s0off, h, s.arg2IntVar(ce[5]), s.ann2ipl(ann));
|
|
} else {
|
|
IntVarArgs iv = s.arg2intvarargs(ce[2], 0);
|
|
element(s, iv, selector1, -s1off, w, selector0, -s0off, h, s.arg2IntVar(ce[5]), s.ann2ipl(ann));
|
|
}
|
|
}
|
|
void p_array_bool_element(FlatZincSpace& s, const ConExpr& ce,
|
|
AST::Node* ann) {
|
|
bool isConstant = true;
|
|
AST::Array* a = ce[1]->getArray();
|
|
for (int i=a->a.size(); i--;) {
|
|
if (!a->a[i]->isBool()) {
|
|
isConstant = false;
|
|
break;
|
|
}
|
|
}
|
|
IntVar selector = s.arg2IntVar(ce[0]);
|
|
rel(s, selector > 0);
|
|
if (isConstant) {
|
|
IntSharedArray sia = s.arg2boolsharedarray(ce[1], 1);
|
|
element(s, sia, selector, s.arg2BoolVar(ce[2]), s.ann2ipl(ann));
|
|
} else {
|
|
BoolVarArgs iv = s.arg2boolvarargs(ce[1], 1);
|
|
element(s, iv, selector, s.arg2BoolVar(ce[2]), s.ann2ipl(ann));
|
|
}
|
|
}
|
|
void p_array_bool_element_offset(FlatZincSpace& s, const ConExpr& ce,
|
|
AST::Node* ann) {
|
|
bool isConstant = true;
|
|
AST::Array* a = ce[2]->getArray();
|
|
for (int i=a->a.size(); i--;) {
|
|
if (!a->a[i]->isBool()) {
|
|
isConstant = false;
|
|
break;
|
|
}
|
|
}
|
|
IntVar selector = s.arg2IntVar(ce[0]);
|
|
int offset = ce[1]->getInt();
|
|
rel(s, selector >= offset);
|
|
if (isConstant) {
|
|
IntSharedArray sia = s.arg2boolsharedarray(ce[2]);
|
|
element(s, sia, selector, -offset, s.arg2BoolVar(ce[3]), s.ann2ipl(ann));
|
|
} else {
|
|
BoolVarArgs iv = s.arg2boolvarargs(ce[2]);
|
|
element(s, iv, selector, -offset, s.arg2BoolVar(ce[3]), s.ann2ipl(ann));
|
|
}
|
|
}
|
|
void p_array_bool_element2d(FlatZincSpace& s, const ConExpr& ce,
|
|
AST::Node* ann) {
|
|
bool isConstant = true;
|
|
AST::Array* a = ce[2]->getArray();
|
|
for (int i=a->a.size(); i--;) {
|
|
if (!a->a[i]->isBool()) {
|
|
isConstant = false;
|
|
break;
|
|
}
|
|
}
|
|
IntVar selector0 = s.arg2IntVar(ce[0]);
|
|
IntVar selector1 = s.arg2IntVar(ce[1]);
|
|
IntSet idxset0 = s.arg2intset(ce[3]);
|
|
IntSet idxset1 = s.arg2intset(ce[4]);
|
|
|
|
int w = idxset1.size();
|
|
int s1off = idxset1.min();
|
|
int h = idxset0.size();
|
|
int s0off = idxset0.min();
|
|
|
|
if (isConstant) {
|
|
IntSharedArray sia = s.arg2boolsharedarray(ce[2], 0);
|
|
element(s, sia, selector1, -s1off, w, selector0, -s0off, h, s.arg2BoolVar(ce[5]), s.ann2ipl(ann));
|
|
} else {
|
|
BoolVarArgs iv = s.arg2boolvarargs(ce[2], 0);
|
|
element(s, iv, selector1, -s1off, w, selector0, -s0off, h, s.arg2BoolVar(ce[5]), s.ann2ipl(ann));
|
|
}
|
|
}
|
|
|
|
/* coercion constraints */
|
|
void p_bool2int(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
BoolVar x0 = s.arg2BoolVar(ce[0]);
|
|
IntVar x1 = s.arg2IntVar(ce[1]);
|
|
if (ce[0]->isBoolVar() && ce[1]->isIntVar()) {
|
|
s.aliasBool2Int(ce[1]->getIntVar(), ce[0]->getBoolVar());
|
|
}
|
|
channel(s, x0, x1, s.ann2ipl(ann));
|
|
}
|
|
|
|
void p_int_in(FlatZincSpace& s, const ConExpr& ce, AST::Node *) {
|
|
IntSet d = s.arg2intset(ce[1]);
|
|
if (ce[0]->isBoolVar()) {
|
|
IntSetRanges dr(d);
|
|
Iter::Ranges::Singleton sr(0,1);
|
|
Iter::Ranges::Inter<IntSetRanges,Iter::Ranges::Singleton> i(dr,sr);
|
|
IntSet d01(i);
|
|
if (d01.size() == 0) {
|
|
s.fail();
|
|
} else {
|
|
rel(s, s.arg2BoolVar(ce[0]), IRT_GQ, d01.min());
|
|
rel(s, s.arg2BoolVar(ce[0]), IRT_LQ, d01.max());
|
|
}
|
|
} else {
|
|
dom(s, s.arg2IntVar(ce[0]), d);
|
|
}
|
|
}
|
|
void p_int_in_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node *) {
|
|
IntSet d = s.arg2intset(ce[1]);
|
|
if (ce[0]->isBoolVar()) {
|
|
IntSetRanges dr(d);
|
|
Iter::Ranges::Singleton sr(0,1);
|
|
Iter::Ranges::Inter<IntSetRanges,Iter::Ranges::Singleton> i(dr,sr);
|
|
IntSet d01(i);
|
|
if (d01.size() == 0) {
|
|
rel(s, s.arg2BoolVar(ce[2]) == 0);
|
|
} else if (d01.max() == 0) {
|
|
rel(s, s.arg2BoolVar(ce[2]) == !s.arg2BoolVar(ce[0]));
|
|
} else if (d01.min() == 1) {
|
|
rel(s, s.arg2BoolVar(ce[2]) == s.arg2BoolVar(ce[0]));
|
|
} else {
|
|
rel(s, s.arg2BoolVar(ce[2]) == 1);
|
|
}
|
|
} else {
|
|
dom(s, s.arg2IntVar(ce[0]), d, s.arg2BoolVar(ce[2]));
|
|
}
|
|
}
|
|
void p_int_in_imp(FlatZincSpace& s, const ConExpr& ce, AST::Node *) {
|
|
IntSet d = s.arg2intset(ce[1]);
|
|
if (ce[0]->isBoolVar()) {
|
|
IntSetRanges dr(d);
|
|
Iter::Ranges::Singleton sr(0,1);
|
|
Iter::Ranges::Inter<IntSetRanges,Iter::Ranges::Singleton> i(dr,sr);
|
|
IntSet d01(i);
|
|
if (d01.size() == 0) {
|
|
rel(s, s.arg2BoolVar(ce[2]) == 0);
|
|
} else if (d01.max() == 0) {
|
|
rel(s, s.arg2BoolVar(ce[2]) >> !s.arg2BoolVar(ce[0]));
|
|
} else if (d01.min() == 1) {
|
|
rel(s, s.arg2BoolVar(ce[2]) >> s.arg2BoolVar(ce[0]));
|
|
}
|
|
} else {
|
|
dom(s, s.arg2IntVar(ce[0]), d, Reify(s.arg2BoolVar(ce[2]),RM_IMP));
|
|
}
|
|
}
|
|
|
|
/* constraints from the standard library */
|
|
|
|
void p_abs(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
IntVar x0 = s.arg2IntVar(ce[0]);
|
|
IntVar x1 = s.arg2IntVar(ce[1]);
|
|
abs(s, x0, x1, s.ann2ipl(ann));
|
|
}
|
|
|
|
void p_array_int_lt(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
IntVarArgs iv0 = s.arg2intvarargs(ce[0]);
|
|
IntVarArgs iv1 = s.arg2intvarargs(ce[1]);
|
|
rel(s, iv0, IRT_LE, iv1, s.ann2ipl(ann));
|
|
}
|
|
|
|
void p_array_int_lq(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
IntVarArgs iv0 = s.arg2intvarargs(ce[0]);
|
|
IntVarArgs iv1 = s.arg2intvarargs(ce[1]);
|
|
rel(s, iv0, IRT_LQ, iv1, s.ann2ipl(ann));
|
|
}
|
|
|
|
void p_array_bool_lt(FlatZincSpace& s, const ConExpr& ce,
|
|
AST::Node* ann) {
|
|
BoolVarArgs bv0 = s.arg2boolvarargs(ce[0]);
|
|
BoolVarArgs bv1 = s.arg2boolvarargs(ce[1]);
|
|
rel(s, bv0, IRT_LE, bv1, s.ann2ipl(ann));
|
|
}
|
|
|
|
void p_array_bool_lq(FlatZincSpace& s, const ConExpr& ce,
|
|
AST::Node* ann) {
|
|
BoolVarArgs bv0 = s.arg2boolvarargs(ce[0]);
|
|
BoolVarArgs bv1 = s.arg2boolvarargs(ce[1]);
|
|
rel(s, bv0, IRT_LQ, bv1, s.ann2ipl(ann));
|
|
}
|
|
|
|
void p_count(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
IntVarArgs iv = s.arg2intvarargs(ce[0]);
|
|
if (!ce[1]->isIntVar()) {
|
|
if (!ce[2]->isIntVar()) {
|
|
count(s, iv, ce[1]->getInt(), IRT_EQ, ce[2]->getInt(),
|
|
s.ann2ipl(ann));
|
|
} else {
|
|
count(s, iv, ce[1]->getInt(), IRT_EQ, s.arg2IntVar(ce[2]),
|
|
s.ann2ipl(ann));
|
|
}
|
|
} else if (!ce[2]->isIntVar()) {
|
|
count(s, iv, s.arg2IntVar(ce[1]), IRT_EQ, ce[2]->getInt(),
|
|
s.ann2ipl(ann));
|
|
} else {
|
|
count(s, iv, s.arg2IntVar(ce[1]), IRT_EQ, s.arg2IntVar(ce[2]),
|
|
s.ann2ipl(ann));
|
|
}
|
|
}
|
|
|
|
void p_count_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
IntVarArgs iv = s.arg2intvarargs(ce[0]);
|
|
IntVar x = s.arg2IntVar(ce[1]);
|
|
IntVar y = s.arg2IntVar(ce[2]);
|
|
BoolVar b = s.arg2BoolVar(ce[3]);
|
|
IntVar c(s,0,Int::Limits::max);
|
|
count(s,iv,x,IRT_EQ,c,s.ann2ipl(ann));
|
|
rel(s, b == (c==y));
|
|
}
|
|
void p_count_imp(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
IntVarArgs iv = s.arg2intvarargs(ce[0]);
|
|
IntVar x = s.arg2IntVar(ce[1]);
|
|
IntVar y = s.arg2IntVar(ce[2]);
|
|
BoolVar b = s.arg2BoolVar(ce[3]);
|
|
IntVar c(s,0,Int::Limits::max);
|
|
count(s,iv,x,IRT_EQ,c,s.ann2ipl(ann));
|
|
rel(s, b >> (c==y));
|
|
}
|
|
|
|
void count_rel(IntRelType irt,
|
|
FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
IntVarArgs iv = s.arg2intvarargs(ce[1]);
|
|
count(s, iv, ce[2]->getInt(), irt, ce[0]->getInt(), s.ann2ipl(ann));
|
|
}
|
|
|
|
void p_at_most(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
count_rel(IRT_LQ, s, ce, ann);
|
|
}
|
|
|
|
void p_at_least(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
count_rel(IRT_GQ, s, ce, ann);
|
|
}
|
|
|
|
void p_bin_packing_load(FlatZincSpace& s, const ConExpr& ce,
|
|
AST::Node* ann) {
|
|
int minIdx = ce[3]->getInt();
|
|
IntVarArgs load = s.arg2intvarargs(ce[0]);
|
|
IntVarArgs l;
|
|
IntVarArgs bin = s.arg2intvarargs(ce[1]);
|
|
for (int i=bin.size(); i--;)
|
|
rel(s, bin[i] >= minIdx);
|
|
if (minIdx > 0) {
|
|
for (int i=minIdx; i--;)
|
|
l << IntVar(s,0,0);
|
|
} else if (minIdx < 0) {
|
|
IntVarArgs bin2(bin.size());
|
|
for (int i=bin.size(); i--;)
|
|
bin2[i] = expr(s, bin[i]-minIdx, s.ann2ipl(ann));
|
|
bin = bin2;
|
|
}
|
|
l << load;
|
|
IntArgs sizes = s.arg2intargs(ce[2]);
|
|
|
|
IntVarArgs allvars = l + bin;
|
|
unshare(s, allvars);
|
|
binpacking(s, allvars.slice(0,1,l.size()), allvars.slice(l.size(),1,bin.size()),
|
|
sizes, s.ann2ipl(ann));
|
|
}
|
|
|
|
void p_global_cardinality(FlatZincSpace& s, const ConExpr& ce,
|
|
AST::Node* ann) {
|
|
IntVarArgs iv0 = s.arg2intvarargs(ce[0]);
|
|
IntArgs cover = s.arg2intargs(ce[1]);
|
|
IntVarArgs iv1 = s.arg2intvarargs(ce[2]);
|
|
|
|
Region re;
|
|
IntSet cover_s(cover);
|
|
IntSetRanges cover_r(cover_s);
|
|
IntVarRanges* iv0_ri = re.alloc<IntVarRanges>(iv0.size());
|
|
for (int i=iv0.size(); i--;)
|
|
iv0_ri[i] = IntVarRanges(iv0[i]);
|
|
Iter::Ranges::NaryUnion iv0_r(re,iv0_ri,iv0.size());
|
|
Iter::Ranges::Diff<Iter::Ranges::NaryUnion,IntSetRanges>
|
|
extra_r(iv0_r,cover_r);
|
|
Iter::Ranges::ToValues<Iter::Ranges::Diff<
|
|
Iter::Ranges::NaryUnion,IntSetRanges> > extra(extra_r);
|
|
for (; extra(); ++extra) {
|
|
cover << extra.val();
|
|
iv1 << IntVar(s,0,iv0.size());
|
|
}
|
|
IntPropLevel ipl = s.ann2ipl(ann);
|
|
if (ipl==IPL_DEF)
|
|
ipl=IPL_BND;
|
|
if (ipl==IPL_DOM) {
|
|
IntVarArgs allvars = iv0+iv1;
|
|
unshare(s, allvars);
|
|
count(s, allvars.slice(0,1,iv0.size()),
|
|
allvars.slice(iv0.size(),1,iv1.size()),
|
|
cover, ipl);
|
|
} else {
|
|
unshare(s, iv0);
|
|
count(s, iv0, iv1, cover, ipl);
|
|
}
|
|
}
|
|
|
|
void p_global_cardinality_closed(FlatZincSpace& s, const ConExpr& ce,
|
|
AST::Node* ann) {
|
|
IntVarArgs iv0 = s.arg2intvarargs(ce[0]);
|
|
IntArgs cover = s.arg2intargs(ce[1]);
|
|
IntVarArgs iv1 = s.arg2intvarargs(ce[2]);
|
|
IntPropLevel ipl = s.ann2ipl(ann);
|
|
if (ipl==IPL_DEF)
|
|
ipl=IPL_BND;
|
|
if (ipl==IPL_DOM) {
|
|
IntVarArgs allvars = iv0+iv1;
|
|
unshare(s, allvars);
|
|
count(s, allvars.slice(0,1,iv0.size()),
|
|
allvars.slice(iv0.size(),1,iv1.size()),
|
|
cover, ipl);
|
|
} else {
|
|
unshare(s, iv0);
|
|
count(s, iv0, iv1, cover, ipl);
|
|
}
|
|
}
|
|
|
|
void p_global_cardinality_low_up(FlatZincSpace& s, const ConExpr& ce,
|
|
AST::Node* ann) {
|
|
IntVarArgs x = s.arg2intvarargs(ce[0]);
|
|
IntArgs cover = s.arg2intargs(ce[1]);
|
|
|
|
IntArgs lbound = s.arg2intargs(ce[2]);
|
|
IntArgs ubound = s.arg2intargs(ce[3]);
|
|
IntSetArgs y(cover.size());
|
|
for (int i=cover.size(); i--;)
|
|
y[i] = IntSet(lbound[i],ubound[i]);
|
|
|
|
IntSet cover_s(cover);
|
|
Region re;
|
|
IntVarRanges* xrs = re.alloc<IntVarRanges>(x.size());
|
|
for (int i=x.size(); i--;)
|
|
xrs[i].init(x[i]);
|
|
Iter::Ranges::NaryUnion u(re, xrs, x.size());
|
|
Iter::Ranges::ToValues<Iter::Ranges::NaryUnion> uv(u);
|
|
for (; uv(); ++uv) {
|
|
if (!cover_s.in(uv.val())) {
|
|
cover << uv.val();
|
|
y << IntSet(0,x.size());
|
|
}
|
|
}
|
|
unshare(s, x);
|
|
IntPropLevel ipl = s.ann2ipl(ann);
|
|
if (ipl==IPL_DEF)
|
|
ipl=IPL_BND;
|
|
count(s, x, y, cover, ipl);
|
|
}
|
|
|
|
void p_global_cardinality_low_up_closed(FlatZincSpace& s,
|
|
const ConExpr& ce,
|
|
AST::Node* ann) {
|
|
IntVarArgs x = s.arg2intvarargs(ce[0]);
|
|
IntArgs cover = s.arg2intargs(ce[1]);
|
|
|
|
IntArgs lbound = s.arg2intargs(ce[2]);
|
|
IntArgs ubound = s.arg2intargs(ce[3]);
|
|
IntSetArgs y(cover.size());
|
|
for (int i=cover.size(); i--;)
|
|
y[i] = IntSet(lbound[i],ubound[i]);
|
|
unshare(s, x);
|
|
IntPropLevel ipl = s.ann2ipl(ann);
|
|
if (ipl==IPL_DEF)
|
|
ipl=IPL_BND;
|
|
count(s, x, y, cover, ipl);
|
|
}
|
|
|
|
void p_minimum(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
IntVarArgs iv = s.arg2intvarargs(ce[1]);
|
|
min(s, iv, s.arg2IntVar(ce[0]), s.ann2ipl(ann));
|
|
}
|
|
|
|
void p_maximum(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
IntVarArgs iv = s.arg2intvarargs(ce[1]);
|
|
max(s, iv, s.arg2IntVar(ce[0]), s.ann2ipl(ann));
|
|
}
|
|
|
|
void p_minimum_arg(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
IntVarArgs iv = s.arg2intvarargs(ce[0]);
|
|
int offset = ce[1]->getInt();
|
|
argmin(s, iv, offset, s.arg2IntVar(ce[2]), true, s.ann2ipl(ann));
|
|
}
|
|
|
|
void p_maximum_arg(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
IntVarArgs iv = s.arg2intvarargs(ce[0]);
|
|
int offset = ce[1]->getInt();
|
|
argmax(s, iv, offset, s.arg2IntVar(ce[2]), true, s.ann2ipl(ann));
|
|
}
|
|
|
|
void p_minimum_arg_bool(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
BoolVarArgs bv = s.arg2boolvarargs(ce[0]);
|
|
int offset = ce[1]->getInt();
|
|
argmin(s, bv, offset, s.arg2IntVar(ce[2]), true, s.ann2ipl(ann));
|
|
}
|
|
|
|
void p_maximum_arg_bool(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
BoolVarArgs bv = s.arg2boolvarargs(ce[0]);
|
|
int offset = ce[1]->getInt();
|
|
argmax(s, bv, offset, s.arg2IntVar(ce[2]), true, s.ann2ipl(ann));
|
|
}
|
|
|
|
void p_regular(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
IntVarArgs iv = s.arg2intvarargs(ce[0]);
|
|
int q = ce[1]->getInt();
|
|
int symbols = ce[2]->getInt();
|
|
IntArgs d = s.arg2intargs(ce[3]);
|
|
int q0 = ce[4]->getInt();
|
|
|
|
int noOfTrans = 0;
|
|
for (int i=1; i<=q; i++) {
|
|
for (int j=1; j<=symbols; j++) {
|
|
if (d[(i-1)*symbols+(j-1)] > 0)
|
|
noOfTrans++;
|
|
}
|
|
}
|
|
|
|
Region re;
|
|
DFA::Transition* t = re.alloc<DFA::Transition>(noOfTrans+1);
|
|
noOfTrans = 0;
|
|
for (int i=1; i<=q; i++) {
|
|
for (int j=1; j<=symbols; j++) {
|
|
if (d[(i-1)*symbols+(j-1)] > 0) {
|
|
t[noOfTrans].i_state = i;
|
|
t[noOfTrans].symbol = j;
|
|
t[noOfTrans].o_state = d[(i-1)*symbols+(j-1)];
|
|
noOfTrans++;
|
|
}
|
|
}
|
|
}
|
|
t[noOfTrans].i_state = -1;
|
|
|
|
// Final states
|
|
AST::SetLit* sl = ce[5]->getSet();
|
|
int* f;
|
|
if (sl->interval) {
|
|
f = static_cast<int*>(heap.ralloc(sizeof(int)*(sl->max-sl->min+2)));
|
|
for (int i=sl->min; i<=sl->max; i++)
|
|
f[i-sl->min] = i;
|
|
f[sl->max-sl->min+1] = -1;
|
|
} else {
|
|
f = static_cast<int*>(heap.ralloc(sizeof(int)*(sl->s.size()+1)));
|
|
for (int j=sl->s.size(); j--; )
|
|
f[j] = sl->s[j];
|
|
f[sl->s.size()] = -1;
|
|
}
|
|
|
|
DFA dfa(q0,t,f);
|
|
free(f);
|
|
unshare(s, iv);
|
|
extensional(s, iv, s.getSharedDFA(dfa), s.ann2ipl(ann));
|
|
}
|
|
|
|
void
|
|
p_sort(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
IntVarArgs x = s.arg2intvarargs(ce[0]);
|
|
IntVarArgs y = s.arg2intvarargs(ce[1]);
|
|
IntVarArgs xy(x.size()+y.size());
|
|
for (int i=x.size(); i--;)
|
|
xy[i] = x[i];
|
|
for (int i=y.size(); i--;)
|
|
xy[i+x.size()] = y[i];
|
|
unshare(s, xy);
|
|
for (int i=x.size(); i--;)
|
|
x[i] = xy[i];
|
|
for (int i=y.size(); i--;)
|
|
y[i] = xy[i+x.size()];
|
|
sorted(s, x, y, s.ann2ipl(ann));
|
|
}
|
|
|
|
void
|
|
p_inverse_offsets(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
IntVarArgs x = s.arg2intvarargs(ce[0]);
|
|
unshare(s, x);
|
|
int xoff = ce[1]->getInt();
|
|
IntVarArgs y = s.arg2intvarargs(ce[2]);
|
|
unshare(s, y);
|
|
int yoff = ce[3]->getInt();
|
|
channel(s, x, xoff, y, yoff, s.ann2ipl(ann));
|
|
}
|
|
|
|
void
|
|
p_increasing_int(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
IntVarArgs x = s.arg2intvarargs(ce[0]);
|
|
rel(s,x,IRT_LQ,s.ann2ipl(ann));
|
|
}
|
|
|
|
void
|
|
p_increasing_bool(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
BoolVarArgs x = s.arg2boolvarargs(ce[0]);
|
|
rel(s,x,IRT_LQ,s.ann2ipl(ann));
|
|
}
|
|
|
|
void
|
|
p_decreasing_int(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
IntVarArgs x = s.arg2intvarargs(ce[0]);
|
|
rel(s,x,IRT_GQ,s.ann2ipl(ann));
|
|
}
|
|
|
|
void
|
|
p_decreasing_bool(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
BoolVarArgs x = s.arg2boolvarargs(ce[0]);
|
|
rel(s,x,IRT_GQ,s.ann2ipl(ann));
|
|
}
|
|
|
|
void
|
|
p_table_int(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
IntVarArgs x = s.arg2intvarargs(ce[0]);
|
|
IntArgs tuples = s.arg2intargs(ce[1]);
|
|
TupleSet ts = s.arg2tupleset(tuples,x.size());
|
|
extensional(s,x,ts,s.ann2ipl(ann));
|
|
}
|
|
|
|
void
|
|
p_table_int_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
IntVarArgs x = s.arg2intvarargs(ce[0]);
|
|
IntArgs tuples = s.arg2intargs(ce[1]);
|
|
TupleSet ts = s.arg2tupleset(tuples,x.size());
|
|
extensional(s,x,ts,Reify(s.arg2BoolVar(ce[2]),RM_EQV),s.ann2ipl(ann));
|
|
}
|
|
|
|
void
|
|
p_table_int_imp(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
IntVarArgs x = s.arg2intvarargs(ce[0]);
|
|
IntArgs tuples = s.arg2intargs(ce[1]);
|
|
TupleSet ts = s.arg2tupleset(tuples,x.size());
|
|
extensional(s,x,ts,Reify(s.arg2BoolVar(ce[2]),RM_IMP),s.ann2ipl(ann));
|
|
}
|
|
|
|
void
|
|
p_table_bool(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
BoolVarArgs x = s.arg2boolvarargs(ce[0]);
|
|
IntArgs tuples = s.arg2boolargs(ce[1]);
|
|
TupleSet ts = s.arg2tupleset(tuples,x.size());
|
|
extensional(s,x,ts,s.ann2ipl(ann));
|
|
}
|
|
|
|
void
|
|
p_table_bool_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
BoolVarArgs x = s.arg2boolvarargs(ce[0]);
|
|
IntArgs tuples = s.arg2boolargs(ce[1]);
|
|
TupleSet ts = s.arg2tupleset(tuples,x.size());
|
|
extensional(s,x,ts,Reify(s.arg2BoolVar(ce[2]),RM_EQV),s.ann2ipl(ann));
|
|
}
|
|
|
|
void
|
|
p_table_bool_imp(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
BoolVarArgs x = s.arg2boolvarargs(ce[0]);
|
|
IntArgs tuples = s.arg2boolargs(ce[1]);
|
|
TupleSet ts = s.arg2tupleset(tuples,x.size());
|
|
extensional(s,x,ts,Reify(s.arg2BoolVar(ce[2]),RM_IMP),s.ann2ipl(ann));
|
|
}
|
|
|
|
void p_cumulative_opt(FlatZincSpace& s, const ConExpr& ce,
|
|
AST::Node* ann) {
|
|
IntVarArgs start = s.arg2intvarargs(ce[0]);
|
|
IntArgs duration = s.arg2intargs(ce[1]);
|
|
IntArgs height = s.arg2intargs(ce[2]);
|
|
BoolVarArgs opt = s.arg2boolvarargs(ce[3]);
|
|
int bound = ce[4]->getInt();
|
|
unshare(s,start);
|
|
cumulative(s,bound,start,duration,height,opt,s.ann2ipl(ann));
|
|
}
|
|
|
|
void p_cumulatives(FlatZincSpace& s, const ConExpr& ce,
|
|
AST::Node* ann) {
|
|
IntVarArgs start = s.arg2intvarargs(ce[0]);
|
|
IntVarArgs duration = s.arg2intvarargs(ce[1]);
|
|
IntVarArgs height = s.arg2intvarargs(ce[2]);
|
|
int n = start.size();
|
|
IntVar bound = s.arg2IntVar(ce[3]);
|
|
|
|
if (n==0)
|
|
return;
|
|
|
|
if (n == 1) {
|
|
rel(s, height[0] <= bound);
|
|
return;
|
|
}
|
|
|
|
bool nonzeroDuration = true;
|
|
for (int i=0; i<n; i++) {
|
|
if (duration[i].min() <= 0) {
|
|
nonzeroDuration = false;
|
|
break;
|
|
}
|
|
}
|
|
|
|
int minHeight = std::min(height[0].min(),height[1].min());
|
|
int minHeight2 = std::max(height[0].min(),height[1].min());
|
|
for (int i=2; i<n; i++) {
|
|
if (height[i].min() < minHeight) {
|
|
minHeight2 = minHeight;
|
|
minHeight = height[i].min();
|
|
} else if (height[i].min() < minHeight2) {
|
|
minHeight2 = height[i].min();
|
|
}
|
|
}
|
|
bool disjunctive = nonzeroDuration && (
|
|
(minHeight > bound.max()/2) ||
|
|
(minHeight2 > bound.max()/2 && minHeight+minHeight2>bound.max()));
|
|
if (disjunctive) {
|
|
rel(s, bound >= max(height));
|
|
// Unary
|
|
if (duration.assigned()) {
|
|
IntArgs durationI(n);
|
|
for (int i=n; i--;)
|
|
durationI[i] = duration[i].val();
|
|
unshare(s,start);
|
|
unary(s,start,durationI);
|
|
} else {
|
|
IntVarArgs end(n);
|
|
for (int i=n; i--;)
|
|
end[i] = expr(s,start[i]+duration[i]);
|
|
unshare(s,start);
|
|
unary(s,start,duration,end);
|
|
}
|
|
} else if (nonzeroDuration && height.assigned()) {
|
|
IntArgs heightI(n);
|
|
for (int i=n; i--;)
|
|
heightI[i] = height[i].val();
|
|
if (duration.assigned()) {
|
|
IntArgs durationI(n);
|
|
for (int i=n; i--;)
|
|
durationI[i] = duration[i].val();
|
|
cumulative(s, bound, start, durationI, heightI);
|
|
} else {
|
|
IntVarArgs end(n);
|
|
for (int i = n; i--; )
|
|
end[i] = expr(s,start[i]+duration[i]);
|
|
cumulative(s, bound, start, duration, end, heightI);
|
|
}
|
|
} else if (nonzeroDuration && bound.assigned()) {
|
|
IntArgs machine = IntArgs::create(n,0,0);
|
|
IntArgs limit({bound.val()});
|
|
IntVarArgs end(n);
|
|
for (int i=n; i--;)
|
|
end[i] = expr(s,start[i]+duration[i]);
|
|
cumulatives(s, machine, start, duration, end, height, limit, true,
|
|
s.ann2ipl(ann));
|
|
} else {
|
|
int min = Gecode::Int::Limits::max;
|
|
int max = Gecode::Int::Limits::min;
|
|
IntVarArgs end(start.size());
|
|
for (int i = start.size(); i--; ) {
|
|
min = std::min(min, start[i].min());
|
|
max = std::max(max, start[i].max() + duration[i].max());
|
|
end[i] = expr(s, start[i] + duration[i]);
|
|
}
|
|
for (int time = min; time < max; ++time) {
|
|
IntVarArgs x(start.size());
|
|
for (int i = start.size(); i--; ) {
|
|
IntVar overlaps = channel(s, expr(s, (start[i] <= time) &&
|
|
(time < end[i])));
|
|
x[i] = expr(s, overlaps * height[i]);
|
|
}
|
|
linear(s, x, IRT_LQ, bound);
|
|
}
|
|
}
|
|
}
|
|
|
|
void p_among_seq_int(FlatZincSpace& s, const ConExpr& ce,
|
|
AST::Node* ann) {
|
|
IntVarArgs x = s.arg2intvarargs(ce[0]);
|
|
IntSet S = s.arg2intset(ce[1]);
|
|
int q = ce[2]->getInt();
|
|
int l = ce[3]->getInt();
|
|
int u = ce[4]->getInt();
|
|
unshare(s, x);
|
|
sequence(s, x, S, q, l, u, s.ann2ipl(ann));
|
|
}
|
|
|
|
void p_among_seq_bool(FlatZincSpace& s, const ConExpr& ce,
|
|
AST::Node* ann) {
|
|
BoolVarArgs x = s.arg2boolvarargs(ce[0]);
|
|
bool val = ce[1]->getBool();
|
|
int q = ce[2]->getInt();
|
|
int l = ce[3]->getInt();
|
|
int u = ce[4]->getInt();
|
|
IntSet S(val, val);
|
|
unshare(s, x);
|
|
sequence(s, x, S, q, l, u, s.ann2ipl(ann));
|
|
}
|
|
|
|
void p_schedule_unary(FlatZincSpace& s, const ConExpr& ce, AST::Node*) {
|
|
IntVarArgs x = s.arg2intvarargs(ce[0]);
|
|
IntArgs p = s.arg2intargs(ce[1]);
|
|
unshare(s,x);
|
|
unary(s, x, p);
|
|
}
|
|
|
|
void p_schedule_unary_optional(FlatZincSpace& s, const ConExpr& ce,
|
|
AST::Node*) {
|
|
IntVarArgs x = s.arg2intvarargs(ce[0]);
|
|
IntArgs p = s.arg2intargs(ce[1]);
|
|
BoolVarArgs m = s.arg2boolvarargs(ce[2]);
|
|
unshare(s,x);
|
|
unary(s, x, p, m);
|
|
}
|
|
|
|
void p_circuit(FlatZincSpace& s, const ConExpr& ce, AST::Node *ann) {
|
|
int off = ce[0]->getInt();
|
|
IntVarArgs xv = s.arg2intvarargs(ce[1]);
|
|
unshare(s,xv);
|
|
circuit(s,off,xv,s.ann2ipl(ann));
|
|
}
|
|
void p_circuit_cost_array(FlatZincSpace& s, const ConExpr& ce,
|
|
AST::Node *ann) {
|
|
IntArgs c = s.arg2intargs(ce[0]);
|
|
IntVarArgs xv = s.arg2intvarargs(ce[1]);
|
|
IntVarArgs yv = s.arg2intvarargs(ce[2]);
|
|
IntVar z = s.arg2IntVar(ce[3]);
|
|
unshare(s,xv);
|
|
circuit(s,c,xv,yv,z,s.ann2ipl(ann));
|
|
}
|
|
void p_circuit_cost(FlatZincSpace& s, const ConExpr& ce, AST::Node *ann) {
|
|
IntArgs c = s.arg2intargs(ce[0]);
|
|
IntVarArgs xv = s.arg2intvarargs(ce[1]);
|
|
IntVar z = s.arg2IntVar(ce[2]);
|
|
unshare(s,xv);
|
|
circuit(s,c,xv,z,s.ann2ipl(ann));
|
|
}
|
|
|
|
void p_nooverlap(FlatZincSpace& s, const ConExpr& ce, AST::Node *ann) {
|
|
IntVarArgs x0 = s.arg2intvarargs(ce[0]);
|
|
IntVarArgs w = s.arg2intvarargs(ce[1]);
|
|
IntVarArgs y0 = s.arg2intvarargs(ce[2]);
|
|
IntVarArgs h = s.arg2intvarargs(ce[3]);
|
|
if (w.assigned() && h.assigned()) {
|
|
IntArgs iw(w.size());
|
|
for (int i=w.size(); i--;)
|
|
iw[i] = w[i].val();
|
|
IntArgs ih(h.size());
|
|
for (int i=h.size(); i--;)
|
|
ih[i] = h[i].val();
|
|
nooverlap(s,x0,iw,y0,ih,s.ann2ipl(ann));
|
|
|
|
int miny = y0[0].min();
|
|
int maxy = y0[0].max();
|
|
int maxdy = ih[0];
|
|
for (int i=1; i<y0.size(); i++) {
|
|
miny = std::min(miny,y0[i].min());
|
|
maxy = std::max(maxy,y0[i].max());
|
|
maxdy = std::max(maxdy,ih[i]);
|
|
}
|
|
int minx = x0[0].min();
|
|
int maxx = x0[0].max();
|
|
int maxdx = iw[0];
|
|
for (int i=1; i<x0.size(); i++) {
|
|
minx = std::min(minx,x0[i].min());
|
|
maxx = std::max(maxx,x0[i].max());
|
|
maxdx = std::max(maxdx,iw[i]);
|
|
}
|
|
if (miny > Int::Limits::min && maxy < Int::Limits::max) {
|
|
cumulative(s,maxdy+maxy-miny,x0,iw,ih);
|
|
cumulative(s,maxdx+maxx-minx,y0,ih,iw);
|
|
}
|
|
} else {
|
|
IntVarArgs x1(x0.size()), y1(y0.size());
|
|
for (int i=x0.size(); i--; )
|
|
x1[i] = expr(s, x0[i] + w[i]);
|
|
for (int i=y0.size(); i--; )
|
|
y1[i] = expr(s, y0[i] + h[i]);
|
|
nooverlap(s,x0,w,x1,y0,h,y1,s.ann2ipl(ann));
|
|
}
|
|
}
|
|
|
|
void p_precede(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
IntVarArgs x = s.arg2intvarargs(ce[0]);
|
|
int p_s = ce[1]->getInt();
|
|
int p_t = ce[2]->getInt();
|
|
precede(s,x,p_s,p_t,s.ann2ipl(ann));
|
|
}
|
|
|
|
void p_nvalue(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
IntVarArgs x = s.arg2intvarargs(ce[1]);
|
|
if (ce[0]->isIntVar()) {
|
|
IntVar y = s.arg2IntVar(ce[0]);
|
|
nvalues(s,x,IRT_EQ,y,s.ann2ipl(ann));
|
|
} else {
|
|
nvalues(s,x,IRT_EQ,ce[0]->getInt(),s.ann2ipl(ann));
|
|
}
|
|
}
|
|
|
|
void p_among(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
IntVarArgs x = s.arg2intvarargs(ce[1]);
|
|
IntSet v = s.arg2intset(ce[2]);
|
|
if (ce[0]->isIntVar()) {
|
|
IntVar n = s.arg2IntVar(ce[0]);
|
|
unshare(s, x);
|
|
count(s,x,v,IRT_EQ,n,s.ann2ipl(ann));
|
|
} else {
|
|
unshare(s, x);
|
|
count(s,x,v,IRT_EQ,ce[0]->getInt(),s.ann2ipl(ann));
|
|
}
|
|
}
|
|
|
|
void p_member_int(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
IntVarArgs x = s.arg2intvarargs(ce[0]);
|
|
IntVar y = s.arg2IntVar(ce[1]);
|
|
member(s,x,y,s.ann2ipl(ann));
|
|
}
|
|
void p_member_int_reif(FlatZincSpace& s, const ConExpr& ce,
|
|
AST::Node* ann) {
|
|
IntVarArgs x = s.arg2intvarargs(ce[0]);
|
|
IntVar y = s.arg2IntVar(ce[1]);
|
|
BoolVar b = s.arg2BoolVar(ce[2]);
|
|
member(s,x,y,b,s.ann2ipl(ann));
|
|
}
|
|
void p_member_bool(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
BoolVarArgs x = s.arg2boolvarargs(ce[0]);
|
|
BoolVar y = s.arg2BoolVar(ce[1]);
|
|
member(s,x,y,s.ann2ipl(ann));
|
|
}
|
|
void p_member_bool_reif(FlatZincSpace& s, const ConExpr& ce,
|
|
AST::Node* ann) {
|
|
BoolVarArgs x = s.arg2boolvarargs(ce[0]);
|
|
BoolVar y = s.arg2BoolVar(ce[1]);
|
|
member(s,x,y,s.arg2BoolVar(ce[2]),s.ann2ipl(ann));
|
|
}
|
|
|
|
class IntPoster {
|
|
public:
|
|
IntPoster(void) {
|
|
registry().add("all_different_int", &p_distinct);
|
|
registry().add("all_different_offset", &p_distinctOffset);
|
|
registry().add("all_equal_int", &p_all_equal);
|
|
registry().add("int_eq", &p_int_eq);
|
|
registry().add("int_ne", &p_int_ne);
|
|
registry().add("int_ge", &p_int_ge);
|
|
registry().add("int_gt", &p_int_gt);
|
|
registry().add("int_le", &p_int_le);
|
|
registry().add("int_lt", &p_int_lt);
|
|
registry().add("int_eq_reif", &p_int_eq_reif);
|
|
registry().add("int_ne_reif", &p_int_ne_reif);
|
|
registry().add("int_ge_reif", &p_int_ge_reif);
|
|
registry().add("int_gt_reif", &p_int_gt_reif);
|
|
registry().add("int_le_reif", &p_int_le_reif);
|
|
registry().add("int_lt_reif", &p_int_lt_reif);
|
|
registry().add("int_eq_imp", &p_int_eq_imp);
|
|
registry().add("int_ne_imp", &p_int_ne_imp);
|
|
registry().add("int_ge_imp", &p_int_ge_imp);
|
|
registry().add("int_gt_imp", &p_int_gt_imp);
|
|
registry().add("int_le_imp", &p_int_le_imp);
|
|
registry().add("int_lt_imp", &p_int_lt_imp);
|
|
registry().add("int_lin_eq", &p_int_lin_eq);
|
|
registry().add("int_lin_eq_reif", &p_int_lin_eq_reif);
|
|
registry().add("int_lin_eq_imp", &p_int_lin_eq_imp);
|
|
registry().add("int_lin_ne", &p_int_lin_ne);
|
|
registry().add("int_lin_ne_reif", &p_int_lin_ne_reif);
|
|
registry().add("int_lin_ne_imp", &p_int_lin_ne_imp);
|
|
registry().add("int_lin_le", &p_int_lin_le);
|
|
registry().add("int_lin_le_reif", &p_int_lin_le_reif);
|
|
registry().add("int_lin_le_imp", &p_int_lin_le_imp);
|
|
registry().add("int_lin_lt", &p_int_lin_lt);
|
|
registry().add("int_lin_lt_reif", &p_int_lin_lt_reif);
|
|
registry().add("int_lin_lt_imp", &p_int_lin_lt_imp);
|
|
registry().add("int_lin_ge", &p_int_lin_ge);
|
|
registry().add("int_lin_ge_reif", &p_int_lin_ge_reif);
|
|
registry().add("int_lin_ge_imp", &p_int_lin_ge_imp);
|
|
registry().add("int_lin_gt", &p_int_lin_gt);
|
|
registry().add("int_lin_gt_reif", &p_int_lin_gt_reif);
|
|
registry().add("int_lin_gt_imp", &p_int_lin_gt_imp);
|
|
registry().add("int_plus", &p_int_plus);
|
|
registry().add("int_minus", &p_int_minus);
|
|
registry().add("int_times", &p_int_times);
|
|
registry().add("gecode_int_pow", &p_int_pow);
|
|
registry().add("int_div", &p_int_div);
|
|
registry().add("int_mod", &p_int_mod);
|
|
registry().add("int_min", &p_int_min);
|
|
registry().add("int_max", &p_int_max);
|
|
registry().add("int_abs", &p_abs);
|
|
registry().add("int_negate", &p_int_negate);
|
|
registry().add("bool_eq", &p_bool_eq);
|
|
registry().add("bool_eq_reif", &p_bool_eq_reif);
|
|
registry().add("bool_eq_imp", &p_bool_eq_imp);
|
|
registry().add("bool_ne", &p_bool_ne);
|
|
registry().add("bool_ne_reif", &p_bool_ne_reif);
|
|
registry().add("bool_ne_imp", &p_bool_ne_imp);
|
|
registry().add("bool_ge", &p_bool_ge);
|
|
registry().add("bool_ge_reif", &p_bool_ge_reif);
|
|
registry().add("bool_ge_imp", &p_bool_ge_imp);
|
|
registry().add("bool_le", &p_bool_le);
|
|
registry().add("bool_le_reif", &p_bool_le_reif);
|
|
registry().add("bool_le_imp", &p_bool_le_imp);
|
|
registry().add("bool_gt", &p_bool_gt);
|
|
registry().add("bool_gt_reif", &p_bool_gt_reif);
|
|
registry().add("bool_gt_imp", &p_bool_gt_imp);
|
|
registry().add("bool_lt", &p_bool_lt);
|
|
registry().add("bool_lt_reif", &p_bool_lt_reif);
|
|
registry().add("bool_lt_imp", &p_bool_lt_imp);
|
|
registry().add("bool_or", &p_bool_or);
|
|
registry().add("bool_or_imp", &p_bool_or_imp);
|
|
registry().add("bool_and", &p_bool_and);
|
|
registry().add("bool_and_imp", &p_bool_and_imp);
|
|
registry().add("bool_xor", &p_bool_xor);
|
|
registry().add("bool_xor_imp", &p_bool_xor_imp);
|
|
registry().add("array_bool_and", &p_array_bool_and);
|
|
registry().add("array_bool_and_imp", &p_array_bool_and_imp);
|
|
registry().add("array_bool_or", &p_array_bool_or);
|
|
registry().add("array_bool_or_imp", &p_array_bool_or_imp);
|
|
registry().add("array_bool_xor", &p_array_bool_xor);
|
|
registry().add("array_bool_xor_imp", &p_array_bool_xor_imp);
|
|
registry().add("bool_clause", &p_array_bool_clause);
|
|
registry().add("bool_clause_reif", &p_array_bool_clause_reif);
|
|
registry().add("bool_clause_imp", &p_array_bool_clause_imp);
|
|
registry().add("bool_left_imp", &p_bool_l_imp);
|
|
registry().add("bool_right_imp", &p_bool_r_imp);
|
|
registry().add("bool_not", &p_bool_not);
|
|
registry().add("array_int_element", &p_array_int_element);
|
|
registry().add("array_var_int_element", &p_array_int_element);
|
|
registry().add("gecode_int_element", &p_array_int_element_offset);
|
|
registry().add("gecode_var_int_element", &p_array_int_element_offset);
|
|
registry().add("gecode_int_element2d", &p_array_int_element2d);
|
|
registry().add("array_bool_element", &p_array_bool_element);
|
|
registry().add("array_var_bool_element", &p_array_bool_element);
|
|
registry().add("gecode_bool_element", &p_array_bool_element_offset);
|
|
registry().add("gecode_var_bool_element", &p_array_bool_element_offset);
|
|
registry().add("gecode_bool_element2d", &p_array_bool_element2d);
|
|
registry().add("bool2int", &p_bool2int);
|
|
registry().add("int_in", &p_int_in);
|
|
registry().add("int_in_reif", &p_int_in_reif);
|
|
registry().add("int_in_imp", &p_int_in_imp);
|
|
#ifndef GECODE_HAS_SET_VARS
|
|
registry().add("set_in", &p_int_in);
|
|
registry().add("set_in_reif", &p_int_in_reif);
|
|
registry().add("set_in_imp", &p_int_in_imp);
|
|
#endif
|
|
|
|
registry().add("array_int_lt", &p_array_int_lt);
|
|
registry().add("array_int_lq", &p_array_int_lq);
|
|
registry().add("array_bool_lt", &p_array_bool_lt);
|
|
registry().add("array_bool_lq", &p_array_bool_lq);
|
|
registry().add("count", &p_count);
|
|
registry().add("count_reif", &p_count_reif);
|
|
registry().add("count_imp", &p_count_imp);
|
|
registry().add("count_eq", &p_count);
|
|
registry().add("count_eq_reif", &p_count_reif);
|
|
registry().add("count_eq_imp", &p_count_imp);
|
|
registry().add("at_least_int", &p_at_least);
|
|
registry().add("at_most_int", &p_at_most);
|
|
registry().add("gecode_bin_packing_load", &p_bin_packing_load);
|
|
registry().add("gecode_global_cardinality", &p_global_cardinality);
|
|
registry().add("gecode_global_cardinality_closed",
|
|
&p_global_cardinality_closed);
|
|
registry().add("global_cardinality_low_up",
|
|
&p_global_cardinality_low_up);
|
|
registry().add("global_cardinality_low_up_closed",
|
|
&p_global_cardinality_low_up_closed);
|
|
registry().add("array_int_minimum", &p_minimum);
|
|
registry().add("array_int_maximum", &p_maximum);
|
|
registry().add("gecode_minimum_arg_int_offset", &p_minimum_arg);
|
|
registry().add("gecode_maximum_arg_int_offset", &p_maximum_arg);
|
|
registry().add("gecode_minimum_arg_bool_offset", &p_minimum_arg_bool);
|
|
registry().add("gecode_maximum_arg_bool_offset", &p_maximum_arg_bool);
|
|
registry().add("array_int_maximum", &p_maximum);
|
|
registry().add("gecode_regular", &p_regular);
|
|
registry().add("sort", &p_sort);
|
|
registry().add("inverse_offsets", &p_inverse_offsets);
|
|
registry().add("increasing_int", &p_increasing_int);
|
|
registry().add("increasing_bool", &p_increasing_bool);
|
|
registry().add("decreasing_int", &p_decreasing_int);
|
|
registry().add("decreasing_bool", &p_decreasing_bool);
|
|
registry().add("gecode_table_int", &p_table_int);
|
|
registry().add("gecode_table_int_reif", &p_table_int_reif);
|
|
registry().add("gecode_table_int_imp", &p_table_int_imp);
|
|
registry().add("gecode_table_bool", &p_table_bool);
|
|
registry().add("gecode_table_bool_reif", &p_table_bool_reif);
|
|
registry().add("gecode_table_bool_imp", &p_table_bool_imp);
|
|
registry().add("cumulatives", &p_cumulatives);
|
|
registry().add("gecode_among_seq_int", &p_among_seq_int);
|
|
registry().add("gecode_among_seq_bool", &p_among_seq_bool);
|
|
|
|
registry().add("bool_lin_eq", &p_bool_lin_eq);
|
|
registry().add("bool_lin_ne", &p_bool_lin_ne);
|
|
registry().add("bool_lin_le", &p_bool_lin_le);
|
|
registry().add("bool_lin_lt", &p_bool_lin_lt);
|
|
registry().add("bool_lin_ge", &p_bool_lin_ge);
|
|
registry().add("bool_lin_gt", &p_bool_lin_gt);
|
|
|
|
registry().add("bool_lin_eq_reif", &p_bool_lin_eq_reif);
|
|
registry().add("bool_lin_eq_imp", &p_bool_lin_eq_imp);
|
|
registry().add("bool_lin_ne_reif", &p_bool_lin_ne_reif);
|
|
registry().add("bool_lin_ne_imp", &p_bool_lin_ne_imp);
|
|
registry().add("bool_lin_le_reif", &p_bool_lin_le_reif);
|
|
registry().add("bool_lin_le_imp", &p_bool_lin_le_imp);
|
|
registry().add("bool_lin_lt_reif", &p_bool_lin_lt_reif);
|
|
registry().add("bool_lin_lt_imp", &p_bool_lin_lt_imp);
|
|
registry().add("bool_lin_ge_reif", &p_bool_lin_ge_reif);
|
|
registry().add("bool_lin_ge_imp", &p_bool_lin_ge_imp);
|
|
registry().add("bool_lin_gt_reif", &p_bool_lin_gt_reif);
|
|
registry().add("bool_lin_gt_imp", &p_bool_lin_gt_imp);
|
|
|
|
registry().add("gecode_schedule_unary", &p_schedule_unary);
|
|
registry().add("gecode_schedule_unary_optional", &p_schedule_unary_optional);
|
|
registry().add("gecode_schedule_cumulative_optional", &p_cumulative_opt);
|
|
|
|
registry().add("gecode_circuit", &p_circuit);
|
|
registry().add("gecode_circuit_cost_array", &p_circuit_cost_array);
|
|
registry().add("gecode_circuit_cost", &p_circuit_cost);
|
|
registry().add("gecode_nooverlap", &p_nooverlap);
|
|
registry().add("gecode_precede", &p_precede);
|
|
registry().add("nvalue",&p_nvalue);
|
|
registry().add("among",&p_among);
|
|
registry().add("member_int",&p_member_int);
|
|
registry().add("gecode_member_int_reif",&p_member_int_reif);
|
|
registry().add("member_bool",&p_member_bool);
|
|
registry().add("gecode_member_bool_reif",&p_member_bool_reif);
|
|
}
|
|
};
|
|
IntPoster __int_poster;
|
|
|
|
#ifdef GECODE_HAS_SET_VARS
|
|
void p_set_OP(FlatZincSpace& s, SetOpType op,
|
|
const ConExpr& ce, AST::Node *) {
|
|
rel(s, s.arg2SetVar(ce[0]), op, s.arg2SetVar(ce[1]),
|
|
SRT_EQ, s.arg2SetVar(ce[2]));
|
|
}
|
|
void p_set_union(FlatZincSpace& s, const ConExpr& ce, AST::Node *ann) {
|
|
p_set_OP(s, SOT_UNION, ce, ann);
|
|
}
|
|
void p_set_intersect(FlatZincSpace& s, const ConExpr& ce, AST::Node *ann) {
|
|
p_set_OP(s, SOT_INTER, ce, ann);
|
|
}
|
|
void p_set_diff(FlatZincSpace& s, const ConExpr& ce, AST::Node *ann) {
|
|
p_set_OP(s, SOT_MINUS, ce, ann);
|
|
}
|
|
|
|
void p_set_symdiff(FlatZincSpace& s, const ConExpr& ce, AST::Node*) {
|
|
SetVar x = s.arg2SetVar(ce[0]);
|
|
SetVar y = s.arg2SetVar(ce[1]);
|
|
|
|
SetVarLubRanges xub(x);
|
|
IntSet xubs(xub);
|
|
SetVar x_y(s,IntSet::empty,xubs);
|
|
rel(s, x, SOT_MINUS, y, SRT_EQ, x_y);
|
|
|
|
SetVarLubRanges yub(y);
|
|
IntSet yubs(yub);
|
|
SetVar y_x(s,IntSet::empty,yubs);
|
|
rel(s, y, SOT_MINUS, x, SRT_EQ, y_x);
|
|
|
|
rel(s, x_y, SOT_UNION, y_x, SRT_EQ, s.arg2SetVar(ce[2]));
|
|
}
|
|
|
|
void p_array_set_OP(FlatZincSpace& s, SetOpType op,
|
|
const ConExpr& ce, AST::Node *) {
|
|
SetVarArgs xs = s.arg2setvarargs(ce[0]);
|
|
rel(s, op, xs, s.arg2SetVar(ce[1]));
|
|
}
|
|
void p_array_set_union(FlatZincSpace& s, const ConExpr& ce, AST::Node *ann) {
|
|
p_array_set_OP(s, SOT_UNION, ce, ann);
|
|
}
|
|
void p_array_set_partition(FlatZincSpace& s, const ConExpr& ce, AST::Node *ann) {
|
|
p_array_set_OP(s, SOT_DUNION, ce, ann);
|
|
}
|
|
|
|
|
|
void p_set_rel(FlatZincSpace& s, SetRelType srt, const ConExpr& ce) {
|
|
rel(s, s.arg2SetVar(ce[0]), srt, s.arg2SetVar(ce[1]));
|
|
}
|
|
|
|
void p_set_eq(FlatZincSpace& s, const ConExpr& ce, AST::Node *) {
|
|
p_set_rel(s, SRT_EQ, ce);
|
|
}
|
|
void p_set_ne(FlatZincSpace& s, const ConExpr& ce, AST::Node *) {
|
|
p_set_rel(s, SRT_NQ, ce);
|
|
}
|
|
void p_set_subset(FlatZincSpace& s, const ConExpr& ce, AST::Node *) {
|
|
p_set_rel(s, SRT_SUB, ce);
|
|
}
|
|
void p_set_superset(FlatZincSpace& s, const ConExpr& ce, AST::Node *) {
|
|
p_set_rel(s, SRT_SUP, ce);
|
|
}
|
|
void p_set_le(FlatZincSpace& s, const ConExpr& ce, AST::Node *) {
|
|
p_set_rel(s, SRT_LQ, ce);
|
|
}
|
|
void p_set_lt(FlatZincSpace& s, const ConExpr& ce, AST::Node *) {
|
|
p_set_rel(s, SRT_LE, ce);
|
|
}
|
|
void p_set_card(FlatZincSpace& s, const ConExpr& ce, AST::Node *) {
|
|
if (!ce[1]->isIntVar()) {
|
|
cardinality(s, s.arg2SetVar(ce[0]), ce[1]->getInt(),
|
|
ce[1]->getInt());
|
|
} else {
|
|
cardinality(s, s.arg2SetVar(ce[0]), s.arg2IntVar(ce[1]));
|
|
}
|
|
}
|
|
void p_set_in(FlatZincSpace& s, const ConExpr& ce, AST::Node *) {
|
|
if (!ce[1]->isSetVar()) {
|
|
IntSet d = s.arg2intset(ce[1]);
|
|
if (ce[0]->isBoolVar()) {
|
|
IntSetRanges dr(d);
|
|
Iter::Ranges::Singleton sr(0,1);
|
|
Iter::Ranges::Inter<IntSetRanges,Iter::Ranges::Singleton> i(dr,sr);
|
|
IntSet d01(i);
|
|
if (d01.size() == 0) {
|
|
s.fail();
|
|
} else {
|
|
rel(s, s.arg2BoolVar(ce[0]), IRT_GQ, d01.min());
|
|
rel(s, s.arg2BoolVar(ce[0]), IRT_LQ, d01.max());
|
|
}
|
|
} else {
|
|
dom(s, s.arg2IntVar(ce[0]), d);
|
|
}
|
|
} else {
|
|
if (!ce[0]->isIntVar()) {
|
|
dom(s, s.arg2SetVar(ce[1]), SRT_SUP, ce[0]->getInt());
|
|
} else {
|
|
rel(s, s.arg2SetVar(ce[1]), SRT_SUP, s.arg2IntVar(ce[0]));
|
|
}
|
|
}
|
|
}
|
|
void p_set_rel_reif(FlatZincSpace& s, SetRelType srt, const ConExpr& ce) {
|
|
rel(s, s.arg2SetVar(ce[0]), srt, s.arg2SetVar(ce[1]),
|
|
s.arg2BoolVar(ce[2]));
|
|
}
|
|
|
|
void p_set_eq_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node *) {
|
|
p_set_rel_reif(s,SRT_EQ,ce);
|
|
}
|
|
void p_set_le_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node *) {
|
|
p_set_rel_reif(s,SRT_LQ,ce);
|
|
}
|
|
void p_set_lt_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node *) {
|
|
p_set_rel_reif(s,SRT_LE,ce);
|
|
}
|
|
void p_set_ne_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node *) {
|
|
p_set_rel_reif(s,SRT_NQ,ce);
|
|
}
|
|
void p_set_subset_reif(FlatZincSpace& s, const ConExpr& ce,
|
|
AST::Node *) {
|
|
p_set_rel_reif(s,SRT_SUB,ce);
|
|
}
|
|
void p_set_superset_reif(FlatZincSpace& s, const ConExpr& ce,
|
|
AST::Node *) {
|
|
p_set_rel_reif(s,SRT_SUP,ce);
|
|
}
|
|
void p_set_in_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann, ReifyMode rm) {
|
|
if (!ce[1]->isSetVar()) {
|
|
if (rm==RM_EQV) {
|
|
p_int_in_reif(s,ce,ann);
|
|
} else {
|
|
assert(rm==RM_IMP);
|
|
p_int_in_imp(s,ce,ann);
|
|
}
|
|
} else {
|
|
if (!ce[0]->isIntVar()) {
|
|
dom(s, s.arg2SetVar(ce[1]), SRT_SUP, ce[0]->getInt(),
|
|
Reify(s.arg2BoolVar(ce[2]),rm));
|
|
} else {
|
|
rel(s, s.arg2SetVar(ce[1]), SRT_SUP, s.arg2IntVar(ce[0]),
|
|
Reify(s.arg2BoolVar(ce[2]),rm));
|
|
}
|
|
}
|
|
}
|
|
void p_set_in_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
p_set_in_reif(s,ce,ann,RM_EQV);
|
|
}
|
|
void p_set_in_imp(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
p_set_in_reif(s,ce,ann,RM_IMP);
|
|
}
|
|
void p_set_disjoint(FlatZincSpace& s, const ConExpr& ce, AST::Node *) {
|
|
rel(s, s.arg2SetVar(ce[0]), SRT_DISJ, s.arg2SetVar(ce[1]));
|
|
}
|
|
|
|
void p_link_set_to_booleans(FlatZincSpace& s, const ConExpr& ce,
|
|
AST::Node *) {
|
|
SetVar x = s.arg2SetVar(ce[0]);
|
|
int idx = ce[2]->getInt();
|
|
assert(idx >= 0);
|
|
rel(s, x || IntSet(Set::Limits::min,idx-1));
|
|
BoolVarArgs y = s.arg2boolvarargs(ce[1],idx);
|
|
unshare(s, y);
|
|
channel(s, y, x);
|
|
}
|
|
|
|
void p_array_set_element(FlatZincSpace& s, const ConExpr& ce,
|
|
AST::Node*) {
|
|
bool isConstant = true;
|
|
AST::Array* a = ce[1]->getArray();
|
|
for (int i=a->a.size(); i--;) {
|
|
if (a->a[i]->isSetVar()) {
|
|
isConstant = false;
|
|
break;
|
|
}
|
|
}
|
|
IntVar selector = s.arg2IntVar(ce[0]);
|
|
rel(s, selector > 0);
|
|
if (isConstant) {
|
|
IntSetArgs sv = s.arg2intsetargs(ce[1],1);
|
|
element(s, sv, selector, s.arg2SetVar(ce[2]));
|
|
} else {
|
|
SetVarArgs sv = s.arg2setvarargs(ce[1], 1);
|
|
element(s, sv, selector, s.arg2SetVar(ce[2]));
|
|
}
|
|
}
|
|
|
|
void p_array_set_element_op(FlatZincSpace& s, const ConExpr& ce,
|
|
AST::Node*, SetOpType op,
|
|
const IntSet& universe =
|
|
IntSet(Set::Limits::min,Set::Limits::max)) {
|
|
bool isConstant = true;
|
|
AST::Array* a = ce[1]->getArray();
|
|
for (int i=a->a.size(); i--;) {
|
|
if (a->a[i]->isSetVar()) {
|
|
isConstant = false;
|
|
break;
|
|
}
|
|
}
|
|
SetVar selector = s.arg2SetVar(ce[0]);
|
|
dom(s, selector, SRT_DISJ, 0);
|
|
if (isConstant) {
|
|
IntSetArgs sv = s.arg2intsetargs(ce[1], 1);
|
|
element(s, op, sv, selector, s.arg2SetVar(ce[2]), universe);
|
|
} else {
|
|
SetVarArgs sv = s.arg2setvarargs(ce[1], 1);
|
|
element(s, op, sv, selector, s.arg2SetVar(ce[2]), universe);
|
|
}
|
|
}
|
|
|
|
void p_array_set_element_union(FlatZincSpace& s, const ConExpr& ce,
|
|
AST::Node* ann) {
|
|
p_array_set_element_op(s, ce, ann, SOT_UNION);
|
|
}
|
|
|
|
void p_array_set_element_intersect(FlatZincSpace& s, const ConExpr& ce,
|
|
AST::Node* ann) {
|
|
p_array_set_element_op(s, ce, ann, SOT_INTER);
|
|
}
|
|
|
|
void p_array_set_element_intersect_in(FlatZincSpace& s,
|
|
const ConExpr& ce,
|
|
AST::Node* ann) {
|
|
IntSet d = s.arg2intset(ce[3]);
|
|
p_array_set_element_op(s, ce, ann, SOT_INTER, d);
|
|
}
|
|
|
|
void p_array_set_element_partition(FlatZincSpace& s, const ConExpr& ce,
|
|
AST::Node* ann) {
|
|
p_array_set_element_op(s, ce, ann, SOT_DUNION);
|
|
}
|
|
|
|
void p_set_convex(FlatZincSpace& s, const ConExpr& ce, AST::Node *) {
|
|
convex(s, s.arg2SetVar(ce[0]));
|
|
}
|
|
|
|
void p_array_set_seq(FlatZincSpace& s, const ConExpr& ce, AST::Node *) {
|
|
SetVarArgs sv = s.arg2setvarargs(ce[0]);
|
|
sequence(s, sv);
|
|
}
|
|
|
|
void p_array_set_seq_union(FlatZincSpace& s, const ConExpr& ce,
|
|
AST::Node *) {
|
|
SetVarArgs sv = s.arg2setvarargs(ce[0]);
|
|
sequence(s, sv, s.arg2SetVar(ce[1]));
|
|
}
|
|
|
|
void p_int_set_channel(FlatZincSpace& s, const ConExpr& ce,
|
|
AST::Node *) {
|
|
int xoff=ce[1]->getInt();
|
|
assert(xoff >= 0);
|
|
int yoff=ce[3]->getInt();
|
|
assert(yoff >= 0);
|
|
IntVarArgs xv = s.arg2intvarargs(ce[0], xoff);
|
|
SetVarArgs yv = s.arg2setvarargs(ce[2], yoff, 1, IntSet(0, xoff-1));
|
|
IntSet xd(yoff,yv.size()-1);
|
|
for (int i=xoff; i<xv.size(); i++) {
|
|
dom(s, xv[i], xd);
|
|
}
|
|
IntSet yd(xoff,xv.size()-1);
|
|
for (int i=yoff; i<yv.size(); i++) {
|
|
dom(s, yv[i], SRT_SUB, yd);
|
|
}
|
|
channel(s,xv,yv);
|
|
}
|
|
|
|
void p_range(FlatZincSpace& s, const ConExpr& ce, AST::Node*) {
|
|
int xoff=ce[1]->getInt();
|
|
assert(xoff >= 0);
|
|
IntVarArgs xv = s.arg2intvarargs(ce[0],xoff);
|
|
element(s, SOT_UNION, xv, s.arg2SetVar(ce[2]), s.arg2SetVar(ce[3]));
|
|
}
|
|
|
|
void p_weights(FlatZincSpace& s, const ConExpr& ce, AST::Node*) {
|
|
IntArgs e = s.arg2intargs(ce[0]);
|
|
IntArgs w = s.arg2intargs(ce[1]);
|
|
SetVar x = s.arg2SetVar(ce[2]);
|
|
IntVar y = s.arg2IntVar(ce[3]);
|
|
weights(s,e,w,x,y);
|
|
}
|
|
|
|
void p_inverse_set(FlatZincSpace& s, const ConExpr& ce, AST::Node*) {
|
|
int xoff = ce[2]->getInt();
|
|
int yoff = ce[3]->getInt();
|
|
SetVarArgs x = s.arg2setvarargs(ce[0],xoff);
|
|
SetVarArgs y = s.arg2setvarargs(ce[1],yoff);
|
|
channel(s, x, y);
|
|
}
|
|
|
|
void p_precede_set(FlatZincSpace& s, const ConExpr& ce, AST::Node*) {
|
|
SetVarArgs x = s.arg2setvarargs(ce[0]);
|
|
int p_s = ce[1]->getInt();
|
|
int p_t = ce[2]->getInt();
|
|
precede(s,x,p_s,p_t);
|
|
}
|
|
|
|
class SetPoster {
|
|
public:
|
|
SetPoster(void) {
|
|
registry().add("set_eq", &p_set_eq);
|
|
registry().add("set_le", &p_set_le);
|
|
registry().add("set_lt", &p_set_lt);
|
|
registry().add("equal", &p_set_eq);
|
|
registry().add("set_ne", &p_set_ne);
|
|
registry().add("set_union", &p_set_union);
|
|
registry().add("array_set_element", &p_array_set_element);
|
|
registry().add("array_var_set_element", &p_array_set_element);
|
|
registry().add("set_intersect", &p_set_intersect);
|
|
registry().add("set_diff", &p_set_diff);
|
|
registry().add("set_symdiff", &p_set_symdiff);
|
|
registry().add("set_subset", &p_set_subset);
|
|
registry().add("set_superset", &p_set_superset);
|
|
registry().add("set_card", &p_set_card);
|
|
registry().add("set_in", &p_set_in);
|
|
registry().add("set_eq_reif", &p_set_eq_reif);
|
|
registry().add("set_le_reif", &p_set_le_reif);
|
|
registry().add("set_lt_reif", &p_set_lt_reif);
|
|
registry().add("equal_reif", &p_set_eq_reif);
|
|
registry().add("set_ne_reif", &p_set_ne_reif);
|
|
registry().add("set_subset_reif", &p_set_subset_reif);
|
|
registry().add("set_superset_reif", &p_set_superset_reif);
|
|
registry().add("set_in_reif", &p_set_in_reif);
|
|
registry().add("set_in_imp", &p_set_in_imp);
|
|
registry().add("disjoint", &p_set_disjoint);
|
|
registry().add("gecode_link_set_to_booleans",
|
|
&p_link_set_to_booleans);
|
|
|
|
registry().add("array_set_union", &p_array_set_union);
|
|
registry().add("array_set_partition", &p_array_set_partition);
|
|
registry().add("set_convex", &p_set_convex);
|
|
registry().add("array_set_seq", &p_array_set_seq);
|
|
registry().add("array_set_seq_union", &p_array_set_seq_union);
|
|
registry().add("gecode_array_set_element_union",
|
|
&p_array_set_element_union);
|
|
registry().add("gecode_array_set_element_intersect",
|
|
&p_array_set_element_intersect);
|
|
registry().add("gecode_array_set_element_intersect_in",
|
|
&p_array_set_element_intersect_in);
|
|
registry().add("gecode_array_set_element_partition",
|
|
&p_array_set_element_partition);
|
|
registry().add("gecode_int_set_channel",
|
|
&p_int_set_channel);
|
|
registry().add("gecode_range",
|
|
&p_range);
|
|
registry().add("gecode_set_weights",
|
|
&p_weights);
|
|
registry().add("gecode_inverse_set", &p_inverse_set);
|
|
registry().add("gecode_precede_set", &p_precede_set);
|
|
}
|
|
};
|
|
SetPoster __set_poster;
|
|
#endif
|
|
|
|
#ifdef GECODE_HAS_FLOAT_VARS
|
|
|
|
void p_int2float(FlatZincSpace& s, const ConExpr& ce, AST::Node*) {
|
|
IntVar x0 = s.arg2IntVar(ce[0]);
|
|
FloatVar x1 = s.arg2FloatVar(ce[1]);
|
|
channel(s, x0, x1);
|
|
}
|
|
|
|
void p_float_lin_cmp(FlatZincSpace& s, FloatRelType frt,
|
|
const ConExpr& ce, AST::Node*) {
|
|
FloatValArgs fa = s.arg2floatargs(ce[0]);
|
|
FloatVarArgs fv = s.arg2floatvarargs(ce[1]);
|
|
linear(s, fa, fv, frt, ce[2]->getFloat());
|
|
}
|
|
void p_float_lin_cmp_reif(FlatZincSpace& s, FloatRelType frt,
|
|
const ConExpr& ce, AST::Node*) {
|
|
FloatValArgs fa = s.arg2floatargs(ce[0]);
|
|
FloatVarArgs fv = s.arg2floatvarargs(ce[1]);
|
|
linear(s, fa, fv, frt, ce[2]->getFloat(), s.arg2BoolVar(ce[3]));
|
|
}
|
|
void p_float_lin_eq(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
p_float_lin_cmp(s,FRT_EQ,ce,ann);
|
|
}
|
|
void p_float_lin_eq_reif(FlatZincSpace& s, const ConExpr& ce,
|
|
AST::Node* ann) {
|
|
p_float_lin_cmp_reif(s,FRT_EQ,ce,ann);
|
|
}
|
|
void p_float_lin_le(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
p_float_lin_cmp(s,FRT_LQ,ce,ann);
|
|
}
|
|
void p_float_lin_lt(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
|
|
p_float_lin_cmp(s,FRT_LE,ce,ann);
|
|
}
|
|
void p_float_lin_le_reif(FlatZincSpace& s, const ConExpr& ce,
|
|
AST::Node* ann) {
|
|
p_float_lin_cmp_reif(s,FRT_LQ,ce,ann);
|
|
}
|
|
void p_float_lin_lt_reif(FlatZincSpace& s, const ConExpr& ce,
|
|
AST::Node* ann) {
|
|
p_float_lin_cmp_reif(s,FRT_LE,ce,ann);
|
|
}
|
|
|
|
void p_float_times(FlatZincSpace& s, const ConExpr& ce, AST::Node*) {
|
|
FloatVar x = s.arg2FloatVar(ce[0]);
|
|
FloatVar y = s.arg2FloatVar(ce[1]);
|
|
FloatVar z = s.arg2FloatVar(ce[2]);
|
|
mult(s,x,y,z);
|
|
}
|
|
|
|
void p_float_div(FlatZincSpace& s, const ConExpr& ce, AST::Node*) {
|
|
FloatVar x = s.arg2FloatVar(ce[0]);
|
|
FloatVar y = s.arg2FloatVar(ce[1]);
|
|
FloatVar z = s.arg2FloatVar(ce[2]);
|
|
div(s,x,y,z);
|
|
}
|
|
|
|
void p_float_plus(FlatZincSpace& s, const ConExpr& ce, AST::Node*) {
|
|
FloatVar x = s.arg2FloatVar(ce[0]);
|
|
FloatVar y = s.arg2FloatVar(ce[1]);
|
|
FloatVar z = s.arg2FloatVar(ce[2]);
|
|
rel(s,x+y==z);
|
|
}
|
|
|
|
void p_float_sqrt(FlatZincSpace& s, const ConExpr& ce, AST::Node*) {
|
|
FloatVar x = s.arg2FloatVar(ce[0]);
|
|
FloatVar y = s.arg2FloatVar(ce[1]);
|
|
sqrt(s,x,y);
|
|
}
|
|
|
|
void p_float_abs(FlatZincSpace& s, const ConExpr& ce, AST::Node*) {
|
|
FloatVar x = s.arg2FloatVar(ce[0]);
|
|
FloatVar y = s.arg2FloatVar(ce[1]);
|
|
abs(s,x,y);
|
|
}
|
|
|
|
void p_float_eq(FlatZincSpace& s, const ConExpr& ce, AST::Node*) {
|
|
FloatVar x = s.arg2FloatVar(ce[0]);
|
|
FloatVar y = s.arg2FloatVar(ce[1]);
|
|
rel(s,x,FRT_EQ,y);
|
|
}
|
|
void p_float_eq_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node*) {
|
|
FloatVar x = s.arg2FloatVar(ce[0]);
|
|
FloatVar y = s.arg2FloatVar(ce[1]);
|
|
BoolVar b = s.arg2BoolVar(ce[2]);
|
|
rel(s,x,FRT_EQ,y,b);
|
|
}
|
|
void p_float_le(FlatZincSpace& s, const ConExpr& ce, AST::Node*) {
|
|
FloatVar x = s.arg2FloatVar(ce[0]);
|
|
FloatVar y = s.arg2FloatVar(ce[1]);
|
|
rel(s,x,FRT_LQ,y);
|
|
}
|
|
void p_float_le_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node*) {
|
|
FloatVar x = s.arg2FloatVar(ce[0]);
|
|
FloatVar y = s.arg2FloatVar(ce[1]);
|
|
BoolVar b = s.arg2BoolVar(ce[2]);
|
|
rel(s,x,FRT_LQ,y,b);
|
|
}
|
|
void p_float_max(FlatZincSpace& s, const ConExpr& ce, AST::Node*) {
|
|
FloatVar x = s.arg2FloatVar(ce[0]);
|
|
FloatVar y = s.arg2FloatVar(ce[1]);
|
|
FloatVar z = s.arg2FloatVar(ce[2]);
|
|
max(s,x,y,z);
|
|
}
|
|
void p_float_min(FlatZincSpace& s, const ConExpr& ce, AST::Node*) {
|
|
FloatVar x = s.arg2FloatVar(ce[0]);
|
|
FloatVar y = s.arg2FloatVar(ce[1]);
|
|
FloatVar z = s.arg2FloatVar(ce[2]);
|
|
min(s,x,y,z);
|
|
}
|
|
void p_float_lt(FlatZincSpace& s, const ConExpr& ce, AST::Node*) {
|
|
FloatVar x = s.arg2FloatVar(ce[0]);
|
|
FloatVar y = s.arg2FloatVar(ce[1]);
|
|
rel(s, x, FRT_LQ, y);
|
|
rel(s, x, FRT_EQ, y, BoolVar(s,0,0));
|
|
}
|
|
|
|
void p_float_lt_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node*) {
|
|
FloatVar x = s.arg2FloatVar(ce[0]);
|
|
FloatVar y = s.arg2FloatVar(ce[1]);
|
|
BoolVar b = s.arg2BoolVar(ce[2]);
|
|
BoolVar b0(s,0,1);
|
|
BoolVar b1(s,0,1);
|
|
rel(s, b == (b0 && !b1));
|
|
rel(s, x, FRT_LQ, y, b0);
|
|
rel(s, x, FRT_EQ, y, b1);
|
|
}
|
|
|
|
void p_float_ne(FlatZincSpace& s, const ConExpr& ce, AST::Node*) {
|
|
FloatVar x = s.arg2FloatVar(ce[0]);
|
|
FloatVar y = s.arg2FloatVar(ce[1]);
|
|
rel(s, x, FRT_EQ, y, BoolVar(s,0,0));
|
|
}
|
|
|
|
#ifdef GECODE_HAS_MPFR
|
|
#define P_FLOAT_OP(Op) \
|
|
void p_float_ ## Op (FlatZincSpace& s, const ConExpr& ce, AST::Node*) {\
|
|
FloatVar x = s.arg2FloatVar(ce[0]);\
|
|
FloatVar y = s.arg2FloatVar(ce[1]);\
|
|
Op(s,x,y);\
|
|
}
|
|
P_FLOAT_OP(acos)
|
|
P_FLOAT_OP(asin)
|
|
P_FLOAT_OP(atan)
|
|
P_FLOAT_OP(cos)
|
|
P_FLOAT_OP(exp)
|
|
P_FLOAT_OP(sin)
|
|
P_FLOAT_OP(tan)
|
|
// P_FLOAT_OP(sinh)
|
|
// P_FLOAT_OP(tanh)
|
|
// P_FLOAT_OP(cosh)
|
|
#undef P_FLOAT_OP
|
|
|
|
void p_float_ln(FlatZincSpace& s, const ConExpr& ce, AST::Node*) {
|
|
FloatVar x = s.arg2FloatVar(ce[0]);
|
|
FloatVar y = s.arg2FloatVar(ce[1]);
|
|
log(s,x,y);
|
|
}
|
|
void p_float_log10(FlatZincSpace& s, const ConExpr& ce, AST::Node*) {
|
|
FloatVar x = s.arg2FloatVar(ce[0]);
|
|
FloatVar y = s.arg2FloatVar(ce[1]);
|
|
log(s,10.0,x,y);
|
|
}
|
|
void p_float_log2(FlatZincSpace& s, const ConExpr& ce, AST::Node*) {
|
|
FloatVar x = s.arg2FloatVar(ce[0]);
|
|
FloatVar y = s.arg2FloatVar(ce[1]);
|
|
log(s,2.0,x,y);
|
|
}
|
|
|
|
#endif
|
|
|
|
class FloatPoster {
|
|
public:
|
|
FloatPoster(void) {
|
|
registry().add("int2float",&p_int2float);
|
|
registry().add("float_abs",&p_float_abs);
|
|
registry().add("float_sqrt",&p_float_sqrt);
|
|
registry().add("float_eq",&p_float_eq);
|
|
registry().add("float_eq_reif",&p_float_eq_reif);
|
|
registry().add("float_le",&p_float_le);
|
|
registry().add("float_le_reif",&p_float_le_reif);
|
|
registry().add("float_lt",&p_float_lt);
|
|
registry().add("float_lt_reif",&p_float_lt_reif);
|
|
registry().add("float_ne",&p_float_ne);
|
|
registry().add("float_times",&p_float_times);
|
|
registry().add("float_div",&p_float_div);
|
|
registry().add("float_plus",&p_float_plus);
|
|
registry().add("float_max",&p_float_max);
|
|
registry().add("float_min",&p_float_min);
|
|
|
|
registry().add("float_lin_eq",&p_float_lin_eq);
|
|
registry().add("float_lin_eq_reif",&p_float_lin_eq_reif);
|
|
registry().add("float_lin_le",&p_float_lin_le);
|
|
registry().add("float_lin_lt",&p_float_lin_lt);
|
|
registry().add("float_lin_le_reif",&p_float_lin_le_reif);
|
|
registry().add("float_lin_lt_reif",&p_float_lin_lt_reif);
|
|
|
|
#ifdef GECODE_HAS_MPFR
|
|
registry().add("float_acos",&p_float_acos);
|
|
registry().add("float_asin",&p_float_asin);
|
|
registry().add("float_atan",&p_float_atan);
|
|
registry().add("float_cos",&p_float_cos);
|
|
// registry().add("float_cosh",&p_float_cosh);
|
|
registry().add("float_exp",&p_float_exp);
|
|
registry().add("float_ln",&p_float_ln);
|
|
registry().add("float_log10",&p_float_log10);
|
|
registry().add("float_log2",&p_float_log2);
|
|
registry().add("float_sin",&p_float_sin);
|
|
// registry().add("float_sinh",&p_float_sinh);
|
|
registry().add("float_tan",&p_float_tan);
|
|
// registry().add("float_tanh",&p_float_tanh);
|
|
#endif
|
|
}
|
|
} __float_poster;
|
|
#endif
|
|
|
|
}
|
|
}}
|
|
|
|
// STATISTICS: flatzinc-any
|