Skip to content

Commit 287cbbb

Browse files
simonbeyer1claude
andcommitted
symmetryReduction: zero limits; trust control lists take any trust() argument
- reportZeroCompatibility=: which coordinates the orbit can drive to 0 with nothing running off to infinity, sets found by growing the face rather than by enumeration. A conditional zero is never announced as reachable -- the report states the inequality, as an R expression over the model's own names - .trustControl(): cm1/inner/optControl accept every trust()/trustL1() argument and reject typos instead of passing them to objfun through `...`; ftol/mtol spelling at the call sites, the FOCEI kernels still read fterm/mterm Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JZqEHV1S16pq2b7W61HoQg
1 parent 4e9b144 commit 287cbbb

23 files changed

Lines changed: 768 additions & 172 deletions

R/L1Clustering.R

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -280,9 +280,9 @@ solveFusedComplete <- function(m, w, lambda) {
280280
rho <- K * (n - 1L)
281281
mu_of <- stats::setNames(paste0("log_", params), eta_cols) # eta_<par> -> log_<par>
282282

283-
cm1 <- modifyList(list(rinit = 1, rmax = 10, iterlim = 30L,
284-
fterm = 1e-6, mterm = 1e-6),
285-
if (is.null(control$cm1)) list() else control$cm1)
283+
cm1 <- .trustControl(list(rinit = 1, rmax = 10, iterlim = 30L,
284+
ftol = 1e-6, mtol = 1e-6),
285+
control$cm1, label = "control$cm1")
286286
clc <- modifyList(list(maxit = 60L, tol = 1e-9),
287287
if (is.null(control$cluster)) list() else control$cluster)
288288
## lambda is HELD FIXED by default. The closed-form MAP M-step
@@ -346,10 +346,8 @@ solveFusedComplete <- function(m, w, lambda) {
346346
fusion <- sum(vapply(seq_len(K), function(kk) sum(stats::dist(Eta[, kk])), 0.0))
347347
if (estimateLambda && fusion > 0) lambda_cur <- rho / fusion
348348
## CM-1: structural M-step at the frozen anchored etas
349-
cm1_fit <- suppressMessages(trust(
350-
function(th, ...) cm1_obj(th, Eta), parinit = struct_cur,
351-
rinit = cm1$rinit, rmax = cm1$rmax, iterlim = cm1$iterlim,
352-
fterm = cm1$fterm, mterm = cm1$mterm))
349+
cm1_fit <- suppressMessages(do.call(trust, modifyList(cm1, list(
350+
objfun = function(th, ...) cm1_obj(th, Eta), parinit = struct_cur))))
353351
struct_cur <- cm1_fit$argument
354352
ofv <- cm1_fit$value + lambda_cur * fusion # MAP penalised objective
355353

@@ -1024,11 +1022,11 @@ plot.sparsify <- function(x, type = c("grouping", "chain"), ...) {
10241022
mu_of <- stats::setNames(paste0("log_", params), eta_cols)
10251023

10261024
sc <- modifyList(list(nBurnin = 150L, nEM = 150L, nMcmc = 8L, stepsize = 0.15,
1027-
cm1 = list(rinit = 1, rmax = 10, iterlim = 30L,
1028-
fterm = 1e-6, mterm = 1e-6)),
1025+
cm1 = list()),
10291026
if (is.null(control$saem)) list() else control$saem)
1030-
cm1 <- modifyList(list(rinit = 1, rmax = 10, iterlim = 30L,
1031-
fterm = 1e-6, mterm = 1e-6), sc$cm1)
1027+
cm1 <- .trustControl(list(rinit = 1, rmax = 10, iterlim = 30L,
1028+
ftol = 1e-6, mtol = 1e-6),
1029+
sc$cm1, label = "control$saem$cm1")
10321030
nBurnin <- as.integer(sc$nBurnin); nEM <- as.integer(sc$nEM); nMcmc <- as.integer(sc$nMcmc)
10331031

10341032
struct_cur <- free[struct_names]; lambda_cur <- as.numeric(free[[lam_name]])
@@ -1078,8 +1076,8 @@ plot.sparsify <- function(x, type = c("grouping", "chain"), ...) {
10781076
fc <- fus_of(Eta); S_fus <- if (is.null(S_fus)) fc else S_fus + gamma * (fc - S_fus)
10791077
lambda_cur <- if (S_fus > 0) 2 * rho / S_fus else lambda_cur
10801078
## CM-1: structural M-step at the drawn etas, RM-damped in convergence
1081-
cf <- suppressMessages(trust(function(th, ...) cm1_obj(th, Eta), parinit = struct_cur,
1082-
rinit = cm1$rinit, rmax = cm1$rmax, iterlim = cm1$iterlim, fterm = cm1$fterm, mterm = cm1$mterm))
1079+
cf <- suppressMessages(do.call(trust, modifyList(cm1, list(
1080+
objfun = function(th, ...) cm1_obj(th, Eta), parinit = struct_cur))))
10831081
struct_cur <- if (it <= nBurnin) cf$argument else struct_cur + gamma * (cf$argument - struct_cur)
10841082
if (it > nBurnin) { EtaMean <- EtaMean + Eta; nAcc <- nAcc + 1L }
10851083
cur_par <- c(struct_cur, stats::setNames(lambda_cur, lam_name))

R/mcmcClass.R

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,11 +71,11 @@ flatTarget <- function(likObj, priorObj = NULL, priorSample = NULL) {
7171
pars_full_names = pars_full_names)
7272

7373
ic <- modifyList(list(rinit = 1, rmax = 10, iterlim = 30,
74-
fterm = 1e-7, mterm = 1e-7,
74+
ftol = 1e-7, mtol = 1e-7,
7575
eigen_floor_relative = 1e-10),
7676
innerControl)
7777
oc <- modifyList(list(rinit = 1, rmax = 10, iterlim = 200,
78-
fterm = 1e-7, mterm = 1e-7),
78+
ftol = 1e-7, mtol = 1e-7),
7979
trustControl)
8080

8181
pars_probe <- setNames(numeric(length(pars_full_names)), pars_full_names)

R/nlmeClass.R

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -302,7 +302,7 @@ updateOmegaChol <- function(MHatList, omega) {
302302
fit <- suppressMessages(trust(Q_objlist, parinit = start,
303303
rinit = 1, rmax = 10,
304304
iterlim = 50,
305-
fterm = 1e-10, mterm = 1e-10))
305+
ftol = 1e-10, mtol = 1e-10))
306306
setNames(as.numeric(fit$argument), chol_pars)
307307
}
308308

