Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
79 commits
Select commit Hold shift + click to select a range
dc6f37f
moved some utility functions to MCMC_util.R
danielturek Apr 8, 2025
ba23006
draft of derived_logProb
danielturek Apr 9, 2025
f1f23bf
working on derived quantities
danielturek Apr 9, 2025
88f017d
update to printing
danielturek Apr 10, 2025
a71de52
working on logProb function
danielturek Apr 10, 2025
a053fc5
working on derived functions
danielturek Apr 10, 2025
8323764
updated notes
danielturek Apr 11, 2025
8bae542
update to derived function
danielturek Apr 11, 2025
fc4961d
working on names
danielturek Apr 11, 2025
0ab40d1
working on derived quantities
danielturek Apr 11, 2025
f9b509e
minor update to build
danielturek Apr 11, 2025
ff39203
updates to derived functions
danielturek Apr 13, 2025
4ae12eb
high level function calls
danielturek Apr 13, 2025
803fa08
running name change, and dealing with length 1 vectors
danielturek Apr 15, 2025
efa4fc0
fixed length = 1 vectors
danielturek Apr 15, 2025
550cdb6
changed mean and variance to use mvSamples
danielturek Apr 16, 2025
53e09b0
updates
danielturek Apr 16, 2025
0bd0e22
name change to printing
danielturek Apr 16, 2025
e38cd2e
added frequencyRecord and saved old mvSamples implementations
danielturek Apr 17, 2025
368b694
working on argument names
danielturek Apr 17, 2025
5b3dc2c
comments on questions
danielturek Apr 18, 2025
bf1bf97
updated comments
danielturek Apr 18, 2025
706b14a
updated notes based on discussion
danielturek Apr 23, 2025
2db7f87
removed old versions of mean and variance
danielturek Apr 23, 2025
4828ca7
removed storage arrays in mean and variance
danielturek Apr 23, 2025
2b22c47
changelog
danielturek Apr 23, 2025
8a7710c
new nimble option MCMCreturnDerivedQuantities to control derived return
danielturek Apr 23, 2025
4c7ad1b
derived has final position in runMCMC output list
danielturek Apr 23, 2025
695e45f
updated comments
danielturek Apr 23, 2025
2d24b99
list names for logProb derived quantity
danielturek Apr 23, 2025
896026b
fixed error in saveFrequency
danielturek Apr 23, 2025
f87442d
added names generation section to derived functions
danielturek Apr 24, 2025
ca2be2e
updates to saveFrequency
danielturek Apr 24, 2025
db09855
update to comments
danielturek Apr 24, 2025
2bd4bcc
change chain index variable from i to chain in runMCMC
danielturek Apr 24, 2025
2619b15
fix name of nchains argument to chain
danielturek Apr 24, 2025
1502fed
updated comments
danielturek Apr 24, 2025
cd23f61
derived NF setup functions now take mcmc argument
danielturek Apr 24, 2025
ce9c032
comments on changes
danielturek Apr 24, 2025
581e58a
updates to fhanges
danielturek Apr 24, 2025
aa15e48
updates
danielturek Apr 25, 2025
21ff58d
logical error in recording frequency zero
danielturek Apr 25, 2025
57b3016
added predictive
danielturek Apr 25, 2025
1b41ddb
updated comments
danielturek Apr 25, 2025
84a55f6
typo
danielturek Apr 25, 2025
bb625e0
option to not sample posterior predictive nodes
danielturek Apr 26, 2025
ae74e91
added check to predictive derived function for sampled nodes
danielturek Apr 27, 2025
40a2e5f
dealing with burnin
danielturek Apr 28, 2025
9422117
added comments
danielturek Apr 28, 2025
5d1ea50
removed legacy comments
danielturek May 6, 2025
eeceaa4
added comments from meeting
danielturek May 6, 2025
ec1e4b5
readded nburnin and thin arguments to before_chain method
danielturek May 7, 2025
2c75d49
added samplerPredictiveNodes argument to configureMCMC
danielturek May 7, 2025
477f686
added sort control argument to predictive derived quantity funciton
danielturek May 7, 2025
60e54fa
changed derived quantity run method argumnet to index
danielturek May 7, 2025
b2c95a0
commit changed name of index argument to timesRan
danielturek May 7, 2025
8c0c032
updated comments about timesRan
danielturek May 7, 2025
8c87e68
default value for derived interval is thin
danielturek May 8, 2025
5749b9a
updated nodes argument and simNodes for predictive sampler
danielturek May 9, 2025
ff5d647
updated roxygen for predictive derived quantity
danielturek May 9, 2025
7f61c90
changed name to samplePredictiveNodes
danielturek May 12, 2025
f9515b5
update to logic for determing simNodes
danielturek May 12, 2025
ea1118e
predictive sampler updates mvSaved also
danielturek May 12, 2025
e819b0c
updates to predictive determination of node sets
danielturek May 12, 2025
adf77da
updates
danielturek May 12, 2025
093b1ff
catch for buildMCMC erroring out before on.exit code
danielturek May 13, 2025
b84b686
changed get_names and get_results
danielturek May 16, 2025
fd5e9eb
dervied mean and variance handle nodes as a list
danielturek May 27, 2025
4745448
runMCMC handles derivedQuantity results with zero columns
danielturek May 27, 2025
45926f7
more complete handling of NAs in derived quantity functions
danielturek May 27, 2025
bd9d2b0
updated use of .all as a list for logProb derived quantity
danielturek May 27, 2025
5584530
reverted handling of .all for logProb
danielturek May 27, 2025
aa974bd
revert logProb = TRUE behavior from configureMCMC
danielturek May 27, 2025
319e411
Tests for derived quantities feature (#1548)
kenkellner May 29, 2025
422fac8
Fix minor roxygen conflict in MCMC_build.R.
paciorek Jun 20, 2025
37864b3
compulsory reset on first run of MCMC
danielturek Jun 24, 2025
b449cdc
Merge branch 'devel' into derived_quantities
danielturek Jun 24, 2025
7870b8c
Fix local assignment for reset argument
danielturek Jun 26, 2025
f5daeae
removed extra space at end of samplerConf$show method
danielturek Jun 26, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/nimble/DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ Collate:
MCMC_build.R
MCMC_run.R
MCMC_samplers.R
MCMC_derived.R
MCMC_conjugacy.R
MCMC_autoBlock.R
MCMC_RJ.R
Expand Down
5 changes: 5 additions & 0 deletions packages/nimble/NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,11 @@ export(dcar_proper)
export(dcat)
export(dconstraint)
export(ddexp)
export(derived_BASE)
export(derived_logProb)
export(derived_mean)
export(derived_predictive)
export(derived_variance)
export(ddirch)
export(decide)
export(decideAndJump)
Expand Down
2 changes: 1 addition & 1 deletion packages/nimble/R/MCMC_autoBlock.R
Original file line number Diff line number Diff line change
Expand Up @@ -416,7 +416,7 @@ autoBlockClass <- setRefClass(
## msg <- 'using \'posterior_predictive\' sampler may lead to results we don\'t want'
## cat(paste0('\nWARNING: ', msg, '\n\n')); warning(msg)
## }
if(grepl('^conjugate_', ss$name) && getNimbleOption('verifyConjugatePosteriors')) {
if(grepl('^conjugate_', ss$name) && getNimbleOption('MCMCverifyConjugatePosteriors')) {
##msg <- 'conjugate sampler running slow due to checking the posterior'
##cat(paste0('\nWARNING: ', msg, '\n\n')); warning(msg)
warn <- TRUE
Expand Down
123 changes: 98 additions & 25 deletions packages/nimble/R/MCMC_build.R
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#'
#' \code{initializeModel}: Boolean specifying whether to run the initializeModel routine on the underlying model object, prior to beginning MCMC sampling (default = TRUE).
#'
#' \code{chain}: Integer specifying the MCMC chain number. The chain number is passed to each MCMC sampler's before_chain method. The value for this argument is specified automatically from invocation via runMCMC, and need not be supplied when calling mcmc$run (default = 1).
#' \code{chain}: Integer specifying the MCMC chain number. The chain number is passed to each MCMC sampler's before_chain and after_chain methods. The value for this argument is specified automatically from invocation via runMCMC, and genernally need not be supplied when calling mcmc$run (default = 1).
#'
#' \code{time}: Boolean specifying whether to record runtimes of the individual internal MCMC samplers. When \code{time = TRUE}, a vector of runtimes (measured in seconds) can be extracted from the MCMC using the method \code{mcmc$getTimes()} (default = FALSE).
Expand Down Expand Up @@ -180,16 +181,47 @@ buildMCMC <- nimbleFunction(
for(i in seq_along(conf$samplerConfs))
samplerFunctions[[i]] <- conf$samplerConfs[[i]]$buildSampler(model=model, mvSaved=mvSaved)
}

## construct mvSamples and mvSamples2
mvSamplesConf <- conf$getMvSamplesConf(1)
mvSamples2Conf <- conf$getMvSamplesConf(2)
mvSamples <- modelValues(mvSamplesConf)
mvSamples2 <- modelValues(mvSamples2Conf)

## build derived quantity intervals
derivedFunctions <- nimbleFunctionList(derived_BASE)
numDerived <- length(conf$derivedConfs)
derivedIntervals <- numeric(max(numDerived, 2)) ## force to be a vector
for(i in seq_along(conf$derivedConfs)) {
derivedIntervals[i] <- conf$derivedConfs[[i]]$interval
}

## build derived quantity function list
derivedFunctions <- nimbleFunctionList(derived_BASE)
## code below allows 'mcmc' to be a setup argument of derived quantity nimbleFunctions
on.exit({
for(i in seq_along(conf$derivedConfs)) {
derivedFunctions[[i]] <- conf$derivedConfs[[i]]$buildDerived(model=model, mcmc=nfRefClassObject)
}
## need to catch the case where buildMCMC errors out early,
## prior to executing the final lines which actually create the nfRefClassObject object:
if(exists('nfRefClassObject', inherits = FALSE)) {
nfRefClassObject[['derivedFunctions']] <- nf_preProcessMemberDataObject(get('derivedFunctions'))
}
}, add = TRUE)

## for naming the derivedList return object from runMCMC
derivedTypes <- sapply(conf$derivedConfs, `[[`, 'name')
if(length(derivedTypes) == 0) derivedTypes <- character()
## used for extracting names of derived quantities,
## having as member data is necessary for compilation
derivedNames <- character(2)

samplerExecutionOrderFromConfPlusTwoZeros <- c(conf$samplerExecutionOrder, 0, 0) ## establish as a vector
monitors <- mcmc_processMonitorNames(model, conf$monitors)
monitors2 <- mcmc_processMonitorNames(model, conf$monitors2)
thinFromConfVec <- c(conf$thin, conf$thin2) ## vector
thinToUseVec <- c(0, 0) ## vector, needs to member data
mvSamplesConf <- conf$getMvSamplesConf(1)
mvSamples2Conf <- conf$getMvSamplesConf(2)
mvSamples <- modelValues(mvSamplesConf)
mvSamples2 <- modelValues(mvSamples2Conf)
samplerTimes <- c(0,0) ## establish as a vector
progressBarLength <- 52 ## multiples of 4 only
progressBarDefaultSetting <- getNimbleOption('MCMCprogressBar')
Expand All @@ -212,6 +244,8 @@ buildMCMC <- nimbleFunction(
thinWAIC <- FALSE
nburnin_extraWAIC <- 0
}
firstRun <- TRUE
setupOutputs(derivedTypes)
},

run = function(
Expand All @@ -231,23 +265,34 @@ buildMCMC <- nimbleFunction(
if(niter < 0) stop('cannot specify niter < 0')
if(nburnin < 0) stop('cannot specify nburnin < 0')
if(nburnin > niter) stop('cannot specify nburnin > niter')
thinToUseVec <<- thinFromConfVec
if(thin != -1) thinToUseVec[1] <<- thin
if(thin2 != -1) thinToUseVec[2] <<- thin2
for(iThin in 1:2) {
if(thinToUseVec[iThin] < 1) stop('cannot use thin < 1')
if(thinToUseVec[iThin] != floor(thinToUseVec[iThin])) stop('cannot use non-integer thin')
}
if(initializeModel) my_initializeModel$run()
nimCopy(from = model, to = mvSaved, row = 1, logProb = TRUE)
if(firstRun) reset <- TRUE ## compulsory reset on first run of MCMC
firstRun <<- FALSE
if(reset) {
samplerTimes <<- numeric(length(samplerFunctions) + 1) ## default inititialization to zero
if(initializeModel) my_initializeModel$run()
thinToUseVec <<- thinFromConfVec
if(thin != -1) thinToUseVec[1] <<- thin
if(thin2 != -1) thinToUseVec[2] <<- thin2
for(iThin in 1:2) {
if(thinToUseVec[iThin] < 1) stop('cannot use thin < 1')
if(thinToUseVec[iThin] != floor(thinToUseVec[iThin])) stop('cannot use non-integer thin')
}
for(i in seq_along(derivedFunctions)) {
if(derivedIntervals[i] == 0) {
derivedIntervals[i] <<- thinToUseVec[1]
derivedFunctions[[i]]$set_interval(thinToUseVec[1])
}
}
for(i in seq_along(samplerFunctions)) samplerFunctions[[i]]$reset()
for(i in seq_along(samplerFunctions)) samplerFunctions[[i]]$before_chain(niter, nburnin, chain)
for(i in seq_along(derivedFunctions)) derivedFunctions[[i]]$reset()
for(i in seq_along(samplerFunctions)) samplerFunctions[[i]]$before_chain(niter, nburnin, chain)
for(i in seq_along(derivedFunctions)) derivedFunctions[[i]]$before_chain(niter-nburnin, nburnin, thinToUseVec, chain)
samplerTimes <<- numeric(length(samplerFunctions) + 1) ## default inititialization to zero
mvSamples_copyRow <- 0
mvSamples2_copyRow <- 0
} else {
if(nburnin != 0) stop('cannot specify nburnin when using reset = FALSE.')
if(nburnin != 0) stop('cannot specify nburnin when using reset = FALSE.')
if(thin != -1) stop('cannot specify thin when using reset = FALSE.')
if(thin2 != -1) stop('cannot specify thin2 when using reset = FALSE.')
if(dim(samplerTimes)[1] != length(samplerFunctions) + 1) samplerTimes <<- numeric(length(samplerFunctions) + 1) ## first run: default inititialization to zero
if (resetMV) {
mvSamples_copyRow <- 0
Expand All @@ -257,8 +302,8 @@ buildMCMC <- nimbleFunction(
mvSamples2_copyRow <- getsize(mvSamples2)
}
}
if(onlineWAIC & resetWAIC)
waicFun[[1]]$reset()
nimCopy(from = model, to = mvSaved, row = 1, logProb = TRUE)
if(onlineWAIC & resetWAIC) waicFun[[1]]$reset()
resize(mvSamples, mvSamples_copyRow + floor((niter-nburnin) / thinToUseVec[1]))
resize(mvSamples2, mvSamples2_copyRow + floor((niter-nburnin) / thinToUseVec[2]))
## reinstate samplerExecutionOrder as a runtime argument, once we support non-scalar default values for runtime arguments:
Expand All @@ -278,6 +323,7 @@ buildMCMC <- nimbleFunction(
if(niter < 1) return()
for(iter in 1:niter) {
checkInterrupt()
## execute samplerFunctions
if(time) {
for(i in seq_along(samplerExecutionOrderToUse)) {
ind <- samplerExecutionOrderToUse[i]
Expand All @@ -289,42 +335,69 @@ buildMCMC <- nimbleFunction(
samplerFunctions[[ind]]$run()
}
}
## adding "accumulators" to MCMC
## https://en.wikipedia.org/wiki/Algorithms_for_calculating_variance
if(iter > nburnin) {
sampleNumber <- iter - nburnin
if(sampleNumber %% thinToUseVec[1] == 0) {
## save samples
iterPostBurnin <- iter - nburnin
if(iterPostBurnin %% thinToUseVec[1] == 0) {
mvSamples_copyRow <- mvSamples_copyRow + 1
nimCopy(from = model, to = mvSamples, row = mvSamples_copyRow, nodes = monitors)
}
if(sampleNumber %% thinToUseVec[2] == 0) {
if(iterPostBurnin %% thinToUseVec[2] == 0) {
mvSamples2_copyRow <- mvSamples2_copyRow + 1
nimCopy(from = model, to = mvSamples2, row = mvSamples2_copyRow, nodes = monitors2)
}
## save WAIC
if(enableWAIC & onlineWAIC & iter > nburnin + nburnin_extraWAIC) {
if (!thinWAIC) {
waicFun[[1]]$updateStats()
} else if (sampleNumber %% thinToUseVec[1] == 0){
} else if (iterPostBurnin %% thinToUseVec[1] == 0) {
waicFun[[1]]$updateStats()
}
}
## execute derivedFunctions
for(i in seq_along(derivedFunctions)) {
if(iterPostBurnin %% derivedIntervals[i] == 0) {
derivedFunctions[[i]]$run( iterPostBurnin/derivedIntervals[i] )
}
}
}
## progress bar
if(progressBar & (iter == progressBarNextFloor)) {
cat('-')
progressBarNext <- progressBarNext + progressBarIncrement
progressBarNextFloor <- floor(progressBarNext)
}
}
if(progressBar) print('|')
## after_chain methods
for(i in seq_along(samplerFunctions)) samplerFunctions[[i]]$after_chain()
for(i in seq_along(derivedFunctions)) derivedFunctions[[i]]$after_chain()
returnType(void())
},
methods = list(
getTimes = function() {
returnType(double(1))
return(samplerTimes[1:(length(samplerTimes)-1)])
},
## Old-style post-sampling WAIC calculation.
getNumDerived = function() {
returnType(double())
return(numDerived)
},
getDerivedQuantityResults = function(ind = double()) {
if(ind > numDerived) {
print('there aren\'t that many derived functions')
return(array(0, c(0,0)))
}
returnType(double(2))
return(derivedFunctions[[ind]]$get_results())
},
getDerivedQuantityNames = function(ind = double()) {
if(ind > numDerived) print('there aren\'t that many derived functions')
returnType(character(1))
derivedNames <<- derivedFunctions[[ind]]$get_names()
return(derivedNames)
},
## old-style post-sampling WAIC calculation
calculateWAIC = function(nburnin = integer(default = 0)) {
if(!enableWAIC) {
print('Error: One must set enableWAIC = TRUE in \'configureMCMC\' or \'buildMCMC\'. See \'help(configureMCMC)\' for additional information.')
Expand Down
Loading
Loading