diff --git a/pom.xml b/pom.xml index 7e8bdc8..20924e6 100644 --- a/pom.xml +++ b/pom.xml @@ -47,7 +47,6 @@ beast.base.minimal.BeastMain CCD - 1.2.0 @@ -194,7 +193,7 @@ src/assembly/beast-package.xml - ${beast.pkg.name}.v${beast.pkg.version} + ${beast.pkg.name}.v${project.version} false diff --git a/src/main/java/ccd/algorithms/NNICladeExpansion.java b/src/main/java/ccd/algorithms/NNICladeExpansion.java index 60dd3fa..6f71260 100644 --- a/src/main/java/ccd/algorithms/NNICladeExpansion.java +++ b/src/main/java/ccd/algorithms/NNICladeExpansion.java @@ -120,6 +120,17 @@ private NovelClade(BitSet taxa) { private long candidatesAlreadyPresent = 0; private boolean computed = false; + /** + * Parent-probability gate: a parent clade whose marginal probability is at + * or above this threshold is not expanded, on the premise that a near-certain + * parent has no alternative resolution worth adding. The default + * {@link Double#POSITIVE_INFINITY} disables the gate (full expansion). Setting + * 1.0 skips only fully-supported parents; lower values prune more. Benchmark + * (Remco): 1.0 is strictly lossless yet ~halves the novel-clade count, and + * 0.99 prunes further for a ~0.02% loss in recovered probability mass. + */ + private double parentProbabilityThreshold = Double.POSITIVE_INFINITY; + /** Taxa-only bits of every clade in the CCD, for fast presence tests. */ private Set existingTaxa; @@ -132,12 +143,42 @@ public NNICladeExpansion(AbstractCCD ccd, PairingMode mode) { this.mode = mode; } + /** + * Sets the parent-probability gate: parent clades whose marginal probability + * is {@code >= threshold} are not expanded. Use + * {@link Double#POSITIVE_INFINITY} (the default) for full expansion. Must be + * called before {@link #compute()}. + * + * @param threshold parent-probability cutoff (skip a parent if its + * probability is at or above this value) + * @return this, for chaining + */ + public NNICladeExpansion setParentProbabilityThreshold(double threshold) { + if (computed) { + throw new IllegalStateException( + "setParentProbabilityThreshold must be called before compute()"); + } + this.parentProbabilityThreshold = threshold; + return this; + } + + /** @return the parent-probability gate (parents with prob >= this are skipped). */ + public double getParentProbabilityThreshold() { + return parentProbabilityThreshold; + } + /** Runs the expansion if not already done; idempotent. */ public NNICladeExpansion compute() { if (computed) { return this; } + // the parent-probability gate reads Clade#getProbability(), which is + // computed lazily and otherwise defaults to -1; populate it when gating + if (parentProbabilityThreshold < Double.POSITIVE_INFINITY) { + ccd.computeCladeProbabilitiesIfDirty(); + } + existingTaxa = new HashSet<>(ccd.getNumberOfClades() * 2); for (Clade clade : ccd.getClades()) { existingTaxa.add(clade.getCladeInBitsTaxaOnly()); @@ -160,6 +201,10 @@ private void expandGraphWide() { if (parent.size() < 3) { continue; } + // skip near-certain parents: a stable parent yields no novel resolution + if (parent.getProbability() >= parentProbabilityThreshold) { + continue; + } for (CladePartition split : parent.getPartitions()) { Clade childA = split.getChildClades()[0]; Clade childB = split.getChildClades()[1]; @@ -226,12 +271,15 @@ private void recombineTree(Node vertex, Map map) { Node left = children.get(0); Node right = children.get(1); Clade parent = map.get(vertex); - // edge above an internal child = NNI site; the other child is the sibling - if (!left.isLeaf()) { - recombineAt(parent, left, right, map); - } - if (!right.isLeaf()) { - recombineAt(parent, right, left, map); + // skip near-certain parents: a stable parent yields no novel resolution + if (parent.getProbability() < parentProbabilityThreshold) { + // edge above an internal child = NNI site; the other child is the sibling + if (!left.isLeaf()) { + recombineAt(parent, left, right, map); + } + if (!right.isLeaf()) { + recombineAt(parent, right, left, map); + } } } for (Node child : children) { diff --git a/src/test/java/test/ccd/algorithms/KRegCCDParameterOptimiserTest.java b/src/test/java/ccd/KRegCCDParameterOptimiserTest.java similarity index 99% rename from src/test/java/test/ccd/algorithms/KRegCCDParameterOptimiserTest.java rename to src/test/java/ccd/KRegCCDParameterOptimiserTest.java index 15dd5e7..a9e87f3 100644 --- a/src/test/java/test/ccd/algorithms/KRegCCDParameterOptimiserTest.java +++ b/src/test/java/ccd/KRegCCDParameterOptimiserTest.java @@ -1,4 +1,4 @@ -package test.ccd.algorithms; +package ccd; import beast.base.evolution.tree.Tree; import beast.base.evolution.tree.TreeParser; diff --git a/src/test/java/test/ccd/algorithms/NNICladeExpansionTest.java b/src/test/java/ccd/NNICladeExpansionTest.java similarity index 99% rename from src/test/java/test/ccd/algorithms/NNICladeExpansionTest.java rename to src/test/java/ccd/NNICladeExpansionTest.java index f73830c..84848c3 100644 --- a/src/test/java/test/ccd/algorithms/NNICladeExpansionTest.java +++ b/src/test/java/ccd/NNICladeExpansionTest.java @@ -1,4 +1,4 @@ -package test.ccd.algorithms; +package ccd; import beast.base.evolution.tree.Tree; import beast.base.evolution.tree.TreeParser; diff --git a/src/test/java/test/ccd/algorithms/NNIRegCCDOptimiserTest.java b/src/test/java/ccd/NNIRegCCDOptimiserTest.java similarity index 99% rename from src/test/java/test/ccd/algorithms/NNIRegCCDOptimiserTest.java rename to src/test/java/ccd/NNIRegCCDOptimiserTest.java index ad642e5..2c96947 100644 --- a/src/test/java/test/ccd/algorithms/NNIRegCCDOptimiserTest.java +++ b/src/test/java/ccd/NNIRegCCDOptimiserTest.java @@ -1,4 +1,4 @@ -package test.ccd.algorithms; +package ccd; import beast.base.evolution.tree.Tree; import beast.base.evolution.tree.TreeParser; diff --git a/src/test/java/test/ccd/algorithms/TreeDistancesTest.java b/src/test/java/ccd/TreeDistancesTest.java similarity index 99% rename from src/test/java/test/ccd/algorithms/TreeDistancesTest.java rename to src/test/java/ccd/TreeDistancesTest.java index b73f1da..04fa0fc 100644 --- a/src/test/java/test/ccd/algorithms/TreeDistancesTest.java +++ b/src/test/java/ccd/TreeDistancesTest.java @@ -1,4 +1,4 @@ -package test.ccd.algorithms; +package ccd; import beast.base.evolution.tree.Tree; import beast.base.evolution.tree.TreeParser; diff --git a/src/test/java/test/ccd/model/CCD0SJTest.java b/src/test/java/ccd/model/CCD0SJTest.java similarity index 98% rename from src/test/java/test/ccd/model/CCD0SJTest.java rename to src/test/java/ccd/model/CCD0SJTest.java index b13f81e..ca64b33 100644 --- a/src/test/java/test/ccd/model/CCD0SJTest.java +++ b/src/test/java/ccd/model/CCD0SJTest.java @@ -1,10 +1,7 @@ -package test.ccd.model; +package ccd.model; -import beast.base.evolution.tree.Node; import beast.base.evolution.tree.Tree; import beast.base.evolution.tree.TreeParser; -import beastfx.app.inputeditor.BeautiPanelConfig; -import ccd.model.*; import org.junit.jupiter.api.Test; import java.util.ArrayList; diff --git a/src/test/java/test/ccd/model/CCD0Test.java b/src/test/java/ccd/model/CCD0Test.java similarity index 99% rename from src/test/java/test/ccd/model/CCD0Test.java rename to src/test/java/ccd/model/CCD0Test.java index 829b470..989fedd 100644 --- a/src/test/java/test/ccd/model/CCD0Test.java +++ b/src/test/java/ccd/model/CCD0Test.java @@ -1,9 +1,8 @@ -package test.ccd.model; +package ccd.model; import beast.base.evolution.tree.Tree; import beast.base.evolution.tree.TreeParser; import beastfx.app.treeannotator.TreeAnnotator; -import ccd.model.*; import org.junit.jupiter.api.Test; import java.io.IOException; diff --git a/src/test/java/test/ccd/model/CCD1CPTest.java b/src/test/java/ccd/model/CCD1CPTest.java similarity index 99% rename from src/test/java/test/ccd/model/CCD1CPTest.java rename to src/test/java/ccd/model/CCD1CPTest.java index 0ae9f82..a72d62a 100644 --- a/src/test/java/test/ccd/model/CCD1CPTest.java +++ b/src/test/java/ccd/model/CCD1CPTest.java @@ -1,10 +1,9 @@ -package test.ccd.model; +package ccd.model; import beast.base.evolution.tree.Tree; import beast.base.evolution.tree.TreeParser; import beastfx.app.treeannotator.TreeAnnotator; import ccd.algorithms.TreeDistances; -import ccd.model.*; import org.junit.jupiter.api.Test; import java.io.IOException; diff --git a/src/test/java/test/ccd/model/CCD1SJTest.java b/src/test/java/ccd/model/CCD1SJTest.java similarity index 99% rename from src/test/java/test/ccd/model/CCD1SJTest.java rename to src/test/java/ccd/model/CCD1SJTest.java index 9c9a933..331236d 100644 --- a/src/test/java/test/ccd/model/CCD1SJTest.java +++ b/src/test/java/ccd/model/CCD1SJTest.java @@ -1,8 +1,7 @@ -package test.ccd.model; +package ccd.model; import beast.base.evolution.tree.Tree; import beast.base.evolution.tree.TreeParser; -import ccd.model.*; import org.junit.jupiter.api.Test; import java.util.ArrayList; diff --git a/src/test/java/test/ccd/model/FiveTaxaTest.java b/src/test/java/ccd/model/FiveTaxaTest.java similarity index 91% rename from src/test/java/test/ccd/model/FiveTaxaTest.java rename to src/test/java/ccd/model/FiveTaxaTest.java index e527f68..418a2ff 100644 --- a/src/test/java/test/ccd/model/FiveTaxaTest.java +++ b/src/test/java/ccd/model/FiveTaxaTest.java @@ -1,10 +1,7 @@ -package test.ccd.model; +package ccd.model; import beast.base.evolution.tree.Tree; import beast.base.evolution.tree.TreeParser; -import ccd.model.CCD0CP; -import ccd.model.Clade; -import ccd.model.CladePartition; import org.junit.jupiter.api.Test; import java.util.ArrayList; diff --git a/src/test/java/test/ccd/model/FourTaxaRootSATest1.java b/src/test/java/ccd/model/FourTaxaRootSATest1.java similarity index 91% rename from src/test/java/test/ccd/model/FourTaxaRootSATest1.java rename to src/test/java/ccd/model/FourTaxaRootSATest1.java index ff2c6ca..ffd7a35 100644 --- a/src/test/java/test/ccd/model/FourTaxaRootSATest1.java +++ b/src/test/java/ccd/model/FourTaxaRootSATest1.java @@ -1,10 +1,7 @@ -package test.ccd.model; +package ccd.model; import beast.base.evolution.tree.Tree; import beast.base.evolution.tree.TreeParser; -import ccd.model.CCD0CP; -import ccd.model.Clade; -import ccd.model.CladePartition; import org.junit.jupiter.api.Test; import java.util.ArrayList; diff --git a/src/test/java/test/ccd/model/FourTaxaRootSATest2.java b/src/test/java/ccd/model/FourTaxaRootSATest2.java similarity index 97% rename from src/test/java/test/ccd/model/FourTaxaRootSATest2.java rename to src/test/java/ccd/model/FourTaxaRootSATest2.java index ca8d03f..79daeaf 100644 --- a/src/test/java/test/ccd/model/FourTaxaRootSATest2.java +++ b/src/test/java/ccd/model/FourTaxaRootSATest2.java @@ -1,8 +1,7 @@ -package test.ccd.model; +package ccd.model; import beast.base.evolution.tree.Tree; import beast.base.evolution.tree.TreeParser; -import ccd.model.*; import org.junit.jupiter.api.Test; import java.util.ArrayList; diff --git a/src/test/java/test/ccd/model/FourTaxaTest1.java b/src/test/java/ccd/model/FourTaxaTest1.java similarity index 92% rename from src/test/java/test/ccd/model/FourTaxaTest1.java rename to src/test/java/ccd/model/FourTaxaTest1.java index 013e3d2..a1b0141 100644 --- a/src/test/java/test/ccd/model/FourTaxaTest1.java +++ b/src/test/java/ccd/model/FourTaxaTest1.java @@ -1,10 +1,7 @@ -package test.ccd.model; +package ccd.model; import beast.base.evolution.tree.Tree; import beast.base.evolution.tree.TreeParser; -import ccd.model.CCD0CP; -import ccd.model.Clade; -import ccd.model.CladePartition; import org.junit.jupiter.api.Test; import java.util.ArrayList; diff --git a/src/test/java/test/ccd/model/FourTaxaTest2.java b/src/test/java/ccd/model/FourTaxaTest2.java similarity index 92% rename from src/test/java/test/ccd/model/FourTaxaTest2.java rename to src/test/java/ccd/model/FourTaxaTest2.java index da2d4d1..8c5ba05 100644 --- a/src/test/java/test/ccd/model/FourTaxaTest2.java +++ b/src/test/java/ccd/model/FourTaxaTest2.java @@ -1,11 +1,7 @@ -package test.ccd.model; +package ccd.model; import beast.base.evolution.tree.Tree; import beast.base.evolution.tree.TreeParser; -import ccd.model.CCD0CP; -import ccd.model.CCD1CP; -import ccd.model.Clade; -import ccd.model.CladePartition; import org.junit.jupiter.api.Test; import java.util.ArrayList; diff --git a/src/test/java/test/ccd/model/GRegCCDTest.java b/src/test/java/ccd/model/GRegCCDTest.java similarity index 98% rename from src/test/java/test/ccd/model/GRegCCDTest.java rename to src/test/java/ccd/model/GRegCCDTest.java index 6b8b74f..6e5d246 100644 --- a/src/test/java/test/ccd/model/GRegCCDTest.java +++ b/src/test/java/ccd/model/GRegCCDTest.java @@ -1,8 +1,7 @@ -package test.ccd.model; +package ccd.model; import beast.base.evolution.tree.Tree; import beast.base.evolution.tree.TreeParser; -import ccd.model.GRegCCD; import org.junit.jupiter.api.Test; import java.util.ArrayList; diff --git a/src/test/java/test/ccd/model/GRegZApproxTest.java b/src/test/java/ccd/model/GRegZApproxTest.java similarity index 96% rename from src/test/java/test/ccd/model/GRegZApproxTest.java rename to src/test/java/ccd/model/GRegZApproxTest.java index 70df756..89d8467 100644 --- a/src/test/java/test/ccd/model/GRegZApproxTest.java +++ b/src/test/java/ccd/model/GRegZApproxTest.java @@ -1,9 +1,7 @@ -package test.ccd.model; +package ccd.model; import beast.base.evolution.tree.Tree; import beast.base.evolution.tree.TreeParser; -import ccd.model.GRegCCD; -import ccd.model.GRegZApprox; import org.junit.jupiter.api.Test; import java.util.ArrayList; diff --git a/src/test/java/test/ccd/model/KRegCCDEntropyTest.java b/src/test/java/ccd/model/KRegCCDEntropyTest.java similarity index 99% rename from src/test/java/test/ccd/model/KRegCCDEntropyTest.java rename to src/test/java/ccd/model/KRegCCDEntropyTest.java index 3fd857e..e114848 100644 --- a/src/test/java/test/ccd/model/KRegCCDEntropyTest.java +++ b/src/test/java/ccd/model/KRegCCDEntropyTest.java @@ -1,8 +1,7 @@ -package test.ccd.model; +package ccd.model; import beast.base.evolution.tree.Tree; import beast.base.evolution.tree.TreeParser; -import ccd.model.KRegCCD; import org.junit.jupiter.api.Test; import java.util.ArrayList; diff --git a/src/test/java/test/ccd/model/KRegCCDMapTreeTest.java b/src/test/java/ccd/model/KRegCCDMapTreeTest.java similarity index 98% rename from src/test/java/test/ccd/model/KRegCCDMapTreeTest.java rename to src/test/java/ccd/model/KRegCCDMapTreeTest.java index adf74e4..b5955b2 100644 --- a/src/test/java/test/ccd/model/KRegCCDMapTreeTest.java +++ b/src/test/java/ccd/model/KRegCCDMapTreeTest.java @@ -1,9 +1,7 @@ -package test.ccd.model; +package ccd.model; import beast.base.evolution.tree.Tree; import beast.base.evolution.tree.TreeParser; -import ccd.model.HeightSettingStrategy; -import ccd.model.KRegCCD; import org.junit.jupiter.api.Test; import java.util.ArrayList; diff --git a/src/test/java/test/ccd/model/KRegCCDSamplingTest.java b/src/test/java/ccd/model/KRegCCDSamplingTest.java similarity index 98% rename from src/test/java/test/ccd/model/KRegCCDSamplingTest.java rename to src/test/java/ccd/model/KRegCCDSamplingTest.java index 229ee77..d98175a 100644 --- a/src/test/java/test/ccd/model/KRegCCDSamplingTest.java +++ b/src/test/java/ccd/model/KRegCCDSamplingTest.java @@ -1,11 +1,8 @@ -package test.ccd.model; +package ccd.model; import beast.base.evolution.tree.Node; import beast.base.evolution.tree.Tree; import beast.base.evolution.tree.TreeParser; -import ccd.model.AbstractCCD; -import ccd.model.HeightSettingStrategy; -import ccd.model.KRegCCD; import org.junit.jupiter.api.Test; import java.util.ArrayList; diff --git a/src/test/java/test/ccd/model/KRegFourTaxaTest.java b/src/test/java/ccd/model/KRegFourTaxaTest.java similarity index 95% rename from src/test/java/test/ccd/model/KRegFourTaxaTest.java rename to src/test/java/ccd/model/KRegFourTaxaTest.java index 017c814..282cf91 100644 --- a/src/test/java/test/ccd/model/KRegFourTaxaTest.java +++ b/src/test/java/ccd/model/KRegFourTaxaTest.java @@ -1,11 +1,7 @@ -package test.ccd.model; +package ccd.model; import beast.base.evolution.tree.Tree; import beast.base.evolution.tree.TreeParser; -import ccd.model.Clade; -import ccd.model.CladePartition; -import ccd.model.KRegCCD; -import ccd.model.RegCCD; import org.junit.jupiter.api.Test; import java.util.ArrayList; diff --git a/src/test/java/test/ccd/model/MRegCCDTest.java b/src/test/java/ccd/model/MRegCCDTest.java similarity index 98% rename from src/test/java/test/ccd/model/MRegCCDTest.java rename to src/test/java/ccd/model/MRegCCDTest.java index 0dc134e..ea8eb4a 100644 --- a/src/test/java/test/ccd/model/MRegCCDTest.java +++ b/src/test/java/ccd/model/MRegCCDTest.java @@ -1,11 +1,7 @@ -package test.ccd.model; +package ccd.model; import beast.base.evolution.tree.Tree; import beast.base.evolution.tree.TreeParser; -import ccd.model.CCD0; -import ccd.model.Clade; -import ccd.model.CladePartition; -import ccd.model.MRegCCD; import ccd.model.bitsets.BitSet; import org.junit.jupiter.api.Test; diff --git a/src/test/java/test/ccd/model/NNIRegCCDTest.java b/src/test/java/ccd/model/NNIRegCCDTest.java similarity index 98% rename from src/test/java/test/ccd/model/NNIRegCCDTest.java rename to src/test/java/ccd/model/NNIRegCCDTest.java index 5d159b9..b8307eb 100644 --- a/src/test/java/test/ccd/model/NNIRegCCDTest.java +++ b/src/test/java/ccd/model/NNIRegCCDTest.java @@ -1,12 +1,8 @@ -package test.ccd.model; +package ccd.model; import beast.base.evolution.tree.Tree; import beast.base.evolution.tree.TreeParser; import ccd.algorithms.NNICladeExpansion.PairingMode; -import ccd.model.Clade; -import ccd.model.CladePartition; -import ccd.model.NNIRegCCD; -import ccd.model.RegCCD; import org.junit.jupiter.api.Test; import java.util.ArrayList; diff --git a/src/test/java/test/ccd/model/ThreeTaxaRootSATest.java b/src/test/java/ccd/model/ThreeTaxaRootSATest.java similarity index 97% rename from src/test/java/test/ccd/model/ThreeTaxaRootSATest.java rename to src/test/java/ccd/model/ThreeTaxaRootSATest.java index 6bf73e1..0e225f4 100644 --- a/src/test/java/test/ccd/model/ThreeTaxaRootSATest.java +++ b/src/test/java/ccd/model/ThreeTaxaRootSATest.java @@ -1,8 +1,7 @@ -package test.ccd.model; +package ccd.model; import beast.base.evolution.tree.Tree; import beast.base.evolution.tree.TreeParser; -import ccd.model.*; import org.junit.jupiter.api.Test; import java.util.ArrayList; diff --git a/src/test/java/test/ccd/model/UniformEscapeCCDTest.java b/src/test/java/ccd/model/UniformEscapeCCDTest.java similarity index 98% rename from src/test/java/test/ccd/model/UniformEscapeCCDTest.java rename to src/test/java/ccd/model/UniformEscapeCCDTest.java index d031256..c05f65b 100644 --- a/src/test/java/test/ccd/model/UniformEscapeCCDTest.java +++ b/src/test/java/ccd/model/UniformEscapeCCDTest.java @@ -1,8 +1,7 @@ -package test.ccd.model; +package ccd.model; import beast.base.evolution.tree.Tree; import beast.base.evolution.tree.TreeParser; -import ccd.model.UniformEscapeCCD; import org.junit.jupiter.api.Test; import java.math.BigInteger;