package statalign.mcmc;
import java.util.List;
import java.util.ArrayList;
import statalign.base.Utils;
import static statalign.utils.Reversed.reversed;
public class McmcCombinationMove extends McmcMove {
protected List<McmcMove> mcmcMoves = new ArrayList<McmcMove>();
public McmcCombinationMove (ArrayList<McmcMove> moves) {
if (moves.size() < 2) {
throw new IllegalArgumentException("McmcCombinationMove must contain at least two McmcMove objects");
}
name = moves.get(0).name;
mcmcMoves.add(moves.get(0));
for (int i=1; i<moves.size(); i++) {
name += "_"+moves.get(i).name;
mcmcMoves.add(moves.get(i));
}
}
public void copyState(Object externalState) {
if (Utils.DEBUG) System.out.println(name+" "+proposalWidthControlVariable);
for (McmcMove mcmcMove : mcmcMoves) {
mcmcMove.inCombination = true;
mcmcMove.copyState(externalState);
mcmcMove.inCombination = false;
}
}
public double proposal(Object externalState) {
double logProposalRatio = 0;
for (McmcMove mcmcMove : mcmcMoves) {
if (Utils.DEBUG) System.out.print(mcmcMove.name+" "+mcmcMove.proposalWidthControlVariable+" ");
mcmcMove.inCombination = true;
double oldProposalWidthControlVariable = mcmcMove.proposalWidthControlVariable;
mcmcMove.proposalWidthControlVariable *= proposalWidthControlVariable;
//mcmcMove.proposalCount++;
logProposalRatio += mcmcMove.proposal(externalState);
mcmcMove.proposalWidthControlVariable = oldProposalWidthControlVariable;
mcmcMove.inCombination = false;
// In combination moves, the counts of the sub-moves are not incremented
}
if (Utils.DEBUG) System.out.println();
// We implicitly assume here that the order of the proposals
// does not matter.
return logProposalRatio;
}
@Override
public McmcModule getOwner() {
return mcmcMoves.get(0).getOwner();
// NB it doesn't matter which McmcMove we use here, since it is
// only used to call back to the Mcmc object running
// all of them, but since the McmcCombinationMove does not necessarily
// have a unique ModelExtension as its owner, we must use one of
// its McmcMove objects to do the callback.
}
public double logPriorDensity(Object externalState) {
double logPriorDensity = 0;
for (McmcMove mcmcMove : mcmcMoves) {
mcmcMove.inCombination = true;
logPriorDensity += mcmcMove.logPriorDensity(externalState);
mcmcMove.inCombination = false;
}
return logPriorDensity;
}
public void updateLikelihood(Object externalState) {
for (McmcMove mcmcMove : mcmcMoves) {
mcmcMove.inCombination = true;
mcmcMove.updateLikelihood(externalState);
mcmcMove.inCombination = false;
}
}
public void afterMove(Object externalState) {
if (Utils.DEBUG) System.out.println((this.lastMoveAccepted ? "Accepted (" : "Rejected (") + this.acceptanceRate() + ")");
for (McmcMove mcmcMove : mcmcMoves) {
mcmcMove.inCombination = true;
mcmcMove.afterMove(externalState);
mcmcMove.inCombination = false;
}
}
public void restoreState(Object externalState) {
for (McmcMove mcmcMove : reversed(mcmcMoves)) {
mcmcMove.inCombination = true;
mcmcMove.restoreState(externalState);
mcmcMove.inCombination = false;
}
}
}