package statalign.base.mcmc; import statalign.base.Tree; import statalign.base.Utils; import statalign.base.Vertex; import statalign.mcmc.McmcModule; import statalign.mcmc.McmcMove; public class AlignmentMove extends McmcMove { Tree tree = null; Vertex selectedRoot; double[] weights; double P; // for hmm3 double proposalParamMultiplier = 1.0; double[] realParams; public boolean autoTunable = true; private boolean useModelExtInProposal = false; private boolean useModextEm = false, useModextUpp = false; double oldll; final static double LEAFCOUNT_POWER = 1.0; // Original //final static double LEAFCOUNT_POWER = -2.0; final static double SELTRLEVPROB[] = { 0.9, 0.6, 0.4, 0.2, 0 }; // Original //final static double SELTRLEVPROB[] = { 0.6, 0.6, 0.4, 0.2, 0 }; public double minAcceptance = 0.05; // keep tuning till we get to this public static final double MIN_WINDOW_MULTIPLIER = 0.5; public static final double MAX_WINDOW_MULTIPLIER = 1.5; public AlignmentMove (McmcModule m, double _P, String n) { owner = m; name = n; P = _P; spanMultiplier = 0.9; autoTune = false; } public void setProposalParamMultiplier(double p) { proposalParamMultiplier = p; } public void useModelExtInProposal() { useModelExtInProposal = true; } public void copyState(Object externalState) { if (externalState instanceof Tree) { if (tree == null) { tree = (Tree) externalState; } } else { throw new IllegalArgumentException("AlignmentMove.copyState must take an argument of type Tree."); } if (!useModelExtInProposal) { useModextEm = Utils.USE_MODEXT_EM; useModextUpp = Utils.USE_MODEXT_UPP; Utils.USE_MODEXT_EM = false; Utils.USE_MODEXT_UPP = false; } if (proposalWidthControlVariable < MIN_WINDOW_MULTIPLIER) { proposalWidthControlVariable = MIN_WINDOW_MULTIPLIER; } if (proposalWidthControlVariable > MAX_WINDOW_MULTIPLIER) { proposalWidthControlVariable = MAX_WINDOW_MULTIPLIER; } Utils.WINDOW_MULTIPLIER = proposalWidthControlVariable; oldll = owner.curLogLike; weights = new double[tree.vertex.length]; for (int i = 0; i < tree.vertex.length; i++) { tree.vertex[i].selected = false; } tree.countLeaves(); for (int i = 0; i < weights.length; i++) { weights[i] = Math.pow(tree.vertex[i].leafCount, LEAFCOUNT_POWER); } int k = Utils.weightedChoose(weights, null); selectedRoot = tree.vertex[k]; selectedRoot.selectSubtree(SELTRLEVPROB, 0); // tree.hmm3.updateParam(new double[]{P}); // selectedRoot.recursivelyUpdateHmm3Matrices(); } public double proposal(Object externalState) { ((CoreMcmcModule) owner).getModelExtMan().beforeAlignChange(tree, selectedRoot); if (proposalParamMultiplier != 1.0 && selectedRoot != tree.root) { realParams = tree.hmm2.params.clone(); selectedRoot.updateHmm2Matrix(new double[] {realParams[0], proposalParamMultiplier*realParams[1], proposalParamMultiplier*realParams[2]}); } double logProposalRatio = selectedRoot.selectAndResampleAlignment(); if (proposalParamMultiplier != 1.0 && selectedRoot != tree.root) { selectedRoot.updateHmm2Matrix(realParams); selectedRoot.calcOrphan(); selectedRoot.parent.calcFelsen(); selectedRoot.parent.calcOrphan(); selectedRoot.parent.calcIndelLogLike(); selectedRoot.calcAllUp(); } // NB need to reset them here, because they're used in the likelihood computation as well return logProposalRatio; } public double logPriorDensity(Object externalState) { return 0.0; } public void updateLikelihood(Object externalState) { owner.setLogLike(((CoreMcmcModule) owner).getModelExtMan().logLikeAlignChange(tree, selectedRoot)); } public void restoreState(Object externalState) { selectedRoot.alignRestore(); ///selectedRoot.calcOrphan(); if (selectedRoot != tree.root) { // selectedRoot.parent.calcFelsen(); // selectedRoot.parent.calcOrphan(); // selectedRoot.parent.calcIndelLogLike(); ///selectedRoot.calcAllUp(); } // tree.root.calcFelsenRecursively(); // tree.root.calcOrphanRecursively(); // tree.root.calcIndelLogLikeRecursively(); // selectedRoot.calcFelsenRecursively(); // selectedRoot.calcOrphanRecursively(); // selectedRoot.calcIndelLogLikeRecursively(); if (Utils.USE_UPPER) { //owner.root.calcFelsenRecursively(); //tree.root.calcUpperRecursively(); ///selectedRoot.calcUpperFromRoot(); } if (Utils.USE_MODEXT_EM) { selectedRoot.updateAlignedParentInWindow(); } } public void afterMove(Object externalState) { ((CoreMcmcModule) owner).getModelExtMan().afterAlignChange(tree, selectedRoot,lastMoveAccepted); if (lastMoveAccepted && (owner.curLogLike == oldll)) acceptanceCount--; if (!useModelExtInProposal) { Utils.USE_MODEXT_EM = useModextEm; Utils.USE_MODEXT_UPP = useModextUpp; if (lastMoveAccepted) { //if (Utils.DEBUG) tree.root.updateAlignedRecursivelyWithCheck(); //tree.root.updateAlignedRecursively(); if (Utils.USE_MODEXT_EM) { selectedRoot.updateAlignedRecursivelyInWindow(); selectedRoot.updateAlignedParentInWindow(); } } } if (Utils.DEBUG && Utils.USE_MODEXT_EM) { tree.root.updateAlignedRecursivelyWithCheck(); } } @Override public void afterFirstHalfBurnin() { if (autoTunable) { autoTune = true; } } }