R/nlmeLaplace.R

Lines changed: 24 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -164,9 +164,10 @@
164164
## strength name for each candidate coordinate, in the eta-column (= short) order
165165
lamByCoord <- unname(penalty$lambdaByParam[penalty$short])
166166

167-
rinit <- if (is.null(control$rinit)) 1 else control$rinit
168-
rmax <- if (is.null(control$rmax)) 10 else control$rmax
169-
iterlim <- if (is.null(control$iterlim)) 50L else control$iterlim
167+
inner <- .trustControl(
168+
list(rinit = control$rinit %||% 1, rmax = control$rmax %||% 10,
169+
iterlim = control$iterlim %||% 50L, ftol = 1e-8, mtol = 1e-8),
170+
control$inner, optimizer = trustL1, label = "control$inner")
170171

171172
total <- 0
172173
gStruct <- setNames(numeric(length(struct_names)), struct_names)
@@ -191,8 +192,7 @@
191192
## compat), else a per-coordinate named vector for trustL1 / normalLaplace.
192193
lambda_k <- if (length(lam_name) == 1L) lambda_vec[[1L]]
193194
else setNames(unname(lambda_vec[lamByCoord]), eta_names_i)
194-
sm <- .laplaceSubjectMarginal(objfun_i, eta0, tg, lambda_k,
195-
rinit = rinit, rmax = rmax, iterlim = iterlim)
195+
sm <- .laplaceSubjectMarginal(objfun_i, eta0, tg, lambda_k, inner)
196196
if (!is.null(warm)) warm[[s]] <- sm$etahat
197197
total <- total + sm$value
198198

@@ -383,11 +383,11 @@
383383
targets_by_subject[[s]][eta_names_by[[s]]]), subjects)
384384

