
org.xcsp.parser.loaders.CtrLoaderInteger Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of xcsp3-tools Show documentation
Show all versions of xcsp3-tools Show documentation
Java Tools for parsing XCSP3 instances, compiling JvCSP3 models, and checking solutions. For more information about XCSP3, follow www.xcsp.org
The newest version!
package org.xcsp.parser.loaders;
import static org.xcsp.common.Types.TypeConditionOperatorRel.EQ;
import static org.xcsp.parser.callbacks.XCallbacks.XCallbacksParameters.CONVERT_INTENSION_TO_EXTENSION_ARITY_LIMIT;
import static org.xcsp.parser.callbacks.XCallbacks.XCallbacksParameters.CONVERT_INTENSION_TO_EXTENSION_SPACE_LIMIT;
import static org.xcsp.parser.callbacks.XCallbacks.XCallbacksParameters.RECOGNIZING_BEFORE_CONVERTING;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.function.BiFunction;
import java.util.stream.IntStream;
import java.util.stream.Stream;
import org.xcsp.common.Condition;
import org.xcsp.common.Condition.ConditionRel;
import org.xcsp.common.Constants;
import org.xcsp.common.Types.TypeAtt;
import org.xcsp.common.Types.TypeChild;
import org.xcsp.common.Types.TypeCtr;
import org.xcsp.common.Types.TypeExpr;
import org.xcsp.common.Types.TypeOperator;
import org.xcsp.common.Types.TypeOperatorRel;
import org.xcsp.common.Types.TypeRank;
import org.xcsp.common.Utilities;
import org.xcsp.common.Utilities.ModifiableBoolean;
import org.xcsp.common.domains.Domains.Dom;
import org.xcsp.common.domains.Values.IntegerEntity;
import org.xcsp.common.domains.Values.IntegerInterval;
import org.xcsp.common.domains.Values.Occurrences;
import org.xcsp.common.predicates.TreeEvaluator;
import org.xcsp.common.predicates.XNode;
import org.xcsp.common.predicates.XNodeLeaf;
import org.xcsp.common.predicates.XNodeParent;
import org.xcsp.common.structures.AbstractTuple;
import org.xcsp.common.structures.Transition;
import org.xcsp.parser.callbacks.XCallbacks;
import org.xcsp.parser.entries.XConstraints.CChild;
import org.xcsp.parser.entries.XConstraints.XCtr;
import org.xcsp.parser.entries.XVariables.XVar;
import org.xcsp.parser.entries.XVariables.XVarInteger;
/**
* This class allows us to load integer constraints, at parsing time.
*
* @author Christophe Lecoutre -- {@literal [email protected]}
*
*/
public class CtrLoaderInteger {
// ************************************************************************
// ***** Static fields and methods
// ************************************************************************
/**
* Constant used to control the maximum allowed number of values in the domain of a variable.
*/
public static final int N_MAX_VALUES = 10000000;
/**
* Transforms the specified {@code long} into an {@code int} (while controlling that no information is lost).
*
* @param l
* a specified long integer
* @return an {@code int} corresponding to the specified {@code long}
*/
static int trInteger(Object l) {
return Utilities.safeInt((Long) l);
}
/**
* Transforms the specified object into a 1-dimensional array of integers
*
* @param value
* an object denoting a sequence of integers
* @return a 1-dimensional array of integers
*/
static public int[] trIntegers(Object value) {
if (value instanceof int[])
return (int[]) value;
if (value instanceof Long[]) {
// Note that STAR is not allowed in simple lists (because this is irrelevant), which allows us to write:
return IntStream.range(0, Array.getLength(value)).map(i -> trInteger((long) Array.get(value, i))).toArray();
}
if (value instanceof IntegerEntity[]) {
int[] values = IntegerEntity.toIntArray((IntegerEntity[]) value, N_MAX_VALUES);
Utilities.control(values != null, "Too many values. The parser needs an extension.");
return values;
}
List list = new ArrayList<>();
for (int i = 0; i < Array.getLength(value); i++) {
Object v = Array.get(value, i);
if (v instanceof Long)
list.add((Long) v);
else {
Utilities.control(v instanceof Occurrences, "should be a long or an object occurrences " + v.getClass());
Long l = (Long) ((Occurrences) v).value;
for (int j = 0; j < ((Occurrences) v).nOccurrences; j++)
list.add(l);
}
}
return list.stream().mapToInt(v -> trInteger(v)).toArray();
}
/**
* Builds a 2-dimensional array of integers, whose size is specified and whose values are computed from the specified function.
*
* @param size1
* the size of the first dimension of the array
* @param size2
* the size of the second dimension of the array
* @param f
* a function mapping a pair of integers into an integer
* @return a 2-dimensional array of integers
*/
static int[][] build(int size1, int size2, BiFunction f) {
return IntStream.range(0, size1).mapToObj(i -> IntStream.range(0, size2).map(j -> f.apply(i, j)).toArray()).toArray(int[][]::new);
}
/**
* Transforms the specified object into a 2-dimensional array of integers
*
* @param value
* an object denoting a 2-dimensional array of integers
* @return a 2-dimensional array of integers
*/
static int[][] trIntegers2D(Object value) {
if (value instanceof int[][])
return (int[][]) value;
if (value instanceof byte[][]) {
byte[][] m = (byte[][]) value;
return build(m.length, m[0].length, (i, j) -> m[i][j] == Constants.STAR_BYTE ? Constants.STAR : m[i][j]);
}
if (value instanceof short[][]) {
short[][] m = (short[][]) value;
return build(m.length, m[0].length, (i, j) -> m[i][j] == Constants.STAR_SHORT ? Constants.STAR : m[i][j]);
}
if (value instanceof long[][]) {
long[][] m = (long[][]) value;
return build(m.length, m[0].length, (i, j) -> m[i][j] == Constants.STAR_LONG ? Constants.STAR : trInteger(m[i][j]));
}
if (value instanceof Long[][]) {
Long[][] m = (Long[][]) value;
return build(m.length, m[0].length, (i, j) -> m[i][j] == Constants.STAR_LONG ? Constants.STAR : trInteger(m[i][j]));
}
return (int[][]) Utilities.exit(value + " was expected to be an object denoting a 2-dimensional array of integers");
}
// ************************************************************************
// ***** Methods for loading integer constraints
// ************************************************************************
/**
* A reference to the main parsing object, responsible for dealing with callback functions.
*/
private XCallbacks xc;
/**
* The object used to recognize special forms (primitive, sum, count, ...) forms of intension constraints.
*/
private ConstraintRecognizer recognizer;
/**
* Builds an object that can be used to load integer constraints.
*
* @param xc
* the main parsing object, responsible for dealing with callback functions
*/
public CtrLoaderInteger(XCallbacks xc) {
this.xc = xc;
this.recognizer = new ConstraintRecognizer(xc);
}
/**
* Loads the specified object denoting a parsed constraint. A callback function (or possibly several) will be called.
*
* @param c
* an object denoting a parsed constraint
*/
public void load(XCtr c) {
switch (c.getType()) {
case intension:
intension(c);
break;
case extension:
extension(c);
break;
case regular:
regular(c);
break;
case mdd:
mdd(c);
break;
case allDifferent:
allDifferent(c);
break;
case allEqual:
allEqual(c);
break;
case ordered:
ordered(c);
break;
case lex:
lex(c);
break;
case precedence:
precedence(c);
break;
case sum:
sum(c);
break;
case count:
count(c);
break;
case nValues:
nValues(c);
break;
case cardinality:
cardinality(c);
break;
case maximum:
maximum(c);
break;
case minimum:
minimum(c);
break;
case maximumArg:
maximumArg(c);
break;
case minimumArg:
minimumArg(c);
break;
case element:
element(c);
break;
case channel:
channel(c);
break;
case stretch: // no more in XCSP3-core
stretch(c);
break;
case noOverlap:
noOverlap(c);
break;
case cumulative:
cumulative(c);
break;
case instantiation:
instantiation(c);
break;
case clause: // not in XCSP3-core (but could enter)
clause(c);
break;
case circuit: // now in XCSP3-core
circuit(c);
break;
case binPacking: // not in XCSP3-core (but could enter)
binPacking(c);
break;
case knapsack: // not in XCSP3-core (but could enter)
knapsack(c);
break;
case flow: // not in XCSP3-core (but could enter)
flow(c);
break;
default:
xc.unimplementedCase(c);
}
}
private boolean intensionToExtension(String id, XVarInteger[] scp, XNodeParent root) {
int arityLimit = ((Integer) xc.implem().currParameters.get(CONVERT_INTENSION_TO_EXTENSION_ARITY_LIMIT));
if (scp.length > arityLimit)
return false;
long spaceLimit = ((Long) xc.implem().currParameters.get(CONVERT_INTENSION_TO_EXTENSION_SPACE_LIMIT));
long size = XVarInteger.domainCartesianProductSize(scp);
if (size == -1 || size > spaceLimit)
return false;
int[][] domValues = Stream.of(scp).map(x -> IntegerEntity.toIntArray((IntegerEntity[]) ((Dom) x.dom).values, Integer.MAX_VALUE)).toArray(int[][]::new);
ModifiableBoolean b = new ModifiableBoolean(null); // later, maybe a control parameter
int[][] tuples = new TreeEvaluator(root).generateTuples(domValues, b);
assert b.value != null;
if (tuples.length == 0) { // special case because 0 tuple
if (b.value)
xc.buildCtrFalse(id, scp);
else
xc.buildCtrTrue(id, scp);
} else if (scp.length == 1) // unary constraint
xc.buildCtrExtension(id, scp[0], Stream.of(tuples).mapToInt(t -> t[0]).toArray(), b.value, new HashSet<>());
else
xc.buildCtrExtension(id, scp, tuples, b.value, new HashSet<>());
return true;
}
private void intension(XCtr c) {
// System.out.println("\nROOT1= " + c.childs[0].value + "\nROOT2= " + ((XNodeParent>)
// c.childs[0].value).canonization());
XNode r = ((XNode) c.childs[0].value).canonization(); // we first canonize the
// predicate
if (r.type == TypeExpr.LONG) {
Utilities.control(r.val(0) == 0 || r.val(0) == 1, "Bad form of the predicate obtained after canonization");
if (r.val(0) == 0)
xc.buildCtrFalse(c.id, c.vars());
else
xc.buildCtrTrue(c.id, c.vars());
return;
}
XNodeParent root = (XNodeParent) r;
XVarInteger[] scope = root.vars();
if (xc.implem().currParameters.get(RECOGNIZING_BEFORE_CONVERTING) == Boolean.FALSE) // we try first converting
// into extension
if (intensionToExtension(c.id, scope, root))
return;
if (recognizer.specificIntensionCases(c.id, root, scope.length)) // we try to recognize special forms of
// intension constraints
return;
if (xc.implem().currParameters.get(RECOGNIZING_BEFORE_CONVERTING) == Boolean.TRUE) // we now try converting into
// extension
if (intensionToExtension(c.id, scope, root))
return;
xc.buildCtrIntension(c.id, scope, root);
}
private void extension(XCtr c) {
CChild c1 = c.childs[1];
boolean positive = c1.type == TypeChild.supports;
if (c1.value == null || Array.getLength(c1.value) == 0) { // special case because 0 tuple
if (positive)
xc.buildCtrFalse(c.id, c.vars());
else
xc.buildCtrTrue(c.id, c.vars());
} else {
XVarInteger[] list = (XVarInteger[]) c.childs[0].value;
if (list.length == 1) // unary constraint
xc.buildCtrExtension(c.id, list[0], trIntegers(c1.value), positive, c1.flags);
else {
if (c1.value instanceof AbstractTuple[]) {
xc.buildCtrExtension(c.id, list, (AbstractTuple[]) c1.value, positive, c1.flags);
} else {
int[][] tuples = xc.implem().cache4Tuples.computeIfAbsent(c1.value, k -> trIntegers2D(c1.value));
// if (tuples == null)
// xc.implem().cache4Tuples.put(c1.value, tuples = trIntegers2D(c1.value));
// control to insert later below ?
// for (int i = 0; i < tuples.length - 1; i++) if (Utilities.lexComparatorInt.compare(tuples[i],
// tuples[i + 1]) >= 0) {
// System.out.println("\nSAME " + c + " " + Utilities.join(tuples[i]) + " " +
// Utilities.join(tuples[i + 1]) + " (" + i + ")");
// System.exit(1); }
xc.buildCtrExtension(c.id, list, tuples, positive, c1.flags);
}
}
}
}
private void regular(XCtr c) {
xc.buildCtrRegular(c.id, (XVarInteger[]) c.childs[0].value, (Transition[]) c.childs[1].value, (String) c.childs[2].value, (String[]) c.childs[3].value);
}
private void mdd(XCtr c) {
xc.buildCtrMDD(c.id, (XVarInteger[]) c.childs[0].value, (Transition[]) c.childs[1].value);
}
private void allDifferent(XCtr c) {
CChild[] childs = c.childs;
if (childs[0].value instanceof XNode[]) {
Utilities.control(childs.length == 1 && childs[0].type == TypeChild.list, "Other forms not implemented");
XNode[] trees = ((XNode[]) childs[0].value);
xc.buildCtrAllDifferent(c.id, trees);
} else if (childs[0].type == TypeChild.matrix) {
if (childs.length == 1)
xc.buildCtrAllDifferentMatrix(c.id, (XVarInteger[][]) (childs[0].value));
else
xc.buildCtrAllDifferentMatrix(c.id, (XVarInteger[][]) (childs[0].value), trIntegers(childs[1].value));
} else if (childs[0].type == TypeChild.list) {
if (childs.length == 1)
xc.buildCtrAllDifferent(c.id, (XVarInteger[]) childs[0].value);
else if (childs[1].type == TypeChild.except)
xc.buildCtrAllDifferentExcept(c.id, (XVarInteger[]) childs[0].value, trIntegers(childs[1].value));
else if (childs[childs.length - 1].type == TypeChild.list)
xc.buildCtrAllDifferentList(c.id, Stream.of(childs).map(p -> p.value).toArray(XVarInteger[][]::new));
else if (childs[childs.length - 1].type == TypeChild.except) {
XVarInteger[][] lists = IntStream.range(0, childs.length - 1).mapToObj(i -> childs[i].value).toArray(XVarInteger[][]::new);
xc.buildCtrAllDifferentList(c.id, lists, trIntegers2D(childs[childs.length - 1].value));
} else
xc.unimplementedCase(c);
} else
xc.unimplementedCase(c);
}
private void allEqual(XCtr c) {
if (c.childs[0].type == TypeChild.list)
if (c.childs.length == 1) {
if (c.childs[0].value instanceof XNode[]) {
xc.buildCtrAllEqual(c.id, ((XNode[]) c.childs[0].value));
} else
xc.buildCtrAllEqual(c.id, (XVarInteger[]) c.childs[0].value);
} else
xc.unimplementedCase(c);
else
xc.unimplementedCase(c);
}
private void ordered(XCtr c) {
if (c.childs[0].type == TypeChild.list)
if (c.childs.length == 2)
xc.buildCtrOrdered(c.id, (XVarInteger[]) c.childs[0].value, ((TypeOperator) c.childs[1].value).toRel());
else if (c.childs.length == 3 && c.childs[1].type == TypeChild.lengths) {
if (c.childs[1].value instanceof XVarInteger[])
xc.buildCtrOrdered(c.id, (XVarInteger[]) c.childs[0].value, (XVarInteger[]) c.childs[1].value, ((TypeOperator) c.childs[2].value).toRel());
else
xc.buildCtrOrdered(c.id, (XVarInteger[]) c.childs[0].value, trIntegers(c.childs[1].value), ((TypeOperator) c.childs[2].value).toRel());
} else
xc.unimplementedCase(c);
else
xc.unimplementedCase(c);
}
private void lex(XCtr c) {
TypeOperatorRel op = ((TypeOperator) c.childs[c.childs.length - 1].value).toRel();
if (c.childs[0].type == TypeChild.matrix)
xc.buildCtrLexMatrix(c.id, (XVarInteger[][]) c.childs[0].value, op);
else if (c.childs.length == 3 && c.childs[1].value instanceof Long[])
xc.buildCtrLex(c.id, (XVarInteger[]) c.childs[0].value, trIntegers(c.childs[1].value), op);
else {
xc.buildCtrLex(c.id, IntStream.range(0, c.childs.length - 1).mapToObj(i -> c.childs[i].value).toArray(XVarInteger[][]::new), op);
}
}
private void precedence(XCtr c) {
if (c.childs[0].type == TypeChild.list) {
if (c.childs.length == 1)
xc.buildCtrPrecedence(c.id, (XVarInteger[]) c.childs[0].value);
else {
Utilities.control(c.childs.length == 2, "bad form");
boolean covered = c.childs[1].getAttributeValue(TypeAtt.covered, false);
xc.buildCtrPrecedence(c.id, (XVarInteger[]) c.childs[0].value, trIntegers(c.childs[1].value), covered);
}
} else
xc.unimplementedCase(c);
}
private void sum(XCtr c) {
Condition condition = (Condition) c.childs[c.childs.length - 1].value;
// System.out.println(c.childs[0].value);
if (c.childs[0].value instanceof XNode[]) {
XNode[] trees = ((XNode[]) c.childs[0].value);
if (c.childs.length == 2)
xc.buildCtrSum(c.id, trees, condition);
else if (c.childs[1].value instanceof XVarInteger[])
xc.buildCtrSum(c.id, trees, (XVarInteger[]) c.childs[1].value, condition);
else
xc.buildCtrSum(c.id, trees, trIntegers(c.childs[1].value), condition);
} else if (c.childs[0].value instanceof XVarInteger[]) {
XVarInteger[] list = (XVarInteger[]) c.childs[0].value;
if (c.childs.length == 2)
xc.buildCtrSum(c.id, list, condition);
else if (c.childs[1].value instanceof XVarInteger[])
xc.buildCtrSum(c.id, list, (XVarInteger[]) c.childs[1].value, condition);
else
xc.buildCtrSum(c.id, list, trIntegers(c.childs[1].value), condition);
} else {
// mix between variables and nodes
XNode[] trees = Stream.of((Object[]) c.childs[0].value)
.map(obj -> obj instanceof XVarInteger ? new XNodeLeaf<>(TypeExpr.VAR, obj) : (XNode) obj).toArray(XNode[]::new);
if (c.childs.length == 2)
xc.buildCtrSum(c.id, trees, condition); // System.out.println(o);
else
xc.buildCtrSum(c.id, trees, trIntegers(c.childs[1].value), condition);
}
}
private void count(XCtr c) {
Condition condition = (Condition) c.childs[2].value;
int[] values = c.childs[1].value instanceof Long[] ? trIntegers(c.childs[1].value) : null;
if (c.childs[0].value instanceof XNode[]) {
XNode[] trees = ((XNode[]) c.childs[0].value);
Utilities.control(values != null, "Not possible variant for the moment");
xc.buildCtrCount(c.id, trees, values, condition);
} else if (c.childs[0].value instanceof XVarInteger[]) {
XVarInteger[] list = (XVarInteger[]) c.childs[0].value;
if (values != null) { // values are given by integers
if (condition instanceof ConditionRel && recognizer.specificCountCases(c.id, list, values, ((ConditionRel) condition).operator, condition))
return;
xc.buildCtrCount(c.id, list, values, condition);
} else // values are given by variables
xc.buildCtrCount(c.id, list, (XVarInteger[]) c.childs[1].value, condition);
} else {
// mix between variables and nodes
XNode[] trees = Stream.of((Object[]) c.childs[0].value)
.map(obj -> obj instanceof XVarInteger ? new XNodeLeaf<>(TypeExpr.VAR, obj) : (XNode) obj).toArray(XNode[]::new);
Utilities.control(values != null, "Not possible variant for the moment");
xc.buildCtrCount(c.id, trees, values, condition);
}
}
private void nValues(XCtr c) {
Condition condition = (Condition) c.childs[c.childs.length - 1].value;
if (c.childs[0].value instanceof XNode[]) {
XNode[] trees = ((XNode[]) c.childs[0].value);
xc.buildCtrNValues(c.id, trees, condition);
} else {
XVarInteger[] list = (XVarInteger[]) c.childs[0].value;
if (c.childs.length == 2 && recognizer.specificNvaluesCases(c.id, list, condition))
return;
if (c.childs.length == 2)
xc.buildCtrNValues(c.id, list, condition);
else
xc.buildCtrNValuesExcept(c.id, list, trIntegers(c.childs[1].value), condition);
}
}
private void cardinality(XCtr c) {
XVarInteger[] list = (XVarInteger[]) c.childs[0].value;
Object values = c.childs[1].value;
Object[] occurs = (Object[]) c.childs[2].value;
if (Stream.of(occurs).anyMatch(v -> v instanceof Long) && Stream.of(occurs).anyMatch(v -> v instanceof IntegerInterval))
occurs = Stream.of(occurs).map(v -> v instanceof IntegerInterval ? v : new IntegerInterval((Long) v)).toArray(IntegerInterval[]::new);
boolean closed = c.childs[1].getAttributeValue(TypeAtt.closed, false);
if (values instanceof Long[]) {
if (occurs instanceof Long[])
xc.buildCtrCardinality(c.id, list, closed, trIntegers(values), trIntegers(occurs));
else if (occurs instanceof XVar[])
xc.buildCtrCardinality(c.id, list, closed, trIntegers(values), (XVarInteger[]) occurs);
else {
Utilities.control(occurs instanceof IntegerInterval[], "Pb");
int[] occursMin = Stream.of((IntegerInterval[]) occurs).mapToInt(ii -> Utilities.safeInt(ii.inf)).toArray();
int[] occursMax = Stream.of((IntegerInterval[]) occurs).mapToInt(ii -> Utilities.safeInt(ii.sup)).toArray();
xc.buildCtrCardinality(c.id, list, closed, trIntegers(values), occursMin, occursMax);
}
} else {
if (occurs instanceof Long[])
xc.buildCtrCardinality(c.id, list, closed, (XVarInteger[]) values, trIntegers(occurs));
else if (occurs instanceof XVar[])
xc.buildCtrCardinality(c.id, list, closed, (XVarInteger[]) values, (XVarInteger[]) occurs);
else {
Utilities.control(occurs instanceof IntegerInterval[], "Pb");
int[] occursMin = Stream.of((IntegerInterval[]) occurs).mapToInt(ii -> Utilities.safeInt(ii.inf)).toArray();
int[] occursMax = Stream.of((IntegerInterval[]) occurs).mapToInt(ii -> Utilities.safeInt(ii.sup)).toArray();
xc.buildCtrCardinality(c.id, list, closed, (XVarInteger[]) values, occursMin, occursMax);
}
}
}
private void minimumMaximum(XCtr c) {
CChild[] childs = c.childs;
Condition condition = childs[childs.length - 1].type == TypeChild.condition ? (Condition) childs[childs.length - 1].value : null;
if (childs[1].type == TypeChild.condition) {
if (Arrays.stream((Object[]) (childs[0].value)).allMatch(o -> o instanceof XNode)) {
XNode[] trees = Arrays.stream((Object[]) (childs[0].value)).map(o -> (XNode) o).toArray(XNode[]::new);
if (c.getType() == TypeCtr.maximum)
xc.buildCtrMaximum(c.id, trees, condition);
else
xc.buildCtrMinimum(c.id, trees, condition);
} else {
XVarInteger[] list = (XVarInteger[]) childs[0].value;
if (c.getType() == TypeCtr.maximum)
xc.buildCtrMaximum(c.id, list, condition);
else
xc.buildCtrMinimum(c.id, list, condition);
}
} else {
XVarInteger[] list = (XVarInteger[]) childs[0].value;
int startIndex = childs[0].getAttributeValue(TypeAtt.startIndex, 0);
TypeRank rank = childs[1].getAttributeValue(TypeAtt.rank, TypeRank.class, TypeRank.ANY);
if (c.getType() == TypeCtr.maximum)
xc.buildCtrMaximum(c.id, list, startIndex, (XVarInteger) childs[1].value, rank, condition);
else
xc.buildCtrMinimum(c.id, list, startIndex, (XVarInteger) childs[1].value, rank, condition);
}
}
private void maximum(XCtr c) {
minimumMaximum(c);
}
private void minimum(XCtr c) {
minimumMaximum(c);
}
private void minimumMaximumArg(XCtr c) {
CChild[] childs = c.childs;
TypeRank rank = c.getAttributeValue(TypeAtt.rank, TypeRank.class, TypeRank.ANY);
Condition condition = (Condition) childs[childs.length - 1].value;
if (Arrays.stream((Object[]) (childs[0].value)).allMatch(o -> o instanceof XNode)) {
XNode[] trees = Arrays.stream((Object[]) (childs[0].value)).map(o -> (XNode) o).toArray(XNode[]::new);
if (c.getType() == TypeCtr.maximumArg)
xc.buildCtrMaximumArg(c.id, trees, rank, condition);
else
xc.buildCtrMinimumArg(c.id, trees, rank, condition);
} else {
XVarInteger[] list = (XVarInteger[]) childs[0].value;
if (c.getType() == TypeCtr.maximumArg)
xc.buildCtrMaximumArg(c.id, list, rank, condition);
else
xc.buildCtrMinimumArg(c.id, list, rank, condition);
}
}
private void maximumArg(XCtr c) {
minimumMaximumArg(c);
}
private void minimumArg(XCtr c) {
minimumMaximumArg(c);
}
private Condition conditionEq(Object obj) {
return obj instanceof Condition ? (Condition) obj : Condition.buildFrom(EQ, obj instanceof XVar ? (XVarInteger) obj : trInteger(obj));
}
private void element(XCtr c) {
CChild[] childs = c.childs;
CChild lastChild = childs[childs.length - 1];
Condition condition = lastChild.type == TypeChild.value ? conditionEq(lastChild.value) : (Condition) lastChild.value;
if (childs[0].value instanceof XVarInteger[]) {
XVarInteger[] list = (XVarInteger[]) childs[0].value;
if (childs.length == 2) // [1].type == TypeChild.value)
xc.buildCtrElement(c.id, list, condition);
else {
int startIndex = childs[0].getAttributeValue(TypeAtt.startIndex, 0);
TypeRank rank = childs[1].getAttributeValue(TypeAtt.rank, TypeRank.class, TypeRank.ANY);
xc.buildCtrElement(c.id, list, startIndex, (XVarInteger) childs[1].value, rank, condition);
}
} else if (childs[0].value instanceof Long[]) {
int[] list = trIntegers(c.childs[0].value);
int startIndex = childs[0].getAttributeValue(TypeAtt.startIndex, 0);
TypeRank rank = childs[1].getAttributeValue(TypeAtt.rank, TypeRank.class, TypeRank.ANY);
xc.buildCtrElement(c.id, list, startIndex, (XVarInteger) childs[1].value, rank, condition);
} else if (childs[0].value instanceof XVarInteger[][]) {
XVarInteger[][] matrix = (XVarInteger[][]) childs[0].value;
int startRowIndex = childs[0].getAttributeValue(TypeAtt.startRowIndex, 0);
int startColIndex = childs[0].getAttributeValue(TypeAtt.startColIndex, 0);
XVarInteger[] t = (XVarInteger[]) childs[1].value;
assert t.length == 2;
xc.buildCtrElement(c.id, matrix, startRowIndex, t[0], startColIndex, t[1], condition);
} else {
assert childs[0].value instanceof Long[][];
int[][] matrix = trIntegers2D(childs[0].value);
int startRowIndex = childs[0].getAttributeValue(TypeAtt.startRowIndex, 0);
int startColIndex = childs[0].getAttributeValue(TypeAtt.startColIndex, 0);
XVarInteger[] t = (XVarInteger[]) childs[1].value;
assert t.length == 2;
assert childs[2].value instanceof XVar;
xc.buildCtrElement(c.id, matrix, startRowIndex, t[0], startColIndex, t[1], condition);
}
}
private void channel(XCtr c) {
XVarInteger[] list = (XVarInteger[]) c.childs[0].value;
int startIndex0 = c.childs[0].getAttributeValue(TypeAtt.startIndex, 0);
if (c.childs.length == 1)
xc.buildCtrChannel(c.id, list, startIndex0);
else if (c.childs[1].type == TypeChild.list) {
int startIndex1 = c.childs[1].getAttributeValue(TypeAtt.startIndex, 0);
xc.buildCtrChannel(c.id, list, startIndex0, (XVarInteger[]) c.childs[1].value, startIndex1);
} else
xc.buildCtrChannel(c.id, list, startIndex0, (XVarInteger) c.childs[1].value);
}
private void stretch(XCtr c) {
XVarInteger[] list = (XVarInteger[]) c.childs[0].value;
int[] values = trIntegers(c.childs[1].value);
int[] widthsMin = Stream.of((IntegerInterval[]) c.childs[2].value).mapToInt(ii -> Utilities.safeInt(ii.inf)).toArray();
int[] widthsMax = Stream.of((IntegerInterval[]) c.childs[2].value).mapToInt(ii -> Utilities.safeInt(ii.sup)).toArray();
if (c.childs.length == 3)
xc.buildCtrStretch(c.id, list, values, widthsMin, widthsMax);
else
xc.buildCtrStretch(c.id, list, values, widthsMin, widthsMax, trIntegers2D(c.childs[3].value));
}
private void noOverlap(XCtr c) {
boolean zeroIgnored = c.getAttributeValue(TypeAtt.zeroIgnored, true);
if (c.childs[0].value instanceof XVarInteger[][]) {
XVarInteger[][] origins = (XVarInteger[][]) c.childs[0].value;
if (c.childs[1].value instanceof XVarInteger[][])
xc.buildCtrNoOverlap(c.id, origins, (XVarInteger[][]) c.childs[1].value, zeroIgnored);
else if (c.childs[1].value instanceof Long[][])
xc.buildCtrNoOverlap(c.id, origins, trIntegers2D(c.childs[1].value), zeroIgnored);
else {
XVarInteger[] xs = Stream.of(origins).map(o -> o[0]).toArray(XVarInteger[]::new);
XVarInteger[] ys = Stream.of(origins).map(o -> o[1]).toArray(XVarInteger[]::new);
Object[] lengths = (Object[]) c.childs[1].value;
XVarInteger[] lx = Stream.of(lengths).map(o -> (XVarInteger) ((Object[]) o)[0]).toArray(XVarInteger[]::new);
Long[] ly = Stream.of(lengths).map(o -> (Long) ((Object[]) o)[1]).toArray(Long[]::new);
xc.buildCtrNoOverlap(c.id, xs, ys, lx, trIntegers(ly), zeroIgnored);
}
} else {
XVarInteger[] origins = (XVarInteger[]) c.childs[0].value;
if (c.childs[1].value instanceof XVarInteger[])
xc.buildCtrNoOverlap(c.id, origins, (XVarInteger[]) c.childs[1].value, zeroIgnored);
else
xc.buildCtrNoOverlap(c.id, origins, trIntegers(c.childs[1].value), zeroIgnored);
}
}
private void cumulative(XCtr c) {
CChild[] childs = c.childs;
XVarInteger[] origins = (XVarInteger[]) childs[0].value;
Condition condition = (Condition) childs[childs.length - 1].value;
if (childs.length == 4) {
if (childs[1].value instanceof XVarInteger[] && childs[2].value instanceof XVarInteger[])
xc.buildCtrCumulative(c.id, origins, (XVarInteger[]) childs[1].value, (XVarInteger[]) childs[2].value, condition);
else if (!(childs[1].value instanceof XVarInteger[]) && childs[2].value instanceof XVarInteger[])
xc.buildCtrCumulative(c.id, origins, trIntegers(childs[1].value), (XVarInteger[]) childs[2].value, condition);
else if (childs[1].value instanceof XVarInteger[] && !(childs[2].value instanceof XVarInteger[]))
xc.buildCtrCumulative(c.id, origins, (XVarInteger[]) childs[1].value, trIntegers(childs[2].value), condition);
else
xc.buildCtrCumulative(c.id, origins, trIntegers(childs[1].value), trIntegers(childs[2].value), condition);
} else {
XVarInteger[] ends = (XVarInteger[]) childs[2].value;
if (childs[1].value instanceof Long[] && childs[3].value instanceof Long[])
xc.buildCtrCumulative(c.id, origins, trIntegers(childs[1].value), ends, trIntegers(childs[3].value), condition);
else if (childs[1].value instanceof Long[] && !(childs[3].value instanceof Long[]))
xc.buildCtrCumulative(c.id, origins, trIntegers(childs[1].value), ends, (XVarInteger[]) childs[3].value, condition);
else if (!(childs[1].value instanceof Long[]) && childs[3].value instanceof Long[])
xc.buildCtrCumulative(c.id, origins, (XVarInteger[]) childs[1].value, ends, trIntegers(childs[3].value), condition);
else
xc.buildCtrCumulative(c.id, origins, (XVarInteger[]) childs[1].value, ends, (XVarInteger[]) childs[3].value, condition);
}
}
private void instantiation(XCtr c) {
xc.buildCtrInstantiation(c.id, (XVarInteger[]) c.childs[0].value, trIntegers(c.childs[1].value));
}
private void clause(XCtr c) {
Object[] t = (Object[]) c.childs[0].value;
XVarInteger[] pos = Stream.of(t).filter(o -> o instanceof XVar || o instanceof XNodeLeaf)
.map(o -> o instanceof XVar ? (XVar) o : (XVar) ((XNodeLeaf>) o).value).toArray(XVarInteger[]::new);
XVarInteger[] neg = Stream.of(t).filter(o -> o instanceof XNodeParent).map(o -> (XVar) ((XNodeLeaf>) ((XNodeParent>) o).sons[0]).value)
.toArray(XVarInteger[]::new);
xc.buildCtrClause(c.id, pos, neg);
}
private void circuit(XCtr c) {
CChild[] childs = c.childs;
XVarInteger[] list = (XVarInteger[]) childs[0].value;
int startIndex = childs[0].getAttributeValue(TypeAtt.startIndex, 0);
if (childs.length == 1)
xc.buildCtrCircuit(c.id, list, startIndex);
else if (childs[1].value instanceof XVar)
xc.buildCtrCircuit(c.id, list, startIndex, (XVarInteger) childs[1].value);
else
xc.buildCtrCircuit(c.id, list, startIndex, Utilities.safeInt((Long) childs[1].value));
}
private void binPacking(XCtr c) {
CChild[] childs = c.childs;
XVarInteger[] list = (XVarInteger[]) childs[0].value;
int[] sizes = trIntegers(c.childs[1].value);
if (childs[2].type == TypeChild.limits) {
if (childs[2].value instanceof XVarInteger[])
xc.buildCtrBinPacking(c.id, list, sizes, (XVarInteger[]) childs[2].value, false);
else
xc.buildCtrBinPacking(c.id, list, sizes, trIntegers(childs[2].value), false);
} else if (childs[2].type == TypeChild.loads) {
if (childs[2].value instanceof XVarInteger[])
xc.buildCtrBinPacking(c.id, list, sizes, (XVarInteger[]) childs[2].value, true);
else
xc.buildCtrBinPacking(c.id, list, sizes, trIntegers(childs[2].value), true);
} else if (childs[2].type == TypeChild.condition)
xc.buildCtrBinPacking(c.id, list, sizes, (Condition) childs[2].value);
else
xc.buildCtrBinPacking(c.id, list, sizes, (Condition[]) childs[2].value, childs[2].getAttributeValue(TypeAtt.startIndex, 0));
}
private void knapsack(XCtr c) {
CChild[] childs = c.childs;
XVarInteger[] list = (XVarInteger[]) childs[0].value;
int[] weights = trIntegers(childs[1].value);
Condition condition1 = (Condition) childs[2].value;
int[] profits = trIntegers(childs[3].value);
Condition condition2 = (Condition) childs[4].value;
xc.buildCtrKnapsack(c.id, list, weights, condition1, profits, condition2);
}
private void flow(XCtr c) {
CChild[] childs = c.childs;
XVarInteger[] list = (XVarInteger[]) childs[0].value;
int[] balance = trIntegers(childs[1].value);
int[][] arcs = trIntegers2D(childs[2].value);
if (childs.length == 3)
xc.buildCtrFlow(c.id, list, balance, arcs);
else {
Condition condition = (Condition) childs[4].value;
xc.buildCtrFlow(c.id, list, balance, arcs, trIntegers(childs[3].value), condition);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy