package statalign.model.ext.plugins.structalign;
import java.util.ArrayList;
import statalign.base.Utils;
import statalign.base.Vertex;
import statalign.base.Tree;
import statalign.mcmc.McmcMove;
import statalign.model.ext.plugins.StructAlign;
public class AlignmentMove extends McmcMove {
Tree tree;
public StructAlignMoveParams moveParams = new StructAlignMoveParams();
double[][] oldaxes = null;
double[] oldangles = null;
double[][] oldxlats = null;
double[][][] oldrots = null;
double oldll;
double heat = 1.0;
double secondHeat = 1.0;
boolean autoTunable = true;
public Vertex subtreeRoot;
int nLeaves;
ArrayList<Integer> subtreeLeaves;
int index;
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 (StructAlign s, String n) {
owner = s;
name = n;
autoTune = false;
proposalWidthControlVariable = 1.0;
// This move gets autoTune'd via the core AlignmentMove
}
public Vertex getSubtreeRoot() {
return subtreeRoot;
}
public void copyState(Object externalState) {
if (externalState instanceof Tree) {
tree = (Tree) externalState;
}
else {
throw new IllegalArgumentException("AlignmentMove.copyState must take an argument of type Tree.");
}
if (proposalWidthControlVariable < MIN_WINDOW_MULTIPLIER) {
proposalWidthControlVariable = MIN_WINDOW_MULTIPLIER;
}
if (proposalWidthControlVariable > MAX_WINDOW_MULTIPLIER) {
proposalWidthControlVariable = MAX_WINDOW_MULTIPLIER;
}
Utils.WINDOW_MULTIPLIER = proposalWidthControlVariable;
subtreeRoot = Funcs.sampleVertex(tree);
if (Utils.DEBUG) System.out.println("subtreeRoot = "+subtreeRoot.index);
nLeaves = ((StructAlign) owner).coords.length;
subtreeLeaves = Subtree.getSubtreeLeaves(tree, subtreeRoot, nLeaves);
index = subtreeLeaves.get(Utils.generator.nextInt(subtreeLeaves.size()));
((StructAlign) owner).oldAlign = ((StructAlign) owner).curAlign;
oldll = owner.getLogLike();
}
public double proposal(Object externalState) {
double logProposalRatio = subtreeRoot.realignToParent(heat);
((StructAlign) owner).curAlign = tree.getState().getLeafAlign();
return logProposalRatio;
}
public double logPriorDensity(Object externalState) {
return 0; // Uniform prior
}
public void updateLikelihood(Object externalState) {
owner.setLogLike( ((StructAlign) owner).calcAllColumnContrib() );
}
public void restoreState(Object externalState) {
if (Utils.DEBUG && Utils.USE_MODEXT_EM) tree.root.updateAlignedRecursivelyWithCheck();
if (Utils.DEBUG) tree.root.recomputeCheckLogLike();
subtreeRoot.alignRestore();
// subtreeRoot.calcOrphan();
// subtreeRoot.calcAllUp();
//System.out.println("oldll = "+oldll+", newll = "+owner.getLogLike());
if (Utils.DEBUG) tree.root.recomputeCheckLogLike();
if (Utils.USE_MODEXT_EM) subtreeRoot.updateAlignedParentInWindow();
if (Utils.DEBUG && Utils.USE_MODEXT_EM) tree.root.updateAlignedRecursivelyInWindowWithCheck();
if (Utils.DEBUG && Utils.USE_MODEXT_EM) tree.root.updateAlignedRecursivelyWithCheck();
((StructAlign) owner).curAlign = ((StructAlign) owner).oldAlign;
owner.setLogLike(oldll);
}
public void afterMove(Object externalState) {
if (lastMoveAccepted && lastLogProposalRatio == 0) acceptanceCount--;
if (Utils.DEBUG) {
// tree.root.calcFelsenRecursively();
// tree.root.calcOrphanRecursively();
// tree.root.calcIndelLogLikeRecursively();
// if (Utils.USE_UPPER) {
// //owner.root.calcFelsenRecursively();
// subtreeRoot.calcUpperFromRoot();
// //tree.root.calcUpperRecursively();
// }
//tree.root.recomputeCheckLogLike();
}
// if (lastMoveAccepted && subtreeRoot != tree.root) {
// subtreeRoot.updateAlignedParent();
// }
//if (lastMoveAccepted && (owner.getLogLike() == oldll)) acceptanceCount--;
}
@Override
public void afterFirstHalfBurnin() {
heat = secondHeat;
//autoTune = autoTunable;
}
}