385385
sc <- modifyList(list(nBurnin = 150L, nEM = 150L, nMcmc = 10L, stepsize = 0.4,
386-
cm1 = list(rinit = 1, rmax = 10, iterlim = 30L,
387-
fterm = 1e-6, mterm = 1e-6)),
386+
cm1 = list()),
388387
if (is.null(control$saem)) list() else control$saem)
389-
cm1 <- modifyList(list(rinit = 1, rmax = 10, iterlim = 30L,
390-
fterm = 1e-6, mterm = 1e-6), sc$cm1)
388+
cm1 <- .trustControl(list(rinit = 1, rmax = 10, iterlim = 30L,
389+
ftol = 1e-6, mtol = 1e-6),
390+
sc$cm1, label = "control$saem$cm1")
391391
nBurnin <- as.integer(sc$nBurnin); nEM <- as.integer(sc$nEM)
392392
nMcmc <- as.integer(sc$nMcmc)
393393

@@ -468,10 +468,8 @@
468468
pmin(countByLam / S_abs, lambdaMax)[lam_free_names]
469469

470470
## CM-1: structural M-step at the drawn etas, RM-damped in convergence.
471-
fit <- suppressMessages(trust(
472-
function(th, ...) cm1_obj(th), parinit = struct_cur,
473-
rinit = cm1$rinit, rmax = cm1$rmax, iterlim = cm1$iterlim,
474-
fterm = cm1$fterm, mterm = cm1$mterm))
471+
fit <- suppressMessages(do.call(trust, modifyList(cm1, list(
472+
objfun = function(th, ...) cm1_obj(th), parinit = struct_cur))))
475473
struct_new <- fit$argument
476474
struct_cur <- if (k <= nBurnin) struct_new
477475
else struct_cur + gamma * (struct_new - struct_cur)
@@ -548,8 +546,8 @@
548546
#' a per-subject random-walk Metropolis E-step, provided as an independent
549547
#' cross-check.
550548
#' @param control List of tuning options: inner per-subject trust-region
551-
#' (`rinit`, `rmax`, `iterlim`); outer CM-1 trust-region (`cm1` = a list of
552-
#' `rinit`, `rmax`, `iterlim`, `fterm`, `mterm`); ECM controls (`maxOuter`,
549+
#' (`rinit`, `rmax`, `iterlim`, or `inner` = a list of any [trustL1] argument);
550+
#' outer CM-1 trust-region (`cm1` = a list of any [trust] argument); ECM controls (`maxOuter`,
553551
#' `epsPar`, `epsOfvRel`); `warm` (opt-in inner-mode warm-starting); `correction`
554552
#' (logical, default `TRUE`: the normal-Laplace FOCEI volume term in the CM-1
555553
#' gradient, exact for the error-model parameters, at the cost of a frozen-mode
@@ -634,9 +632,9 @@
634632
## shared E-step. NB the outer trust() here is a *different* trust-region from
635633
## the one inside trustL1: this one works on the smooth marginal over (mu, sigma)
636634
## with no L1 kink, trustL1's works on the per-subject L1-penalised mode.
637-
cm1 <- modifyList(list(rinit = 1, rmax = 10, iterlim = 30L,
638-
fterm = 1e-6, mterm = 1e-6),
639-
if (is.null(control$cm1)) list() else control$cm1)
635+
cm1 <- .trustControl(list(rinit = 1, rmax = 10, iterlim = 30L,
636+
ftol = 1e-6, mtol = 1e-6),
637+
control$cm1, label = "control$cm1")
640638
maxOuter <- if (is.null(control$maxOuter)) 50L else as.integer(control$maxOuter)
641639
epsPar <- if (is.null(control$epsPar)) 1e-4 else control$epsPar
642640
epsOfvRel <- if (is.null(control$epsOfvRel)) 1e-5 else control$epsOfvRel
@@ -685,10 +683,8 @@
685683
for (it in seq_len(maxOuter)) {
686684
nOuter <- it
687685
## CM-1: structural block via the outer trust(), lambda held.
688-
cm1_fit <- suppressMessages(trust(
689-
emReg, parinit = psi_struct,
690-
rinit = cm1$rinit, rmax = cm1$rmax, iterlim = cm1$iterlim,
691-
fterm = cm1$fterm, mterm = cm1$mterm))
686+
cm1_fit <- suppressMessages(do.call(trust, modifyList(cm1, list(
687+
objfun = emReg, parinit = psi_struct))))
692688
psi_struct <- cm1_fit$argument
693689

694690
## moments at the new structural point (lambda still frozen): drive CM-2 + OFV.
@@ -1003,7 +999,7 @@
1003999
p0 <- p0 + do.call("rnorm", list(n = length(p0), sd = sd))
10041000
f <- try(suppressWarnings(trust(
10051001
obj_data, parinit = p0, fixed = fixed0, rinit = 1, rmax = 10,
1006-
iterlim = 200L, fterm = 1e-8, mterm = 1e-8)), silent = TRUE)
1002+
iterlim = 200L, ftol = 1e-8, mtol = 1e-8)), silent = TRUE)
10071003
if (!inherits(f, "try-error") && isTRUE(f$converged) &&
10081004
(is.null(best) || f$value < best$value)) best <- f
10091005
}
@@ -1202,12 +1198,12 @@ normalLaplace <- function(a, m, lambda) {
12021198
## -2 log L_i = value(etahat) - (1/2) sum grad_k^2 / Hd_k - 2 sum log I_k,
12031199
## with I_k = normalLaplace(a_k, m_k - target_k, lambda).
12041200
.laplaceSubjectMarginal <- function(objfun, eta0, targets, lambda,
1205-
rinit = 1, rmax = 10, iterlim = 100L,
1206-
fterm = 1e-8, mterm = 1e-8) {
1201+
control = list(rinit = 1, rmax = 10,
1202+
iterlim = 100L,
1203+
ftol = 1e-8, mtol = 1e-8)) {
12071204
nm <- names(eta0)
1208-
fit <- trustL1(objfun, parinit = eta0, mu = targets, lambda = lambda,
1209-
rinit = rinit, rmax = rmax, iterlim = iterlim,
1210-
fterm = fterm, mterm = mterm)
1205+
fit <- do.call(trustL1, modifyList(control, list(
1206+
objfun = objfun, parinit = eta0, mu = targets, lambda = lambda)))
12111207
etahat <- fit$argument[nm]
12121208

12131209
di <- objfun(etahat)

R/nlmeNormal.R

Lines changed: 26 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -708,11 +708,11 @@ emObjfn <- function(obj, control = list()) {
708708
pars_full_names = pars_full_names
709709
)
710710
ic <- modifyList(list(rinit = 1, rmax = 10, iterlim = 30,
711-
fterm = 1e-7, mterm = 1e-7,
711+
ftol = 1e-7, mtol = 1e-7,
712712
eigen_floor_relative = 1e-10),
713713
innerControl)
714714
oc <- modifyList(list(rinit = 1, rmax = 10, iterlim = 200,
715-
fterm = 1e-7, mterm = 1e-7),
715+
ftol = 1e-7, mtol = 1e-7),
716716
trustControl)
717717
control_cpp <- list(inner = ic, outer = oc)
718718

@@ -779,8 +779,8 @@ emObjfn <- function(obj, control = list()) {
779779
K <- om$K
780780
chol_pars <- om$cholPars
781781
if (is.null(epsQuadLevels)) epsQuadLevels <- K + 1:3
782-
cm1 <- modifyList(list(rinit = 1, rmax = 10,
783-
fterm = 1e-6, mterm = 1e-6), cm1Control)
782+
cm1 <- .trustControl(list(rinit = 1, rmax = 10, ftol = 1e-6, mtol = 1e-6),
783+
cm1Control, label = "cm1Control")
784784
psi <- init
785785
if (!all(chol_pars %in% names(psi)))
786786
stop(".fitNormal: `init` is missing omega$cholPars (",
@@ -801,11 +801,9 @@ emObjfn <- function(obj, control = list()) {
801801
if (ecmIter > 1L)
802802
e_info <- rebuild(psi, level_new = level, fixed = fixed,
803803
eta_init = e_info$etaModes)
804-
cm1_fit <- suppressMessages(trust(
805-
em, parinit = psi[structural_names], fixed = fixed,
806-
rinit = cm1$rinit, rmax = cm1$rmax,
807-
iterlim = maxCm1Iter,
808-
fterm = cm1$fterm, mterm = cm1$mterm))
804+
cm1_fit <- suppressMessages(do.call(trust, modifyList(cm1, list(
805+
objfun = em, parinit = psi[structural_names], fixed = fixed,
806+
iterlim = maxCm1Iter))))
809807
psi[structural_names] <- cm1_fit$argument
810808
out_after_cm1 <- em(psi[structural_names], fixed = fixed, deriv = FALSE)
811809
diag_after <- attr(out_after_cm1, "emDiag")
@@ -881,8 +879,8 @@ emObjfn <- function(obj, control = list()) {
881879
N <- nrow(om$subjectEtas)
882880
chol_pars <- om$cholPars
883881
level <- K # single-node Smolyak == Laplace
884-
cm1 <- modifyList(list(rinit = 1, rmax = 10, fterm = 1e-6, mterm = 1e-6),
885-
cm1Control)
882+
cm1 <- .trustControl(list(rinit = 1, rmax = 10, ftol = 1e-6, mtol = 1e-6),
883+
cm1Control, label = "cm1Control")
886884
psi <- init
887885
if (!all(chol_pars %in% names(psi)))
888886
stop(".fitNormal: `init` is missing omega$cholPars (",
@@ -898,10 +896,9 @@ emObjfn <- function(obj, control = list()) {
898896
eta_init = e_info$etaModes)
899897

900898
# CM-1: structural pars via the Laplace marginal, Omega frozen.
901-
cm1_fit <- suppressMessages(trust(
902-
em, parinit = psi[structural_names], fixed = fixed,
903-
rinit = cm1$rinit, rmax = cm1$rmax, iterlim = maxCm1Iter,
904-
fterm = cm1$fterm, mterm = cm1$mterm))
899+
cm1_fit <- suppressMessages(do.call(trust, modifyList(cm1, list(
900+
objfun = em, parinit = psi[structural_names], fixed = fixed,
901+
iterlim = maxCm1Iter))))
905902
psi[structural_names] <- cm1_fit$argument
906903

907904
# CM-2: closed-form Omega from covariance-corrected posterior moments.
@@ -979,8 +976,9 @@ emObjfn <- function(obj, control = list()) {
979976
N <- meta_pkg$N; K <- meta_pkg$K
980977
chol_pars <- omega$cholPars
981978
structural_names <- setdiff(names(init), chol_pars)
982-
cm1 <- modifyList(list(rinit = 1, rmax = 10, iterlim = 30,
983-
fterm = 1e-6, mterm = 1e-6), cm1Control)
979+
cm1 <- .trustControl(list(rinit = 1, rmax = 10, iterlim = 30,
980+
ftol = 1e-6, mtol = 1e-6),
981+
cm1Control, label = "cm1Control")
984982

985983
parsFull <- setNames(numeric(length(meta$pars_full_names)),
986984
meta$pars_full_names)
@@ -1050,10 +1048,8 @@ emObjfn <- function(obj, control = list()) {
10501048
parsFull[chol_pars] <- updateOmegaChol(list(S_omega), omega)
10511049

10521050
# CM-1: structural M-step at the drawn etas, RM-damped in convergence phase.
1053-
cm1_fit <- suppressMessages(trust(
1054-
cm1_obj, parinit = parsFull[structural_names],
1055-
rinit = cm1$rinit, rmax = cm1$rmax, iterlim = cm1$iterlim,
1056-
fterm = cm1$fterm, mterm = cm1$mterm))
1051+
cm1_fit <- suppressMessages(do.call(trust, modifyList(cm1, list(
1052+
objfun = cm1_obj, parinit = parsFull[structural_names]))))
10571053
theta_hat <- cm1_fit$argument
10581054
parsFull[structural_names] <-
10591055
if (k <= nBurnin) theta_hat
@@ -1146,10 +1142,12 @@ emObjfn <- function(obj, control = list()) {
11461142
fc <- control$focei %||% list()
11471143
.normalCheckControlKeys(fc, c("innerControl", "trustControl", "cores"), "focei")
11481144
.normalCheckControlKeys(fc$innerControl %||% list(),
1149-
c("rinit", "rmax", "iterlim", "fterm", "mterm",
1150-
"eigen_floor_relative"), "focei$innerControl")
1145+
c("rinit", "rmax", "iterlim", "ftol", "mtol",
1146+
"fterm", "mterm", "eigen_floor_relative"),
1147+
"focei$innerControl")
11511148
.normalCheckControlKeys(fc$trustControl %||% list(),
1152-
c("rinit", "rmax", "iterlim", "fterm", "mterm"),
1149+
c("rinit", "rmax", "iterlim", "ftol", "mtol",
1150+
"fterm", "mterm"),
11531151
"focei$trustControl")
11541152
.normalCheckControlKeys(control$quadrature %||% list(),
11551153
c("level", "cores", "epsQuadLevels", "epsEcm", "epsOfvRel",
@@ -1246,7 +1244,10 @@ emObjfn <- function(obj, control = list()) {
12461244
#' \item{`$saem`}{Recognised keys: `nBurnin`, `nEM`, `nMcmc`, `cm1Control`,
12471245
#' `cores`.}
12481246
#' }
1249-
#' Unrecognised keys raise a warning.
1247+
#' Unrecognised keys raise a warning. `cm1Control` accepts any [trust]
1248+
#' argument; `innerControl`/`trustControl` steer the C++ FOCEI loops and take
1249+
#' `rinit`, `rmax`, `iterlim`, `ftol`, `mtol` (plus `eigen_floor_relative`
1250+
#' for the inner one).
12501251
#' @param verbose Logical. If TRUE prints solver progress.
12511252
#'
12521253
#' @return An `EM` S3 list with fields `argument`, `value` (plain-ML

R/statistics.R

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@
1414
#' @param algoControl List of arguments controlling the fast PL algorithm. defaults to
1515
#' \code{list(gamma = 1, W = "hessian", reoptimize = FALSE, correction = 1, reg = .Machine$double.eps)}
1616
#' @param optControl List of arguments controlling the \code{trust()} optimizer. Defaults to
17-
#' \code{list(rinit = .1, rmax = 10, iterlim = 10, fterm = 1e-6, mterm = 1e-6)}.
18-
#' See \link{trust} for more details.
17+
#' \code{list(rinit = .1, rmax = 10, iterlim = 10)}; any other argument of \link{trust},
18+
#' e.g. \code{ftol} or \code{parupper}, can be added. See \link{trust} for more details.
1919
#' @param verbose Logical, print verbose messages.
2020
#' @param cores number of cores used when computing profiles for several
2121
#' parameters. Multiplies with the OpenMP threads each objective function uses
@@ -80,12 +80,12 @@ profile <- function(objfun, pars, whichPar, alpha = 0.05,
8080
if (method == "integrate") {
8181
sControl <- list(stepsize = 1e-4, min = 1e-4, max = Inf, atol = 1e-2, rtol = 1e-2, limit = 500, stop = "value")
8282
aControl <- list(gamma = 1, W = "hessian", reoptimize = FALSE, correction = 1, reg = .Machine$double.eps)
83-
oControl <- list(rinit = .1, rmax = 10, iterlim = 10, fterm = 1e-6, mterm = 1e-6)
83+
oControl <- list(rinit = .1, rmax = 10, iterlim = 10)
8484
}
8585
if (method == "optimize") {
8686
sControl <- list(stepsize = 1e-2, min = 1e-4, max = Inf, atol = 1e-1, rtol = 1e-1, limit = 100, stop = "value")
8787
aControl <- list(gamma = 0, W = "identity", reoptimize = TRUE, correction = 1, reg = 0)
88-
oControl <- list(rinit = .1, rmax = 10, iterlim = 100, fterm = 1e-6, mterm = 1e-6)
88+
oControl <- list(rinit = .1, rmax = 10, iterlim = 100)
8989
}
9090

9191
# Check if on Windows
@@ -95,9 +95,7 @@ profile <- function(objfun, pars, whichPar, alpha = 0.05,
9595
# Substitute user-set control parameters
9696
if (!is.null(stepControl)) sControl[match(names(stepControl), names(sControl))] <- stepControl
9797
if (!is.null(algoControl)) aControl[match(names(algoControl), names(aControl))] <- algoControl
98-
# Assign by name rather than by match(): any trust() argument is passable,
99-
# not just the ones already carried in oControl.
100-
if (!is.null(optControl )) oControl[names(optControl)] <- optControl
98+
oControl <- .trustControl(oControl, optControl, label = "optControl")
10199

102100

103101
# Create interRes folder for cautiousMode

0 commit comments

Comments
 (0)