All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.xcsp.modeler.implementation.ProblemIMP3 Maven / Gradle / Ivy

Go to download

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.modeler.implementation;

import static org.xcsp.modeler.definitions.ICtr.LIST;
import static org.xcsp.modeler.definitions.ICtr.LISTS;
import static org.xcsp.modeler.definitions.ICtr.MATRIX;

import java.util.HashMap;
import java.util.Map;
import java.util.function.IntFunction;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;

import org.xcsp.common.Condition;
import org.xcsp.common.IVar;
import org.xcsp.common.IVar.Var;
import org.xcsp.common.IVar.VarSymbolic;
import org.xcsp.common.Range;
import org.xcsp.common.Types.TypeExpr;
import org.xcsp.common.Types.TypeObjective;
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.Domains.DomSymbolic;
import org.xcsp.common.domains.Domains.IDom;
import org.xcsp.common.domains.Values.IntegerEntity;
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.Automaton;
import org.xcsp.common.structures.Table;
import org.xcsp.common.structures.TableSymbolic;
import org.xcsp.common.structures.Transition;
import org.xcsp.modeler.api.ProblemAPI;
import org.xcsp.modeler.definitions.ICtr;
import org.xcsp.modeler.definitions.ICtr.ICtrAllDifferent;
import org.xcsp.modeler.definitions.ICtr.ICtrAllEqual;
import org.xcsp.modeler.definitions.ICtr.ICtrCardinality;
import org.xcsp.modeler.definitions.ICtr.ICtrChannel;
import org.xcsp.modeler.definitions.ICtr.ICtrCircuit;
import org.xcsp.modeler.definitions.ICtr.ICtrClause;
import org.xcsp.modeler.definitions.ICtr.ICtrCount;
import org.xcsp.modeler.definitions.ICtr.ICtrCumulative;
import org.xcsp.modeler.definitions.ICtr.ICtrElement;
import org.xcsp.modeler.definitions.ICtr.ICtrElementMatrix;
import org.xcsp.modeler.definitions.ICtr.ICtrExtension;
import org.xcsp.modeler.definitions.ICtr.ICtrIfThen;
import org.xcsp.modeler.definitions.ICtr.ICtrIfThenElse;
import org.xcsp.modeler.definitions.ICtr.ICtrInstantiation;
import org.xcsp.modeler.definitions.ICtr.ICtrIntension;
import org.xcsp.modeler.definitions.ICtr.ICtrMaximum;
import org.xcsp.modeler.definitions.ICtr.ICtrMdd;
import org.xcsp.modeler.definitions.ICtr.ICtrMinimum;
import org.xcsp.modeler.definitions.ICtr.ICtrNValues;
import org.xcsp.modeler.definitions.ICtr.ICtrNoOverlap;
import org.xcsp.modeler.definitions.ICtr.ICtrOrdered;
import org.xcsp.modeler.definitions.ICtr.ICtrRegular;
import org.xcsp.modeler.definitions.ICtr.ICtrSlide;
import org.xcsp.modeler.definitions.ICtr.ICtrStretch;
import org.xcsp.modeler.definitions.ICtr.ICtrSum;
import org.xcsp.modeler.definitions.IObj;
import org.xcsp.modeler.definitions.IObj.IObjFunctional;
import org.xcsp.modeler.definitions.IObj.IObjSpecialized;
import org.xcsp.modeler.entities.CtrEntities.CtrAlone;
import org.xcsp.modeler.entities.CtrEntities.CtrEntity;
import org.xcsp.modeler.entities.ObjEntities.ObjEntity;
import org.xcsp.modeler.implementation.ProblemIMP3.MVariable.MVarInteger;
import org.xcsp.modeler.implementation.ProblemIMP3.MVariable.MVarSymbolic;

public class ProblemIMP3 extends ProblemIMP {

	private static final Object unimplementedCase(Object... objects) {
		System.out.println("\n\n**********************");
		System.out.println("Missing Implementation");
		StackTraceElement[] t = Thread.currentThread().getStackTrace();
		System.out.println("  Method " + t[2].getMethodName());
		System.out.println("  Class " + t[2].getClassName());
		System.out.println("  Line " + t[2].getLineNumber());
		System.out.println("**********************");
		System.out.println(Stream.of(objects).filter(o -> o != null).map(o -> o.toString()).collect(Collectors.joining("\n")));
		// throw new RuntimeException();
		System.exit(1);
		return null;
	}

	public static class MVariable implements IVar, Comparable {

		@Override
		public int compareTo(MVariable x) {
			int res = idPrefix.compareTo(x.idPrefix);
			if (res != 0)
				return res;
			if (idIndexes == null)
				return 0;
			return Utilities.lexComparatorInt.compare(idIndexes, x.idIndexes);
		}

		protected String id;
		private String idPrefix;
		private int[] idIndexes;
		public IDom dom;

		public MVariable(String id, IDom dom) {
			this.id = id;
			int pos = id.indexOf('[');
			this.idPrefix = pos == -1 ? id : id.substring(0, pos);
			this.idIndexes = pos == -1 ? null : Utilities.splitToInts(id.substring(pos), "\\[|\\]");
			this.dom = dom;
		}

		@Override
		public String id() {
			return id;
		}

		@Override
		public String toString() {
			return id;
		}

		public static class MVarSymbolic extends MVariable implements VarSymbolic {
			public MVarSymbolic(String id, DomSymbolic dom) {
				super(id, dom);
			}
		}

		public static class MVarInteger extends MVariable implements Var {
			public MVarInteger(String id, Dom dom) {
				super(id, dom);
			}

			@Override
			public Object allValues() {
				return null; // Not useful for the moment
			}
		}
	}

	@Override
	public Class classVI() {
		return MVarInteger.class;
	}

	@Override
	public Class classVS() {
		return MVarSymbolic.class;
	}

	public ProblemIMP3(ProblemAPI api, String modelVariant, String data, String dataFormat, boolean dataSaving, String[] argsForPb) {
		super(api, modelVariant, argsForPb);
		loadData(data, dataFormat, dataSaving);
		api.model();
	}

	/** A map that gives access to each variable through its id. */
	public final Map mapForVars = new HashMap<>();

	/** Adds a variable that has already be built. Should not be called directly when modeling. */
	public final MVariable addVar(MVariable x) {
		Utilities.control(!mapForVars.containsKey(x.id()), x.id() + " duplicated");
		mapForVars.put(x.id(), x);
		return x;
	}

	@Override
	public MVarInteger buildVarInteger(String id, Dom dom) {
		return (MVarInteger) addVar(new MVarInteger(id, dom));
	}

	@Override
	public MVarSymbolic buildVarSymbolic(String id, DomSymbolic dom) {
		return (MVarSymbolic) addVar(new MVarSymbolic(id, dom));
	}

	public CtrAlone post(ICtr c) {
		// StackTraceElement[] t = Thread.currentThread().getStackTrace();
		// for (StackTraceElement s : t)
		// System.out.println(s);
		// System.out.println(t[t.length - 5].getLineNumber());
		return ctrEntities.new CtrAlone(c);
	}

	// ************************************************************************
	// ***** Constraint intension
	// ************************************************************************

	@Override
	public CtrEntity intension(XNodeParent tree) {
		return post(ICtrIntension.buildFrom(tree.vars(), tree));
	}

	// ************************************************************************
	// ***** Converting Intension to Extension
	// ************************************************************************

	private Converter converter = new Converter() {
		@Override
		public StringBuilder signatureFor(Var[] scp) {
			StringBuilder sb = new StringBuilder();
			for (MVarInteger x : (MVarInteger[]) scp)
				sb.append(System.identityHashCode(x.dom)).append(' ');
			return sb;
		}

		@Override
		public int[][] domValuesOf(Var[] scp) {
			IntegerEntity[][] ies = Stream.of((MVarInteger[]) scp).map(x -> (IntegerEntity[]) ((Dom) x.dom).values).toArray(IntegerEntity[][]::new);
			Utilities.control(Stream.of(ies).allMatch(t -> IntegerEntity.nValues(t) != -1 && IntegerEntity.nValues(t) < 1000000), "");
			return Stream.of(ies).map(t -> IntegerEntity.toIntArray(t, 1000000)).toArray(int[][]::new);
		}

		@Override
		public ModifiableBoolean mode() {
			return new ModifiableBoolean(null);
		}
	};

	@Override
	protected Converter getConverter() {
		return converter;
	}

	// ************************************************************************
	// ***** Constraint extension
	// ************************************************************************

	@Override
	public CtrAlone extension(Var[] list, int[][] tuples, boolean positive) {
		return post(ICtrExtension.buildFrom(list, varEntities.compactOrdered(list), list.length, Table.clean(tuples), positive));
	}

	@Override
	public CtrAlone extension(VarSymbolic[] list, String[][] tuples, boolean positive) {
		return post(ICtrExtension.buildFrom(list, varEntities.compactOrdered(list), list.length, TableSymbolic.clean(tuples), positive));
	}

	@Override
	public CtrAlone extension(Var[] scp, AbstractTuple[] tuples, boolean positive) {
		return (CtrAlone) unimplementedCase();
	}

	// ************************************************************************
	// ***** Constraint regular
	// ***************************** *******************************************

	@Override
	public CtrAlone regular(Var[] list, Automaton automaton) {
		return post(ICtrRegular.buildFrom(list, varEntities.compactOrdered(list),
				Stream.of(automaton.transitions).map(t -> t.toString()).collect(Collectors.joining()), automaton.startState, automaton.finalStates));
	}

	// ************************************************************************
	// ***** Constraint mdd
	// ************************************************************************

	@Override
	public CtrAlone mdd(Var[] list, Transition[] transitions) {
		return post(ICtrMdd.buildFrom(list, varEntities.compactOrdered(list), Stream.of(transitions).map(t -> t.toString()).collect(Collectors.joining())));
	}

	// ************************************************************************
	// ***** Constraint allDifferent
	// ************************************************************************

	@Override
	public CtrEntity allDifferent(Var[] list) {
		return post(ICtrAllDifferent.buildFrom(list, LIST, varEntities.compact(list), null));
	}

	@Override
	public CtrEntity allDifferent(VarSymbolic[] list) {
		return post(ICtrAllDifferent.buildFrom(list, LIST, varEntities.compact(list), null));
	}

	@Override
	public CtrEntity allDifferent(Var[] list, int[] exceptValues) {
		return post(ICtrAllDifferent.buildFrom(list, LIST, varEntities.compact(list), Utilities.join(exceptValues)));
	}

	@Override
	public CtrEntity allDifferentList(Var[]... lists) {
		return post(ICtrAllDifferent.buildFrom(vars(lists), LISTS, varEntities.compactOrdered(lists), null));
	}

	@Override
	public CtrEntity allDifferentList(Var[][] lists, int[][] except) {
		return (CtrAlone) unimplementedCase();
	}

	@Override
	public CtrEntity allDifferentMatrix(Var[][] matrix) {
		return post(ICtrAllDifferent.buildFrom(vars(matrix), MATRIX, varEntities.compactMatrix(matrix), null));
	}

	@Override
	public CtrEntity allDifferent(XNode[] trees) {
		String s = Stream.of(trees).map(t -> t.toString()).collect(Collectors.joining(" "));
		return post(ICtrAllDifferent.buildFrom(scope(Stream.of(trees).map(t -> t.vars())), LIST, s, null));
	}

	// ************************************************************************
	// ***** Constraint allEqual
	// ************************************************************************

	@Override
	public CtrEntity allEqual(Var... list) {
		return post(ICtrAllEqual.buildFrom(list, LIST, varEntities.compact(list)));
	}

	@Override
	public CtrEntity allEqual(VarSymbolic... list) {
		return post(ICtrAllEqual.buildFrom(list, LIST, varEntities.compact(list)));
	}

	@Override
	public CtrEntity allEqualList(Var[]... lists) {
		return post(ICtrAllEqual.buildFrom(vars(lists), LISTS, varEntities.compactOrdered(lists)));
	}

	// ************************************************************************
	// ***** Constraint ordered and lex
	// ************************************************************************

	@Override
	public CtrEntity ordered(Var[] list, int[] lengths, TypeOperatorRel operator) {
		return post(ICtrOrdered.buildFrom(list, LIST, varEntities.compactOrdered(list),
				IntStream.of(lengths).allMatch(v -> v == 0) ? null : Utilities.join(lengths), operator));
	}

	@Override
	public CtrEntity ordered(Var[] list, Var[] lengths, TypeOperatorRel operator) {
		return post(ICtrOrdered.buildFrom(list, LIST, varEntities.compactOrdered(list), varEntities.compactOrdered(lengths), operator));
	}

	@Override
	public CtrEntity lex(Var[][] lists, TypeOperatorRel operator) {
		return post(ICtrOrdered.buildFrom(vars(lists), LISTS, varEntities.compactOrdered(lists), null, operator));
	}

	@Override
	public CtrEntity lexMatrix(Var[][] matrix, TypeOperatorRel operator) {
		return post(ICtrOrdered.buildFrom(vars(matrix), MATRIX, varEntities.compactMatrix(matrix), null, operator));
	}

	@Override
	public CtrEntity precedence(Var[] list, int[] values, boolean covered) {
		throw new AssertionError("not implemented");
	}

	// ************************************************************************
	// ***** Constraint sum
	// ************************************************************************

