From e8a5e8fec49fa676862cb78e80cbebedad75b400 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 18 Mar 2026 21:02:57 +0000 Subject: [PATCH 1/5] Initial plan From 0fe65d1d814fe6129f3ee3f626a872209cae31db Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 22 Mar 2026 22:02:28 +0000 Subject: [PATCH 2/5] Refactor allFit to use refit path for start_from_mle Co-authored-by: annahuynhly <97189987+annahuynhly@users.noreply.github.com> Agent-Logs-Url: https://github.com/annahuynhly/lme4/sessions/30bb2320-1032-4bfe-83c2-4a0189123f9c --- R/allFit.R | 43 +++++++++--------------------------- tests/testthat/test-allFit.R | 12 ++++++++++ 2 files changed, 23 insertions(+), 32 deletions(-) diff --git a/R/allFit.R b/R/allFit.R index f3b9a120e..3698b0166 100644 --- a/R/allFit.R +++ b/R/allFit.R @@ -165,46 +165,25 @@ allFit <- function(object, meth.tab = NULL, ctrl$optCtrl <- sanitize(ctrl$optCtrl, opt.ctrls[[optimizer[..i]]]) ctrl <- do.call(if(isGLMM(object)) glmerControl else lmerControl, ctrl) - ## need to stick ctrl in formula env so it can be found ... - form <- formula(object) - env <- environment(form) - tmp_env <- new.env(parent = env) - # temporarily changing the environment - environment(form) <- tmp_env - assign("ctrl", ctrl, envir = tmp_env, inherits = FALSE) - # Using the MLE as a starting point - if (start_from_mle) { - if (isGLMM(object)) { - pars <- getME(object, c("theta", "fixef")) - } else { - pars <- getME(object, "theta") - if(isNLMM(object)){ - warning("results are not guaranteed when using nlmer") + fit_once <- function() { + if (start_from_mle) { + return(refit(object, control = ctrl)) } - } - assign("pars", pars, envir = tmp_env, inherits = FALSE) + form <- formula(object) + env <- environment(form) + tmp_env <- new.env(parent = env) + environment(form) <- tmp_env + assign("ctrl", ctrl, envir = tmp_env, inherits = FALSE) + on.exit({ environment(form) <- env }, add = TRUE) + update(object, control = ctrl) } - - fit_call <- if (start_from_mle) { - quote(update(object, start = pars, control = ctrl)) - } else { - quote(update(object, control = ctrl)) - } - tt <- system.time( - rr <- if (catch.errs) { - tryCatch(eval(fit_call), error = function(e) e) - } else { - eval(fit_call) - } + rr <- if (catch.errs) tryCatch(fit_once(), error = function(e) e) else fit_once() ) attr(rr, "optCtrl") <- ctrl$optCtrl # contains crucial info here attr(rr, "time") <- tt # store timing info - ## restore original values to environment of the object - on.exit({ environment(form) <- env }, add = TRUE) - if (verbose) { if (inherits(rr,"error")) { cat("[failed]\n") diff --git a/tests/testthat/test-allFit.R b/tests/testthat/test-allFit.R index 30be68e75..23ee637d0 100644 --- a/tests/testthat/test-allFit.R +++ b/tests/testthat/test-allFit.R @@ -110,6 +110,18 @@ if (testLevel>1) { cc <- capture.output(ff <- fit_func(cbpp)) expect_true(all(summary(ff)$which.OK)) }) + + test_that("allFit(start_from_mle=TRUE) does not depend on update() data lookup", { + gm1 <- glmer( + cbind(incidence, size - incidence) ~ period + (1 | herd), + data = cbpp, family = binomial + ) + gm1@call$data <- quote(.allFit_missing_data_symbol.) + cc <- capture.output(ff <- allFit(gm1, verbose = FALSE, + catch.errs = FALSE, + start_from_mle = TRUE)) + expect_true(all(summary(ff)$which.OK)) + }) test_that("maxfun works", { gm_it10 <- suppressWarnings(allFit(fit_cbpp_1, verbose=FALSE, maxfun = 10)) From 70d31d69b267ff7728ad39f6af70567423afa0e9 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 22 Mar 2026 22:04:09 +0000 Subject: [PATCH 3/5] Preserve allFit start handling while using refit fast path Co-authored-by: annahuynhly <97189987+annahuynhly@users.noreply.github.com> Agent-Logs-Url: https://github.com/annahuynhly/lme4/sessions/30bb2320-1032-4bfe-83c2-4a0189123f9c --- R/allFit.R | 31 ++++++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/R/allFit.R b/R/allFit.R index 3698b0166..484c52981 100644 --- a/R/allFit.R +++ b/R/allFit.R @@ -165,17 +165,38 @@ allFit <- function(object, meth.tab = NULL, ctrl$optCtrl <- sanitize(ctrl$optCtrl, opt.ctrls[[optimizer[..i]]]) ctrl <- do.call(if(isGLMM(object)) glmerControl else lmerControl, ctrl) - fit_once <- function() { - if (start_from_mle) { - return(refit(object, control = ctrl)) - } + update_fit <- function(start = NULL) { form <- formula(object) env <- environment(form) tmp_env <- new.env(parent = env) environment(form) <- tmp_env assign("ctrl", ctrl, envir = tmp_env, inherits = FALSE) + if (!is.null(start)) { + assign("pars", start, envir = tmp_env, inherits = FALSE) + } on.exit({ environment(form) <- env }, add = TRUE) - update(object, control = ctrl) + if (is.null(start)) { + update(object, control = ctrl) + } else { + update(object, start = start, control = ctrl) + } + } + fit_once <- function() { + if (start_from_mle && !isNLMM(object)) { + return(refit(object, control = ctrl)) + } + if (start_from_mle) { + pars <- if (isGLMM(object)) { + getME(object, c("theta", "fixef")) + } else { + getME(object, "theta") + } + if (isNLMM(object)) { + warning("results are not guaranteed when using nlmer") + } + return(update_fit(start = pars)) + } + update_fit() } tt <- system.time( rr <- if (catch.errs) tryCatch(fit_once(), error = function(e) e) else fit_once() From b0e5dae15076677eee72bbc80268ad484781d1c5 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 23 Mar 2026 03:03:34 +0000 Subject: [PATCH 4/5] Remove remaining update usage from allFit refit path Co-authored-by: annahuynhly <97189987+annahuynhly@users.noreply.github.com> Agent-Logs-Url: https://github.com/annahuynhly/lme4/sessions/895f4c08-9385-4848-bffd-3b521aaec1cb --- R/allFit.R | 33 +++------------------------------ tests/testthat/test-allFit.R | 5 ++--- 2 files changed, 5 insertions(+), 33 deletions(-) diff --git a/R/allFit.R b/R/allFit.R index 484c52981..9af9f15a7 100644 --- a/R/allFit.R +++ b/R/allFit.R @@ -165,38 +165,11 @@ allFit <- function(object, meth.tab = NULL, ctrl$optCtrl <- sanitize(ctrl$optCtrl, opt.ctrls[[optimizer[..i]]]) ctrl <- do.call(if(isGLMM(object)) glmerControl else lmerControl, ctrl) - update_fit <- function(start = NULL) { - form <- formula(object) - env <- environment(form) - tmp_env <- new.env(parent = env) - environment(form) <- tmp_env - assign("ctrl", ctrl, envir = tmp_env, inherits = FALSE) - if (!is.null(start)) { - assign("pars", start, envir = tmp_env, inherits = FALSE) - } - on.exit({ environment(form) <- env }, add = TRUE) - if (is.null(start)) { - update(object, control = ctrl) - } else { - update(object, start = start, control = ctrl) - } - } fit_once <- function() { - if (start_from_mle && !isNLMM(object)) { - return(refit(object, control = ctrl)) - } - if (start_from_mle) { - pars <- if (isGLMM(object)) { - getME(object, c("theta", "fixef")) - } else { - getME(object, "theta") - } - if (isNLMM(object)) { - warning("results are not guaranteed when using nlmer") - } - return(update_fit(start = pars)) + if (isNLMM(object)) { + warning("results are not guaranteed when using nlmer") } - update_fit() + refit(object, control = ctrl) } tt <- system.time( rr <- if (catch.errs) tryCatch(fit_once(), error = function(e) e) else fit_once() diff --git a/tests/testthat/test-allFit.R b/tests/testthat/test-allFit.R index 23ee637d0..ec23756b6 100644 --- a/tests/testthat/test-allFit.R +++ b/tests/testthat/test-allFit.R @@ -111,15 +111,14 @@ if (testLevel>1) { expect_true(all(summary(ff)$which.OK)) }) - test_that("allFit(start_from_mle=TRUE) does not depend on update() data lookup", { + test_that("allFit does not depend on update() data lookup", { gm1 <- glmer( cbind(incidence, size - incidence) ~ period + (1 | herd), data = cbpp, family = binomial ) gm1@call$data <- quote(.allFit_missing_data_symbol.) cc <- capture.output(ff <- allFit(gm1, verbose = FALSE, - catch.errs = FALSE, - start_from_mle = TRUE)) + catch.errs = FALSE)) expect_true(all(summary(ff)$which.OK)) }) From e950e493570c2bbec349c3a278e3b093614901d7 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 23 Mar 2026 03:04:01 +0000 Subject: [PATCH 5/5] Restrict nlmer warning to start_from_mle path Co-authored-by: annahuynhly <97189987+annahuynhly@users.noreply.github.com> Agent-Logs-Url: https://github.com/annahuynhly/lme4/sessions/895f4c08-9385-4848-bffd-3b521aaec1cb --- R/allFit.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/allFit.R b/R/allFit.R index 9af9f15a7..5e7fddf06 100644 --- a/R/allFit.R +++ b/R/allFit.R @@ -166,7 +166,7 @@ allFit <- function(object, meth.tab = NULL, opt.ctrls[[optimizer[..i]]]) ctrl <- do.call(if(isGLMM(object)) glmerControl else lmerControl, ctrl) fit_once <- function() { - if (isNLMM(object)) { + if (start_from_mle && isNLMM(object)) { warning("results are not guaranteed when using nlmer") } refit(object, control = ctrl)