private static int mauCanonicalSub( Tree tree, NodeRef node, int loc, NodeRef[] order, boolean[] wasSwaped) { if (tree.isExternal(node)) { order[loc] = node; assert (loc & 0x1) == 0; return loc + 1; } final boolean swap = MathUtils.nextBoolean(); // wasSwaped[(loc-1)/2] = swap; int l = mauCanonicalSub(tree, tree.getChild(node, swap ? 1 : 0), loc, order, wasSwaped); order[l] = node; assert (l & 0x1) == 1; wasSwaped[(l - 1) / 2] = swap; l = mauCanonicalSub(tree, tree.getChild(node, swap ? 0 : 1), l + 1, order, wasSwaped); return l; }
public double splitClade(Clade parent, Clade[] children) { // the number of all possible clades is 2^n with n the number of tips // reduced by 2 because we wont consider the clades with all or no tips // contained // divide this number by 2 because every clade has a matching clade to // form the split // #splits = 2^(n-1) - 1 final double splits = Math.pow(2, parent.getSize() - 1) - 1; double prob = 0; if (cladeCoProbabilities.containsKey(parent.getBits())) { HashMap<BitSet, Clade> childClades = cladeCoProbabilities.get(parent.getBits()); double noChildClades = 0.0; double sum = 0.0; Set<BitSet> keys = childClades.keySet(); for (BitSet child : keys) { Clade tmp = childClades.get(child); if (parent.getSize() > tmp.getSize() + 1) { sum += (tmp.getSampleCount() + EPSILON) / 2.0; noChildClades += 0.5; } else { sum += (tmp.getSampleCount() + EPSILON); noChildClades += 1.0; } } // add epsilon for each not observed clade sum += EPSILON * (splits - noChildClades); // roulette wheel double randomNumber = Math.random() * sum; for (BitSet child : keys) { Clade tmp = childClades.get(child); if (parent.getSize() > tmp.getSize() + 1) { randomNumber -= (tmp.getSampleCount() + EPSILON) / 2.0; } else { randomNumber -= (tmp.getSampleCount() + EPSILON); } if (randomNumber < 0) { children[0] = tmp; prob = (tmp.getSampleCount() + EPSILON) / sum; break; } } if (randomNumber >= 0) { // randomNumber /= EPSILON; prob = EPSILON / sum; BitSet newChild; BitSet inverseBits; do { do { newChild = (BitSet) parent.getBits().clone(); int index = -1; do { index = newChild.nextSetBit(index + 1); if (index > -1 && MathUtils.nextBoolean()) { newChild.clear(index); } } while (index > -1); } while (newChild.cardinality() == 0 || newChild.cardinality() == parent.getSize()); inverseBits = (BitSet) newChild.clone(); inverseBits.xor(parent.getBits()); } while (childClades.containsKey(newChild) || childClades.containsKey(inverseBits)); Clade randomClade = new Clade(newChild, 0.9999 * parent.getHeight()); children[0] = randomClade; BitSet secondChild = (BitSet) children[0].getBits().clone(); secondChild.xor(parent.getBits()); children[1] = new Clade(secondChild, 0.9999 * parent.getHeight()); } else { BitSet secondChild = (BitSet) children[0].getBits().clone(); secondChild.xor(parent.getBits()); children[1] = childClades.get(secondChild); if (children[1] == null) { children[1] = new Clade(secondChild, 0.9999 * parent.getHeight()); } } } else { prob = 1.0 / splits; BitSet newChild; do { newChild = (BitSet) parent.getBits().clone(); int index = -1; do { index = newChild.nextSetBit(index + 1); if (index > -1 && MathUtils.nextBoolean()) { newChild.clear(index); } } while (index > -1); } while (newChild.cardinality() == 0 || newChild.cardinality() == parent.getSize()); Clade randomClade = new Clade(newChild, 0.9999 * parent.getHeight()); // randomClade.addSample(); randomClade.addHeight(0.9999 * parent.getHeight()); children[0] = randomClade; BitSet secondChild = (BitSet) children[0].getBits().clone(); secondChild.xor(parent.getBits()); children[1] = new Clade(secondChild, 0.9999 * parent.getHeight()); // children[1].addSample(); randomClade.addHeight(0.9999 * parent.getHeight()); } return Math.log(prob); }