	@Override
	public CtrEntity sum(Var[] list, int[] coeffs, Condition condition) {
		Utilities.control(Stream.of(list).noneMatch(x -> x == null), "A variable is null");
		Utilities.control(list.length == coeffs.length, "Pb because the number of variables is different form the number of coefficients");
		Var[] newList = list; // api.select(list, i -> coeffs[i] != 0);
		int[] newCoeffs = coeffs; // pi.selectFromIndexing(coeffs, i -> coeffs[i] != 0);
		Utilities.control(newList.length == newCoeffs.length, "Pb because the number of variables is different form the number of coefficients");
		return post(ICtrSum.buildFrom(scope(newList, condition), varEntities.compactOrdered(newList),
				IntStream.range(0, newCoeffs.length).allMatch(i -> newCoeffs[i] == 1) ? null : Utilities.join(newCoeffs), condition));
	}

	@Override
	public CtrEntity sum(Var[] list, Var[] coeffs, Condition condition) {
		Utilities.control(Stream.of(list).noneMatch(x -> x == null) && Stream.of(coeffs).noneMatch(x -> x == null), "A variable is null");
		Utilities.control(list.length == coeffs.length, "Pb because the number of variables is different form the number of coefficients");
		return post(ICtrSum.buildFrom(scope(list, coeffs, condition), varEntities.compactOrdered(list), varEntities.compactOrdered(coeffs), condition));
	}

	@Override
	public CtrEntity sum(XNode[] trees, int[] coeffs, Condition condition) {
		Utilities.control(trees.length == coeffs.length, "Pb because the number of trees is different form the number of coefficients");
		String s = Stream.of(trees).map(t -> t.toString()).collect(Collectors.joining(" "));
		return post(ICtrSum.buildFrom(scope(Stream.of(trees).map(t -> t.vars()), condition), s,
				IntStream.range(0, coeffs.length).allMatch(i -> coeffs[i] == 1) ? null : Utilities.join(coeffs), condition));
	}

	// ************************************************************************
	// ***** Constraint count
	// ************************************************************************

	@Override
	public CtrEntity count(Var[] list, int[] values, Condition condition) {
		return post(ICtrCount.buildFrom(scope(list, condition), varEntities.compact(clean(list)), Utilities.join(values), condition));
	}

	@Override
	public CtrEntity count(Var[] list, Var[] values, Condition condition) {
		return post(ICtrCount.buildFrom(scope(list, values, condition), varEntities.compact(clean(list)), varEntities.compact(clean(values)), condition));
	}

	// ************************************************************************
	// ***** Constraint nValues
	// ************************************************************************

	@Override
	public CtrEntity nValues(Var[] list, Condition condition) {
		return post(ICtrNValues.buildFrom(scope(list, condition), varEntities.compact(clean(list)), null, condition));
	}

	@Override
	public CtrEntity nValues(Var[] list, Condition condition, int[] exceptValues) {
		return post(ICtrNValues.buildFrom(scope(list, condition), varEntities.compact(clean(list)), Utilities.join(exceptValues), condition));
	}

	// ************************************************************************
	// ***** Constraint cardinality
	// ************************************************************************

	@Override
	public CtrEntity cardinality(Var[] list, int[] values, boolean mustBeClosed, int[] occurs) {
		Utilities.control(values.length == occurs.length, "Arrays values and occurs have different length.");
		return post(ICtrCardinality.buildFrom(list, varEntities.compact(clean(list)), Utilities.join(values), mustBeClosed, Utilities.join(occurs)));
	}

	@Override
	public CtrEntity cardinality(Var[] list, int[] values, boolean mustBeClosed, Var[] occurs) {
		Utilities.control(values.length == occurs.length, "Arrays values and occurs have different length.");
		Utilities.control(Stream.of(occurs).noneMatch(x -> x == null), "A variable in array occurs is null");
		return post(ICtrCardinality.buildFrom(scope(list, occurs), varEntities.compact(clean(list)), Utilities.join(values), mustBeClosed,
				varEntities.compactOrdered(occurs)));
	}

	@Override
	public CtrEntity cardinality(Var[] list, int[] values, boolean mustBeClosed, int[] minOccurs, int[] maxOccurs) {
		Utilities.control(values.length == minOccurs.length && values.length == maxOccurs.length,
				"Arrays values, minOccurs and maxOccurs have different length.");
		return post(ICtrCardinality.buildFrom(list, varEntities.compact(clean(list)), Utilities.join(values), mustBeClosed,
				intervalAsString(minOccurs, maxOccurs)));
	}

