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

org.chocosolver.util.objects.setDataStructures.iterable.IntIterableSetUtils Maven / Gradle / Ivy

There is a newer version: 4.10.16
Show newest version
/**
 * Copyright (c) 2016, 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:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. 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.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *    This product includes software developed by the .
 * 4. Neither the name of the  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  ''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  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 org.chocosolver.util.objects.setDataStructures.iterable;

import org.chocosolver.solver.variables.IntVar;
import org.chocosolver.util.iterators.DisposableRangeIterator;

import java.util.Arrays;

/**
 *
 * 

* Project: choco. * @author Charles Prud'homme * @since 25/01/2016. */ public class IntIterableSetUtils { /** * Copy the domain of var in set. * First, it clears set, then it fills it with the value in var. * * @param var an integer variable * @param set set to transfer values to */ public static void copyIn(IntVar var, IntIterableRangeSet set) { set.clear(); DisposableRangeIterator rit = var.getRangeIterator(true); while (rit.hasNext()) { int lb = rit.min(); int ub = rit.max(); set.pushRange(lb,ub); rit.next(); } rit.dispose(); } /** * @param set on which the complement is based * @param lbu lower bound (inclusive) of the universe * @param ubu upper bound (inclusive) of the universe * @return the complement of this set wrt to universe set [lbu, ubu]. * Values smaller than lbu and greater than ubu are ignored. */ public static IntIterableRangeSet complement(IntIterableRangeSet set, int lbu, int ubu) { assert lbu <= ubu; IntIterableRangeSet t = new IntIterableRangeSet(); t.ELEMENTS = new int[set.SIZE + 2]; int i = 0; int lb = lbu; while (i < set.SIZE && set.ELEMENTS[i] <= lbu) { i += 2; lb = set.ELEMENTS[i - 1] + 1; } if (i == set.SIZE) { if (lb < ubu) { t.pushRange(lb, ubu); }// else: empty set } else { assert set.ELEMENTS[i] > lb; t.pushRange(lb, set.ELEMENTS[i++] - 1); while (i < set.SIZE - 2 && set.ELEMENTS[i] < ubu) { t.pushRange(set.ELEMENTS[i++] + 1, set.ELEMENTS[i++] - 1); } if (set.ELEMENTS[i] < ubu) { t.pushRange(set.ELEMENTS[i] + 1, ubu); } } return t; } /** * @param set1 a set of ints * @param set2 a set of ints * @return return a set {a + b | a in set1, b in set2} */ public static IntIterableRangeSet plus(IntIterableRangeSet set1, IntIterableRangeSet set2) { IntIterableRangeSet t = new IntIterableRangeSet(); plus(t, set1, set2); return t; } /** * Set setr to {a + b | a in set1, b in set2} * * @param setr set of ints * @param set1 a set of ints * @param set2 a set of ints */ public static void plus(IntIterableRangeSet setr, IntIterableRangeSet set1, IntIterableRangeSet set2) { setr.clear(); int s1 = set1.SIZE >> 1; int s2 = set2.SIZE >> 1; if (s1 > 0 && s2 > 0) { setr.grow(set1.SIZE); int i = 0, j = 0; int[] is = new int[s2]; Arrays.fill(is, -1); is[0] = 0; int lb = set1.ELEMENTS[0] + set2.ELEMENTS[0]; int ub = set1.ELEMENTS[1] + set2.ELEMENTS[1]; do { boolean extend = false; for (int k = i; k <= j; k++) { int _lb = set1.ELEMENTS[is[k] << 1] + set2.ELEMENTS[k << 1]; if (lb <= _lb && _lb <= ub + 1) { ub = Math.max(set1.ELEMENTS[(is[k] << 1) + 1] + set2.ELEMENTS[(k << 1) + 1], ub); extend = true; // add neighbors to evaluate // 1. left neighbor if (k < s2 - 1 && k == j) { is[k + 1]++; if (is[k + 1] == 0) { j++; } } // 2. bottom neighbor is[k]++; if (is[k] == s1) { i++; } } } if (!extend) { setr.pushRange(lb, ub); lb = Integer.MAX_VALUE; for (int k = i; k <= j; k++) { int _lb = set1.ELEMENTS[is[k] << 1] + set2.ELEMENTS[k << 1]; if (lb > _lb) { lb = _lb; ub = set1.ELEMENTS[(is[k] << 1) + 1] + set2.ELEMENTS[(k << 1) + 1]; } } } } while (is[s2 - 1] < s1); setr.pushRange(lb, ub); } } /** * Set setr to {a + b | a in set1, b in [l..u]} * * @param setr set of ints * @param set1 a set of ints * @param l an int * @param u an int */ public static void plus(IntIterableRangeSet setr, IntIterableRangeSet set1, int l, int u) { setr.clear(); int s1 = set1.SIZE >> 1; if (s1 > 0 && l <= u) { int k = 0; setr.grow(set1.SIZE); int lb = set1.ELEMENTS[0] + l; int ub = set1.ELEMENTS[1] + u; for (; k < s1; k++) { int _lb = set1.ELEMENTS[k << 1] + l; if (lb <= _lb && _lb <= ub + 1) { ub = Math.max(set1.ELEMENTS[(k << 1) + 1] + u, ub); } else { setr.pushRange(lb, ub); lb = set1.ELEMENTS[k << 1] + l; ub = set1.ELEMENTS[(k << 1) + 1] + u; } } setr.pushRange(lb,ub); } } /** * @param set1 a set of ints * @param set2 a set of ints * @return return a set {a - b | a in set1, b in set2} */ public static IntIterableRangeSet minus(IntIterableRangeSet set1, IntIterableRangeSet set2) { IntIterableRangeSet t = new IntIterableRangeSet(); minus(t, set1, set2); return t; } /** * Set setr to {a - b | a in set1, b in set2} * * @param setr set of ints * @param set1 a set of ints * @param set2 a set of ints */ public static void minus(IntIterableRangeSet setr, IntIterableRangeSet set1, IntIterableRangeSet set2) { setr.clear(); int s1 = set1.SIZE >> 1; int s2 = set2.SIZE >> 1; if (s1 > 0 && s2 > 0) { setr.grow(set1.SIZE); int i = s2 - 1, j = s2 - 1; int[] is = new int[s2]; Arrays.fill(is, -1); is[s2 - 1] = 0; int lb = set1.ELEMENTS[0] - set2.ELEMENTS[((s2 - 1) << 1) + 1]; int ub = set1.ELEMENTS[1] - set2.ELEMENTS[(s2 - 1) << 1]; do { boolean extend = false; for (int k = j; k >= i; k--) { int _lb = set1.ELEMENTS[is[k] << 1] - set2.ELEMENTS[(k << 1) + 1]; if (lb <= _lb && _lb <= ub + 1) { ub = Math.max(set1.ELEMENTS[(is[k] << 1) + 1] - set2.ELEMENTS[(k << 1)], ub); extend = true; // add neighbors to evaluate // 1. left neighbor if (k > 0 && k == i) { is[k - 1]++; if (is[k - 1] == 0) { i--; } } // 2. bottom neighbor is[k]++; if (is[k] == s1) { j--; } } } if (!extend) { setr.pushRange(lb, ub); lb = Integer.MAX_VALUE; for (int k = i; k <= j; k++) { int _lb = set1.ELEMENTS[is[k] << 1] - set2.ELEMENTS[(k << 1) + 1]; if (lb > _lb) { lb = _lb; ub = set1.ELEMENTS[(is[k] << 1) + 1] - set2.ELEMENTS[k << 1]; } } } } while (is[0] < s1); setr.pushRange(lb, ub); } } /** * Set setr to {a - b | a in set1, b in [l..u]} * * @param setr set of ints * @param set1 a set of ints * @param l an int * @param u an int */ public static void minus(IntIterableRangeSet setr, IntIterableRangeSet set1, int l, int u) { setr.clear(); int s1 = set1.SIZE >> 1; if (s1 > 0 && l <= u) { setr.grow(set1.SIZE); int k = s1; int lb = set1.ELEMENTS[0] - u; int ub = set1.ELEMENTS[1] - l; for (; k >= 0; k--) { int _lb = set1.ELEMENTS[k << 1] - u; if (lb <= _lb && _lb <= ub + 1) { ub = Math.max(set1.ELEMENTS[(k << 1) + 1] - l, ub); } else { setr.pushRange(lb, ub); lb = set1.ELEMENTS[k << 1] - u; ub = set1.ELEMENTS[(k << 1) + 1] - l; } } setr.pushRange(lb, ub); } } /** * @param set1 a set of ints * @param set2 a set of ints * @return return a set = set1 ∩ set2 */ public static IntIterableRangeSet intersection(IntIterableRangeSet set1, IntIterableRangeSet set2) { IntIterableRangeSet t = new IntIterableRangeSet(); intersection(t, set1, set2); return t; } /** * Set setr to set1set2 * * @param setr set of ints * @param set1 a set of ints * @param set2 a set of ints */ @SuppressWarnings("Duplicates") public static void intersection(IntIterableRangeSet setr, IntIterableRangeSet set1, IntIterableRangeSet set2) { setr.clear(); int s1 = set1.SIZE >> 1; int s2 = set2.SIZE >> 1; if (s1 > 0 && s2 > 0) { setr.grow(set1.SIZE); int i = 0, j = 0; int lbi, ubi, lbj, ubj, lb, ub; lbi = set1.ELEMENTS[0]; ubi = set1.ELEMENTS[1]; lbj = set2.ELEMENTS[0]; ubj = set2.ELEMENTS[1]; while (i < s1 && j < s2) { if ((lbi <= lbj && lbj <= ubi) || (lbj <= lbi && lbi <= ubj)) { lb = Math.max(lbi, lbj); ub = Math.min(ubi, ubj); setr.pushRange(lb, ub); } if (ubi <= ubj && ++i < s1) { lbi = set1.ELEMENTS[i << 1]; ubi = set1.ELEMENTS[(i << 1) + 1]; }else if (ubj <= ubi && ++j < s2) { lbj = set2.ELEMENTS[j << 1]; ubj = set2.ELEMENTS[(j << 1) + 1]; } } } } /** * Set set1 to set1set2 * * @param set1 a set of ints * @param set2 a set of ints * @return true if set1 has changed */ @SuppressWarnings("Duplicates") public static boolean intersectionOf(IntIterableRangeSet set1, IntIterableRangeSet set2) { boolean change = false; int s1 = set1.SIZE >> 1; int s2 = set2.SIZE >> 1; if (s1 > 0 && s2 > 0) { int i = 0, j = 0; int s = 0, c = 0; int[] e = new int[set1.SIZE]; int lbi, ubi, lbj, ubj, lb, ub; lbi = set1.ELEMENTS[0]; ubi = set1.ELEMENTS[1]; lbj = set2.ELEMENTS[0]; ubj = set2.ELEMENTS[1]; while (i < s1 && j < s2) { if ((lbi <= lbj && lbj <= ubi) || (lbj <= lbi && lbi <= ubj)) { lb = Math.max(lbi, lbj); ub = Math.min(ubi, ubj); if (s + 2 > e.length) { // overflow-conscious code int oldCapacity = e.length; int newCapacity = oldCapacity + (oldCapacity >> 1); if (newCapacity < s + 2) newCapacity = s + 2; // minCapacity is usually close to size, so this is a win: e = Arrays.copyOf(e, newCapacity); } e[s++] = lb; e[s++] = ub; c += ub - lb + 1; change = true; } if (ubi <= ubj && ++i < s1) { lbi = set1.ELEMENTS[i << 1]; ubi = set1.ELEMENTS[(i << 1) + 1]; }else if (ubj <= ubi && ++j < s2) { lbj = set2.ELEMENTS[j << 1]; ubj = set2.ELEMENTS[(j << 1) + 1]; } } set1.ELEMENTS = e; set1.SIZE = s; change |= (set1.CARDINALITY != c); set1.CARDINALITY = c; }else{ change = set1.CARDINALITY > 0; set1.clear(); } return change; } /** * @param set1 a set of ints * @param set2 a set of ints * @return return a set = set1 ∪ set2 */ public static IntIterableRangeSet union(IntIterableRangeSet set1, IntIterableRangeSet set2) { IntIterableRangeSet t = new IntIterableRangeSet(); union(t, set1, set2); return t; } /** * Set setr to set1set2 * * @param setr set of ints * @param set1 a set of ints * @param set2 a set of ints */ @SuppressWarnings("Duplicates") public static void union(IntIterableRangeSet setr, IntIterableRangeSet set1, IntIterableRangeSet set2) { setr.clear(); int s1 = set1.SIZE >> 1; int s2 = set2.SIZE >> 1; if (s1 > 0 && s2 > 0) { setr.grow(set1.SIZE); int i = 0, j = 0; int lbi, ubi, lbj, ubj, lb, ub; lb = lbi = set1.ELEMENTS[0]; ub = ubi = set1.ELEMENTS[1]; lbj = set2.ELEMENTS[0]; ubj = set2.ELEMENTS[1]; if(lb > lbj){ lb = lbj; ub = ubj; } boolean extend; while (i < s1 || j < s2) { extend = false; if (lb - 1 <= lbi && lbi <= ub + 1) { ub = Math.max(ub, ubi); extend = i < s1; if(++i < s1){ lbi = set1.ELEMENTS[i << 1]; ubi = set1.ELEMENTS[(i << 1) + 1]; } } if (lb - 1 <= lbj && lbj <= ub + 1) { ub = Math.max(ub, ubj); extend |= j < s2; if(++j < s2){ lbj = set2.ELEMENTS[j << 1]; ubj = set2.ELEMENTS[(j << 1) + 1]; } } if(!extend){ setr.pushRange(lb, ub); if(i < s1) { lb = lbi; ub = ubi; if(j < s2 && lbi > lbj){ lb = lbj; ub = ubj; } }else if(j < s2){ lb = lbj; ub = ubj; } } } setr.pushRange(lb, ub); } } /** * Set set1 to set1set2 * * @param set1 a set of ints * @param set2 a set of ints * @return true if set1 has changed */ @SuppressWarnings("Duplicates") public static boolean unionOf(IntIterableRangeSet set1, IntIterableRangeSet set2) { boolean change = false; int s1 = set1.SIZE >> 1; int s2 = set2.SIZE >> 1; if (s1 > 0 && s2 > 0) { int i = 0, j = 0; int s = 0, c = 0; int[] e = new int[set1.SIZE]; int lbi, ubi, lbj, ubj, lb, ub; lb = lbi = set1.ELEMENTS[0]; ub = ubi = set1.ELEMENTS[1]; lbj = set2.ELEMENTS[0]; ubj = set2.ELEMENTS[1]; if (lb > lbj) { lb = lbj; ub = ubj; } boolean extend; while (i < s1 || j < s2) { extend = false; if (lb - 1 <= lbi && lbi <= ub + 1) { ub = Math.max(ub, ubi); extend = i < s1; if (++i < s1) { lbi = set1.ELEMENTS[i << 1]; ubi = set1.ELEMENTS[(i << 1) + 1]; } } if (lb - 1 <= lbj && lbj <= ub + 1) { ub = Math.max(ub, ubj); extend |= j < s2; if (++j < s2) { lbj = set2.ELEMENTS[j << 1]; ubj = set2.ELEMENTS[(j << 1) + 1]; } } if (!extend) { if (s + 2 > e.length) { // overflow-conscious code int oldCapacity = e.length; int newCapacity = oldCapacity + (oldCapacity >> 1); if (newCapacity < s + 2) newCapacity = s + 2; // minCapacity is usually close to size, so this is a win: e = Arrays.copyOf(e, newCapacity); } e[s++] = lb; e[s++] = ub; c += ub - lb + 1; if (i < s1) { lb = lbi; ub = ubi; if (j < s2 && lbi > lbj) { lb = lbj; ub = ubj; } } else if (j < s2) { lb = lbj; ub = ubj; } } } if (s + 2 > e.length) { // overflow-conscious code int oldCapacity = e.length; int newCapacity = oldCapacity + (oldCapacity >> 1); if (newCapacity < s + 2) newCapacity = s + 2; // minCapacity is usually close to size, so this is a win: e = Arrays.copyOf(e, newCapacity); } e[s++] = lb; e[s++] = ub; c += ub - lb + 1; set1.ELEMENTS = e; set1.SIZE = s; change |= (set1.CARDINALITY != c); set1.CARDINALITY = c; } else { if(s2 > 0){ set1.grow(set2.SIZE); System.arraycopy(set2.ELEMENTS, 0, set1.ELEMENTS, 0, set2.SIZE); set1.SIZE = set2.SIZE; set1.CARDINALITY = set2.CARDINALITY; change = true; } } return change; } /** * Put all value of var into set. * TODO: more efficient operation * * @param set a set of ints * @param var a integer variable */ public static void union(IntIterableRangeSet set, IntVar var) { int ub = var.getUB(); for (int v = var.getLB(); v <= ub; v = var.nextValue(v)) { set.add(v); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy