Package solver.constraints.set

Source Code of solver.constraints.set.SetConstraintsFactory

/**
*  Copyright (c) 1999-2014, Ecole des Mines de Nantes
*  All rights reserved.
*  Redistribution and use in source and binary forms, with or without
*  modification, are permitted provided that the following conditions are met:
*
*      * Redistributions of source code must retain the above copyright
*        notice, this list of conditions and the following disclaimer.
*      * Redistributions in binary form must reproduce the above copyright
*        notice, this list of conditions and the following disclaimer in the
*        documentation and/or other materials provided with the distribution.
*      * Neither the name of the Ecole des Mines de Nantes nor the
*        names of its contributors may be used to endorse or promote products
*        derived from this software without specific prior written permission.
*
*  THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
*  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
*  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
*  DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
*  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
*  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
*  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
*  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
*  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
*  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/


package solver.constraints.set;

import solver.constraints.Constraint;
import solver.constraints.Propagator;
import solver.variables.BoolVar;
import solver.variables.IntVar;
import solver.variables.SetVar;
import solver.variables.VariableFactory;
import util.tools.ArrayUtils;

/**
* Constraints over set variables
*
* @author Jean-Guillaume Fages
*/
public class SetConstraintsFactory {

    SetConstraintsFactory() {
    }

    //***********************************************************************************
    // BASICS : union/inter/subset/card
    //***********************************************************************************

    /**
     * Constraint which ensures that the union of sets in SET_VARS is equal to the set SET_UNION
     *
     * @param SETS  set variables
     * @param UNION set variable representing the union of SET_VARS
     * @return A constraint ensuring that the union of SET_VARS is equal to SET_UNION
     */
    public static Constraint union(SetVar[] SETS, SetVar UNION) {
        return new Constraint("SetUnion",new PropUnion(SETS, UNION), new PropUnion(SETS, UNION));
    }

    /**
     * Constraint which ensures that the intersection of sets in SET_VAR is equal to the set SET_INTER
     *
     * @param SETS         set variables
     * @param INTERSECTION set variable representing the intersection of SET_VARS
     * @return A constraint ensuring that the intersection of sets is equal to set intersection
     */
    public static Constraint intersection(SetVar[] SETS, SetVar INTERSECTION) {
        return new Constraint("SetIntersection",new PropIntersection(SETS, INTERSECTION), new PropIntersection(SETS, INTERSECTION));
    }

    /**
     * Constraint which ensures that i<j <=> SET_VARS[i] subseteq SET_VARS[j]
     *
     * @param SETS set variables
     * @return A constraint which ensures that i<j <=> SET_VARS[i] subseteq SET_VARS[j]
     */
    public static Constraint subsetEq(SetVar[] SETS) {
    Propagator[] props = new Propagator[SETS.length-1];
        for (int i = 0; i < SETS.length - 1; i++) {
            props[i] = new PropSubsetEq(SETS[i], SETS[i + 1]);
        }
        return new Constraint("SetSubsetEq",props);
    }

    /**
     * Cardinality constraint: |SET_VAR| = CARD
     *
     * @param SET  a set variable
     * @param CARD an integer variable representing SET_VAR's cardinality
     *             (i.e. the number of elements in it)
     * @return A constraint ensuring that |SET_VAR| = CARD
     */
    public static Constraint cardinality(SetVar SET, IntVar CARD) {
    return new Constraint("SetCard",new PropCardinality(SET, CARD));
    }

    /**
     * Restricts the number of empty sets in SETS
     * |{s in SETS such that |s|=0}| = NB_EMPTY_SETS
     *
     * @param SETS          set variables
     * @param NB_EMPTY_SETS integer variable restricting the number of empty sets in SETS
     * @return A constraint ensuring that |{s in SETS such that |s|=0}| = NB_EMPTY_SETS
     */
    public static Constraint nbEmpty(SetVar[] SETS, IntVar NB_EMPTY_SETS) {
    return new Constraint("SetNbEmpty",new PropNbEmpty(SETS, NB_EMPTY_SETS));
    }

    /**
     * links SET_1 and SET_2 with OFFSET
     * x in SET_1 <=> x+OFFSET in SET_2
     *
     * @param SET_1  a set variable
     * @param SET_2  a set variable
     * @param OFFSET offset index
     * @return a constraint ensuring that x in SET_1 <=> x+OFFSET in SET_2
     */
    public static Constraint offSet(SetVar SET_1, SetVar SET_2, int OFFSET) {
    return new Constraint("SetOffset",new PropOffSet(SET_1, SET_2, OFFSET));
    }

  /**
   * Prevents SET to be empty
   * @param SET a SetVar
   * @return a constraint ensuring that SET is not empty
   */
  public static Constraint notEmpty(SetVar SET){
    return new Constraint("SetNotEmpty",new PropNotEmpty(SET));
  }

    //***********************************************************************************
    // SUM - MAX - MIN
    //***********************************************************************************

    /**
     * Sums elements of a SET
     * sum{i | i in set} = SUM
     *
     * @param SET a set variable
     * @param SUM an integer variable representing sum{i | i in SET}
   * @param NOT_EMPTY true : the set variable cannot be empty
   *                  false : the set may be empty (if so, the SUM constraint is not applied)
     * @return a constraint ensuring that sum{i | i in set} = SUM
     */
    public static Constraint sum(SetVar SET, IntVar SUM, boolean NOT_EMPTY) {
        return sum(SET, null, 0, SUM, NOT_EMPTY);
    }

    /**
     * Sums weights given by a set of indexes INDEXES:
     * sum{WEIGHTS[i-OFFSET] | i in INDEXES} = SUM
     *
     * @param INDEXES set variables
     * @param WEIGHTS integers
     * @param OFFSET  offset index : should be 0 by default
     *                but generally 1 with MiniZinc API
     *                which counts from 1 to n instead of counting from 0 to n-1 (Java standard)
     * @param SUM     an integer variable representing sum{WEIGHTS[i-OFFSET] | i in INDEXES}
   * @param NOT_EMPTY true : the set variable cannot be empty
   *                  false : the set may be empty (if so, the SUM constraint is not applied)
     * @return a constraint ensuring that sum{WEIGHTS[i-OFFSET] | i in INDEXES} = SUM
     */
    public static Constraint sum(SetVar INDEXES, int[] WEIGHTS, int OFFSET, IntVar SUM, boolean NOT_EMPTY) {
    if (NOT_EMPTY) {
      return new Constraint("SetSum_NotEmpty",new PropNotEmpty(INDEXES),new PropSumOfElements(INDEXES, WEIGHTS, OFFSET, SUM, NOT_EMPTY));
    }else{
      return new Constraint("SetSum",new PropSumOfElements(INDEXES, WEIGHTS, OFFSET, SUM, NOT_EMPTY));
    }
    }

    /**
     * Retrieves the maximum element MAX_ELEMENT_VALUE of SET
     * max{i | i in set} = MAX_ELEMENT_VALUE
     *
     * @param SET               a set variable
     * @param MAX_ELEMENT_VALUE an integer variable representing max{i | i in SET}
   * @param NOT_EMPTY true : the set variable cannot be empty
   *                  false : the set may be empty (if so, the MAX constraint is not applied)
     * @return a constraint ensuring that max{i | i in set} = MAX_ELEMENT_VALUE
     */
    public static Constraint max(SetVar SET, IntVar MAX_ELEMENT_VALUE, boolean NOT_EMPTY) {
        return max(SET, null, 0, MAX_ELEMENT_VALUE, NOT_EMPTY);
    }

    /**
     * Retrieves the maximum element MAX_ELEMENT_VALUE induced by INDEXES
     * max{WEIGHTS[i-OFFSET] | i in INDEXES} = MAX_ELEMENT_VALUE
     *
     * @param INDEXES           a set variable containing elements in range [OFFSET,WEIGHTS.length-1+OFFSET]
     * @param WEIGHTS           integers
     * @param OFFSET            offset index : should be 0 by default
     *                          but generally 1 with MiniZinc API
     *                          which counts from 1 to n instead of counting from 0 to n-1 (Java standard)
     * @param MAX_ELEMENT_VALUE an integer variable representing max{WEIGHTS[i-OFFSET] | i in INDEXES}
   * @param NOT_EMPTY true : the set variable cannot be empty
   *                  false : the set may be empty (if so, the MAX constraint is not applied)
     * @return a constraint ensuring that max{WEIGHTS[i-OFFSET] | i in INDEXES} = MAX_ELEMENT_VALUE
     */
    public static Constraint max(SetVar INDEXES, int[] WEIGHTS, int OFFSET, IntVar MAX_ELEMENT_VALUE, boolean NOT_EMPTY) {
    if (NOT_EMPTY) {
      return new Constraint("SetMax_NotEmpty",new PropNotEmpty(INDEXES),new PropMaxElement(INDEXES, WEIGHTS, OFFSET, MAX_ELEMENT_VALUE, NOT_EMPTY));
    }else{
      return new Constraint("SetMax",new PropMaxElement(INDEXES, WEIGHTS, OFFSET, MAX_ELEMENT_VALUE, NOT_EMPTY));
    }
    }

    /**
     * Retrieves the minimum element MIN_ELEMENT_VALUE of SET:
     * min{i | i in SET} = MIN_ELEMENT_VALUE
     *
     * @param SET               a set variable
     * @param MIN_ELEMENT_VALUE an integer variable representing min{i | i in SET}
   * @param NOT_EMPTY true : the set variable cannot be empty
   *                  false : the set may be empty (if so, the MIN constraint is not applied)
     * @return a constraint ensuring that min{i | i in SET} = MIN_ELEMENT_VALUE
     */
    public static Constraint min(SetVar SET, IntVar MIN_ELEMENT_VALUE, boolean NOT_EMPTY) {
        return min(SET, null, 0, MIN_ELEMENT_VALUE, NOT_EMPTY);
    }

    /**
     * Retrieves the minimum element MIN_ELEMENT_VALUE induced by INDEXES
     * min{WEIGHTS[i-OFFSET] | i in INDEXES} = MIN_ELEMENT_VALUE
     *
     * @param INDEXES           a set variable containing elements in range [OFFSET,WEIGHTS.length-1+OFFSET]
     * @param WEIGHTS           integers
     * @param OFFSET            offset index : should be 0 by default
     *                          but generally 1 with MiniZinc API
     *                          which counts from 1 to n instead of counting from 0 to n-1 (Java standard)
     * @param MIN_ELEMENT_VALUE integer variable representing min{WEIGHTS[i-OFFSET] | i in INDEXES}
   * @param NOT_EMPTY true : the set variable cannot be empty
   *                  false : the set may be empty (if so, the MIN constraint is not applied)
     * @return a constraint ensuring that min{WEIGHTS[i-OFFSET] | i in INDEXES} = MIN_ELEMENT_VALUE
     */
    public static Constraint min(SetVar INDEXES, int[] WEIGHTS, int OFFSET, IntVar MIN_ELEMENT_VALUE, boolean NOT_EMPTY) {
    if (NOT_EMPTY) {
      return new Constraint("SetMin_NotEmpty",new PropNotEmpty(INDEXES),new PropMinElement(INDEXES, WEIGHTS, OFFSET, MIN_ELEMENT_VALUE, NOT_EMPTY));
    }else{
      return new Constraint("SetMin",new PropMinElement(INDEXES, WEIGHTS, OFFSET, MIN_ELEMENT_VALUE, NOT_EMPTY));
    }
    }

    //***********************************************************************************
    // CHANNELING CONSTRAINTS : bool/int/graph
    //***********************************************************************************