	@Override
	public CtrEntity cardinality(Var[] list, Var[] values, boolean mustBeClosed, int[] occurs) {
		Utilities.control(values.length == occurs.length, "Arrays values and occurs have different length.");
		Utilities.control(Stream.of(values).noneMatch(x -> x == null), "A variable in array values is null");
		return post(ICtrCardinality.buildFrom(scope(list, values), varEntities.compact(clean(list)), varEntities.compactOrdered(values), mustBeClosed,
				Utilities.join(occurs)));
	}

	@Override
	public CtrEntity cardinality(Var[] list, Var[] values, boolean mustBeClosed, Var[] occurs) {
		Utilities.control(values.length == occurs.length, "Arrays values and occurs have different length.");
		Utilities.control(Stream.of(values).noneMatch(x -> x == null) && Stream.of(occurs).noneMatch(x -> x == null),
				"A variable in array values or occurs is null");
		return post(ICtrCardinality.buildFrom(scope(list, values, occurs), varEntities.compact(clean(list)), varEntities.compactOrdered(values), mustBeClosed,
				varEntities.compactOrdered(occurs)));
	}

	@Override
	public CtrEntity cardinality(Var[] list, Var[] values, boolean mustBeClosed, int[] minOccurs, int[] maxOccurs) {
		Utilities.control(values.length == minOccurs.length && values.length == maxOccurs.length,
				"Arrays values, minOccurs and maxOccurs have different length.");
		Utilities.control(Stream.of(values).noneMatch(x -> x == null), "A variable in array values is null");
		return post(ICtrCardinality.buildFrom(scope(list, values), varEntities.compact(clean(list)), varEntities.compactOrdered(values), mustBeClosed,
				intervalAsString(minOccurs, maxOccurs)));
	}

	// ************************************************************************
	// ***** Constraint maximum
	// ************************************************************************

	@Override
	public CtrEntity maximum(Var[] list, Condition condition) {
		return post(ICtrMaximum.buildFrom(scope(list, condition), varEntities.compact(clean(list)), null, null, null, condition));

	}

	@Override
	public CtrEntity maximum(Var[] list, int startIndex, Var index, TypeRank rank) {
		Utilities.control(Stream.of(list).noneMatch(x -> x == null), "A variable in array list is null");
		return post(ICtrMaximum.buildFrom(scope(list, index), varEntities.compactOrdered(list), startIndex, index, rank, null));
	}

	@Override
	public CtrEntity maximum(Var[] list, int startIndex, Var index, TypeRank rank, Condition condition) {
		Utilities.control(Stream.of(list).noneMatch(x -> x == null), "A variable in array list is null");
		return post(ICtrMaximum.buildFrom(scope(list, index, condition), varEntities.compactOrdered(list), startIndex, index, rank, condition));
	}

	@Override
	public CtrEntity maximum(XNode[] trees, Condition condition) {
		return (CtrEntity) unimplementedCase();
	}

	// ************************************************************************
	// ***** Constraint minimum
	// ************************************************************************

	@Override
	public CtrEntity minimum(Var[] list, Condition condition) {
		return post(ICtrMinimum.buildFrom(scope(list, condition), varEntities.compact(clean(list)), null, null, null, condition));

	}

	@Override
	public CtrEntity minimum(Var[] list, int startIndex, Var index, TypeRank rank) {
		Utilities.control(Stream.of(list).noneMatch(x -> x == null), "A variable in array list is null");
		return post(ICtrMinimum.buildFrom(scope(list, index), varEntities.compactOrdered(list), startIndex, index, rank, null));
	}

	@Override
	public CtrEntity minimum(Var[] list, int startIndex, Var index, TypeRank rank, Condition condition) {
		Utilities.control(Stream.of(list).noneMatch(x -> x == null), "A variable in array list is null");
		return post(ICtrMinimum.buildFrom(scope(list, index, condition), varEntities.compactOrdered(list), startIndex, index, rank, condition));
	}

	@Override
	public CtrEntity minimum(XNode[] trees, Condition condition) {
		return (CtrEntity) unimplementedCase();
	}

	// ************************************************************************
	// ***** Constraint element
	// ************************************************************************

	@Override
	public CtrEntity element(Var[] list, Condition condition) {
		return post(ICtrElement.buildFrom(list, varEntities.compact(list), null, null, null, condition));
	}

	@Override
	public CtrEntity element(Var[] list, int startIndex, Var index, TypeRank rank, Condition condition) {
		return post(ICtrElement.buildFrom(scope(list, index), varEntities.compactOrdered(list), startIndex, index, rank, condition));
	}

	@Override
	public CtrEntity element(int[] list, int startIndex, Var index, TypeRank rank, Condition condition) {
		return post(ICtrElement.buildFrom(scope(index, condition), Utilities.join(list), startIndex, index, rank, condition));
	}

	@Override
	public CtrEntity element(int[][] matrix, int startRowIndex, Var rowIndex, int startColIndex, Var colIndex, Condition condition) {
		return post(ICtrElementMatrix.buildFrom(vars(rowIndex, colIndex, condition), ICtrExtension.tableAsString(matrix), startRowIndex, rowIndex,
				startColIndex, colIndex, condition));
	}

	// ************************************************************************
	// ***** Constraint channel
	// ************************************************************************

	@Override
	public CtrEntity channel(Var[] list, int startIndex) {
		return post(ICtrChannel.buildFrom(list, varEntities.compactOrdered(list), startIndex, null, null, null));
	}

	@Override
	public CtrEntity channel(Var[] list1, int startIndex1, Var[] list2, int startIndex2) {
		return post(ICtrChannel.buildFrom(scope(list1, list2), varEntities.compactOrdered(list1), startIndex1, varEntities.compactOrdered(list2), startIndex2,
				null));
	}

	@Override
	public CtrEntity channel(Var[] list, int startIndex, Var value) {
		return post(ICtrChannel.buildFrom(list, varEntities.compactOrdered(list), startIndex, null, null, value));
	}

	// ************************************************************************
	// ***** Constraint stretch
	// ************************************************************************

	@Override
	public CtrEntity stretch(Var[] list, int[] values, int[] widthsMin, int[] widthsMax, int[][] patterns) {
		control(values.length == widthsMin.length && values.length == widthsMax.length, "The length of the arrays are not compatible.");
		control(IntStream.range(0, values.length).allMatch(i -> widthsMin[i] <= widthsMax[i]), "a min width is greater than a max width");
		control(patterns == null || Stream.of(patterns).allMatch(t -> t.length == 2), "");
		String t = patterns == null ? null : ICtrExtension.tableAsString(Table.clean(patterns));
		return post(ICtrStretch.buildFrom(list, varEntities.compactOrdered(list), Utilities.join(values), intervalAsString(widthsMin, widthsMax), t));
	}

	// ************************************************************************
	// ***** Constraint noOverlap
	// ************************************************************************

	@Override
	public CtrEntity noOverlap(Var[] origins, int[] lengths, boolean zeroIgnored) {
		return post(ICtrNoOverlap.buildFrom(origins, varEntities.compactOrdered(origins), Utilities.join(lengths), zeroIgnored));
	}

	@Override
	public CtrEntity noOverlap(Var[] origins, Var[] lengths, boolean zeroIgnored) {
		return post(ICtrNoOverlap.buildFrom(scope(origins, lengths), varEntities.compactOrdered(origins), varEntities.compactOrdered(lengths), zeroIgnored));
	}

	@Override
	public CtrEntity noOverlap(Var[][] origins, int[][] lengths, boolean zeroIgnored) {
		return post(ICtrNoOverlap.buildFrom(scope(origins, lengths), varEntities.compactMatrix(origins), "(" + Utilities.join(lengths, ")(", ",") + ")",
				zeroIgnored));
	}

	@Override
	public CtrEntity noOverlap(Var[][] origins, Var[][] lengths, boolean zeroIgnored) {
		return post(ICtrNoOverlap.buildFrom(scope(origins, lengths), varEntities.compactMatrix(origins), "(" + Utilities.join(lengths, ")(", ",") + ")",
				zeroIgnored));
	}

	// ************************************************************************
	// ***** Constraint cumulative
	// ************************************************************************

	@Override
	public final CtrEntity cumulative(Var[] origins, int[] lengths, Var[] ends, int[] heights, Condition condition) {
		return post(ICtrCumulative.buildFrom(scope(origins, ends, condition), varEntities.compactOrdered(origins), Utilities.join(lengths),
				ends == null ? null : varEntities.compactOrdered(ends), Utilities.join(heights), condition));
	}

	@Override
	public final CtrEntity cumulative(Var[] origins, Var[] lengths, Var[] ends, int[] heights, Condition condition) {
		return post(ICtrCumulative.buildFrom(scope(origins, lengths, ends, condition), varEntities.compactOrdered(origins), varEntities.compactOrdered(lengths),
				ends == null ? null : varEntities.compactOrdered(ends), Utilities.join(heights), condition));
	}

	@Override
	public final CtrEntity cumulative(Var[] origins, int[] lengths, Var[] ends, Var[] heights, Condition condition) {
		return post(ICtrCumulative.buildFrom(scope(origins, ends, heights, condition), varEntities.compactOrdered(origins), Utilities.join(lengths),
				ends == null ? null : varEntities.compactOrdered(ends), varEntities.compactOrdered(heights), condition));
	}

