/** Resets the markov chain */ public void reset() { currentLength = 0; // reset operator acceptance levels for (int i = 0; i < schedule.getOperatorCount(); i++) { schedule.getOperator(i).reset(); } }
/** * Updates the proposal parameter, based on the target acceptance probability This method relies * on the proposal parameter being a decreasing function of acceptance probability. * * @param op The operator * @param logr */ private void coerceAcceptanceProbability(CoercableMCMCOperator op, double logr) { if (isCoercable(op)) { final double p = op.getCoercableParameter(); final double i = schedule.getOptimizationTransform(MCMCOperator.Utils.getOperationCount(op)); final double target = op.getTargetAcceptanceProbability(); final double newp = p + ((1.0 / (i + 1.0)) * (Math.exp(logr) - target)); if (newp > -Double.MAX_VALUE && newp < Double.MAX_VALUE) { op.setCoercableParameter(newp); } } }
/** * Run the chain for a given number of states. * * @param length number of states to run the chain. * <p>param onTheFlyOperatorWeights */ public long runChain(long length, boolean disableCoerce /*,int onTheFlyOperatorWeights*/) { likelihood.makeDirty(); currentScore = evaluate(likelihood, prior); long currentState = currentLength; final Model currentModel = likelihood.getModel(); if (currentState == 0) { initialScore = currentScore; bestScore = currentScore; fireBestModel(currentState, currentModel); } if (currentScore == Double.NEGATIVE_INFINITY) { // identify which component of the score is zero... if (prior != null) { double logPrior = prior.getLogPrior(likelihood.getModel()); if (logPrior == Double.NEGATIVE_INFINITY) { throw new IllegalArgumentException( "The initial model is invalid because one of the priors has zero probability."); } } String message = "The initial likelihood is zero"; if (likelihood instanceof CompoundLikelihood) { message += ": " + ((CompoundLikelihood) likelihood).getDiagnosis(); } else { message += "!"; } throw new IllegalArgumentException(message); } pleaseStop = false; isStopped = false; String diagnostic = ""; // int otfcounter = onTheFlyOperatorWeights > 0 ? onTheFlyOperatorWeights : 0; double[] logr = {0.0}; boolean usingFullEvaluation = true; // set ops count in mcmc element instead if (fullEvaluationCount == 0) // Temporary solution until full code review usingFullEvaluation = false; boolean fullEvaluationError = false; while (!pleaseStop && (currentState < (currentLength + length))) { // periodically log states fireCurrentModel(currentState, currentModel); if (pleaseStop) { isStopped = true; break; } // Get the operator final int op = schedule.getNextOperatorIndex(); final MCMCOperator mcmcOperator = schedule.getOperator(op); double oldScore = currentScore; // assert Profiler.startProfile("Store"); // The current model is stored here in case the proposal fails if (currentModel != null) { currentModel.storeModelState(); } // assert Profiler.stopProfile("Store"); boolean operatorSucceeded = true; double hastingsRatio = 1.0; boolean accept = false; logr[0] = -Double.MAX_VALUE; try { // The new model is proposed // assert Profiler.startProfile("Operate"); if (DEBUG) { System.out.println("\n&& Operator: " + mcmcOperator.getOperatorName()); } if (mcmcOperator instanceof GeneralOperator) { hastingsRatio = ((GeneralOperator) mcmcOperator).operate(prior, likelihood); } else { hastingsRatio = mcmcOperator.operate(); } // assert Profiler.stopProfile("Operate"); } catch (OperatorFailedException e) { operatorSucceeded = false; } double score = 0.0; double deviation = 0.0; // System.err.print("" + currentState + ": "); if (operatorSucceeded) { // The new model is proposed // assert Profiler.startProfile("Evaluate"); if (DEBUG) { System.out.println("** Evaluate"); } long elapsedTime = 0; if (PROFILE) { elapsedTime = System.currentTimeMillis(); } // The new model is evaluated score = evaluate(likelihood, prior); if (PROFILE) { mcmcOperator.addEvaluationTime(System.currentTimeMillis() - elapsedTime); } // assert Profiler.stopProfile("Evaluate"); if (usingFullEvaluation) { // This is a test that the state is correctly restored. The // restored state is fully evaluated and the likelihood compared with // that before the operation was made. likelihood.makeDirty(); final double testScore = evaluate(likelihood, prior); if (Math.abs(testScore - score) > EVALUATION_TEST_THRESHOLD) { Logger.getLogger("error") .severe( "State was not correctly calculated after an operator move.\n" + "Likelihood evaluation: " + score + "\nFull Likelihood evaluation: " + testScore + "\n" + "Operator: " + mcmcOperator + " " + mcmcOperator.getOperatorName()); fullEvaluationError = true; } } if (score > bestScore) { bestScore = score; fireBestModel(currentState, currentModel); } accept = mcmcOperator instanceof GibbsOperator || acceptor.accept(oldScore, score, hastingsRatio, logr); deviation = score - oldScore; } // The new model is accepted or rejected if (accept) { if (DEBUG) { System.out.println( "** Move accepted: new score = " + score + ", old score = " + oldScore); } mcmcOperator.accept(deviation); currentModel.acceptModelState(); currentScore = score; // if( otfcounter > 0 ) { // --otfcounter; // if( otfcounter == 0 ) { // adjustOpWeights(currentState); // otfcounter = onTheFlyOperatorWeights; // } // } if (usingFullEvaluation) { oldScore = score; // for the usingFullEvaluation test diagnostic = likelihood instanceof CompoundLikelihood ? ((CompoundLikelihood) likelihood).getDiagnosis() : ""; } } else { if (DEBUG) { System.out.println( "** Move rejected: new score = " + score + ", old score = " + oldScore); } mcmcOperator.reject(); // assert Profiler.startProfile("Restore"); currentModel.restoreModelState(); } // assert Profiler.stopProfile("Restore"); if (usingFullEvaluation) { // This is a test that the state is correctly restored. The // restored state is fully evaluated and the likelihood compared with // that before the operation was made. likelihood.makeDirty(); final double testScore = evaluate(likelihood, prior); final String d2 = likelihood instanceof CompoundLikelihood ? ((CompoundLikelihood) likelihood).getDiagnosis() : ""; if (Math.abs(testScore - oldScore) > EVALUATION_TEST_THRESHOLD) { final Logger logger = Logger.getLogger("error"); logger.severe( "State was not correctly restored after reject step.\n" + "Likelihood before: " + oldScore + " Likelihood after: " + testScore + "\n" + "Operator: " + mcmcOperator + " " + mcmcOperator.getOperatorName() + (diagnostic.length() > 0 ? "\n\nDetails\nBefore: " + diagnostic + "\nAfter: " + d2 : "")); fullEvaluationError = true; } } if (!disableCoerce && mcmcOperator instanceof CoercableMCMCOperator) { coerceAcceptanceProbability((CoercableMCMCOperator) mcmcOperator, logr[0]); } if (usingFullEvaluation) { if (schedule.getMinimumAcceptAndRejectCount() >= minOperatorCountForFullEvaluation && currentState >= fullEvaluationCount) { // full evaluation is only switched off when each operator has done a // minimum number of operations (currently 1) and fullEvalationCount // operations in total. usingFullEvaluation = false; if (fullEvaluationError) { // If there has been an error then stop with an error throw new RuntimeException( "One or more evaluation errors occurred during the test phase of this\n" + "run. These errors imply critical errors which may produce incorrect\n" + "results."); } } } fireEndCurrentIteration(currentState); currentState += 1; } currentLength = currentState; return currentLength; }