private void remIncreTC(int i, int j) { if (i != j) { // reachable nodes from node i in the graph IStateBitSet tempDesc = getDesc(i, j, graph); if (needUpdate) { tcGraph[i] = tempDesc; // compute all the reachble nodes from each ancestor of i in graph IStateBitSet updateAnc = solver.getEnvironment().makeBitSet(nbNodes); for (int k = revTcGraph[i].nextSetBit(0); k >= 0; k = revTcGraph[i].nextSetBit(k + 1)) { if (!updateAnc.get(k)) { tempDesc = getDesc(k, j, graph); if (!needUpdate) updateAnc.or(revTcGraph[k]); else tcGraph[k] = tempDesc; } } // compute the nodes reachable from j in the reverse graph revTcGraph[j] = getDesc(j, i, revGraph); // compute all the nodes reachable from each descendant of j in the reverse graph IStateBitSet updateDesc = solver.getEnvironment().makeBitSet(nbNodes); for (int k = tcGraph[j].nextSetBit(0); k >= 0; k = tcGraph[j].nextSetBit(k + 1)) { if (!updateDesc.get(k)) { tempDesc = getDesc(k, i, revGraph); if (!needUpdate) updateDesc.or(tcGraph[k]); else revTcGraph[k] = tempDesc; } } } } }
@Override public boolean removeValue(int value, ICause cause, boolean informCause) throws ContradictionException { ICause antipromo = cause; if (informCause) { cause = Cause.Null; } boolean change = false; int inf = getLB(); int sup = getUB(); if (value == inf && value == sup) { this.contradiction(cause, MSG_REMOVE); } else { if (inf <= value && value <= sup) { EventType e = EventType.REMOVE; int aValue = value - OFFSET; change = VALUES.get(aValue); this.VALUES.clear(aValue); if (change) { SIZE.add(-1); // todo delta } if (value == inf) { inf = VALUES.nextSetBit(aValue) + OFFSET; LB.set(inf); e = EventType.INCLOW; filterOnGeq(cause, inf); if (cause.reactOnPromotion()) { cause = Cause.Null; } } else if (value == sup) { sup = VALUES.prevSetBit(aValue) + OFFSET; UB.set(sup); e = EventType.DECUPP; filterOnLeq(cause, sup); if (cause.reactOnPromotion()) { cause = Cause.Null; } } if (change && !VALUES.isEmpty()) { if (this.instantiated()) { e = EventType.INSTANTIATE; if (cause.reactOnPromotion()) { cause = Cause.Null; } } this.notifyPropagators(e, cause); } else { if (VALUES.isEmpty()) { this.contradiction(cause, MSG_EMPTY); } } } } return change; }
/** * add a value. * * @param x value to add * @return true wether the value has been added */ public boolean add(int x) { int i = x - offset; if (!contents.get(i)) { addIndex(i); return true; } else { return false; } }
/** Removes a value. */ public boolean remove(int x) { int i = x - offset; if (contents.get(i)) { removeIndex(i); return true; } else { return false; } }
private IStateBitSet getDesc(int i, int j, IStateBitSet[] graph) { // retrieve the set of reachable nodes from i in the graph needUpdate = true; Stack<Integer> stack = new Stack<Integer>(); IStateBitSet reached = solver.getEnvironment().makeBitSet(nbNodes); stack.push(i); while (!stack.isEmpty()) { int a = stack.pop(); for (int b = graph[a].nextSetBit(0); b >= 0; b = graph[a].nextSetBit(b + 1)) { if (!stack.contains(b) && !reached.get(b)) { reached.set(b, true); if (b == j) { needUpdate = false; return reached; } else stack.push(b); } } } return reached; }
/** * Removes <code>value</code>from the domain of <code>this</code>. The instruction comes from * <code>propagator</code>. * * <ul> * <li>If <code>value</code> is out of the domain, nothing is done and the return value is * <code>false</code>, * <li>if removing <code>value</code> leads to a dead-end (domain wipe-out), a <code> * ContradictionException</code> is thrown, * <li>otherwise, if removing <code>value</code> from the domain can be done safely, the event * type is created (the original event can be promoted) and observers are notified and the * return value is <code>true</code> * </ul> * * @param value value to remove from the domain (int) * @param cause removal releaser * @param informCause * @return true if the value has been removed, false otherwise * @throws solver.exception.ContradictionException if the domain become empty due to this action */ public boolean removeValue(int value, ICause cause, boolean informCause) throws ContradictionException { // BEWARE: THIS CODE SHOULD NOT BE MOVED TO THE DOMAIN TO NOT DECREASE PERFORMANCES! boolean change = false; ICause antipromo = cause; if (informCause) { cause = Cause.Null; } int inf = getLB(); int sup = getUB(); if (value == inf && value == sup) { solver.getExplainer().removeValue(this, value, antipromo); this.contradiction(cause, MSG_REMOVE); } else { if (inf <= value && value <= sup) { EventType e = EventType.REMOVE; int aValue = value - OFFSET; change = VALUES.get(aValue); this.VALUES.set(aValue, false); if (change) { this.SIZE.add(-1); if (reactOnRemoval) { delta.add(aValue + OFFSET); } } if (value == inf) { LB.set(VALUES.nextSetBit(aValue)); e = EventType.INCLOW; if (cause.reactOnPromotion()) { cause = Cause.Null; } } else if (value == sup) { UB.set(VALUES.prevSetBit(aValue)); e = EventType.DECUPP; if (cause.reactOnPromotion()) { cause = Cause.Null; } } if (change && !VALUES.isEmpty()) { if (this.instantiated()) { e = EventType.INSTANTIATE; if (cause.reactOnPromotion()) { cause = Cause.Null; } } this.notifyPropagators(e, cause); } else { if (VALUES.isEmpty()) { solver.getExplainer().removeValue(this, value, antipromo); this.contradiction(cause, MSG_EMPTY); } } } } if (change) { solver.getExplainer().removeValue(this, value, antipromo); } return change; }
@Override public boolean contains(int aValue) { // based on "Bounds Consistency Techniques for Long Linear Constraint" aValue -= OFFSET; return aValue >= 0 && VALUES.get(aValue); }
private void addIndex(int i) { contents.set(i); delatDom.remove(i + offset); if (!contents.get(i)) LOGGER.severe("etrange etrange"); size.add(1); }
private void removeIndex(int i) { contents.clear(i); delatDom.remove(i + offset); if (contents.get(i)) LOGGER.severe("etrange etrange"); size.add(-1); }
/** * Checks if the value is present. * * @param x The value to check. */ public boolean contains(int x) { int i = x - offset; return (i >= 0 && i < capacity && contents.get(i)); }