From e5278caf1f7aa08a612ee96aa0aa7d741f95663a Mon Sep 17 00:00:00 2001 From: perrydv Date: Thu, 15 Oct 2026 20:44:47 -0700 Subject: [PATCH 1/4] remove uses of the nimble namespace, as we move towards nimble2 --- .gitignore | 2 +- nimbleModel/R/miscFunctions.R | 11 ++++++----- nimbleModel/R/modelBaseClass.R | 2 +- nimbleModel/R/modelDecl.R | 2 +- nimbleModel/R/modelDef.R | 8 ++++++-- nimbleModel/R/modelFunctions.R | 6 +++--- nimbleModel/R/options.R | 4 +++- nimbleModel/tests/testthat/test-setupMargNodes.R | 4 ++-- 8 files changed, 23 insertions(+), 16 deletions(-) diff --git a/.gitignore b/.gitignore index 2c21d50..2a20ae3 100644 --- a/.gitignore +++ b/.gitignore @@ -37,4 +37,4 @@ vignettes/*.pdf **/.DS_Store # Symlink to inst/include for devtools::load_all() -nimbleModel/include \ No newline at end of file +nimbleModel/include diff --git a/nimbleModel/R/miscFunctions.R b/nimbleModel/R/miscFunctions.R index d019d01..1c4333e 100644 --- a/nimbleModel/R/miscFunctions.R +++ b/nimbleModel/R/miscFunctions.R @@ -1,7 +1,7 @@ # This needs to be sourced after `nimbleFunction` is defined, so can't be done in `distributions_inputList.R`. -calc_dmnormAltParams <- nimble::nimbleFunction( +calc_dmnormAltParams <- nCompiler::nFunction( name = "calc_dmnormAltParams", - run = function(cholesky = double(2), prec_param = double(), return_prec = double()) { + fun = function(cholesky = double(2), prec_param = double(), return_prec = double()) { if (prec_param == return_prec) { ans <- t(cholesky) %*% cholesky } else { @@ -16,9 +16,9 @@ calc_dmnormAltParams <- nimble::nimbleFunction( } ) -calc_dwishAltParams <- nimble::nimbleFunction( +calc_dwishAltParams <- nCompiler::nFunction( name = "calc_dwishAltParams", - run = function(cholesky = double(2), scale_param = double(), return_scale = double()) { + fun = function(cholesky = double(2), scale_param = double(), return_scale = double()) { if (scale_param == return_scale) { ans <- t(cholesky) %*% cholesky } else { @@ -31,4 +31,5 @@ calc_dwishAltParams <- nimble::nimbleFunction( returnType(double(2)) return(ans) } -) \ No newline at end of file +) + diff --git a/nimbleModel/R/modelBaseClass.R b/nimbleModel/R/modelBaseClass.R index 782a272..1dcaf01 100644 --- a/nimbleModel/R/modelBaseClass.R +++ b/nimbleModel/R/modelBaseClass.R @@ -395,7 +395,7 @@ modelBase_nClass <- nClass( getDependencies = function(nodes, omit = NULL, self = TRUE, determOnly = FALSE, stochOnly = FALSE, includeData = TRUE, dataOnly = FALSE, - includePredictive = nimble::getNimbleOption('getDependenciesIncludesPredictiveNodes'), + includePredictive = getNimbleModelOption('getDependenciesIncludesPredictiveNodes'), predictiveOnly = FALSE, includeRHSonly = FALSE, downstream = FALSE, immediateOnly = FALSE, nodesAsChars = getNimbleModelOption("nodesAsChars"), diff --git a/nimbleModel/R/modelDecl.R b/nimbleModel/R/modelDecl.R index eff0854..80f22d2 100644 --- a/nimbleModel/R/modelDecl.R +++ b/nimbleModel/R/modelDecl.R @@ -102,7 +102,7 @@ modelDeclClass <- R6Class( if (!stoch) { return(NULL) } - types <- nimble:::distributions[[distributionName]]$types + types <- nimbleModel:::distributions[[distributionName]]$types if (is.null(types)) { return(NULL) } diff --git a/nimbleModel/R/modelDef.R b/nimbleModel/R/modelDef.R index 590893c..d6ea155 100644 --- a/nimbleModel/R/modelDef.R +++ b/nimbleModel/R/modelDef.R @@ -34,7 +34,11 @@ modelDefClass <- R6Class( checkAndAssignConstants(constants, code) modelCode <<- codeProcessIfThenElse(code, constants, userEnv) - modelCode <<- nimble:::nf_changeNimKeywords(modelCode) # Formerly in `assignBUGScode`. + + # Disable keyword name transformations until we determine what happens here vs in nimble2. + # We need to not use nimble anymore. + # + # modelCode <<- nimble:::nf_changeNimKeywords(modelCode) # Formerly in `assignBUGScode`. # TODO: add this later. # setModelValuesClassName() @@ -575,7 +579,7 @@ modelDefClass <- R6Class( if (decl$stoch) { params <- as.list(valueExpr[-1]) # Extract the original distribution parameters. paramNames <- names(valueExpr)[-1] - types <- nimble:::distributions[[decl$distributionName]]$types + types <- nimbleModel:::distributions[[decl$distributionName]]$types # `types` may be NULL if all are scalar. for (iParam in seq_along(params)) { diff --git a/nimbleModel/R/modelFunctions.R b/nimbleModel/R/modelFunctions.R index 2558b78..863b55c 100644 --- a/nimbleModel/R/modelFunctions.R +++ b/nimbleModel/R/modelFunctions.R @@ -219,7 +219,7 @@ taggedClass <- R6Class( getDependencies <- function(model, nodes, omit = NULL, self = TRUE, determOnly = FALSE, stochOnly = FALSE, includeData = TRUE, dataOnly = FALSE, - includePredictive = nimble::getNimbleOption('getDependenciesIncludesPredictiveNodes'), + includePredictive = getNimbleModelOption('getDependenciesIncludesPredictiveNodes'), predictiveOnly = FALSE, includeRHSonly = FALSE, downstream = FALSE, immediateOnly = FALSE, nodesAsChars = getNimbleModelOption("nodesAsChars"), @@ -722,7 +722,7 @@ setupMargNodes <- function(model, paramNodes, randomEffectsNodes, calcNodes, if (length(reCheck)) { errorNodes <- head(reCheck, n = 4) if (length(reCheck) > 4) moreText <- ", .." else moreText <- "" - extraMsg <- if (isTRUE(nimble::getNimbleOption("includeUnneededLatents"))) "" else " They will be omitted, but one can force inclusion with\n `nimbleOptions(includeUnneededLatents=TRUE)`.\n" + extraMsg <- if (isTRUE(getNimbleModelOption("includeUnneededLatents"))) "" else " They will be omitted, but one can force inclusion with\n `nimbleOptions(includeUnneededLatents=TRUE)`.\n" messageIfVerbose( " [Warning] There are some `randomEffectsNodes` provided that look like\n", " they are not needed for the provided (or default) `paramNodes`:\n", @@ -731,7 +731,7 @@ setupMargNodes <- function(model, paramNodes, randomEffectsNodes, calcNodes, " (potentially in the control list) for the algorithm or as\n", " an argument to `setupMargNodes`." ) - if (!isTRUE(nimble::getNimbleOption("includeUnneededLatents"))) { + if (!isTRUE(getNimbleModelOption("includeUnneededLatents"))) { randomEffectsNodes <- setdiff_nodes(randomEffectsNodes, reCheck) } } diff --git a/nimbleModel/R/options.R b/nimbleModel/R/options.R index 55e2c7d..aaaaa62 100644 --- a/nimbleModel/R/options.R +++ b/nimbleModel/R/options.R @@ -10,7 +10,9 @@ disallowMultivariateArgumentExpressions = TRUE, legacy_nimble = FALSE, # TRUE means stricter use of original nimble behavior in some cases. nodesAsChars = FALSE, - verbose = TRUE + verbose = TRUE, + getDependenciesIncludesPredictiveNodes = TRUE, ## may be toggled off during MCMC sampler building + includeUnneededLatents = FALSE ) ) diff --git a/nimbleModel/tests/testthat/test-setupMargNodes.R b/nimbleModel/tests/testthat/test-setupMargNodes.R index 198db5b..dffdd8f 100644 --- a/nimbleModel/tests/testthat/test-setupMargNodes.R +++ b/nimbleModel/tests/testthat/test-setupMargNodes.R @@ -497,12 +497,12 @@ test_that("`setupMargNodes` handling of missing/extra latents", { expect_identical(result$paramNodes[[1]]$toNodeChars(), c("mu")) # TODO: presumably rework how this option is handled in nimble 2. - nimble::nimbleOptions(includeUnneededLatents = TRUE) + nimbleModelOptions(includeUnneededLatents = TRUE) expect_message(result <- setupMargNodes(m, randomEffectsNodes = 'b'), "they are not needed for the provided") expect_identical(result$randomEffectsNodes[[1]]$toNodeChars(), c("b[1]", "b[2]", "b[3]")) expect_identical(result$paramNodes[[1]]$toNodeChars(), c("mu")) ## Note `b[3]` is not in `calcNodes` because `predictiveNodes` are excluded. - nimble::nimbleOptions(includeUnneededLatents = FALSE) + nimbleModelOptions(includeUnneededLatents = FALSE) }) test_that("getConditionallyIndependentSets works with grouped data", { From 8b5112fbe4f0eb8f1046ac9f875386d2ac485b9e Mon Sep 17 00:00:00 2001 From: Christopher Paciorek Date: Sat, 17 Oct 2026 11:59:31 -0700 Subject: [PATCH 2/4] Include nCompiler:::nf_changeKeywords in modelDef processing. --- nimbleModel/R/modelDef.R | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nimbleModel/R/modelDef.R b/nimbleModel/R/modelDef.R index d6ea155..7f28fed 100644 --- a/nimbleModel/R/modelDef.R +++ b/nimbleModel/R/modelDef.R @@ -35,10 +35,10 @@ modelDefClass <- R6Class( modelCode <<- codeProcessIfThenElse(code, constants, userEnv) - # Disable keyword name transformations until we determine what happens here vs in nimble2. + # Switch keyword name transformations as a test while we determine what happens here vs in nimble2. # We need to not use nimble anymore. # - # modelCode <<- nimble:::nf_changeNimKeywords(modelCode) # Formerly in `assignBUGScode`. + modelCode <<- nCompiler:::nf_changeKeywords(modelCode) # Formerly in `assignBUGScode`. # TODO: add this later. # setModelValuesClassName() From 0f8f66a8eaf09aed9d91cff8478e59b5a28f23b3 Mon Sep 17 00:00:00 2001 From: Christopher Paciorek Date: Sat, 17 Oct 2026 12:00:21 -0700 Subject: [PATCH 3/4] Add some handling for nC, nMult. --- nimbleModel/R/all_utils.R | 20 ++++++++++++------- nimbleModel/R/context.R | 8 ++++---- nimbleModel/R/getSymbolicParentNodes.R | 4 ++-- nimbleModel/R/indexConstraint.R | 2 +- nimbleModel/R/indexRuleConstant.R | 4 ++-- nimbleModel/R/modelDecl.R | 2 +- nimbleModel/R/model_utils.R | 4 ++-- .../tests/testthat/test-setupMargNodes.R | 5 ++--- 8 files changed, 27 insertions(+), 22 deletions(-) diff --git a/nimbleModel/R/all_utils.R b/nimbleModel/R/all_utils.R index fd3e369..ca156ec 100644 --- a/nimbleModel/R/all_utils.R +++ b/nimbleModel/R/all_utils.R @@ -163,11 +163,12 @@ messageIfVerbose <- function(...) { # Temporarily here as need for initial testing of processing. +# Mis-named now as it also allows for nFunctions. is.rcf <- function(x, inputIsName = FALSE, where = -1) { if (inputIsName) { x <- get(x, pos = where) } - if (inherits(x, "nfMethodRC")) { + if (inherits(x, "nfMethodRC") || inherits(x, "nFunction")) { return(TRUE) } if (is.function(x)) { @@ -184,12 +185,6 @@ is.rcf <- function(x, inputIsName = FALSE, where = -1) { nimbleUniqueID <- labelFunctionCreator("UID") nimbleModelID <- labelFunctionCreator("MID") - -# temporary, as we have some tests of use of `c()` in indexing -nimC <- function(...) { - c(...) -} - evalNumeric <- function(expr) { if (length(expr) == 1) { return(expr) @@ -202,3 +197,14 @@ evalNumeric <- function(expr) { } return(expr) } + +# Placeholders while we sort out packaging. + +nC <- function(...) { + c(...) +} + +nMul <- function(x, y) { + x %*% y +} + diff --git a/nimbleModel/R/context.R b/nimbleModel/R/context.R index b4d50bd..bce2887 100644 --- a/nimbleModel/R/context.R +++ b/nimbleModel/R/context.R @@ -206,8 +206,8 @@ expandContextAndReplacements <- function(allReplacements, allReplacementNameExpr innerLoopCode <- as.call(c(list(quote(`{`)), replacementRecordingCode, indexRecordingCode, quote(iAns <- iAns + 1))) innerLoopCode <- context$embedCodeInForLoop(innerLoopCode, useContext) - # This is a hacky way to deal with `nimC`, which is not in `constantsCopy`. - if (length(innerLoopCode[[3]]) > 1 && innerLoopCode[[3]][[1]] == "nimC") { + # This is a hacky way to deal with `nC`, which is not in `constantsCopy`. + if (length(innerLoopCode[[3]]) > 1 && innerLoopCode[[3]][[1]] == "nC") { innerLoopCode[[3]][[1]] <- quote(c) } @@ -265,8 +265,8 @@ determineContextSize <- function(context, useContext = rep(TRUE, length(context$ innerLoopCode <- quote(iAns <- iAns + 1) innerLoopCode <- context$embedCodeInForLoop(innerLoopCode, useContext) - # This is a hacky way to deal with `nimC`, which is not in `evalEnv`. - if (length(innerLoopCode[[3]]) > 1 && innerLoopCode[[3]][[1]] == "nimC") { + # This is a hacky way to deal with `nC`, which is not in `evalEnv`. + if (length(innerLoopCode[[3]]) > 1 && innerLoopCode[[3]][[1]] == "nC") { innerLoopCode[[3]][[1]] <- quote(c) } diff --git a/nimbleModel/R/getSymbolicParentNodes.R b/nimbleModel/R/getSymbolicParentNodes.R index b3ed2f7..26cd726 100644 --- a/nimbleModel/R/getSymbolicParentNodes.R +++ b/nimbleModel/R/getSymbolicParentNodes.R @@ -89,7 +89,7 @@ nimblePreevaluationFunctionNames <- c( # distribution functions paste0(c("d", "q", "p"), "t"), paste0(c("d", "q", "p"), "exp"), - "nimC", "nimRep", "nimSeq", "diag", + "nC", "nimRep", "nimSeq", "diag", "nMul", "nimNumeric", "nimMatrix", "nimArray", "length" ) @@ -143,7 +143,7 @@ nimbleOrRfunctionNames <- c( # distribution functions paste0(c("d", "r", "q", "p"), "t"), paste0(c("d", "r", "q", "p"), "exp"), - "nimC", "nimRep", "nimSeq", + "nimC", "nimRep", "nimSeq", "nC", "nMul", "diag", "length" ) diff --git a/nimbleModel/R/indexConstraint.R b/nimbleModel/R/indexConstraint.R index 58f6e7b..278269b 100644 --- a/nimbleModel/R/indexConstraint.R +++ b/nimbleModel/R/indexConstraint.R @@ -149,7 +149,7 @@ newIndexConstraint_fromSimple <- function(expr, slot, constants) { slot )) } else { # various other cases such as `x[2]`, `x[k+1]`, `x[c(2,3,5)]`, `x[c(2,3,k)]`. - if (expr[[1]] == "nimC") { + if (expr[[1]] == "nC") { expr[[1]] <- quote(c) } result <- eval(expr, envir = constants) diff --git a/nimbleModel/R/indexRuleConstant.R b/nimbleModel/R/indexRuleConstant.R index 440e4d4..891b6f0 100644 --- a/nimbleModel/R/indexRuleConstant.R +++ b/nimbleModel/R/indexRuleConstant.R @@ -56,8 +56,8 @@ indexRuleConstant_setup <- function(toIndexExprList, eval(toIndexExpr[[2]], envir = constants), eval(toIndexExpr[[3]], envir = constants) ) - } else if (length(toIndexExpr) > 1 && toIndexExpr[[1]] == "nimC") { - toIndexExpr[[1]] <- quote(c) # `nimC` not readily available in series of environments. + } else if (length(toIndexExpr) > 1 && toIndexExpr[[1]] == "nC") { # TODO: revisit handling of c(). + toIndexExpr[[1]] <- quote(c) # `nC` not readily available in series of environments. toConstant <- indexRangeMatrixClass$new(as.matrix(eval(toIndexExpr, envir = constants))) } else { stop("input error in `", safeDeparse(toIndexExprList), "`.") diff --git a/nimbleModel/R/modelDecl.R b/nimbleModel/R/modelDecl.R index 80f22d2..d3fb7a3 100644 --- a/nimbleModel/R/modelDecl.R +++ b/nimbleModel/R/modelDecl.R @@ -352,7 +352,7 @@ modelDeclClass <- R6Class( } } if (is.c(origIndex)) { # Handles new cases like `y[c(2,3,5)] ~ dmnorm(...)`. - if (origIndex[[1]] == "nimC") { + if (origIndex[[1]] == "nC") { logProbExpr[[i]] <- origIndex[[2]] } else { stop("unexpected input in `", safeDeparse(origIndex), "`.") diff --git a/nimbleModel/R/model_utils.R b/nimbleModel/R/model_utils.R index fe39f1c..18e7905 100644 --- a/nimbleModel/R/model_utils.R +++ b/nimbleModel/R/model_utils.R @@ -31,9 +31,9 @@ is.vectorized <- function(node) { is.c <- function(node) { if (is.character(node)) { - return(grepl("^nimC", node)) + return(grepl("^nC", node)) } else { - return("nimC" %in% all.names(node)) + return("nC" %in% all.names(node)) } } diff --git a/nimbleModel/tests/testthat/test-setupMargNodes.R b/nimbleModel/tests/testthat/test-setupMargNodes.R index dffdd8f..abda3a4 100644 --- a/nimbleModel/tests/testthat/test-setupMargNodes.R +++ b/nimbleModel/tests/testthat/test-setupMargNodes.R @@ -496,13 +496,12 @@ test_that("`setupMargNodes` handling of missing/extra latents", { expect_identical(result$randomEffectsNodes[[1]]$toNodeChars(), c("b[1]", "b[2]")) expect_identical(result$paramNodes[[1]]$toNodeChars(), c("mu")) - # TODO: presumably rework how this option is handled in nimble 2. - nimbleModelOptions(includeUnneededLatents = TRUE) + setNimbleModelOption('includeUnneededLatents', TRUE) expect_message(result <- setupMargNodes(m, randomEffectsNodes = 'b'), "they are not needed for the provided") expect_identical(result$randomEffectsNodes[[1]]$toNodeChars(), c("b[1]", "b[2]", "b[3]")) expect_identical(result$paramNodes[[1]]$toNodeChars(), c("mu")) ## Note `b[3]` is not in `calcNodes` because `predictiveNodes` are excluded. - nimbleModelOptions(includeUnneededLatents = FALSE) + setNimbleModelOption('includeUnneededLatents', FALSE) }) test_that("getConditionallyIndependentSets works with grouped data", { From 83c083800fd3563a2024e020fc10db903a971c03 Mon Sep 17 00:00:00 2001 From: Christopher Paciorek Date: Sat, 17 Oct 2026 12:27:36 -0700 Subject: [PATCH 4/4] Remove use of nimC in a test. --- nimbleModel/tests/testthat/test-graphRules.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nimbleModel/tests/testthat/test-graphRules.R b/nimbleModel/tests/testthat/test-graphRules.R index aea01e6..e996582 100644 --- a/nimbleModel/tests/testthat/test-graphRules.R +++ b/nimbleModel/tests/testthat/test-graphRules.R @@ -2058,7 +2058,7 @@ test_that("non-sequential indexing in for loop or indexRule", { NULL ) - rule <- graphRuleClass$new(toExpr = quote(y[nimC(2,3,5)]), + rule <- graphRuleClass$new(toExpr = quote(y[nC(2,3,5)]), fromExpr = quote(x[1:3]), context = context_0)