	@Override
	public final CtrEntity cumulative(Var[] origins, Var[] lengths, Var[] ends, Var[] heights, Condition condition) {
		return post(ICtrCumulative.buildFrom(scope(origins, lengths, ends, heights, condition), varEntities.compactOrdered(origins),
				varEntities.compactOrdered(lengths), ends == null ? null : varEntities.compactOrdered(ends), varEntities.compactOrdered(heights), condition));
	}

	// ************************************************************************
	// ***** Constraint circuit
	// ************************************************************************

	@Override
	public CtrEntity circuit(Var[] list, int startIndex) {
		return post(ICtrCircuit.buildFrom(list, varEntities.compactOrdered(list), startIndex, null));
	}

	@Override
	public CtrEntity circuit(Var[] list, int startIndex, int size) {
		return post(ICtrCircuit.buildFrom(list, varEntities.compactOrdered(list), startIndex, size));
	}

	@Override
	public CtrEntity circuit(Var[] list, int startIndex, Var size) {
		return post(ICtrCircuit.buildFrom(scope(list, size), varEntities.compactOrdered(list), startIndex, size));
	}

	// ************************************************************************
	// ***** Constraint clause
	// ************************************************************************

	@Override
	public CtrEntity clause(Var[] list, Boolean[] phases) {
		Utilities.control(Stream.of(list).noneMatch(x -> x == null), "A variable in array list is null");
		Utilities.control(list.length == phases.length && list.length > 0, "Bad form of clause.");
		String s = IntStream.range(0, list.length).mapToObj(i -> phases[i] ? list[i].id() : "not(" + list[i].id() + ")").collect(Collectors.joining(" "));
		return post(ICtrClause.buildFrom(list, s));
	}

	// ************************************************************************
	// ***** Constraint instantiation
	// ************************************************************************

	@Override
	public CtrEntity instantiation(Var[] list, int[] values) {
		Utilities.control(list.length == values.length && list.length > 0, "Bad form of instantiation.");
		return post(ICtrInstantiation.buildFrom(list, varEntities.compactOrdered(list), Utilities.join(values)));
	}

	// ************************************************************************
	// ***** Meta-Constraint slide
	// ************************************************************************

	private int[] computeOffsets(IVar[][] lists, IVar[] scp0, IVar[] scp1) {
		return IntStream.range(0, lists.length).map(i -> {
			int pos0 = Stream.of(scp0).filter(x -> Utilities.indexOf(x, lists[i]) >= 0).mapToInt(x -> Utilities.indexOf(x, lists[i])).min().orElse(-1);
			int pos1 = Stream.of(scp1).filter(x -> Utilities.indexOf(x, lists[i]) >= 0).mapToInt(x -> Utilities.indexOf(x, lists[i])).min().orElse(-1);
			Utilities.control(pos0 != -1 && pos1 != -1, "");
			return pos1 - pos0;
		}).toArray();
	}

	private int[] computeCollects(IVar[][] lists, IVar[] scp) {
		return IntStream.range(0, lists.length).map(i -> (int) Stream.of(scp).filter(x -> Utilities.indexOf(x, lists[i]) >= 0).count()).toArray();
	}

	@Override
	public CtrEntity slide(IVar[] list, Range range, IntFunction template) {
		Utilities.control(range.start == 0 && range.length() > 0, "Bad form of range");
		if (range.length() == 1)
			return template.apply(0);
		CtrAlone[] cas = range.stream().mapToObj(i -> template.apply(i)).toArray(CtrAlone[]::new);
		for (int i = cas.length - 1; i >= 0; i--) { // we remove them since a slide is posted (necessary for saving into
													// XCSP3)
			ctrEntities.allEntities.remove(cas[i]);
			ctrEntities.ctrToCtrAlone.remove(cas[i].ctr);
		}
		IVar[][] scopes = Stream.of(cas).map(ca -> ca.ctr.scope()).toArray(IVar[][]::new);
		Utilities.control(IntStream.range(1, scopes.length).noneMatch(i -> scopes[i].length != scopes[0].length), "");
		IVar[][] lists = new IVar[][] { list };
		boolean circular = Stream.of(scopes[scopes.length - 1]).anyMatch(x -> x == lists[0][0]);
		int[] offsets = computeOffsets(lists, scopes[0], scopes[1]);
		int[] collects = computeCollects(lists, scopes[0]);
		// todo many other controls to do
		return post(ICtrSlide.buildFrom(list, circular, lists, offsets, collects, cas));
	}

	// ************************************************************************
	// ***** Meta-Constraint ifThen
	// ************************************************************************

	@Override
	public final CtrEntity ifThen(CtrEntity c1, CtrEntity c2) {
		Utilities.control(c1 instanceof CtrAlone && c2 instanceof CtrAlone, "unimplemented for the moment");
		for (CtrEntity c : new CtrEntity[] { c2, c1 }) { // we remove them
			ctrEntities.allEntities.remove(c);
			ctrEntities.ctrToCtrAlone.remove(((CtrAlone) c).ctr);
		}
		return post(ICtrIfThen.buildFrom(scope(((CtrAlone) c1).ctr.scope(), ((CtrAlone) c2).ctr.scope()), (CtrAlone) c1, (CtrAlone) c2));
	}

	// ************************************************************************
	// ***** Meta-Constraint ifThenElse
	// ************************************************************************

	@Override
	public final CtrEntity ifThenElse(CtrEntity c1, CtrEntity c2, CtrEntity c3) {
		Utilities.control(c1 instanceof CtrAlone && c2 instanceof CtrAlone && c3 instanceof CtrAlone, "unimplemented for the moment");
		for (CtrEntity c : new CtrEntity[] { c3, c2, c1 }) { // we remove them
			ctrEntities.allEntities.remove(c);
			ctrEntities.ctrToCtrAlone.remove(((CtrAlone) c).ctr);
		}
		return post(ICtrIfThenElse.buildFrom(scope(((CtrAlone) c1).ctr.scope(), ((CtrAlone) c2).ctr.scope(), ((CtrAlone) c3).ctr.scope()), (CtrAlone) c1,
				(CtrAlone) c2, (CtrAlone) c3));
	}

	// ************************************************************************
	// ***** Managing objectives
	// ************************************************************************

	public ObjEntity postObj(IObj o) {
		return objEntities.new ObjEntity(o);
	}

	@Override
	public final ObjEntity minimize(IVar x) {
		return postObj(IObjFunctional.buildFrom(scope(x), true, new XNodeLeaf<>(TypeExpr.VAR, x)));
	}

	@Override
	public final ObjEntity maximize(IVar x) {
		return postObj(IObjFunctional.buildFrom(scope(x), false, new XNodeLeaf<>(TypeExpr.VAR, x)));
	}

	@Override
	public final ObjEntity minimize(XNode tree) {
		return postObj(IObjFunctional.buildFrom(tree.vars(), true, tree));
	}

	@Override
	public final ObjEntity maximize(XNode tree) {
		return postObj(IObjFunctional.buildFrom(tree.vars(), false, tree));
	}

	@Override
	public final ObjEntity minimize(TypeObjective type, IVar[] list) {
		return postObj(IObjSpecialized.buildFrom(list, true, type, varEntities.compactOrdered(list), null));
	}

	@Override
	public final ObjEntity maximize(TypeObjective type, IVar[] list) {
		return postObj(IObjSpecialized.buildFrom(list, false, type, varEntities.compactOrdered(list), null));
	}

	@Override
	public final ObjEntity minimize(TypeObjective type, IVar[] list, int[] coeffs) {
		return postObj(IObjSpecialized.buildFrom(list, true, type, varEntities.compactOrdered(list), Utilities.join(coeffs)));
	}

	@Override
	public final ObjEntity maximize(TypeObjective type, IVar[] list, int[] coeffs) {
		return postObj(IObjSpecialized.buildFrom(list, false, type, varEntities.compactOrdered(list), Utilities.join(coeffs)));
	}

	private ObjEntity optimizeTreeBasedObjective(boolean minimize, TypeObjective type, XNode[] trees, String coeffs) {
		String s = Stream.of(trees).map(t -> t.toString()).collect(Collectors.joining(" "));
		return postObj(IObjSpecialized.buildFrom(scope(Stream.of(trees).map(t -> t.vars())), minimize, type, s, coeffs));
	}

	@Override
	public ObjEntity minimize(TypeObjective type, XNode[] trees) {
		return optimizeTreeBasedObjective(true, type, trees, null);
	}

	@Override
	public ObjEntity minimize(TypeObjective type, XNode[] trees, int[] coeffs) {
		return optimizeTreeBasedObjective(true, type, trees, Utilities.join(coeffs));
	}

	@Override
	public ObjEntity maximize(TypeObjective type, XNode[] trees) {
		return optimizeTreeBasedObjective(false, type, trees, null);
	}

	@Override
	public ObjEntity maximize(TypeObjective type, XNode[] trees, int[] coeffs) {
		return optimizeTreeBasedObjective(false, type, trees, Utilities.join(coeffs));
	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy