package test.dr.evomodel.substmodel; import dr.evolution.datatype.GeneralDataType; import dr.oldevomodel.substmodel.FrequencyModel; import dr.oldevomodel.substmodel.GeneralF81Model; import junit.framework.TestCase; /** * Test GeneralF81 matrix exponentiation * * @author Walter Xie */ public class GeneralF81Test extends TestCase { interface Instance { double[] getPi(); double getDistance(); double[] getExpectedResult(); } /* * Results obtained by running the following scilab code, piQ = diag([.2, .3, .25, .25]) ; d = 0.05 ; % Q matrix with zeroed diagonal XQ = [0 1 1 1; 1 0 1 1; 1 1 0 1; 1 1 1 0]; xx = XQ * piQ ; % fill diagonal and normalize by total substitution rate q0 = (xx + diag(-sum(xx,2))) / sum(piQ * sum(xx,2)) ; format('v', 15); expm(q0 * d) */ Instance test0 = new Instance() { public double[] getPi() { return new double[]{0.25, 0.25, 0.25, 0.25}; } public double getDistance() { return 0.1; } public double[] getExpectedResult() { return new double[]{ 0.906379989282, 0.031206670239, 0.031206670239, 0.031206670239, 0.031206670239, 0.906379989282, 0.031206670239, 0.031206670239, 0.031206670239, 0.031206670239, 0.906379989282, 0.031206670239, 0.031206670239, 0.031206670239, 0.031206670239, 0.906379989282 }; } }; Instance test1 = new Instance() { public double[] getPi() { return new double[]{0.50, 0.20, 0.2, 0.1}; } public double getDistance() { return 0.1; } public double[] getExpectedResult() { return new double[]{ 0.929702430444, 0.028119027822, 0.028119027822, 0.014059513911, 0.070297569556, 0.887523888711, 0.028119027822, 0.014059513911, 0.070297569556, 0.028119027822, 0.887523888711, 0.014059513911, 0.070297569556, 0.028119027822, 0.028119027822, 0.873464374800 }; } }; Instance test2 = new Instance() { public double[] getPi() { return new double[]{0.20, 0.30, 0.25, 0.25}; } public double getDistance() { return 0.05; } public double[] getExpectedResult() { return new double[]{ 0.948070805840, 0.019473447810, 0.016227873175, 0.016227873175, 0.012982298540, 0.954561955110, 0.016227873175, 0.016227873175, 0.012982298540, 0.019473447810, 0.951316380475, 0.016227873175, 0.012982298540, 0.019473447810, 0.016227873175, 0.951316380475 }; } }; Instance test3 = new Instance() { public double[] getPi() { return new double[]{0.20, 0.30, 0.25, 0.25}; } public double getDistance() { return 0.2; } public double[] getExpectedResult() { return new double[]{ 0.811647020254, 0.070632367405, 0.058860306171, 0.058860306171, 0.047088244936, 0.835191142722, 0.058860306171, 0.058860306171, 0.047088244936, 0.070632367405, 0.823419081488, 0.058860306171, 0.047088244936, 0.070632367405, 0.058860306171, 0.823419081488 }; } }; Instance[] all = {test0, test1, test2, test3}; public void testGF81() { for (Instance test : all) { double[] pi = test.getPi(); // Parameter freqs = new Parameter.Default(pi); GeneralDataType gdt = new GeneralDataType(new String[]{"1", "2", "3", "4"}); FrequencyModel f = new FrequencyModel(gdt, pi); GeneralF81Model generalF81Model = new GeneralF81Model(f); double distance = test.getDistance(); double[] mat = new double[4 * 4]; generalF81Model.getTransitionProbabilities(distance, mat); final double[] result = test.getExpectedResult(); for (int k = 0; k < mat.length; ++k) { assertEquals(mat[k], result[k], 1e-10); // System.out.print(" " + (mat[k] - result[k])); } } } }