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;