package test.beast.evolution.operator;
import org.junit.Test;
import beast.core.State;
import beast.evolution.alignment.Alignment;
import beast.evolution.alignment.Sequence;
import beast.evolution.operators.Exchange;
import beast.util.Randomizer;
import beast.util.TreeParser;
import junit.framework.TestCase;
public class ExchangeOperatorTest extends TestCase {
@Test
public void testNarrowExchange4Taxa() throws Exception {
int runs = 10000;
Randomizer.setSeed(666);
// test that going from source tree to target tree
// is as likely as going the other way around
// taking the HR in account.
Sequence A = new Sequence("A", "A");
Sequence B = new Sequence("B", "A");
Sequence C = new Sequence("C", "A");
Sequence D = new Sequence("D", "A");
Alignment data = new Alignment();
data.initByName("sequence", A, "sequence", B, "sequence", C, "sequence", D,
"dataType", "nucleotide"
);
String sourceTree = "((A:2.0,B:2.0):1.0,(C:1.0,D:1.0):2.0):0.0"; // ((A,B),(C,D))
String targetTree = "((A:2.0,(C:1.0,D:1.0):1.0):1.0,B:3.0):0.0"; // ((A,(C,D)),B)
testNarrowExchange(sourceTree, targetTree, runs, data);
}
@Test
public void testNarrowExchange5Taxa() throws Exception {
int runs = 10000;
Randomizer.setSeed(666);
Sequence A = new Sequence("A", "A");
Sequence B = new Sequence("B", "A");
Sequence C = new Sequence("C", "A");
Sequence D = new Sequence("D", "A");
Sequence E = new Sequence("E", "A");
Alignment data = new Alignment();
data.initByName("sequence", A, "sequence", B, "sequence", C, "sequence", D, "sequence", E,
"dataType", "nucleotide"
);
String sourceTree = "(((A:2.0,B:2.0):1.0,(C:1.0,D:1.0):2.0):1.0,E:4.0):0.0"; // (((A,B),(C,D)),E)
String targetTree = "(((A:2.0,(C:1.0,D:1.0):1.0):1.0,B:3.0):1.0,E:4.0):0.0"; // (((A,(C,D)),B),E)
testNarrowExchange(sourceTree, targetTree, runs, data);
}
@Test
public void testNarrowExchange6Taxa() throws Exception {
int runs = 10000;
Randomizer.setSeed(666);
Sequence A = new Sequence("A", "A");
Sequence B = new Sequence("B", "A");
Sequence C = new Sequence("C", "A");
Sequence D = new Sequence("D", "A");
Sequence E = new Sequence("E", "A");
Sequence F = new Sequence("F", "A");
Alignment data = new Alignment();
data.initByName("sequence", A, "sequence", B, "sequence", C, "sequence", D, "sequence", E, "sequence", F,
"dataType", "nucleotide"
);
//String sourceTree = "((((A:2.0,B:2.0):1.0,(C:1.0,D:1.0):2.0):1.0,E:4.0):1.0,F:5.0):0.0"; // ((((A,B),(C,D)),E),F)
//String targetTree = "((((A:2.0,(C:1.0,D:1.0):1.0):1.0,B:3.0):1.0,E:4.0):1.0,F:5.0):0.0"; // ((((A,(C,D)),B),E),F)
String sourceTree = "(((A:5.0,B:5.0):2.0,((C:5.0,D:5.0):1.0,E:6.0):1.0):1.0,F:8.0):0.0";
String targetTree = "(((A:5.0,B:5.0):2.0,F:7.0):1.0,((C:5.0,D:5.0):1.0,E:6.0):2.0):0.0";
testNarrowExchange(sourceTree, targetTree, runs, data);
}
void testNarrowExchange(String sourceTree, String targetTree, int runs, Alignment data) throws Exception {
// first test going from source to target
double match = 0;
for (int i = 0; i < runs; i++) {
TreeParser tree = new TreeParser();
tree.initByName("taxa", data, "newick", sourceTree, "IsLabelledNewick", true);
State state = new State();
state.initByName("stateNode", tree);
state.initialise();
Exchange operator = new Exchange();
operator.initByName("isNarrow", true, "tree", tree, "weight", 1.0);
double logHR = operator.proposal();
String treeString = tree.getRoot().toNewick();
if (treeString.equals(targetTree) && !Double.isInfinite(logHR)) {
// proportion of accepts equals min(HR, 1.0)
match += Math.min(Math.exp(logHR), 1.0);
}
}
System.out.println(" Matches: " + match * 100.0/runs+ "%");
// now test going from target to source
double match2 = 0;
for (int i = 0; i < runs; i++) {
TreeParser tree = new TreeParser();
tree.initByName("taxa", data, "newick", targetTree, "IsLabelledNewick", true);
State state = new State();
state.initByName("stateNode", tree);
state.initialise();
Exchange operator = new Exchange();
operator.initByName("isNarrow", true, "tree", tree, "weight", 1.0);
double logHR = operator.proposal();
String treeString = tree.getRoot().toNewick();
if (treeString.equals(sourceTree) && !Double.isInfinite(logHR)) {
// proportion of accepts equals min(HR, 1.0)
match2 += Math.min(Math.exp(logHR), 1.0);
}
}
System.out.println(" Matches: " + match2 * 100.0/runs+ "%");
assertTrue("difference(" + 100*(match-match2)/runs + ") exceeds 1.0%", 100.0*Math.abs(match-match2)/runs < 1.0);
}
}