private void preOrderTraverseSample( MultivariateTraitTree treeModel, NodeRef node, int parentIndex, double[][] treePrecision, double[][] treeVariance) { final int thisIndex = node.getNumber(); if (treeModel.isRoot(node)) { // draw root double[] rootMean = new double[dimTrait]; final int rootIndex = treeModel.getRoot().getNumber(); double rootPrecision = lowerPrecisionCache[rootIndex]; for (int datum = 0; datum < numData; datum++) { // System.arraycopy(meanCache, thisIndex * dim + datum * dimTrait, rootMean, 0, dimTrait); System.arraycopy( cacheHelper.getMeanCache(), thisIndex * dim + datum * dimTrait, rootMean, 0, dimTrait); double[][] variance = computeMarginalRootMeanAndVariance( rootMean, treePrecision, treeVariance, rootPrecision); double[] draw = MultivariateNormalDistribution.nextMultivariateNormalVariance(rootMean, variance); if (DEBUG_PREORDER) { Arrays.fill(draw, 1.0); } System.arraycopy(draw, 0, drawnStates, rootIndex * dim + datum * dimTrait, dimTrait); if (DEBUG) { System.err.println("Root mean: " + new Vector(rootMean)); System.err.println("Root var : " + new Matrix(variance)); System.err.println("Root draw: " + new Vector(draw)); } } } else { // draw conditional on parentState if (!missingTraits.isCompletelyMissing(thisIndex) && !missingTraits.isPartiallyMissing(thisIndex)) { // System.arraycopy(meanCache, thisIndex * dim, drawnStates, thisIndex * dim, dim); System.arraycopy( cacheHelper.getMeanCache(), thisIndex * dim, drawnStates, thisIndex * dim, dim); } else { if (missingTraits.isPartiallyMissing(thisIndex)) { throw new RuntimeException("Partially missing values are not yet implemented"); } // This code should work for sampling a missing tip trait as well, but needs testing // parent trait at drawnStates[parentOffset] double precisionToParent = 1.0 / getRescaledBranchLengthForPrecision(node); double precisionOfNode = lowerPrecisionCache[thisIndex]; double totalPrecision = precisionOfNode + precisionToParent; double[] mean = Ay; // temporary storage double[][] var = tmpM; // temporary storage for (int datum = 0; datum < numData; datum++) { int parentOffset = parentIndex * dim + datum * dimTrait; int thisOffset = thisIndex * dim + datum * dimTrait; if (DEBUG) { double[] parentValue = new double[dimTrait]; System.arraycopy(drawnStates, parentOffset, parentValue, 0, dimTrait); System.err.println("Parent draw: " + new Vector(parentValue)); if (parentValue[0] != drawnStates[parentOffset]) { throw new RuntimeException("Error in setting indices"); } } for (int i = 0; i < dimTrait; i++) { mean[i] = (drawnStates[parentOffset + i] * precisionToParent // + meanCache[thisOffset + i] * precisionOfNode) / totalPrecision; + cacheHelper.getMeanCache()[thisOffset + i] * precisionOfNode) / totalPrecision; for (int j = 0; j < dimTrait; j++) { var[i][j] = treeVariance[i][j] / totalPrecision; } } double[] draw = MultivariateNormalDistribution.nextMultivariateNormalVariance(mean, var); System.arraycopy(draw, 0, drawnStates, thisOffset, dimTrait); if (DEBUG) { System.err.println("Int prec: " + totalPrecision); System.err.println("Int mean: " + new Vector(mean)); System.err.println("Int var : " + new Matrix(var)); System.err.println("Int draw: " + new Vector(draw)); System.err.println(""); } } } } if (peel() && !treeModel.isExternal(node)) { preOrderTraverseSample( treeModel, treeModel.getChild(node, 0), thisIndex, treePrecision, treeVariance); preOrderTraverseSample( treeModel, treeModel.getChild(node, 1), thisIndex, treePrecision, treeVariance); } }
public double calculateLogLikelihood() { double logLikelihood = 0; double[][] traitPrecision = diffusionModel.getPrecisionmatrix(); double logDetTraitPrecision = Math.log(diffusionModel.getDeterminantPrecisionMatrix()); double[] conditionalRootMean = tmp2; final boolean computeWishartStatistics = getComputeWishartSufficientStatistics(); if (computeWishartStatistics) { // if (wishartStatistics == null) { wishartStatistics = new WishartSufficientStatistics(dimTrait); // } else { // wishartStatistics.clear(); // } } // Use dynamic programming to compute conditional likelihoods at each internal node postOrderTraverse( treeModel, treeModel.getRoot(), traitPrecision, logDetTraitPrecision, computeWishartStatistics); if (DEBUG) { System.err.println("mean: " + new Vector(cacheHelper.getMeanCache())); System.err.println("correctedMean: " + new Vector(cacheHelper.getCorrectedMeanCache())); System.err.println("upre: " + new Vector(upperPrecisionCache)); System.err.println("lpre: " + new Vector(lowerPrecisionCache)); System.err.println("cach: " + new Vector(logRemainderDensityCache)); } // Compute the contribution of each datum at the root final int rootIndex = treeModel.getRoot().getNumber(); // Precision scalar of datum conditional on root double conditionalRootPrecision = lowerPrecisionCache[rootIndex]; for (int datum = 0; datum < numData; datum++) { double thisLogLikelihood = 0; // Get conditional mean of datum conditional on root // System.arraycopy(meanCache, rootIndex * dim + datum * dimTrait, conditionalRootMean, 0, // dimTrait); System.arraycopy( cacheHelper.getMeanCache(), rootIndex * dim + datum * dimTrait, conditionalRootMean, 0, dimTrait); if (DEBUG) { System.err.println("Datum #" + datum); System.err.println("root mean: " + new Vector(conditionalRootMean)); System.err.println("root prec: " + conditionalRootPrecision); System.err.println("diffusion prec: " + new Matrix(traitPrecision)); } // B = root prior precision // z = root prior mean // A = likelihood precision // y = likelihood mean // y'Ay double yAy = computeWeightedAverageAndSumOfSquares( conditionalRootMean, Ay, traitPrecision, dimTrait, conditionalRootPrecision); // Also fills in Ay if (conditionalRootPrecision != 0) { thisLogLikelihood += -LOG_SQRT_2_PI * dimTrait + 0.5 * (logDetTraitPrecision + dimTrait * Math.log(conditionalRootPrecision) - yAy); } if (DEBUG) { double[][] T = new double[dimTrait][dimTrait]; for (int i = 0; i < dimTrait; i++) { for (int j = 0; j < dimTrait; j++) { T[i][j] = traitPrecision[i][j] * conditionalRootPrecision; } } System.err.println("Conditional root MVN precision = \n" + new Matrix(T)); System.err.println( "Conditional root MVN density = " + MultivariateNormalDistribution.logPdf( conditionalRootMean, new double[dimTrait], T, Math.log(MultivariateNormalDistribution.calculatePrecisionMatrixDeterminate(T)), 1.0)); } if (integrateRoot) { // Integrate root trait out against rootPrior thisLogLikelihood += integrateLogLikelihoodAtRoot( conditionalRootMean, Ay, tmpM, traitPrecision, conditionalRootPrecision); // Ay is destroyed } if (DEBUG) { System.err.println("yAy = " + yAy); System.err.println( "logLikelihood (before remainders) = " + thisLogLikelihood + " (should match conditional root MVN density when root not integrated out)"); } logLikelihood += thisLogLikelihood; } logLikelihood += sumLogRemainders(); if (DEBUG) { System.out.println("logLikelihood is " + logLikelihood); } if (DEBUG) { // Root trait is univariate!!! System.err.println("logLikelihood (final) = " + logLikelihood); // checkViaLargeMatrixInversion(); } if (DEBUG_PNAS) { checkLogLikelihood( logLikelihood, sumLogRemainders(), conditionalRootMean, conditionalRootPrecision, traitPrecision); } areStatesRedrawn = false; // Should redraw internal node states when needed return logLikelihood; }