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

org.chocosolver.solver.variables.IVariableFactory Maven / Gradle / Ivy

The newest version!
/*
 * This file is part of choco-solver, http://choco-solver.org/
 *
 * Copyright (c) 2025, 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.solver.variables;

import org.chocosolver.solver.ISelf;
import org.chocosolver.solver.Model;
import org.chocosolver.solver.exception.SolverException;
import org.chocosolver.solver.variables.impl.*;
import org.chocosolver.util.objects.graphs.DirectedGraph;
import org.chocosolver.util.objects.graphs.UndirectedGraph;
import org.chocosolver.util.objects.setDataStructures.SetType;
import org.chocosolver.util.tools.ArrayUtils;
import org.chocosolver.util.tools.VariableUtils;

/**
 * Interface to make variables (BoolVar, IntVar, RealVar, SetVar, and GraphVar)
 * 

* A kind of factory relying on interface default implementation to allow (multiple) inheritance * * @author Jean-Guillaume FAGES * @author Charles Prud'homme * @since 4.0.0 */ @SuppressWarnings("unused") public interface IVariableFactory extends ISelf { /** * Default prefix for constants */ String CSTE_NAME = "cste -- "; String DEFAULT_PREFIX = "TMP_"; //************************************************************************************* // BOOLEAN VARIABLES //************************************************************************************* /** * Create a constant boolean variable equal to 1 if value is true and 0 otherwise * * @param value constant value of the boolean variable (true or false) * @return a constant of type BoolVar */ default BoolVar boolVar(boolean value) { return boolVar(CSTE_NAME + (value ? 1 : 0), value); } /** * Create a constant boolean variable equal to 1 if value is true and 0 otherwise * * @param name name of the variable * @param value constant value of the boolean variable (true or false) * @return a constant of type BoolVar */ default BoolVar boolVar(String name, boolean value) { int intVal = value ? 1 : 0; if (name.equals(CSTE_NAME + intVal) && ref().getCachedConstants().containsKey(intVal)) { return (BoolVar) ref().getCachedConstants().get(intVal); } BoolVar cste; if (ref().getSolver().isLCG()) { cste = new BoolVarEagerLit(name, ref(), intVal, intVal); } else { cste = new FixedBoolVarImpl(name, intVal, ref()); } if (name.equals(CSTE_NAME + intVal)) { ref().getCachedConstants().put(intVal, cste); } return cste; } /** * Create a boolean variable, i.e. a particular integer variable of domain {0, 1} * * @return a BoolVar of domain {0, 1} */ default BoolVar boolVar() { return boolVar(generateName("BV_")); } /** * Create a boolean variable * * @param name name of the variable * @return a BoolVar of domain {0, 1} */ default BoolVar boolVar(String name) { BoolVar bvar; if (ref().getSolver().isLCG()) { bvar = new BoolVarEagerLit(name, ref(), 0, 1); } else { bvar = new BoolVarImpl(name, ref()); } return bvar; } // ARRAY /** * Create an array of size boolean variables * * @param size number of variable to create * @return an array of size BoolVar of domain {0, 1} */ default BoolVar[] boolVarArray(int size) { return boolVarArray(generateName("BV_"), size); } /** * Create an array of size boolean variables * * @param name prefix name of the variables to create. The ith variable will be named name[i] * @param size number of variable to create * @return an array of size BoolVar of domain {0, 1} */ default BoolVar[] boolVarArray(String name, int size) { BoolVar[] vars = new BoolVar[size]; for (int i = 0; i < size; i++) { vars[i] = boolVar(name + "[" + i + "]"); } return vars; } // MATRIX /** * Create a dim1*dim2-sized matrix of boolean variables * * @param dim1 number of rows in the matrix * @param dim2 number of columns in the matrix * @return a matrix of dim1*dim2 BoolVar of domain {0, 1} */ default BoolVar[][] boolVarMatrix(int dim1, int dim2) { return boolVarMatrix(generateName("BV_"), dim1, dim2); } /** * Create a dim1*dim2-sized matrix of boolean variables * * @param name prefix name of the variables to create. The variable in row i and col j will be named name[i][j] * @param dim1 number of rows in the matrix * @param dim2 number of columns in the matrix * @return a matrix of dim1*dim2 BoolVar of domain {0, 1} */ default BoolVar[][] boolVarMatrix(String name, int dim1, int dim2) { BoolVar[][] vars = new BoolVar[dim1][]; for (int i = 0; i < dim1; i++) { vars[i] = boolVarArray(name + "[" + i + "]", dim2); } return vars; } //************************************************************************************* // INTEGER VARIABLES //************************************************************************************* // SINGLE /** * Create a constant integer variable equal to value * * @param value constant value of the variable * @return a constant IntVar of domain {value} */ default IntVar intVar(int value) { return intVar(CSTE_NAME + value, value); } /** * Create an integer variable of initial domain values. * Uses an enumerated domain that supports holes * * @param values initial domain of the variable * @return an IntVar of domain values */ default IntVar intVar(int[] values) { return intVar(generateName("IV_"), values); } /** * Create an integer variable of initial domain [lb, ub] * Uses an enumerated domain if ub-lb is small, and a bounded domain otherwise * * @param lb initial domain lower bound * @param ub initial domain upper bound * @return an IntVar of domain [lb, ub] * @implNote When boundedDomain is selected only bounds modifications are handled * (any value removals in the middle of the domain will be ignored). */ default IntVar intVar(int lb, int ub) { if (lb == ub) return intVar(lb); return intVar(generateName("IV_"), lb, ub); } /** * Create an integer variable of initial domain [lb, ub] * * @param lb initial domain lower bound * @param ub initial domain upper bound * @param boundedDomain specifies whether to use a bounded domain or an enumerated domain. * When 'boundedDomain' only bounds modifications are handled * (any value removals in the middle of the domain will be ignored). * @return an IntVar of domain [lb, ub] */ default IntVar intVar(int lb, int ub, boolean boundedDomain) { if (lb == ub) return intVar(lb); return intVar(generateName("IV_"), lb, ub, boundedDomain); } /** * Create a constant integer variable equal to value * * @param name name of the variable * @param value value of the variable * @return a constant IntVar of domain {value} */ default IntVar intVar(String name, int value) { checkIntDomainRange(name, value, value); if (value == 0 || value == 1) { return boolVar(name, value == 1); } if (name.equals(CSTE_NAME + value) && ref().getCachedConstants().containsKey(value)) { return ref().getCachedConstants().get(value); } IntVar cste = new FixedIntVarImpl(name, value, ref()); if (ref().getSolver().isLCG()) { cste = new IntVarEagerLit(cste); } if (name.equals(CSTE_NAME + value)) { ref().getCachedConstants().put(value, cste); } return cste; } /** * Create an integer variable of initial domain [lb, ub] * * @param name name of the variable * @param lb initial domain lower bound * @param ub initial domain upper bound * @param boundedDomain specifies whether to use a bounded domain or an enumerated domain. * When 'boundedDomain' only bounds modifications are handled * (any value removals in the middle of the domain will be ignored). * @return an IntVar of domain [lb, ub] */ default IntVar intVar(String name, int lb, int ub, boolean boundedDomain) { checkIntDomainRange(name, lb, ub); if (lb == ub) { return intVar(name, lb); } else if (lb == 0 && ub == 1) { return boolVar(name); } else if (boundedDomain) { IntVar v = new IntervalIntVarImpl(name, lb, ub, ref()); if (ref().getSolver().isLCG()) { v = new IntVarLazyLit(v); } return v; } else { IntVar v = new BitsetIntVarImpl(name, lb, ub, ref()); if (ref().getSolver().isLCG()) { v = new IntVarEagerLit(v); } return v; } } /** * Create an integer variable of initial domain [lb, ub] * Uses an enumerated domain if ub-lb is small, and a bounded domain otherwise * * @param name name of the variable * @param lb initial domain lower bound * @param ub initial domain upper bound * @return an IntVar of domain [lb, ub] * @implNote When boundedDomain is selected only bounds modifications are handled * (any value removals in the middle of the domain will be ignored). */ default IntVar intVar(String name, int lb, int ub) { boolean bounded = ub - lb + 1 >= ref().getSettings().getMaxDomSizeForEnumerated(); return intVar(name, lb, ub, bounded); } /** * Create an integer variable of initial domain values * Uses an enumerated domain that supports holes * * @param name name of the variable * @param values initial domain * @return an IntVar of domain values */ default IntVar intVar(String name, int[] values) { values = ArrayUtils.mergeAndSortIfNot(values.clone()); checkIntDomainRange(name, values[0], values[values.length - 1]); if (values.length == 1) { return intVar(name, values[0]); } else if (values.length == 2 && values[0] == 0 && values[1] == 1) { return boolVar(name); } else { IntVar v = new BitsetIntVarImpl(name, values, ref()); if (ref().getSettings().isLCG()) { v = new IntVarEagerLit(v); } return v; } } /** * Create an integer variable of initial domain based on from. * * @param from variable to copy values from * @return a new variable whom domain is the same as the one of from */ default IntVar intVar(IntVar from) { String name = generateName("IV_"); if (from.hasEnumeratedDomain()) { int[] values = from.stream().toArray(); return intVar(name, values); } else { int lb = from.getLB(); int ub = from.getUB(); return intVar(name, lb, ub); } } /** * Create an integer variable of initial domain based on from. * * @param name name of the variable to create * @param from variable to copy values from * @return a new variable whom domain is the same as the one of from */ default IntVar intVar(String name, IntVar from) { if (from.hasEnumeratedDomain()) { int[] values = from.stream().toArray(); return intVar(name, values); } else { int lb = from.getLB(); int ub = from.getUB(); return intVar(name, lb, ub); } } // ARRAY /** * Creates an array of size integer variables, taking their domain in values * * @param size number of variables * @param values initial domain of each variable * @return an array of size IntVar of domain values */ default IntVar[] intVarArray(int size, int[] values) { return intVarArray(generateName("IV_"), size, values); } /** * Creates an array of size integer variables, taking their domain in [lb, ub] * Uses an enumerated domain if ub-lb is small, and a bounded domain otherwise * * @param size number of variables * @param lb initial domain lower bound of each variable * @param ub initial domain upper bound of each variable * @return an array of size IntVar of domain [lb, ub] * @implNote When boundedDomain is selected only bounds modifications are handled * (any value removals in the middle of the domain will be ignored). */ default IntVar[] intVarArray(int size, int lb, int ub) { return intVarArray(generateName("IV_"), size, lb, ub); } /** * Creates an array of size integer variables, taking their domain in [lb, ub] * * @param size number of variables * @param lb initial domain lower bound of each variable * @param ub initial domain upper bound of each variable * @param boundedDomain specifies whether to use bounded domains or enumerated domains for each variable. * When 'boundedDomain' only bounds modifications are handled * (any value removals in the middle of the domain will be ignored). * @return an array of size IntVar of domain [lb, ub] */ default IntVar[] intVarArray(int size, int lb, int ub, boolean boundedDomain) { return intVarArray(generateName("IV_"), size, lb, ub, boundedDomain); } /** * Creates an array of size integer variables, taking their domain in [lb, ub] * * @param name prefix name of the variables to create. The ith variable will be named name[i] * @param size number of variables * @param lb initial domain lower bound of each variable * @param ub initial domain upper bound of each variable * @param boundedDomain specifies whether to use bounded domains or enumerated domains for each variable. * When 'boundedDomain' only bounds modifications are handled * (any value removals in the middle of the domain will be ignored). * @return an array of size IntVar of domain [lb, ub] */ default IntVar[] intVarArray(String name, int size, int lb, int ub, boolean boundedDomain) { IntVar[] vars = new IntVar[size]; for (int i = 0; i < size; i++) { vars[i] = intVar(name + "[" + i + "]", lb, ub, boundedDomain); } return vars; } /** * Creates an array of size integer variables, taking their domain in [lb, ub] * Uses an enumerated domain if ub-lb is small, and a bounded domain otherwise * * @param name prefix name of the variables to create. The ith variable will be named name[i] * @param size number of variables * @param lb initial domain lower bound of each variable * @param ub initial domain upper bound of each variable * @return an array of size IntVar of domain [lb, ub] * @implNote When boundedDomain is selected only bounds modifications are handled * (any value removals in the middle of the domain will be ignored). */ default IntVar[] intVarArray(String name, int size, int lb, int ub) { IntVar[] vars = new IntVar[size]; for (int i = 0; i < size; i++) { vars[i] = intVar(name + "[" + i + "]", lb, ub); } return vars; } /** * Creates an array of size integer variables, taking their domain in values * * @param name prefix name of the variables to create. The ith variable will be named name[i] * @param size number of variables * @param values initial domain of each variable * @return an array of size IntVar of domain values */ default IntVar[] intVarArray(String name, int size, int[] values) { IntVar[] vars = new IntVar[size]; for (int i = 0; i < size; i++) { vars[i] = intVar(name + "[" + i + "]", values); } return vars; } // MATRIX /** * Creates a matrix of dim1*dim2 integer variables taking their domain in values * * @param dim1 number of rows in the matrix * @param dim2 number of columns in the matrix * @param values initial domain of each variable * @return a matrix of dim1*dim2 IntVar of domain values */ default IntVar[][] intVarMatrix(int dim1, int dim2, int[] values) { return intVarMatrix(generateName("IV_"), dim1, dim2, values); } /** * Creates a matrix of dim1*dim2 integer variables taking their domain in [lb, ub] * Uses an enumerated domain if ub-lb is small, and a bounded domain otherwise * * @param dim1 number of rows in the matrix * @param dim2 number of columns in the matrix * @param lb initial domain lower bound of each variable * @param ub initial domain upper bound of each variable * @return a matrix of dim1*dim2 IntVar of domain [lb, ub] * @implNote When boundedDomain is selected only bounds modifications are handled * (any value removals in the middle of the domain will be ignored). */ default IntVar[][] intVarMatrix(int dim1, int dim2, int lb, int ub) { return intVarMatrix(generateName("IV_"), dim1, dim2, lb, ub); } /** * Creates a matrix of dim1*dim2 integer variables taking their domain in [lb, ub] * * @param dim1 number of rows in the matrix * @param dim2 number of columns in the matrix * @param lb initial domain lower bound of each variable * @param ub initial domain upper bound of each variable * @param boundedDomain specifies whether to use bounded domains or enumerated domains for each variable. * When 'boundedDomain' only bounds modifications are handled * (any value removals in the middle of the domain will be ignored). * @return a matrix of dim1*dim2 IntVar of domain [lb, ub] */ default IntVar[][] intVarMatrix(int dim1, int dim2, int lb, int ub, boolean boundedDomain) { return intVarMatrix(generateName("IV_"), dim1, dim2, lb, ub, boundedDomain); } /** * Creates a matrix of dim1*dim2 integer variables taking their domain in [lb, ub] * * @param name prefix name of the variables to create. The variable in row i and col j will be named name[i][j] * @param dim1 number of rows in the matrix * @param dim2 number of columns in the matrix * @param lb initial domain lower bound of each variable * @param ub initial domain upper bound of each variable * @param boundedDomain specifies whether to use bounded domains or enumerated domains for each variable. * When 'boundedDomain' only bounds modifications are handled * (any value removals in the middle of the domain will be ignored). * @return a matrix of dim1*dim2 IntVar of domain [lb, ub] */ default IntVar[][] intVarMatrix(String name, int dim1, int dim2, int lb, int ub, boolean boundedDomain) { IntVar[][] vars = new IntVar[dim1][dim2]; for (int i = 0; i < dim1; i++) { vars[i] = intVarArray(name + "[" + i + "]", dim2, lb, ub, boundedDomain); } return vars; } /** * Creates a matrix of dim1*dim2 integer variables taking their domain in [lb, ub] * Uses an enumerated domain if ub-lb is small, and a bounded domain otherwise * * @param name prefix name of the variables to create. The variable in row i and col j will be named name[i][j] * @param dim1 number of rows in the matrix * @param dim2 number of columns in the matrix * @param lb initial domain lower bound of each variable * @param ub initial domain upper bound of each variable * @return a matrix of dim1*dim2 IntVar of domain [lb, ub] * @implNote When boundedDomain is selected only bounds modifications are handled * (any value removals in the middle of the domain will be ignored). */ default IntVar[][] intVarMatrix(String name, int dim1, int dim2, int lb, int ub) { IntVar[][] vars = new IntVar[dim1][dim2]; for (int i = 0; i < dim1; i++) { vars[i] = intVarArray(name + "[" + i + "]", dim2, lb, ub); } return vars; } /** * Creates a matrix of dim1*dim2 integer variables taking their domain in values * * @param name prefix name of the variables to create. The variable in row i and col j will be named name[i][j] * @param dim1 number of rows in the matrix * @param dim2 number of columns in the matrix * @param values initial domain of each variable * @return a matrix of dim1*dim2 IntVar of domain values */ default IntVar[][] intVarMatrix(String name, int dim1, int dim2, int[] values) { IntVar[][] vars = new IntVar[dim1][dim2]; for (int i = 0; i < dim1; i++) { vars[i] = intVarArray(name + "[" + i + "]", dim2, values); } return vars; } //************************************************************************************* // TASK VARIABLES //************************************************************************************* /** * Creates a task variable, based on a starting time s and a duration d * such that: s + d = e, where e is the ending time. *

* A call to {@link Task#ensureBoundConsistency()} is required before launching the resolution, * this will not be done automatically. * * @param s integer variable, starting time * @param d fixed duration * @return a task variable. */ default Task taskVar(IntVar s, int d) { return new Task(s, d); } /** * Creates a task variable, based on a starting time s and a duration d * such that: s + d = e, where e is the ending time. *

* A call to {@link Task#ensureBoundConsistency()} is required before launching the resolution, * this will not be done automatically. * * @param s integer variable, starting time * @param d integer variable, duration * @return a task variable. */ default Task taskVar(IntVar s, IntVar d) { if (d.isInstantiated()) { return new Task(s, d, ref().offset(s, d.getValue())); } else { int[] bounds = VariableUtils.boundsForAddition(s, d); IntVar end = ref().intVar(bounds[0], bounds[1]); return new Task(s, d, end); } } /** * Creates a task variable, based on a starting time s and a duration d * such that: s + d = e, where e is the ending time. *

* A call to {@link Task#ensureBoundConsistency()} is required before launching the resolution, * this will not be done automatically. * * @param s integer variable, starting time * @param d fixed duration * @param e integer variable, ending time * @return a task variable. */ default Task taskVar(IntVar s, int d, IntVar e) { return new Task(s, d, e); } /** * Creates a task variable, made of a starting time s, * a duration d and an ending time e such that: s + d = e. *

* A call to {@link Task#ensureBoundConsistency()} is required before launching the resolution, * this will not be done automatically. * * @param s integer variable, starting time * @param d integer variable, duration * @param e integer variable, ending time * @return a task variable. */ default Task taskVar(IntVar s, IntVar d, IntVar e) { return new Task(s, d, e); } /** * Creates an array of s.length task variables, * where task i is made of a starting time s_i, * a processing time p_i and an ending time e_i such that: s_i + p_i = e_i. *

* A call to {@link Task#ensureBoundConsistency()} is required before launching the resolution, * this will not be done automatically. * * @param s integer variables, starting times * @param p integer variables, processing times * @param e integer variables, ending times * @return an array of task variables. */ default Task[] taskVarArray(IntVar[] s, IntVar[] p, IntVar[] e) { if (s.length != p.length || s.length != e.length) { throw new SolverException("Wrong arrays size"); } Task[] tasks = new Task[s.length]; for (int i = 0; i < s.length; i++) { tasks[i] = taskVar(s[i], p[i], e[i]); } return tasks; } /** * Creates a matrix of s.length * s_0.length task variables, * where task i,j is made of a starting time s_(i,j), * a processing time p_(i,j) and an ending time e_(i,j) such that: * s_(i,j) + p_(i,j) = e_(i,j). *

* A call to {@link Task#ensureBoundConsistency()} is required before launching the resolution, * this will not be done automatically. * * @param s integer variables, starting times * @param p integer variables, processing times * @param e integer variables, ending times * @return a matrix task variable. */ default Task[][] taskVarMatrix(IntVar[][] s, IntVar[][] p, IntVar[][] e) { if (s.length != p.length || s.length != e.length) { throw new SolverException("Wrong arrays size"); } Task[][] tasks = new Task[s.length][]; for (int i = 0; i < s.length; i++) { tasks[i] = taskVarArray(s[i], p[i], e[i]); } return tasks; } //************************************************************************************* // REAL VARIABLES //************************************************************************************* /** * Create a constant real variable equal to value * * @param value constant value of the variable * @return a constant RealVar of domain [value,value] */ default RealVar realVar(double value) { return realVar(CSTE_NAME + value, value); } /** * Create a constant real variable equal to value * * @param name name of the variable * @param value value of the variable * @return a constant RealVar of domain [value,value] */ default RealVar realVar(String name, double value) { return new FixedRealVarImpl(name, value, ref()); } /** * Creates a constant real variable equal to value * * @param value constant value of the variable * @param precision double precision (e.g., 0.00001d) * @return a constant RealVar of domain {value} */ default RealVar realVar(double value, double precision) { return realVar(CSTE_NAME + value, value, value, precision); } /** * Creates a real variable, taking its domain in [lb, ub] * * @param lb initial domain lower bound * @param ub initial domain upper bound * @param precision double precision (e.g., 0.00001d) * @return a RealVar of domain [lb, ub] */ default RealVar realVar(double lb, double ub, double precision) { return realVar(generateName("RV_"), lb, ub, precision); } /** * Creates a real variable, taking its domain in [lb, ub] * * @param name variable name * @param lb initial domain lower bound * @param ub initial domain upper bound * @param precision double precision (e.g., 0.00001d) * @return a RealVar of domain [lb, ub] */ default RealVar realVar(String name, double lb, double ub, double precision) { checkRealDomainRange(name, lb, ub); return new RealVarImpl(name, lb, ub, precision, ref()); } // ARRAY /** * Creates an array of size real variables, each of domain [lb, ub] * * @param size number of variables * @param lb initial domain lower bound * @param ub initial domain upper bound * @param precision double precision (e.g., 0.00001d) * @return an array of size RealVar of domain [lb, ub] */ default RealVar[] realVarArray(int size, double lb, double ub, double precision) { return realVarArray(generateName("RV_"), size, lb, ub, precision); } /** * Creates an array of size real variables, each of domain [lb, ub] * * @param name prefix name of the variables to create. The ith variable will be named name[i] * @param size number of variables * @param lb initial domain lower bound * @param ub initial domain upper bound * @param precision double precision (e.g., 0.00001d) * @return an array of size RealVar of domain [lb, ub] */ default RealVar[] realVarArray(String name, int size, double lb, double ub, double precision) { RealVar[] vars = new RealVar[size]; for (int i = 0; i < size; i++) { vars[i] = realVar(name + "[" + i + "]", lb, ub, precision); } return vars; } // MATRIX /** * Creates a matrix of dim1*dim2 real variables, each of domain [lb, ub] * * @param dim1 number of matrix rows * @param dim2 number of matrix columns * @param lb initial domain lower bound * @param ub initial domain upper bound * @param precision double precision (e.g., 0.00001d) * @return a matrix of dim1*dim2 RealVar of domain [lb, ub] */ default RealVar[][] realVarMatrix(int dim1, int dim2, double lb, double ub, double precision) { return realVarMatrix(generateName("RV_"), dim1, dim2, lb, ub, precision); } /** * Creates a matrix of dim1*dim2 real variables, each of domain [lb, ub] * * @param name prefix name of the variables to create. The variable in row i and col j will be named name[i][j] * @param dim1 number of matrix rows * @param dim2 number of matrix columns * @param lb initial domain lower bound * @param ub initial domain upper bound * @param precision double precision (e.g., 0.00001d) * @return a matrix of dim1*dim2 RealVar of domain [lb, ub] */ default RealVar[][] realVarMatrix(String name, int dim1, int dim2, double lb, double ub, double precision) { RealVar[][] vars = new RealVar[dim1][]; for (int i = 0; i < dim1; i++) { vars[i] = realVarArray(name + "[" + i + "]", dim2, lb, ub, precision); } return vars; } //************************************************************************************* // SET VARIABLES //************************************************************************************* /** * Creates a set variable taking its domain in [lb, ub], * For instance [{0,3},{-2,0,2,3}] means the variable must include both 0 and 3 and can additionnaly include -2, and 2 * * @param lb initial domain lower bound (contains mandatory elements that should be present in every solution) * @param ub initial domain upper bound (contains potential elements) * @return a SetVar of domain [lb, ub] */ default SetVar setVar(int[] lb, int[] ub) { return setVar(generateName("RV_"), lb, ub); } /** * Creates a constant set variable, equal to value * * @param value value of the set variable, e.g. {0,4,9} * @return a constant SetVar of domain {value} */ default SetVar setVar(int... value) { StringBuilder name = new StringBuilder(CSTE_NAME + "{"); for (int i = 0; i < value.length; i++) { name.append(value[i]).append(i < value.length - 1 ? ", " : ""); } name.append("}"); return setVar(name.toString(), value); } /** * Creates a set variable taking its domain in [lb, ub], * For instance [{0,3},{-2,0,2,3}] means the variable must include both 0 and 3 and can additionnaly include -2, and 2 * * @param name name of the variable * @param lb initial domain lower bound (contains mandatory elements that should be present in every solution) * @param ub initial domain upper bound (contains potential elements) * @return a SetVar of domain [lb, ub] */ default SetVar setVar(String name, int[] lb, int[] ub) { return new SetVarImpl(name, lb, SetType.BITSET, ub, SetType.BITSET, ref()); } /** * Creates a constant set variable, equal to value * * @param name name of the variable * @param value value of the set variable, e.g. {0,4,9} * @return a constant SetVar of domain {value} */ default SetVar setVar(String name, int... value) { if (value == null) value = new int[]{}; return new SetVarImpl(name, value, ref()); } // ARRAY /** * Creates an array of size set variables, taking their domain in [lb, ub] * * @param size number of variables * @param lb initial domain lower bound of every variable (contains mandatory elements that should be present in every solution) * @param ub initial domain upper bound of every variable (contains potential elements) * @return an array of size SetVar of domain [lb, ub] */ default SetVar[] setVarArray(int size, int[] lb, int[] ub) { return setVarArray(generateName("SV_"), size, lb, ub); } /** * Creates an array of size set variables, taking their domain in [lb, ub] * * @param name prefix name of the variables to create. The ith variable will be named name[i] * @param size number of variables * @param lb initial domain lower bound of every variable (contains mandatory elements that should be present in every solution) * @param ub initial domain upper bound of every variable (contains potential elements) * @return an array of size SetVar of domain [lb, ub] */ default SetVar[] setVarArray(String name, int size, int[] lb, int[] ub) { SetVar[] vars = new SetVar[size]; for (int i = 0; i < size; i++) { vars[i] = setVar(name + "[" + i + "]", lb, ub); } return vars; } // MATRIX /** * Creates a matrix of dim1*dim2 set variables, taking their domain in [lb, ub] * * @param dim1 number of rows in the matrix * @param dim2 number of columns in the matrix * @param lb initial domain lower bound of every variable (contains mandatory elements that should be present in every solution) * @param ub initial domain upper bound of every variable (contains potential elements) * @return a matrix of dim1*dim2 SetVar of domain [lb, ub] */ default SetVar[][] setVarMatrix(int dim1, int dim2, int[] lb, int[] ub) { return setVarMatrix(generateName("SV_"), dim1, dim2, lb, ub); } /** * Creates a matrix of dim1*dim2 set variables, taking their domain in [lb, ub] * * @param name prefix name of the variables to create. The variable in row i and col j will be named name[i][j] * @param dim1 number of rows in the matrix * @param dim2 number of columns in the matrix * @param lb initial domain lower bound of every variable (contains mandatory elements that should be present in every solution) * @param ub initial domain upper bound of every variable (contains potential elements) * @return a matrix of dim1*dim2 SetVar of domain [lb, ub] */ default SetVar[][] setVarMatrix(String name, int dim1, int dim2, int[] lb, int[] ub) { SetVar[][] vars = new SetVar[dim1][dim2]; for (int i = 0; i < dim1; i++) { vars[i] = setVarArray(name + "[" + i + "]", dim2, lb, ub); } return vars; } //************************************************************************************* // GRAPH VARIABLES //************************************************************************************* /** * Creates an undirected graph variable, taking its values in the graph domain [LB, UB]. * An instantiation of a graph variable is a graph composed of nodes and edges. * LB is the kernel graph (or lower bound), that must be a subgraph of any instantiation. * UB is the envelope graph (or upper bound), such that any instantiation is a subgraph of it. * * @param name Name of the variable * @param LB The lower bound graph (or kernel) * @param UB The upper bound graph (or envelope) * @return An undirected graph variable taking its values in the graph domain [LB, UB]. */ default UndirectedGraphVar graphVar(String name, UndirectedGraph LB, UndirectedGraph UB) { return new UndirectedGraphVarImpl(name, ref(), LB, UB); } /** * Creates a node-induced undirected graph variable guaranteeing that any instantiation is a node-induced subgraph * of the envelope used to construct the graph variable. Any two nodes that are connected in the envelope * are connected by an edge in any instantiation containing these two nodes. More formally: *

* - G = (V, E) \in [G_lb, G_ub], with G_ub = (V_ub, E_ub); * - E = { (x, y) \in E_ub | x \in V \land y \in V }. * * @param name Name of the variable * @param LB The lower bound graph (or kernel) * @param UB The upper bound graph (or envelope) * @return An undirected graph variable taking its values in the graph domain [LB, UB] and such that any value is * a node-induced subgraph of UB. */ default UndirectedNodeInducedGraphVarImpl nodeInducedGraphVar(String name, UndirectedGraph LB, UndirectedGraph UB) { return new UndirectedNodeInducedGraphVarImpl(name, ref(), LB, UB); } /** * Creates a directed graph variable, taking its values in the graph domain [LB, UB]. * An instantiation of a graph variable is a graph composed of nodes and edges. * LB is the kernel graph (or lower bound), that must be a subgraph of any instantiation. * UB is the envelope graph (or upper bound), such that any instantiation is a subgraph of it. * * @param name Name of the variable * @param LB The lower bound graph (or kernel) * @param UB The upper bound graph (or envelope) * @return A directed graph variable taking its values in the graph domain [LB, UB]. */ default DirectedGraphVar digraphVar(String name, DirectedGraph LB, DirectedGraph UB) { return new DirectedGraphVarImpl(name, ref(), LB, UB); } /** * Creates a node-induced directed graph variable guaranteeing that any instantiation is a node-induced subgraph * of the envelope used to construct the graph variable. Any two nodes that are connected in the envelope * are connected by an edge in any instantiation containing these two nodes. More formally: *

* - G = (V, E) \in [G_lb, G_ub], with G_ub = (V_ub, E_ub); * - E = { (x, y) \in E_ub | x \in V \land y \in V }. * * @param name Name of the variable * @param LB The lower bound graph (or kernel) * @param UB The upper bound graph (or envelope) * @return A directed graph variable taking its values in the graph domain [LB, UB] and such that any value is * a node-induced subgraph of UB. */ default DirectedNodeInducedGraphVarImpl nodeInducedDigraphVar(String name, DirectedGraph LB, DirectedGraph UB) { return new DirectedNodeInducedGraphVarImpl(name, ref(), LB, UB); } //************************************************************************************* // UTILS //************************************************************************************* /** * Checks domain range. * Throws an exception if wrong range definition * * @param NAME name of the variable * @param MIN lower bound of the domain * @param MAX upper bound of the domain */ default void checkIntDomainRange(String NAME, int MIN, int MAX) { if (MIN <= Integer.MIN_VALUE || MAX >= Integer.MAX_VALUE) { throw new SolverException(NAME + ": consider reducing the bounds to avoid unexpected results"); } if (MAX < MIN) { throw new SolverException(NAME + ": wrong domain definition, lower bound > upper bound"); } if ((long) MAX - MIN > Integer.MAX_VALUE) { throw new SolverException(NAME + ": too large domain, consider reducing the bounds to avoid unexpected results"); } } /** * Checks domain range. * Throws an exception if wrong range definition * * @param NAME name of the variable * @param MIN lower bound of the domain * @param MAX upper bound of the domain */ default void checkRealDomainRange(String NAME, double MIN, double MAX) { if (MAX < MIN) { throw new SolverException(NAME + ": wrong domain definition, lower bound > upper bound"); } } /** * Converts ivars into an array of boolean variables * * @param ivars an IntVar array containing only boolean variables * @return an array of BoolVar * @throws java.lang.ClassCastException if one variable is not a BoolVar */ default BoolVar[] toBoolVar(IntVar... ivars) { BoolVar[] bvars = new BoolVar[ivars.length]; for (int i = ivars.length - 1; i >= 0; i--) { bvars[i] = (BoolVar) ivars[i]; } return bvars; } /** * Return a generated short string, prefixed with {@link #DEFAULT_PREFIX} * and followed with a single-use number. * * @return generated String to name internally created variables */ default String generateName() { return generateName(DEFAULT_PREFIX); } /** * Return a generated short string prefixed with prefix * and followed with a single-use number. * * @param prefix the prefix name * @return String */ default String generateName(String prefix) { return prefix + ref().nextNameId(); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy