org.chocosolver.parser.flatzinc.ast.FConstraint Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of choco-parsers Show documentation
Show all versions of choco-parsers Show documentation
Provide parsers from FlatZinc, XCSP3 and MSP to Choco-solver.
/*
* This file is part of choco-parsers, http://choco-solver.org/
*
* Copyright (c) 2024, IMT Atlantique. All rights reserved.
*
* Licensed under the BSD 4-clause license.
*
* See LICENSE file in the project root for full license information.
*/
package org.chocosolver.parser.flatzinc.ast;
import gnu.trove.list.array.TIntArrayList;
import org.chocosolver.parser.flatzinc.ast.expression.EAnnotation;
import org.chocosolver.parser.flatzinc.ast.expression.ESetBounds;
import org.chocosolver.parser.flatzinc.ast.expression.Expression;
import org.chocosolver.parser.flatzinc.ast.propagators.PropBoolSumEq0Reif;
import org.chocosolver.solver.Model;
import org.chocosolver.solver.constraints.Constraint;
import org.chocosolver.solver.constraints.extension.Tuples;
import org.chocosolver.solver.constraints.nary.automata.FA.FiniteAutomaton;
import org.chocosolver.solver.expression.discrete.logical.LoExpression;
import org.chocosolver.solver.expression.discrete.logical.NaLoExpression;
import org.chocosolver.solver.variables.*;
import org.chocosolver.util.objects.setDataStructures.iterable.IntIterableRangeSet;
import org.chocosolver.util.tools.VariableUtils;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.IntStream;
/*
* User : CPRUDHOM
* Mail : cprudhom(a)emn.fr
* Date : 12 janv. 2010
* Since : Choco 2.1.1
*
* Constraint builder from flatzinc-like object.
*/
@SuppressWarnings("Duplicates")
public enum FConstraint {
array_bool_and {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
BoolVar[] as = exps.get(0).toBoolVarArray(model);
BoolVar r = exps.get(1).boolVarValue(model);
if (as.length == 0) {
r.eq(1).post();
} else {
if (r.isInstantiatedTo(0)) {
model.addClausesBoolAndArrayEqualFalse(as);
} else {
model.addClausesBoolAndArrayEqVar(as, r);
}
}
}
},
array_bool_element {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
IntVar b = exps.get(0).intVarValue(model);
int[] as = exps.get(1).toIntArray();
IntVar c = exps.get(2).intVarValue(model);
model.element(c, as, b, 1).post();
}
},
array_bool_or {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
BoolVar[] as = exps.get(0).toBoolVarArray(model);
BoolVar r = exps.get(1).boolVarValue(model);
if (as.length == 0) {
r.eq(1).post();
} else {
if (r.isInstantiatedTo(1)) {
model.addClausesBoolOrArrayEqualTrue(as);
} else {
model.addClausesBoolOrArrayEqVar(as, r);
}
}
}
},
array_bool_xor {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
BoolVar[] as = exps.get(0).toBoolVarArray(model);
int[] values = new int[as.length % 2 == 0 ? as.length / 2 : (as.length + 1) / 2];
for (int i = 0, j = 1; i < values.length; i++, j += 2) {
values[i] = j;
}
IntVar res = model.intVar(model.generateName(), values);
model.sum(as, "=", res).post();
}
},
array_int_element {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
IntVar b = exps.get(0).intVarValue(model);
int[] as = exps.get(1).toIntArray();
IntVar c = exps.get(2).intVarValue(model);
model.element(c, as, b, 1).post();
}
},
array_var_bool_element {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
IntVar b = exps.get(0).intVarValue(model);
IntVar[] as = exps.get(1).toIntVarArray(model);
IntVar c = exps.get(2).intVarValue(model);
model.element(c, as, b, 1).post();
}
},
array_var_int_element {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
IntVar b = exps.get(0).intVarValue(model);
IntVar[] as = exps.get(1).toIntVarArray(model);
IntVar c = exps.get(2).intVarValue(model);
model.element(c, as, b, 1).post();
}
},
bool2int {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
BoolVar bVar = exps.get(0).boolVarValue(model);
IntVar iVar = exps.get(1).intVarValue(model);
if (iVar.isBool()) {
model.addClausesBoolEq(bVar, (BoolVar) iVar);
return;
}
model.arithm(bVar, "=", iVar).post();
}
},
bool_and {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
BoolVar a = exps.get(0).boolVarValue(model);
BoolVar b = exps.get(1).boolVarValue(model);
BoolVar r = exps.get(2).boolVarValue(model);
model.addClausesBoolAndEqVar(a, b, r);
}
},
bool_clause {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
BoolVar[] as = exps.get(0).toBoolVarArray(model);
BoolVar[] bs = exps.get(1).toBoolVarArray(model);
model.addClauses(as, bs);
}
},
bool_eq {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
BoolVar a = exps.get(0).boolVarValue(model);
BoolVar b = exps.get(1).boolVarValue(model);
model.addClausesBoolEq(a, b);
}
},
bool_eq_reif {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
BoolVar a = exps.get(0).boolVarValue(model);
BoolVar b = exps.get(1).boolVarValue(model);
BoolVar r = exps.get(2).boolVarValue(model);
model.addClausesBoolIsEqVar(a, b, r);
}
},
bool_le {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
BoolVar a = exps.get(0).boolVarValue(model);
BoolVar b = exps.get(1).boolVarValue(model);
model.addClausesBoolLe(a, b);
}
},
bool_le_reif {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
BoolVar a = exps.get(0).boolVarValue(model);
BoolVar b = exps.get(1).boolVarValue(model);
BoolVar r = exps.get(2).boolVarValue(model);
model.addClausesBoolIsLeVar(a, b, r);
}
},
bool_lin_eq {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
int[] as = exps.get(0).toIntArray();
IntVar[] bs = exps.get(1).toIntVarArray(model);
IntVar c = exps.get(2).intVarValue(model);
model.scalar(bs, as, "=", c).post();
}
},
bool_lin_le {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
int[] as = exps.get(0).toIntArray();
IntVar[] bs = exps.get(1).toIntVarArray(model);
IntVar c = exps.get(2).intVarValue(model);
model.scalar(bs, as, "<=", c).post();
}
},
bool_lt {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
BoolVar a = exps.get(0).boolVarValue(model);
BoolVar b = exps.get(1).boolVarValue(model);
model.addClausesBoolLt(a, b);
}
},
bool_lt_reif {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
BoolVar a = exps.get(0).boolVarValue(model);
BoolVar b = exps.get(1).boolVarValue(model);
BoolVar r = exps.get(2).boolVarValue(model);
model.addClausesBoolIsLtVar(a, b, r);
}
},
bool_not {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
BoolVar a = exps.get(0).boolVarValue(model);
BoolVar b = exps.get(1).boolVarValue(model);
model.addClausesBoolNot(a, b);
}
},
bool_or {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
BoolVar a = exps.get(0).boolVarValue(model);
BoolVar b = exps.get(1).boolVarValue(model);
BoolVar r = exps.get(2).boolVarValue(model);
model.addClausesBoolOrEqVar(a, b, r);
}
},
bool_xor {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
BoolVar a = exps.get(0).boolVarValue(model);
BoolVar b = exps.get(1).boolVarValue(model);
BoolVar r = exps.get(2).boolVarValue(model);
model.addClausesBoolIsNeqVar(a, b, r);
}
},
int_abs {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
IntVar a = exps.get(0).intVarValue(model);
IntVar b = exps.get(1).intVarValue(model);
model.absolute(b, a).post();
}
},
int_div {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
IntVar a = exps.get(0).intVarValue(model);
IntVar b = exps.get(1).intVarValue(model);
IntVar c = exps.get(2).intVarValue(model);
model.div(a, b, c).post();
}
},
int_eq {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
IntVar a = exps.get(0).intVarValue(model);
IntVar b = exps.get(1).intVarValue(model);
if (((a.getTypeAndKind() & Variable.KIND) == Variable.BOOL) && ((b.getTypeAndKind() & Variable.KIND) == Variable.BOOL)) {
model.addClausesBoolEq((BoolVar) a, (BoolVar) b);
} else {
model.arithm(a, "=", b).post();
}
}
},
int_eq_reif {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
IntVar a = exps.get(0).intVarValue(model);
IntVar b = exps.get(1).intVarValue(model);
final BoolVar r = exps.get(2).boolVarValue(model);
// this constraint is not poster, hence not returned, because it is reified
if ((a.getTypeAndKind() & Variable.KIND) == Variable.BOOL && ((b.getTypeAndKind() & Variable.KIND) == Variable.BOOL)) {
model.addClausesBoolIsEqVar((BoolVar) a, (BoolVar) b, r);
} else {
if (a.isInstantiated() || b.isInstantiated()) {
IntVar x;
int c;
if (a.isInstantiated()) {
x = b;
c = a.getValue();
} else {
x = a;
c = b.getValue();
}
model.reifyXeqC(x, c, r);
} else {
model.reifyXeqY(a, b, r);
}
}
}
},
int_le {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
IntVar a = exps.get(0).intVarValue(model);
IntVar b = exps.get(1).intVarValue(model);
if ((a.getTypeAndKind() & Variable.KIND) == Variable.BOOL && ((b.getTypeAndKind() & Variable.KIND) == Variable.BOOL)) {
model.addClausesBoolLe((BoolVar) a, (BoolVar) b);
} else {
model.arithm(a, "<=", b).post();
}
}
},
int_le_reif {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
IntVar a = exps.get(0).intVarValue(model);
IntVar b = exps.get(1).intVarValue(model);
final BoolVar r = exps.get(2).boolVarValue(model);
// this constraint is not poster, hence not returned, because it is reified
if ((a.getTypeAndKind() & Variable.KIND) == Variable.BOOL && ((b.getTypeAndKind() & Variable.KIND) == Variable.BOOL)) {
model.addClausesBoolIsLeVar((BoolVar) a, (BoolVar) b, r);
} else {
if (a.isInstantiated() || b.isInstantiated()) {
final IntVar var;
final int cste;
if (a.isInstantiated()) {
var = b;
cste = a.getValue();
model.reifyXgtC(var, cste - 1, r);
// model.arithm(a, "<=", b).reifyWith(r);
} else {
var = a;
cste = b.getValue();
model.reifyXltC(var, cste + 1, r);
// model.arithm(a, "<=", b).reifyWith(r);
}
} else {
model.reifyXltYC(a, b, +1, r);
}
}
}
},
int_lin_eq {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
int[] as = exps.get(0).toIntArray();
IntVar[] bs = exps.get(1).toIntVarArray(model);
IntVar c = exps.get(2).intVarValue(model);
if (bs.length > 0) {
model.scalar(bs, as, "=", c).post();
}
}
},
int_lin_eq_reif {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
int[] as = exps.get(0).toIntArray();
IntVar[] bs = exps.get(1).toIntVarArray(model);
IntVar c = exps.get(2).intVarValue(model);
BoolVar r = exps.get(3).boolVarValue(model);
if ((boolean) model.getSettings().get("adhocReification").orElse(false)) {
if (bs.length == 1) {
if (bs[0].isInstantiated() || c.isInstantiated()) {
IntVar x;
int t;
if (bs[0].isInstantiated()) {
x = c;
t = bs[0].getValue();
} else {
x = bs[0];
t = c.getValue();
}
model.reifyXeqC(x, t, r);
} else {
model.reifyXeqY(bs[0], c, r);
}
return;
} else {
// detect boolSumEq bool reified
int n = bs.length;
boolean boolSum = c.isBool();
for (int i = 0; i < n; i++) {
boolSum &= bs[i].isBool();
boolSum &= as[i] == 1;
}
if (boolSum && c.isInstantiatedTo(0)) {
BoolVar[] bbs = new BoolVar[n + 1];
for (int i = 0; i < n; i++) {
bbs[i] = (BoolVar) bs[i];
}
bbs[bs.length] = r;
new Constraint("BoolSumLeq0Reif", new PropBoolSumEq0Reif(bbs)).post();
return;
}
}
}
model.scalar(bs, as, "=", c).reifyWith(r);
}
},
int_lin_le {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
int[] as = exps.get(0).toIntArray();
IntVar[] bs = exps.get(1).toIntVarArray(model);
IntVar c = exps.get(2).intVarValue(model);
model.scalar(bs, as, "<=", c).post();
}
},
int_lin_le_reif {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
int[] as = exps.get(0).toIntArray();
IntVar[] bs = exps.get(1).toIntVarArray(model);
IntVar c = exps.get(2).intVarValue(model);
BoolVar r = exps.get(3).boolVarValue(model);
if (c.isInstantiatedTo(0)) {
// detect boolSumLeq 0 reified
int n = bs.length;
boolean boolSum = c.isBool();
for (int i = 0; i < n; i++) {
boolSum &= bs[i].isBool();
boolSum &= as[i] == 1;
}
if (boolSum) {
BoolVar[] bbs = new BoolVar[n + 1];
for (int i = 0; i < n; i++) {
bbs[i] = (BoolVar) bs[i];
}
bbs[bs.length] = r;
new Constraint("BoolSumEq0Reif", new PropBoolSumEq0Reif(bbs)).post();
return;
}
} else if (c.isInstantiated()) {
if (bs.length == 1) {
if (as[0] == -1) {
model.reifyXgtC(bs[0], -(c.getValue() + 1), r);
return;
}
if (as[0] == 1) {
model.reifyXltC(bs[0], c.getValue() + 1, r);
return;
}
}
if (bs.length == 2) {
if (as[0] == -1 && as[1] == 1) {
model.arithm(bs[1], "<=", bs[0], "+", c.getValue()).reifyWith(r);
return;
}
if (as[0] == 1 && as[1] == -1) {
model.reifyXltYC(bs[0], bs[1], c.getValue() + 1, r);
return;
}
}
}
model.scalar(bs, as, "<=", c).reifyWith(r);
// slower version:
/* int[] bnds = VariableUtils.boundsForScalar(bs, as);
IntVar e = model.intVar(bnds[0], bnds[1]);
model.scalar(bs, as, "=", e).post();
model.reifyXleY(e, c, r);
*/
}
},
int_lin_ne {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
int[] as = exps.get(0).toIntArray();
IntVar[] bs = exps.get(1).toIntVarArray(model);
IntVar c = exps.get(2).intVarValue(model);
model.scalar(bs, as, "!=", c).post();
}
},
int_lin_ne_reif {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
int[] as = exps.get(0).toIntArray();
IntVar[] bs = exps.get(1).toIntVarArray(model);
IntVar c = exps.get(2).intVarValue(model);
BoolVar r = exps.get(3).boolVarValue(model);
if (bs.length == 1) {
if (as[0] == 1 || as[0] == -1) {
model.reifyXneC(bs[0], as[0] * c.getValue(), r);
return;
}
}
if (bs.length == 2 && c.isInstantiatedTo(0)) {
if (as[0] == 1 && as[1] == -1) {
model.reifyXneY(bs[0], bs[1], r);
return;
}
if (as[0] == -1 && as[1] == 1) {
model.reifyXneY(bs[0], bs[1], r);
return;
}
}
model.scalar(bs, as, "!=", c).reifyWith(r);
}
},
int_lt {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
IntVar a = exps.get(0).intVarValue(model);
IntVar b = exps.get(1).intVarValue(model);
if ((a.getTypeAndKind() & Variable.KIND) == Variable.BOOL && ((b.getTypeAndKind() & Variable.KIND) == Variable.BOOL)) {
model.addClausesBoolLt((BoolVar) a, (BoolVar) b);
} else {
model.arithm(a, "<", b).post();
}
}
},
int_lt_reif {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
IntVar a = exps.get(0).intVarValue(model);
IntVar b = exps.get(1).intVarValue(model);
final BoolVar r = exps.get(2).boolVarValue(model);
// this constraint is not poster, hence not returned, because it is reified
if ((a.getTypeAndKind() & Variable.KIND) == Variable.BOOL && ((b.getTypeAndKind() & Variable.KIND) == Variable.BOOL)) {
model.addClausesBoolIsLtVar((BoolVar) a, (BoolVar) b, r);
} else {
if (a.isInstantiated() || b.isInstantiated()) {
final IntVar var;
final int cste;
if (a.isInstantiated()) {
var = b;
cste = a.getValue();
model.reifyXgtC(var, cste, r);
} else {
var = a;
cste = b.getValue();
model.reifyXltC(var, cste, r);
}
} else {
model.reifyXltY(a, b, r);
}
}
}
},
int_max {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
IntVar a = exps.get(0).intVarValue(model);
IntVar b = exps.get(1).intVarValue(model);
IntVar c = exps.get(2).intVarValue(model);
model.max(c, a, b).post();
}
},
int_min {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
IntVar a = exps.get(0).intVarValue(model);
IntVar b = exps.get(1).intVarValue(model);
IntVar c = exps.get(2).intVarValue(model);
model.min(c, a, b).post();
}
},
int_mod {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
IntVar a = exps.get(0).intVarValue(model);
IntVar b = exps.get(1).intVarValue(model);
IntVar c = exps.get(2).intVarValue(model);
model.mod(a, b, c).post();
}
},
int_ne {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
IntVar a = exps.get(0).intVarValue(model);
IntVar b = exps.get(1).intVarValue(model);
if ((a.getTypeAndKind() & Variable.KIND) == Variable.BOOL && ((b.getTypeAndKind() & Variable.KIND) == Variable.BOOL)) {
model.addClausesBoolNot((BoolVar) a, (BoolVar) b);
} else {
model.arithm(a, "!=", b).post();
}
}
},
int_ne_reif {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
IntVar a = exps.get(0).intVarValue(model);
IntVar b = exps.get(1).intVarValue(model);
final BoolVar r = exps.get(2).boolVarValue(model);
// this constraint is not poster, hence not returned, because it is reified
if ((a.getTypeAndKind() & Variable.KIND) == Variable.BOOL && ((b.getTypeAndKind() & Variable.KIND) == Variable.BOOL)) {
model.addClausesBoolIsNeqVar((BoolVar) a, (BoolVar) b, r);
} else {
if ((boolean) model.getSettings().get("adhocReification").orElse(false)) {
if (a.isInstantiated() || b.isInstantiated()) {
IntVar x;
int c;
if (a.isInstantiated()) {
x = b;
c = a.getValue();
} else {
x = a;
c = b.getValue();
}
final IntVar var = x;
final int cste = c;
model.reifyXneC(var, cste, r);
} else {
model.reifyXneY(a, b, r);
}
} else {
model.arithm(a, "!=", b).reifyWith(r);
}
}
}
},
int_plus {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
IntVar[] vars = new IntVar[2];
vars[0] = exps.get(0).intVarValue(model);
vars[1] = exps.get(1).intVarValue(model);
IntVar c = exps.get(2).intVarValue(model);
model.sum(vars, "=", c).post();
}
},
int_pow {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
IntVar a = exps.get(0).intVarValue(model);
IntVar b = exps.get(1).intVarValue(model);
IntVar c = exps.get(2).intVarValue(model);
a.pow(b).eq(c).extension().post();
}
},
int_times {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
IntVar a = exps.get(0).intVarValue(model);
IntVar b = exps.get(1).intVarValue(model);
IntVar c = exps.get(2).intVarValue(model);
model.times(a, b, c).post();
}
},
alldifferentChoco {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
fzn_all_different_int.build(model, datas, id, exps, annotations);
}
},
fzn_all_different_int {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
IntVar[] vars = exps.get(0).toIntVarArray(model);
if (vars.length > 1) {
if (annotations.stream().anyMatch(a -> a.id.toString().equals("domain"))) {
model.allDifferent(vars, "AC").post();
} else if (annotations.stream().anyMatch(a -> a.id.toString().startsWith("bounds"))) {
model.allDifferent(vars, "BC").post();
} else {
model.allDifferent(vars).post();
}
}
}
},
alldifferentBut0Choco {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
fzn_alldifferent_except_0.build(model, datas, id, exps, annotations);
}
},
fzn_alldifferent_except_0 {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
IntVar[] vars = exps.get(0).toIntVarArray(model);
if (vars.length > 1) {
model.allDifferentExcept0(vars).post();
}
}
},
fzn_all_equal_int {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
IntVar[] vars = exps.get(0).toIntVarArray(model);
if (vars.length > 1) {
model.allEqual(vars).post();
}
}
},
fzn_all_equal_int_reif {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
IntVar[] vars = exps.get(0).toIntVarArray(model);
BoolVar b = exps.get(1).boolVarValue(model);
IntVar count = model.intVar(1, vars.length);
model.nValues(vars, count).post();
model.reifyXeqC(count, 1, b);
}
},
amongChoco {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
fzn_among.build(model, datas, id, exps, annotations);
}
},
fzn_among {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
//var int: n, array[int] of var int: x, set of int: v
int n = exps.get(0).intValue();
IntVar[] vars = exps.get(1).toIntVarArray(model);
int[] values = exps.get(2).toIntArray();
model.among(model.intVar(n), vars, values).post();
}
},
atleastChoco {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
fzn_at_least_int.build(model, datas, id, exps, annotations);
}
},
fzn_at_least_int {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
//int: n, array[int] of var int: x, int: v
int n = exps.get(0).intValue();
IntVar[] x = exps.get(1).toIntVarArray(model);
int v = exps.get(2).intValue();
IntVar limit = model.intVar("limit_" + n, n, x.length, true);
model.among(limit, x, new int[]{v}).post();
}
},
atmostChoco {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
fzn_at_most_int.build(model, datas, id, exps, annotations);
}
},
fzn_at_most_int {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
//int: n, array[int] of var int: x, int: v
int n = exps.get(0).intValue();
IntVar[] x = exps.get(1).toIntVarArray(model);
int v = exps.get(2).intValue();
IntVar limit = model.intVar("limit_" + n, 0, n, true);
model.among(limit, x, new int[]{v}).post();
}
},
bin_packingChoco {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
fzn_bin_packing.build(model, datas, id, exps, annotations);
}
},
fzn_bin_packing {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
int c = exps.get(0).intValue();
IntVar[] item_bin = exps.get(1).toIntVarArray(model);
int[] item_size = exps.get(2).toIntArray();
int min = Integer.MAX_VALUE / 2;
int max = Integer.MIN_VALUE / 2;
for (int i = 0; i < item_bin.length; i++) {
min = Math.min(min, item_bin[i].getLB());
max = Math.max(max, item_bin[i].getUB());
}
IntVar[] loads = model.intVarArray("TMPload", max - min + 1, 0, c, true);
model.binPacking(item_bin, item_size, loads, min).post();
}
},
bin_packing_capaChoco {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
fzn_bin_packing_capa.build(model, datas, id, exps, annotations);
}
},
fzn_bin_packing_capa {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
int[] c = exps.get(0).toIntArray();
IntVar[] item_bin = exps.get(1).toIntVarArray(model);
int[] item_size = exps.get(2).toIntArray();
for (int i = 0; i < item_bin.length; i++) {
if (item_bin[i].getLB() < 1) {
model.arithm(item_bin[i], ">=", 1).post();
}
if (item_bin[i].getUB() > c.length) {
model.arithm(item_bin[i], "<=", c.length).post();
}
}
IntVar[] loads = new IntVar[c.length];
for (int i = 0; i < c.length; i++) {
loads[i] = model.intVar("load_" + i, 0, c[i], true);
}
model.binPacking(item_bin, item_size, loads, 1).post();
}
},
bin_packing_loadChoco {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
fzn_bin_packing_load.build(model, datas, id, exps, annotations);
}
},
fzn_bin_packing_load {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
IntVar[] loads = exps.get(0).toIntVarArray(model);
IntVar[] item_bin = exps.get(1).toIntVarArray(model);
int[] item_size = exps.get(2).toIntArray();
for (int i = 0; i < item_bin.length; i++) {
if (item_bin[i].getLB() < 1) {
model.arithm(item_bin[i], ">=", 1).post();
}
if (item_bin[i].getUB() > loads.length) {
model.arithm(item_bin[i], "<=", loads.length).post();
}
}
model.binPacking(item_bin, item_size, loads, 1).post();
}
},
circuitChoco {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
IntVar[] vars = exps.get(0).toIntVarArray(model);
if (vars.length > 0) {
int min = vars[0].getLB();
for (IntVar v : vars) {
min = Math.min(min, v.getLB());
}
model.circuit(vars, min).post();
}
}
},
fzn_circuit {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
int offset = exps.get(0).intValue();
IntVar[] vars = exps.get(1).toIntVarArray(model);
model.circuit(vars, offset).post();
}
},
fzn_decreasing_bool {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
BoolVar[] vars = exps.get(0).toBoolVarArray(model);
model.decreasing(vars, 0).post();
}
},
fzn_decreasing_int {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
IntVar[] vars = exps.get(0).toIntVarArray(model);
model.decreasing(vars, 0).post();
}
},
count_eqchoco {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
fzn_count_eq.build(model, datas, id, exps, annotations);
}
},
fzn_count_eq {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
IntVar[] x = exps.get(0).toIntVarArray(model);
IntVar y = exps.get(1).intVarValue(model);
IntVar c = exps.get(2).intVarValue(model);
model.count(y, x, c).post();
}
},
fzn_count_geq {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
IntVar[] x = exps.get(0).toIntVarArray(model);
IntVar y = exps.get(1).intVarValue(model);
IntVar c = exps.get(2).intVarValue(model);
IntVar c2;
if (c.isAConstant()) {
c2 = model.intVar(c.getName() + "_2", 0, c.getValue());
} else {
c2 = model.intVar(c.getName() + "_2", 0, x.length);
model.arithm(c, ">=", c2).post();
}
model.count(y, x, c2).post();
}
},
fzn_count_gt {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
IntVar[] x = exps.get(0).toIntVarArray(model);
IntVar y = exps.get(1).intVarValue(model);
IntVar c = exps.get(2).intVarValue(model);
IntVar c2;
if (c.isAConstant()) {
c2 = model.intVar(c.getName() + "_2", 0, c.getValue() - 1);
} else {
c2 = model.intVar(c.getName() + "_2", 0, x.length);
model.arithm(c, ">", c2).post();
}
model.count(y, x, c2).post();
}
},
fzn_count_leq {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
IntVar[] x = exps.get(0).toIntVarArray(model);
IntVar y = exps.get(1).intVarValue(model);
IntVar c = exps.get(2).intVarValue(model);
IntVar c2;
if (c.isAConstant()) {
c2 = model.intVar(c.getName() + "_2", c.getValue(), x.length);
} else {
c2 = model.intVar(c.getName() + "_2", 0, x.length);
model.arithm(c, "<=", c2).post();
}
model.count(y, x, c2).post();
}
},
fzn_count_lt {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
IntVar[] x = exps.get(0).toIntVarArray(model);
IntVar y = exps.get(1).intVarValue(model);
IntVar c = exps.get(2).intVarValue(model);
IntVar c2;
if (c.isAConstant()) {
c2 = model.intVar(c.getName() + "_2", c.getValue() + 1, x.length);
} else {
c2 = model.intVar(c.getName() + "_2", 0, x.length);
model.arithm(c, "<", c2).post();
}
model.count(y, x, c2).post();
}
},
fzn_count_neq {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
IntVar[] x = exps.get(0).toIntVarArray(model);
IntVar y = exps.get(1).intVarValue(model);
IntVar c = exps.get(2).intVarValue(model);
IntVar c2 = model.intVar(c.getName() + "_2", 0, x.length);
model.count(y, x, c2).post();
model.arithm(c2, "!=", c).post();
}
},
cumulativeChoco {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
fzn_cumulative.build(model, datas, id, exps, annotations);
}
},
fzn_cumulative {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
final IntVar[] starts = exps.get(0).toIntVarArray(model);
final IntVar[] durations = exps.get(1).toIntVarArray(model);
final IntVar[] resources = exps.get(2).toIntVarArray(model);
final IntVar limit = exps.get(3).intVarValue(model);
String decomp = (String) model.getHook("CUMULATIVE");
int n = starts.length;
switch (decomp) {
case "GLB":
final IntVar[] ends = new IntVar[n];
Task[] tasks = new Task[n];
for (int i = 0; i < n; i++) {
ends[i] = model.intVar(starts[i].getName() + "_" + durations[i].getName(),
starts[i].getLB() + durations[i].getLB(),
starts[i].getUB() + durations[i].getUB(),
true);
assert durations[i].getUB() >= 0 && resources[i].getUB() >= 0;
tasks[i] = new Task(starts[i], durations[i], ends[i]);
}
model.cumulative(tasks, resources, limit, true/*, Cumulative.Filter.NAIVETIME*/).post();
break;
case "MZN":
model.cumulativeTimeDec(starts,
Arrays.stream(durations).mapToInt(IntVar::getUB).toArray(),
Arrays.stream(resources).mapToInt(IntVar::getUB).toArray(),
limit.getLB());
break;
case "MIC":
int epsilon = 1;
BoolVar[][] b = new BoolVar[n][];
BoolVar[][] b1 = new BoolVar[n][];
BoolVar[][] b2 = new BoolVar[n][];
for (int i = 0; i < n; i++) {
TIntArrayList sumC = new TIntArrayList();
ArrayList sumV = new ArrayList<>();
b[i] = new BoolVar[n - 1];
b1[i] = new BoolVar[n - 1];
b2[i] = new BoolVar[n - 1];
for (int j = 0, k = 0; j < n; j++) {
if (i != j) {
b[i][k] = model.boolVar();
b1[i][k] = model.boolVar();
b2[i][k] = model.boolVar();
// sum constraint
assert resources[j].isInstantiated() : "resources not fixed";
sumC.add(resources[j].getValue());
sumV.add(b[i][k]);
// bij <=> bij1 and bij2
model.scalar(
new BoolVar[]{b[i][k], b1[i][k]},
new int[]{1, -1},
"<=", 0
).post();
model.scalar(
new BoolVar[]{b[i][k], b2[i][k]},
new int[]{1, -1},
"<=", 0
).post();
model.scalar(
new BoolVar[]{b[i][k], b1[i][k], b2[i][k]},
new int[]{1, -1, -1},
">=", -1
).post();
// b1ij <=> start[j] <= start[i]
int m = starts[j].getLB() - starts[i].getUB();
int M = starts[j].getUB() - starts[i].getLB();
model.scalar(
new IntVar[]{starts[j], starts[i], b1[i][k]},
new int[]{1, -1, M},
"<=", M
).post();
model.scalar(
new IntVar[]{starts[j], starts[i], b1[i][k]},
new int[]{1, -1, -m + 1},
">=", epsilon
).post();
// b2ij <=> start[i] <= start[j] + dur[j] - epsilon
// <=> start[i] - start[j] - dur[j] <= - epsilon
assert durations[j].isInstantiated() : "durations not fixed";
m = starts[i].getLB() - (starts[j].getUB() + durations[j].getValue()) + epsilon;
M = starts[i].getUB() - (starts[j].getLB() + durations[j].getLB()) + epsilon;
//System.out.println("m = "+m+", M = "+M);
model.scalar(
new IntVar[]{starts[i], starts[j], b2[i][k]},
new int[]{1, -1, M},
"<=", M - epsilon + durations[j].getValue()
).post();
model.scalar(
new IntVar[]{starts[i], starts[j], b2[i][k]},
new int[]{1, -1, -m + 1},
">=", durations[j].getValue()
).post();
k++;
}
}
model.scalar(
sumV.toArray(new IntVar[0]),
sumC.toArray(),
"<=",
-resources[i].getValue() + limit.getValue()).post();
}
break;
}
}
},
fzn_disjunctive {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
IntVar[] s = exps.get(0).toIntVarArray(model);
IntVar[] d = exps.get(1).toIntVarArray(model);
Task[] t = new Task[s.length];
IntVar[] h = new IntVar[s.length];
for (int i = 0; i < s.length; i++) {
t[i] = model.taskVar(s[i], d[i]);
h[i] = model.intVar(1);
}
model.cumulative(t, h, model.intVar(1)).post();
}
},
fzn_disjunctive_strict {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
IntVar[] s = exps.get(0).toIntVarArray(model);
IntVar[] d = exps.get(1).toIntVarArray(model);
for (int i = 0; i < s.length; i++) {
for (int j = i + 1; j < s.length; j++) {
BoolVar b = model.boolVar();
model.scalar(new IntVar[]{s[i], d[i], s[j], b},
new int[]{1, 1, -1, -(s[i].getUB() + d[i].getUB())}, "<=", 0).post();
model.scalar(new IntVar[]{s[j], d[j], s[i], b.not()},
new int[]{1, 1, -1, -(s[j].getUB() + d[j].getUB())}, "<=", 0).post();
}
}
}
},
diffnChoco {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
fzn_diffn.build(model, datas, id, exps, annotations);
}
},
fzn_diffn {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
IntVar[] x = exps.get(0).toIntVarArray(model);
IntVar[] y = exps.get(1).toIntVarArray(model);
IntVar[] dx = exps.get(2).toIntVarArray(model);
IntVar[] dy = exps.get(3).toIntVarArray(model);
if (x.length > 1) {
model.diffN(x, y, dx, dy, true).post();
}
}
},
distributeChoco {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
fzn_distribute.build(model, datas, id, exps, annotations);
}
},
fzn_distribute {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
IntVar[] card = exps.get(0).toIntVarArray(model);
IntVar[] value = exps.get(1).toIntVarArray(model);
IntVar[] base = exps.get(2).toIntVarArray(model);
for (int i = 0; i < card.length; i++) {
model.count(value[i], base, card[i]).post();
}
}
},
exactlyChoco {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
fzn_exactly_int.build(model, datas, id, exps, annotations);
}
},
fzn_exactly_int {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
//int: n, array[int] of var int: x, int: v
int n = exps.get(0).intValue();
IntVar[] x = exps.get(1).toIntVarArray(model);
int v = exps.get(2).intValue();
model.among(model.intVar(n), x, new int[]{v}).post();
}
},
globalCardinalityChoco {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
choco_fzn_global_cardinality.build(model, datas, id, exps, annotations);
}
},
choco_fzn_global_cardinality {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
IntVar[] vars = exps.get(0).toIntVarArray(model);
int[] values = exps.get(1).toIntArray();
IntVar[] cards = exps.get(2).toIntVarArray(model);
boolean closed = exps.get(3).boolValue();
model.globalCardinality(vars, values, cards, closed).post();
}
},
globalCardinalityLowUpChoco {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
choco_fzn_global_cardinality_low_up.build(model, datas, id, exps, annotations);
}
},
choco_fzn_global_cardinality_low_up {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
IntVar[] vars = exps.get(0).toIntVarArray(model);
int[] values = exps.get(1).toIntArray();
int[] low = exps.get(2).toIntArray();
int[] up = exps.get(3).toIntArray();
boolean closed = exps.get(4).boolValue();
IntVar[] cards = new IntVar[low.length];
for (int i = 0; i < low.length; i++) {
cards[i] = model.intVar("card of val " + values[i], low[i], up[i], true);
}
model.globalCardinality(vars, values, cards, closed).post();
}
},
fzn_increasing_bool {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
BoolVar[] vars = exps.get(0).toBoolVarArray(model);
model.increasing(vars, 0).post();
}
},
fzn_increasing_int {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
IntVar[] vars = exps.get(0).toIntVarArray(model);
model.increasing(vars, 0).post();
}
},
inverseChoco {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
fzn_inverse.build(model, datas, id, exps, annotations);
}
},
fzn_inverse {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
boolean AC = annotations.stream().anyMatch(a -> a.id.toString().equals("domain"));
IntVar[] x;
int ox = 1;
IntVar[] y;
int oy = 1;
if (exps.size() == 2) {
x = exps.get(0).toIntVarArray(model);
y = exps.get(1).toIntVarArray(model);
} else {
x = exps.get(0).toIntVarArray(model);
ox = exps.get(1).intValue();
y = exps.get(2).toIntVarArray(model);
oy = exps.get(3).intValue();
}
model.inverseChanneling(x, y, ox, oy, AC).post();
}
},
knapsackChoco {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
fzn_knapsack.build(model, datas, id, exps, annotations);
}
},
fzn_knapsack {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
int[] w = exps.get(0).toIntArray();
int[] p = exps.get(1).toIntArray();
IntVar[] x = exps.get(2).toIntVarArray(model);
IntVar W = exps.get(3).intVarValue(model);
IntVar P = exps.get(4).intVarValue(model);
model.knapsack(x, W, P, w, p).post();
}
},
lex2Choco {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
choco_fzn_lex2.build(model, datas, id, exps, annotations);
}
},
choco_fzn_lex2 {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
IntVar[] xs = exps.get(0).toIntVarArray(model);
boolean strict = exps.get(1).boolValue();
int le = (int) Math.sqrt(xs.length);
assert le * le == xs.length;
IntVar[][] ys = new IntVar[le][le];
for (int i = 0; i < le; i++) {
ys[i] = Arrays.copyOfRange(xs, le * i, le * (i + 1));
}
if (strict) {
model.lexChainLess(ys).post();
} else {
model.lexChainLessEq(ys).post();
}
}
},
lex_lessChoco {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
choco_fzn_lex_less.build(model, datas, id, exps, annotations);
}
},
choco_fzn_lex_less {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
IntVar[] xs = exps.get(0).toIntVarArray(model);
IntVar[] ys = exps.get(1).toIntVarArray(model);
boolean strict = exps.get(2).boolValue();
if (strict) {
model.lexLess(xs, ys).post();
} else {
model.lexLessEq(xs, ys).post();
}
}
},
maximumChoco {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
fzn_maximum_int.build(model, datas, id, exps, annotations);
}
},
fzn_maximum_int {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
// var int: m, array[int] of var int: x
IntVar m = exps.get(0).intVarValue(model);
IntVar[] x = exps.get(1).toIntVarArray(model);
model.max(m, x).post();
}
},
memberChoco {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
choco_member_int.build(model, datas, id, exps, annotations);
}
},
fzn_member_int { // legacy
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
choco_member_int.build(model, datas, id, exps, annotations);
}
},
choco_member_int {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
int[] x = exps.get(0).toIntArray();
IntVar y = exps.get(1).intVarValue(model);
model.member(y, x).post();
}
},
memberVarChoco {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
choco_member_int_var.build(model, datas, id, exps, annotations);
}
},
fzn_member_int_var { // legacy
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
choco_member_int_var.build(model, datas, id, exps, annotations);
}
},
choco_member_int_var {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
IntVar[] x = exps.get(0).toIntVarArray(model);
IntVar y = exps.get(1).intVarValue(model);
model.element(y, x, model.intVar(model.generateName(), 0, x.length - 1, false), 0).post();
}
},
memberReifChoco {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
choco_member_int_reif.build(model, datas, id, exps, annotations);
}
},
fzn_member_int_reif { // legacy
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
choco_member_int_reif.build(model, datas, id, exps, annotations);
}
},
choco_member_int_reif {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
int[] x = exps.get(0).toIntArray();
IntVar y = exps.get(1).intVarValue(model);
BoolVar b = exps.get(2).boolVarValue(model);
model.member(y, x).reifyWith(b);
}
},
memberVarReifChoco {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
choco_member_int_var_reif.build(model, datas, id, exps, annotations);
}
},
fzn_member_int_var_reif { // legacy
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
choco_member_int_var_reif.build(model, datas, id, exps, annotations);
}
},
choco_member_int_var_reif {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
IntVar[] xs = exps.get(0).toIntVarArray(model);
IntVar y = exps.get(1).intVarValue(model);
BoolVar b = exps.get(2).boolVarValue(model);
ArrayList eqs = new ArrayList<>();
for (IntVar x : xs) {
if (VariableUtils.intersect(x, y)) {
eqs.add(model.arithm(x, "=", y).reify());
}
}
if (eqs.isEmpty()) {
model.arithm(b, "=", 0).post();
} else {
model.addClausesBoolOrArrayEqVar(eqs.toArray(new BoolVar[0]), b);
}
}
},
minimumChoco {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
fzn_minimum_int.build(model, datas, id, exps, annotations);
}
},
fzn_minimum_int {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
// var int: m, array[int] of var int: x
IntVar m = exps.get(0).intVarValue(model);
IntVar[] x = exps.get(1).toIntVarArray(model);
model.min(m, x).post();
}
},
choco_fzn_network_flow {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
int[] _arc = exps.get(0).toIntArray();
int A = _arc.length / 2;
int[] starts = new int[_arc.length / 2];
int[] ends = new int[_arc.length / 2];
for (int j = 0; j < A; j++) {
starts[j] = _arc[2 * j];
ends[j] = _arc[2 * j + 1];
}
int[] balance = exps.get(1).toIntArray();
IntVar[] flow = exps.get(3).toIntVarArray(model);
model.costFlow(starts, ends, balance, IntStream.range(0, starts.length).map(i -> 0).toArray(),
flow, model.intVar(0), 1);
}
},
choco_fzn_network_flow_cost {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
int[] _arc = exps.get(0).toIntArray();
int A = _arc.length / 2;
int[] starts = new int[_arc.length / 2];
int[] ends = new int[_arc.length / 2];
for (int j = 0; j < A; j++) {
starts[j] = _arc[2 * j];
ends[j] = _arc[2 * j + 1];
}
int[] balance = exps.get(1).toIntArray();
int[] weight = exps.get(2).toIntArray();
IntVar[] flow = exps.get(3).toIntVarArray(model);
IntVar cost = exps.get(4).intVarValue(model);
model.costFlow(starts, ends, balance, weight, flow, cost, 1);
}
},
nvalueChoco {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
fzn_nvalue.build(model, datas, id, exps, annotations);
}
},
fzn_nvalue {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
IntVar nValues = exps.get(0).intVarValue(model);
IntVar[] vars = exps.get(1).toIntVarArray(model);
model.nValues(vars, nValues).post();
}
},
regularChoco {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
fzn_regular.build(model, datas, id, exps, annotations);
}
},
fzn_regular {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
// array[int] of var int: x, int: Q, int: S,
// array[int,int] of int: d, int: q0, set of int: F
IntVar[] vars = exps.get(0).toIntVarArray(model);
int Q = exps.get(1).intValue();
int S = exps.get(2).intValue();
int[] d = exps.get(3).toIntArray();
int q0 = exps.get(4).intValue();
int[] F = exps.get(5).toIntArray();
FiniteAutomaton auto = new FiniteAutomaton();
for (int q = 0; q <= Q; q++) auto.addState();
auto.setInitialState(q0);
auto.setFinal(F);
for (int i = 0, k = 0; i < Q; i++) {
for (int j = 0; j < S; j++, k++) {
// 0 is the fail state;
if (d[k] > 0) {
auto.addTransition(i + 1, d[k], j + 1);
}
}
}
// auto.removeDeadTransitions();
// auto.minimize();
model.regularDec(vars, auto);//.post();
// model.regular(vars, auto).post();
}
},
sortChoco {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
fzn_sort.build(model, datas, id, exps, annotations);
}
},
fzn_sort {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
IntVar[] xs = exps.get(0).toIntVarArray(model);
IntVar[] ys = exps.get(1).toIntVarArray(model);
model.sort(xs, ys).post();
}
},
choco_stable_keysort {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
IntVar[] x = exps.get(0).toIntVarArray(model);
IntVar[] permutations = exps.get(1).toIntVarArray(model);
IntVar[] y = exps.get(2).toIntVarArray(model);
int keys = exps.get(3).intValue();
IntVar[][] unsorted = matrixfy(x, x.length / permutations.length);
IntVar[][] sorted = matrixfy(y, y.length / permutations.length);
model.keySort(unsorted, permutations, sorted, keys).post();
}
},
subcircuitChoco {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
IntVar[] vars = exps.get(0).toIntVarArray(model);
if (vars.length > 0) {
int min = vars[0].getLB();
for (IntVar v : vars) {
min = Math.min(min, v.getLB());
}
model.subCircuit(vars, min, model.intVar("length", 0, vars.length, true)).post();
}
}
},
fzn_subcircuit {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
int offset = exps.get(0).intValue();
IntVar[] vars = exps.get(1).toIntVarArray(model);
model.subCircuit(vars, offset, model.intVar("length", 0, vars.length, true)).post();
}
},
tableChoco {
@Override
public void build(Model model, Datas datas, String id, List exps, List annotations) {
choco_fzn_table.build(model, datas, id, exps, annotations);
}
},
choco_fzn_table {
@Override
public void build(Model model, Datas datas, String id, List exps, List