#!/bin/bash #parameters ### # <...?> # # #CONVTEST : copied to reduce the number of dependencies # #export a different CONVTESTDEBUGFILE to redirect debugging output export CONVTESTDEBUGFILE=${CONVTESTDEBUGFILE-'/dev/null'} function run_comparison(){ ## ##Preconditions: and (at least) exist. ##Parameters : <...?> ##Postconditions: "bpcom.bpdiff" and "tracecom.contdiff" exist in the PWD ## local BURNIN=$1 shift 1 bpcomp -x $BURNIN $* 2>&1 >> ${CONVTESTDEBUGFILE} tracecomp -x $BURNIN $* 2>&1 >> ${CONVTESTDEBUGFILE} local tracefiles="" for one_chain_file in $* do tracefiles="${tracefiles} ${one_chain_file}.trace" done #Get the number of cycles finished by the chain that is furthest behind. tail -q -n1 ${tracefiles} | awk 'BEGIN { min = 1000000000;} ((/^[^#]/) && $0 != "") { if($1 < min) min = $1; } END{print min;}' > min.cycles 2>>${CONVTESTDEBUGFILE} #DEBUG tail -q -n1 ${tracefiles} > numcycles.debug 2>> ${CONVTESTDEBUGFILE} } function convtest(){ ## ##Preconditions: "bpcom.bpdiff" and "tracecom.contdiff" exist in the PWD ##Parameters: $1 : maximum maxdiff to accept < 0.1 for good, < 0.3 for acceptable ## $2 : minimum minimium effective size > 300 for good, > 50 for acceptable ##Returns : 1 if we accept the chain, 0 if not yet converged ## local ACCEPTDIFF=$1 local ACCEPTSIZE=$2 local mineff=$(awk 'BEGIN { min = 100000;} NR>1 && $0 != "" { if($2 < min) min = $2; } END{print min;}' tracecomp.contdiff 2>> ${CONVTESTDEBUGFILE}) local maxdiff=$(awk '$1 == "maxdiff" {print $3;}' bpcomp.bpdiff 2>>${CONVTESTDEBUGFILE}) local accept=$(echo "($maxdiff < ${ACCEPTDIFF}) && ($mineff > ${ACCEPTSIZE})" | bc 2>> ${CONVTESTDEBUGFILE}) #DEBUG echo ${mineff} ${maxdiff} ${accept} >> ${CONVTESTDEBUGFILE} return $accept } function chainstuck(){ ## ##Preconditions: "bpcom.bpdiff" and "tracecom.contdiff" exist in the PWD ##Parameters : GIVEUP : the number of MCMC steps to take before deciding to giveup (if not making any progress) OPTIONAL ##Returns : 1 if stuck, 0 if progressing ## local GIVEUP=${1-'10000'} local maxdiff=$(awk '$1 == "maxdiff" {print $3;}' bpcomp.bpdiff 2>> ${CONVTESTDEBUGFILE}) local numpoints=$(cat min.cycles 2>> ${CONVTESTDEBUGFILE}) local stuck=$(echo "($maxdiff == 1) && ($numpoints >= ${GIVEUP})" | bc 2>> ${CONVTESTDEBUGFILE}) return $stuck } function check_terminate(){ ## ##Parameters : <...?> ## local burnin=$1 local acceptdiff=$2 local acceptsize=$3 local giveup=$4 shift 4 run_comparison $burnin $* convtest $acceptdiff $acceptsize local accept=$? chainstuck $giveup local stuck=$? local terminate=$(( !(($accept==0) && ($stuck==0)) )) return $terminate } # #END CONVTEST : Copied # #main / test #check_terminate 500 0.3 50 10000 $* #echo TERMINATE : $? if [ -n "$DEBUG" ] then export > __terminator_environ.txt #not good. The terminator is assuming there is a directory called "HIDDEN" fi interval=$1 burnin=$2 acceptdiff=$3 acceptsize=$4 giveup=$5 shift 5 #Test that all the programs we need are available set -e which bpcomp which tracecomp set +e echo "#Starting the Terminator, PID= ${$} with an interval of ${interval}, a burnin of ${burnin}, acceptdiff: ${acceptdiff}, acceptsize: ${acceptsize}, giveup: ${giveup}" echo "#These are the chains: $*" export RUNNING='1' trap 'echo Terminator got a signal; RUNNING=0; pkill -9 -P $$; exit 0;' SIGTERM SIGINT EXIT sleep ${interval} while [ "${RUNNING}" == "1" ] do check_terminate ${burnin} ${acceptdiff} ${acceptsize} ${giveup} $* if [ "$?" == 1 ] then echo "Converged!" for onechain in $* do echo 0 > ${onechain}.run done exit 0 else #still running. Maybe give some output? echo "Failed convergence test, continuing..." fi if [ "${RUNNING}" == "1" ] then #Need this check so we don't leave extraneous sleep processes if the exit signal came during the above function calls. sleep ${interval} fi done pkill -9 -P $$ echo "#Terminator Terminating"