Package solver.constraints.nary.alldifferent.algo

Source Code of solver.constraints.nary.alldifferent.algo.AlgoAllDiffBC$Interval

/**
* 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.nary.alldifferent.algo;

import solver.constraints.Propagator;
import solver.exception.ContradictionException;
import solver.variables.IntVar;
import util.sort.ArraySort;

import java.io.Serializable;
import java.util.Comparator;

public class AlgoAllDiffBC {

  int[] t; // Tree links
  int[] d; // Diffs between critical capacities
  int[] h; // Hall interval links
  int[] bounds;

  int nbBounds;

  Interval[] intervals;
  Interval[] minsorted;
  Interval[] maxsorted;

  private Propagator aCause;
  private IntVar[] vars;

  ArraySort sorter;

  public AlgoAllDiffBC(Propagator cause) {
    this.aCause = cause;
  }

  public void reset(IntVar[] variables) {
    this.vars = variables;
    int n = vars.length;
    if(intervals==null || intervals.length<n){
      t = new int[2 * n + 2];
      d = new int[2 * n + 2];
      h = new int[2 * n + 2];
      bounds = new int[2 * n + 2];
      intervals = new Interval[n];
      minsorted = new Interval[n];
      maxsorted = new Interval[n];
      for (int i = 0; i < n; i++) {
        intervals[i] = new Interval();
      }
      sorter = new ArraySort(n,true,false);
    }
    for (int i = 0; i < n; i++) {
      Interval interval = intervals[i];
      interval.idx = i;
      interval.var = vars[i];
      minsorted[i] = interval;
      maxsorted[i] = interval;
    }
  }

  //****************************************************************************************************************//
  //****************************************************************************************************************//
  //****************************************************************************************************************//

  static enum SORT implements Comparator<Interval> {
    MAX {
      @Override
      public final int compare(Interval o1, Interval o2) {
        return o1.ub - o2.ub;
      }
    },
    MIN {
      @Override
      public final int compare(Interval o1, Interval o2) {
        return o1.lb - o2.lb;
      }
    },;
  }

  public void filter() throws ContradictionException {
    boolean again;
    do {
      again = false;
      sortIt();
      again |= filterLower();
      again |= filterUpper();
    } while (again);
  }

  protected void sortIt() {
    int n = vars.length;
    IntVar vt;
    for (int i = 0; i < n; i++) {
      vt = intervals[i].var;
      intervals[i].lb = vt.getLB();
      intervals[i].ub = vt.getUB();
    }
    sorter.sort(minsorted,n,SORT.MIN);
    sorter.sort(maxsorted,n,SORT.MAX);
    int min = minsorted[0].lb;
    int max = maxsorted[0].ub + 1;
    int last = min - 2;
    int nb = 0;
    bounds[0] = last;
    int i = 0, j = 0;
    while (true) {
      if (i < this.vars.length && min <= max) {
        if (min != last) {
          bounds[++nb] = last = min;
        }
        minsorted[i].minrank = nb;
        if (++i < this.vars.length) {
          min = minsorted[i].lb;
        }
      } else {
        if (max != last) {
          bounds[++nb] = last = max;
        }
        maxsorted[j].maxrank = nb;
        if (++j == this.vars.length) {
          break;
        }
        max = maxsorted[j].ub + 1;
      }
    }
    this.nbBounds = nb;
    bounds[nb + 1] = bounds[nb] + 2;
  }

  protected void pathset(int[] tab, int start, int end, int to) {
    int next = start;
    int prev = next;
    while (prev != end) {
      next = tab[prev];
      tab[prev] = to;
      prev = next;
    }
  }

  protected int pathmin(int[] tab, int i) {
    while (tab[i] < i) {
      i = tab[i];
    }
    return i;
  }

  protected int pathmax(int[] tab, int i) {
    while (tab[i] > i) {
      i = tab[i];
    }
    return i;
  }

  protected boolean filterLower() throws ContradictionException {
    boolean filter = false;
    for (int i = 1; i <= nbBounds + 1; i++) {
      t[i] = h[i] = i - 1;
      d[i] = bounds[i] - bounds[i - 1];
    }
    for (int i = 0; i < this.vars.length; i++) {
      int x = maxsorted[i].minrank;
      int y = maxsorted[i].maxrank;
      int z = pathmax(t, x + 1);
      int j = t[z];

      if (--d[z] == 0) {
        t[z] = z + 1;
        z = pathmax(t, t[z]);
        t[z] = j;
      }
      pathset(t, x + 1, z, z);
      if (d[z] < bounds[z] - bounds[y]) {
        aCause.contradiction(null, "");
      }
      if (h[x] > x) {
        int w = pathmax(h, h[x]);
        if (maxsorted[i].var.updateLowerBound(bounds[w], aCause)) {
          filter |= true;
          maxsorted[i].lb = maxsorted[i].var.getLB();//bounds[w];
        }
        pathset(h, x, w, w);
      }
      if (d[z] == bounds[z] - bounds[y]) {
        pathset(h, h[y], j - 1, y);
        h[y] = j - 1;
      }
    }
    return filter;
  }

  protected boolean filterUpper() throws ContradictionException {
    boolean filter = false;
    for (int i = 0; i <= nbBounds; i++) {
      t[i] = h[i] = i + 1;
      d[i] = bounds[i + 1] - bounds[i];
    }
    for (int i = this.vars.length - 1; i >= 0; i--) {
      int x = minsorted[i].maxrank;
      int y = minsorted[i].minrank;
      int z = pathmin(t, x - 1);
      int j = t[z];
      if (--d[z] == 0) {
        t[z] = z - 1;
        z = pathmin(t, t[z]);
        t[z] = j;
      }
      pathset(t, x - 1, z, z);
      if (d[z] < bounds[y] - bounds[z]) {
        aCause.contradiction(null, "");
      }
      if (h[x] < x) {
        int w = pathmin(h, h[x]);
        if (minsorted[i].var.updateUpperBound(bounds[w] - 1, aCause)) {
          filter |= true;
          minsorted[i].ub = minsorted[i].var.getUB();//bounds[w] - 1;
        }
        pathset(h, x, w, w);
      }
      if (d[z] == bounds[y] - bounds[z]) {
        pathset(h, h[y], j + 1, y);
        h[y] = j + 1;
      }
    }
    return filter;
  }

  private static class Interval implements Serializable {
    int minrank, maxrank;
    IntVar var;
    int idx;
    int lb, ub;
  }
}
TOP

Related Classes of solver.constraints.nary.alldifferent.algo.AlgoAllDiffBC$Interval

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.