    /**
     * Channeling between a set variable SET and boolean variables BOOLEANS
     * i in SET <=> BOOLEANS[i-OFFSET] = TRUE
     *
     * @param BOOLEANS boolean variables
     * @param SET      set variables
     * @param OFFSET   offset index : should be 0 by default
     *                 but generally 1 with MiniZinc API
     *                 which counts from 1 to n instead of counting from 0 to n-1 (Java standard)
     * @return a constraint ensuring that i in SET <=> BOOLEANS[i-OFFSET] = TRUE
     */
    public static Constraint bool_channel(BoolVar[] BOOLEANS, SetVar SET, int OFFSET) {
    return new Constraint("SetBoolChanneling",new PropBoolChannel(SET, BOOLEANS, OFFSET));
    }

    /**
     * Channeling between set variables SETS and integer variables INTEGERS
     * x in SETS[y-OFFSET_1] <=> INTEGERS[x-OFFSET_2] = y
     *
     * @param SETS     set variables
     * @param INTEGERS integer variables
     * @param OFFSET_1 offset index : should be 0 by default
     *                 but generally 1 with MiniZinc API
     *                 which counts from 1 to n instead of counting from 0 to n-1 (Java standard)
     * @param OFFSET_2 offset index : should be 0 by default
     *                 but generally 1 with MiniZinc API
     *                 which counts from 1 to n instead of counting from 0 to n-1 (Java standard)
     * @return a constraint ensuring that x in SETS[y-OFFSET_1] <=> INTEGERS[x-OFFSET_2] = y
     */
    public static Constraint int_channel(SetVar[] SETS, IntVar[] INTEGERS, int OFFSET_1, int OFFSET_2) {
    return new Constraint("SetIntChanneling",
        new PropIntChannel(SETS, INTEGERS, OFFSET_1, OFFSET_2),
                new PropIntChannel(SETS, INTEGERS, OFFSET_1, OFFSET_2),new PropAllDisjoint(SETS)
    );
    }

  /**
   * Channeling constraint ensuring that
   * VALUES is exactly the set of values taken by VARS,
   * @param VARS    integer variables
   * @param VALUES  a set variable
   * @return  a channeling constraint ensuring that VALUES = {value(x) | x in VARS}
   */
  public static Constraint int_values_union(IntVar[] VARS, SetVar VALUES){
    return new Constraint("SetIntValuesUnion"
        ,new PropSetIntValuesUnion(VARS,VALUES)
        ,new PropSetIntValuesUnion(VARS,VALUES)
    );
  }

    //***********************************************************************************
    // MINIZINC API
    //***********************************************************************************

    /**
     * SET_1 and SET_2 are disjoint, i.e. they cannot contain the same element.
     * Note that they can be both empty
     *
     * @param SET_1 a set variable
     * @param SET_2 a set variable
     * @return a constraint ensuring that set1 and set2 are disjoint
     */
    public static Constraint disjoint(SetVar SET_1, SetVar SET_2) {
        return all_disjoint(new SetVar[]{SET_1, SET_2});
    }

    /**
     * Sets in SETS are all disjoint
     * Note that there can be multiple empty sets
     *
     * @param SETS disjoint set variables
     * @return a constraint ensuring that non-empty sets are all disjoint
     */
    public static Constraint all_disjoint(SetVar[] SETS) {
    return new Constraint("SetAllDisjoint",new PropAllDisjoint(SETS));
    }

    /**
     * Sets in SETS are all different (not necessarily disjoint)
     * Note that there cannot be more than two empty sets
     *
     * @param SETS different set variables
     * @return a constraint ensuring that SETS are all different
     */
    public static Constraint all_different(SetVar[] SETS) {
    return new Constraint("SetAllDifferent",new PropAllDiff(SETS),
        new PropAllDiff(SETS),new PropAtMost1Empty(SETS)
    );
    }

    /**
     * SETS are all equal
     *
     * @param SETS set variables to be equals
     * @return a constraint ensuring that all sets in SETS are equal
     */
    public static Constraint all_equal(SetVar[] SETS) {
    return new Constraint("SetAllEqual",new PropAllEqual(SETS));
    }

    /**
     * Partitions UNIVERSE into disjoint sets, SETS
     *
     * @param SETS     set variables whose values are subsets of UNIVERSE
     * @param UNIVERSE a set variable representing union(SETS)
     * @return a constraint which ensures that SETS form a partition of UNIVERSE
     */
    public static Constraint partition(SetVar[] SETS, SetVar UNIVERSE) {
        return new Constraint("SetPartition",ArrayUtils.append(
        all_disjoint(SETS).getPropagators(),
        new Propagator[]{new PropUnion(SETS, UNIVERSE), new PropUnion(SETS, UNIVERSE)}
    ));
    }

    /**
     * Inverse set constraint
     * x in SETS[y-OFFSET_1] <=> y in INVERSE_SETS[x-OFFSET_2]
     *
     * @param SETS         set variables
     * @param INVERSE_SETS set variables
     * @param OFFSET_1     offset index : should be 0 by default
     *                     but generally 1 with MiniZinc API
     *                     which counts from 1 to n instead of counting from 0 to n-1 (Java standard)
     * @param OFFSET_2     offset index : should be 0 by default
     *                     but generally 1 with MiniZinc API
     *                     which counts from 1 to n instead of counting from 0 to n-1 (Java standard)
     * @return a constraint ensuring that x in SETS[y-OFFSET_1] <=> y in INVERSE_SETS[x-OFFSET_2]
     */
    public static Constraint inverse_set(SetVar[] SETS, SetVar[] INVERSE_SETS, int OFFSET_1, int OFFSET_2) {
    return new Constraint("SetInverse",new PropInverse(SETS, INVERSE_SETS, OFFSET_1, OFFSET_2));
    }

    /**
     * Symmetric sets constraint
     * x in SETS[y-OFFSET] <=> y in SETS[x-OFFSET]
     *
     * @param SETS   set variables
     * @param OFFSET offset index : should be 0 by default
     *               but generally 1 with MiniZinc API
     *               which counts from 1 to n instead of counting from 0 to n-1 (Java standard)
     * @return a constraint ensuring that x in SETS[y-OFFSET] <=> y in SETS[x-OFFSET]
     */
    public static Constraint symmetric(SetVar[] SETS, int OFFSET) {
    return new Constraint("SetSymmetric",new PropSymmetric(SETS, OFFSET));
    }

    /**
     * Element constraint over sets
     * states that SETS[INDEX-OFFSET] = SET
     *
     * @param INDEX  an integer variable pointing to SET's index into array SETS
     * @param SETS   set variables representing possible values for SET
     * @param OFFSET offset index : should be 0 by default
     *               but generally 1 with MiniZinc API
     *               which counts from 1 to n instead of counting from 0 to n-1 (Java standard)
     * @param SET    a set variable which takes its value in SETS
     * @return a constraint ensuring that SETS[INDEX-OFFSET] = SET
     */
    public static Constraint element(IntVar INDEX, SetVar[] SETS, int OFFSET, SetVar SET) {
    return new Constraint("SetElement",new PropElement(INDEX, SETS, OFFSET, SET), new PropElement(INDEX, SETS, OFFSET, SET));
    }

    /**
     * Member constraint over sets
     * states that SET belongs to SETS
     *
     * @param SETS set variables representing possible values for SET
     * @param SET  a set variable which takes its value in SETS
     * @return a constraint ensuring that SET belongs to SETS
     */
    public static Constraint member(SetVar[] SETS, SetVar SET) {
        IntVar index = VariableFactory.enumerated("idx_tmp", 0, SETS.length - 1, SET.getSolver());
        return element(index, SETS, 0, SET);
    }

    /**
     * Member constraint over an IntVar and a SetVar
     * states that INTEGER is included in SET
     *
     * @param INTEGER an integer variables which takes its values in SET
     * @param SET     a set variables representing possible values of INTEGER
     * @return a constraint ensuring that INTEGER belongs to SET
     */
    public static Constraint member(IntVar INTEGER, SetVar SET) {
    return new Constraint("SetMember",new PropIntMemberSet(SET, INTEGER));
    }
}
TOP

Related Classes of solver.constraints.set.SetConstraintsFactory

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.