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

org.chocosolver.parser.xcsp.tools.XDomains Maven / Gradle / Ivy

package org.chocosolver.parser.xcsp.tools;

import org.chocosolver.parser.xcsp.tools.XValues.*;
import org.chocosolver.parser.xcsp.tools.XVariables.TypeVar;
import org.chocosolver.parser.xcsp.tools.XVariables.Var;

import java.util.Arrays;
import java.util.stream.IntStream;
import java.util.stream.Stream;

import static org.chocosolver.parser.xcsp.tools.XVariables.TypeVar.*;

/** In this class, we find intern classes for managing all types of domains. */
public class XDomains {

	/** The root interface to tag domain objects. */
	public static interface Dom {
	}

	/** A class for representing basic domains, i.e. domains for integer, symbolic, real and stochastic variables. */
	public static class DomBasic implements Dom {

		/** Returns the basic domain obtained by parsing the specified string, according to the value of the specified type. */
		public static DomBasic parse(String s, TypeVar type) {
			return type == integer ? new DomInteger(s) : type == symbolic ? new DomSymbolic(s) : type == real ? new DomReal(s) : DomStochastic.parse(s, type);
		}

		/** Returns the sequence of basic domains for the variables in the specified array. */
		public static DomBasic[] domainsFor(Var[] vars) {
			return Stream.of(vars).map(x -> ((DomBasic) x.dom)).toArray(DomBasic[]::new);
		}

		/**
		 * Returns the sequence of basic domains for the variables in the first row of the specified two-dimensional array, provided that variables of the other
		 * rows have similar domains. Returns null otherwise.
		 */
		public static DomBasic[] domainsFor(Var[][] varss) {
			DomBasic[] doms = domainsFor(varss[0]);
			for (Var[] vars : varss)
				if (IntStream.range(0, vars.length).anyMatch(i -> doms[i] != vars[i].dom))
					return null;
			return doms;
		}

		/**
		 * The values of the domain: for an integer domain, values are IntegerEntity, for a symbolic domain, values are String, and for a float domain, values
		 * are RealInterval.
		 */
		public final Object[] values;

		/** Builds a basic domain, with the specified values. */
		protected DomBasic(Object[] values) {
			this.values = values;
		}

		@Override
		public String toString() {
			return "Values: " + XUtility.join(values);
		}
	}

	/** The class for representing the domain of an integer variable. */
	public static class DomInteger extends DomBasic {

		/** Builds an integer domain, with the integer values (entities that are either integers or integer intervals) obtained by parsing the specified string. */
		protected DomInteger(String seq) {
			super(IntegerEntity.parseSeq(seq)); // must be already sorted.
		}

		/** Returns the first (smallest) value of the domain. It may be VAL_M_INFINITY for -infinity. */
		public long getFirstValue() {
			return ((IntegerEntity) values[0]).smallest();
		}

		/** Returns the last (greatest) value of the domain. It may be VAL_P_INFINITY for +infinity. */
		public long getLastValue() {
			return ((IntegerEntity) values[values.length - 1]).greatest();
		}

		/** Returns the smallest (the most efficient in term of space consumption) primitive that can be used for representing any value of the domain. */
		public TypePrimitive whichPrimitive() {
			return TypePrimitive.whichPrimitiveFor(getFirstValue(), getLastValue());
		}

		/** Returns true iff the domain contains the specified value. */
		public boolean contains(long v) {
			for (int left = 0, right = values.length - 1; left <= right;) {
				int center = (left + right) / 2;
				int res = ((IntegerEntity) values[center]).compareContains(v);
				if (res == 0)
					return true;
				if (res == -1)
					left = center + 1;
				else
					right = center - 1;
			}
			return false;
		}

		private Long nbValues; // cache for lazy initialization

		/** Returns the number of values in the domain, if the domain is finite. Return -1 otherwise. */
		public long getNbValues() {
			if (nbValues != null)
				return nbValues;
			if (getFirstValue() == XConstants.VAL_M_INFINITY || getLastValue() == XConstants.VAL_P_INFINITY)
				return nbValues = -1L; // infinite number of values
			long cnt = 0;
			for (IntegerEntity entity : (IntegerEntity[]) values)
				if (entity instanceof IntegerValue)
					cnt++;
				else {
					long diff = entity.width(), l = cnt + diff;
					XUtility.control(cnt == l - diff, "Overflow");
					cnt = l;
				}
			return nbValues = cnt;
		}
	}

	/** The class for representing the domain of a symbolic variable. */
	public static final class DomSymbolic extends DomBasic {

		/** Builds a symbolic domain, with the symbols obtained by parsing the specified string. */
		protected DomSymbolic(String seq) {
			super(XUtility.sort(seq.split("\\s+")));
		}

		/** Returns true iff the domain contains the specified value. */
		protected boolean contains(String s) {
			return Arrays.binarySearch((String[]) values, s) >= 0;
		}
	}

	/** The class for representing the domain of a real variable. */
	public static class DomReal extends DomBasic {

		/** Builds a real domain, with the intervals obtained by parsing the specified string. */
		protected DomReal(String seq) {
			super(RealInterval.parseSeq(seq));
		}
	}

	/** The class for representing the domain of a stochastic variable. */
	public static final class DomStochastic extends DomBasic {
		/** Returns the stochastic domain obtained by parsing the specified string, according to the specified type. */
		public static DomStochastic parse(String s, TypeVar type) {
			String[] toks = s.split("\\s+");
			Object[] values = new Object[toks.length];
			SimpleValue[] probas = new SimpleValue[toks.length];
			for (int i = 0; i < toks.length; i++) {
				String[] t = toks[i].split(":");
				values[i] = type == TypeVar.symbolic_stochastic ? t[0] : IntegerEntity.parse(t[0]);
				probas[i] = SimpleValue.parse(t[1]);
			}
			return new DomStochastic(values, probas);
		}

		/**
		 * The probabilities associated with the values of the domain: probas[i] is the probability of values[i]. Probabilities can be given as rational,
		 * decimal, or integer values (only, 0 and 1 for integer).
		 */
		public final SimpleValue[] probas;

		/** Builds a stochastic domain, with the specified values and the specified probabilities. */
		protected DomStochastic(Object[] values, SimpleValue[] probas) {
			super(values);
			this.probas = probas;
			assert values.length == probas.length;
		}

		@Override
		public String toString() {
			return super.toString() + " Probas: " + XUtility.join(probas);
		}
	}

	/** The interface to tag complex domains, i.e. domains for set or graph variables. */
	public static interface DomComplex extends Dom {
	}

	/** The class for representing the domain of a set variable. */
	public static final class DomSet implements DomComplex {
		/** Returns the set domain obtained by parsing the specified strings, according to the specified type. */
		public static DomSet parse(String req, String pos, TypeVar type) {
			return type == TypeVar.set ? new DomSet(IntegerEntity.parseSeq(req), IntegerEntity.parseSeq(pos))
					: new DomSet(req.split("\\s+"), pos.split("\\s+"));
		}

		/** The required and possible values. For an integer set domain, values are IntegerEntity. For a symbolic set domain, values are String. */
		public final Object[] required, possible;

		/** Builds a set domain, with the specified required and possible values. */
		protected DomSet(Object[] required, Object[] possible) {
			this.required = required;
			this.possible = possible;
		}

		@Override
		public String toString() {
			return "[{" + XUtility.join(required) + "},{" + XUtility.join(possible) + "}]";
		}
	}

	/** The class for representing the domain of a graph variable. */
	public static final class DomGraph implements DomComplex {
		/** Returns the graph domain obtained by parsing the specified strings, according to the specified type. */
		public static DomGraph parse(String reqV, String reqE, String posV, String posE, TypeVar type) {
			String[] rV = reqV.split("\\s+"), pV = posV.split("\\s+");
			String[][] rE = Stream.of(reqE.split(XConstants.DELIMITER_LISTS)).skip(1).map(tok -> tok.split("\\s*,\\s*")).toArray(String[][]::new);
			String[][] pE = Stream.of(posE.split(XConstants.DELIMITER_LISTS)).skip(1).map(tok -> tok.split("\\s*,\\s*")).toArray(String[][]::new);
			return new DomGraph(rV, pV, rE, pE);
		}

		/** The required and possible nodes (vertices). */
		public final String[] requiredV, possibleV;

		/** The required and possible edges or arcs. */
		public final String[][] requiredE, possibleE;

		/** Builds a graph domain, with the specified required and possible values (nodes and edges/arcs). */
		protected DomGraph(String[] requiredV, String[] possibleV, String[][] requiredE, String[][] possibleE) {
			this.requiredV = requiredV;
			this.possibleV = possibleV;
			this.requiredE = requiredE;
			this.possibleE = possibleE;
		}

		@Override
		public String toString() {
			return "[{" + XUtility.join(requiredV) + "-" + XUtility.join(requiredE) + "},{" + XUtility.join(possibleV) + "-" + XUtility.join(possibleE) + "}]";
		}
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy