protected void inheritMerged(HierNode<T> x) { BitSet mask = new BitSet(x.getBitMask() != null ? x.getBitMask().length() : 1); for (HierNode<T> p : x.getParents()) { mask.or(p.getBitMask()); } updateMask(x, mask); }
protected void resolveConflicts(HierNode<T> x) { boolean conflicted = false; Collection<HierNode<T>> nodes = new ArrayList<HierNode<T>>(getNodes()); for (HierNode<T> y : nodes) { if (incomparable(x, y)) { // System.out.println( " \t\tIncomparability between " + x + " and " + y ); int sup = superset(y, x); if (sup == 0) { // System.out.println( " \t\tIncomparable, with same mask " + y ); // can't use update mask here, or the already existing node would be removed x.setBitMask(increment(x.getBitMask(), freeBit(x))); propagate(y, freeBit(x, y)); } if (sup > 0) { // System.out.println( " \t\tIncomparable, but as parent " + y ); updateMask(x, increment(x.getBitMask(), freeBit(x))); } int sub = superset(x, y); if (sub > 0) { // System.out.println( " \t\tIncomparable, but as child " + y ); modify(x, y); conflicted = true; } } } if (conflicted) { inheritMerged(x); resolveConflicts(x); } }
// Debug only List<T> ancestorValues(T name) { List<T> anx = new ArrayList<T>(); Set<HierNode<T>> nodes = ancestorNodes(getNode(name)); for (HierNode<T> node : nodes) { anx.add(node.getValue()); } return anx; }
protected void updateMask(HierNode<T> node, BitSet mask) { boolean in = node.getBitMask() != null && contains(node); if (in) { remove(node); } node.setBitMask(mask); if (in) { add(node); } }
protected Set<HierNode<T>> gcs(Set<HierNode<T>> set) { Set<HierNode<T>> s = new HashSet<HierNode<T>>(); Iterator<HierNode<T>> iter = set.iterator(); BitSet a = new BitSet(this.size()); a.or(iter.next().getBitMask()); while (iter.hasNext()) { a.and(iter.next().getBitMask()); } // System.out.println( "Root mask for ceil " + toBinaryString( a ) ); for (HierNode<T> node : getNodes()) { if (superset(node.getBitMask(), a) >= 0) { s.add(node); } } Set<HierNode<T>> cl = ceil(s); return cl; }
public BitSet encode(T member, Collection<T> parents) { BitSet existing = getCode(member); if (existing != null) { return existing; } HierNode<T> node = new HierNode<T>(member); Set<HierNode<T>> parentNodes = floor(parents); for (HierNode<T> parentNode : parentNodes) { node.addParent(parentNode); parentNode.addChild(node); } encode(node); add(node); return node.getBitMask(); }
protected int freeBit(HierNode<T> x, HierNode<T> z) { // System.out.println( "Looking for a free bit in node " + x ); BitSet forbid = new BitSet(this.size()); forbid.or(x.getBitMask()); for (HierNode<T> y : getNodes()) { if (superset(y, x) > 0) { // System.out.println( "\t\t Subtype " + y + " contributes " + toBinaryString( // y.getBitMask() ) ); forbid.or(y.getBitMask()); } if (z != null) { if (superset(y, z) > 0) { // System.out.println( "\t\t Subtype " + y + " contributes " + // toBinaryString( y.getBitMask() ) ); forbid.or(y.getBitMask()); } } if (superset(x, y) < 0) { BitSet diff = singleBitDiff(x.getBitMask(), y.getBitMask()); // System.out.println( "\t\t Incomparable " + y + " contributes " + toBinaryString( diff ) // ); forbid.or(diff); } } // System.out.println( "\t Forbidden mask " + toBinaryString( forbid ) ); return firstZero(forbid); }
@Override protected void add(HierNode<T> node) { super.add(node); bottom.merge(node.getBitMask()); }
protected void propagate(HierNode<T> y, int bit) { Set<HierNode<T>> descendants = descendantNodes(y); for (HierNode<T> s : descendants) { updateMask(s, increment(s.getBitMask(), bit)); } }
protected void modify(HierNode<T> x, HierNode<T> y) { // System.out.println( "Modifying on a inc between " + x + " and " + y ); int i = freeBit(x, y); // System.out.println( "I " + i ); // System.out.println( "Getting parents of " + y + " >> " + y.getParents() ); Collection<HierNode<T>> py = y.getParents(); BitSet t = new BitSet(y.getBitMask().length()); for (HierNode<T> parent : py) { t.or(parent.getBitMask()); } BitSet d = singleBitDiff(t, y.getBitMask()); int inDex = d.nextSetBit(0); if (inDex < 0) { propagate(y, i); } else { // System.out.println( "D " + toBinaryString( d ) ); Set<HierNode<T>> ancestors = ancestorNodes(x); Set<HierNode<T>> affectedAncestors = new HashSet<HierNode<T>>(); for (HierNode<T> anc : ancestors) { if (anc.getBitMask().get(inDex)) { affectedAncestors.add(anc); } } // System.out.println( "Ancestors of " + x + " >> " + ancestors ); // System.out.println( "Affected " + x + " >> " + affectedAncestors ); if (affectedAncestors.size() == 0) { return; } Set<HierNode<T>> gcs = gcs(affectedAncestors); // System.out.println( "GCS of Affected " + gcs ); Set<HierNode<T>> affectedDescendants = new HashSet<HierNode<T>>(); for (HierNode<T> g : gcs) { affectedDescendants.addAll(descendantNodes(g)); } affectedDescendants.remove(x); // take x out it's not yet in the set int dx = firstOne(d); if (bottom.get(i)) { i = freeBit(new HierNode<T>(bottom)); } for (HierNode<T> sub : affectedDescendants) { boolean keepsBit = false; for (HierNode<T> sup : sub.getParents()) { if (!keepsBit && !affectedDescendants.contains(sup) && sup.getBitMask().get(inDex)) { keepsBit = true; } } BitSet subMask = sub.getBitMask(); if (!keepsBit) { subMask = decrement(subMask, dx); } subMask = increment(subMask, i); updateMask(sub, subMask); // System.out.println( "\tModified Desc" + sub ); } inDex = d.nextSetBit(inDex + 1); } }
protected void encode(HierNode<T> node) { Collection<HierNode<T>> parents = node.getParents(); // System.out.println( "Trying to encode " + node ); switch (parents.size()) { case 0: BitSet zero = new BitSet(); if (hasKey(zero)) { HierNode root = getNodeByKey(zero); if (root.getValue() != null) { fixedRoot = true; HierNode previousRoot = root; root = new HierNode((Object) null); root.addChild(previousRoot); previousRoot.addParent(root); root.setBitMask(zero); propagate(previousRoot, freeBit(root)); add(root); } node.addParent(root); updateMask(node, increment(root.getBitMask(), freeBit(root))); } else { updateMask(node, new BitSet()); } break; case 1: HierNode<T> parent = parents.iterator().next(); updateMask(node, increment(parent.getBitMask(), freeBit(parent))); break; default: inheritMerged(node); // System.out.println( " // ----------------------------------------------------------------------------------------- // " ); resolveConflicts(node); break; } }