mxOption(m1, "Default optimizer", "NPSOL") not setting optimizer?

Hi,
I was expecting this to set the optimizer for a model:


# Set optimizer for this model
m1 = mxRun(mxOption(m1, "Default optimizer", "NPSOL"))

But

testthat::expect_match(m1@runstate$compute$steps[1][[1]]$engine, "NPSOL")
# Error: m1@runstate$compute$steps[1][[1]]$engine does not match 'NPSOL'. Actual value: "CSOLNP"

Is that a bug in me, mxOption(), or OpenMx?

worked examples


library(OpenMx)
manifests = c("mpg", "disp", "gear")
m1 <- mxModel("ind", type = "RAM",
manifestVars = manifests,
mxPath(from = manifests, arrows = 2),
mxPath(from = "one", to = manifests),
mxData(mtcars[,manifests], type="raw")
)

m1 = mxRun(m1)
m1@runstate$compute$steps[1][[1]]$engine
# returns CSOLNP (# PS: Is this the only way to get at engine directly?)

# toggle optimizer to NPSOL for this model
m1 = mxRun(mxOption(m1, "Default optimizer", "NPSOL"))
testthat::expect_match(m1@runstate$compute$steps[1][[1]]$engine, "NPSOL")
# Error: m1@runstate$compute$steps[1][[1]]$engine does not match 'NPSOL'. Actual value: "CSOLNP"

# try global switch
mxOption(NULL, "Default optimizer", "NPSOL")
m1 = mxRun(mxOption(m1, "Default optimizer", "NPSOL"))
testthat::expect_match(m1@runstate$compute$steps[1][[1]]$engine, "NPSOL")
# all OK

With 3525,

Error in mxOption(m1, "Default optimizer", "NPSOL") :
Default optimizer is a global option and cannot be set on models

Could be you, the following change (adding m1 <- inside the mxRun) works:

library(OpenMx)
manifests = c("mpg", "disp", "gear")
m1 <- mxModel("ind", type = "RAM",
manifestVars = manifests,
mxPath(from = manifests, arrows = 2),
mxPath(from = "one", to = manifests),
mxData(mtcars[,manifests], type="raw")
)

m1 = mxRun(m1)
m1@runstate$compute$steps[1][[1]]$engine
# returns CSOLNP (# PS: Is this the only way to get at engine directly?)

# toggle optimizer to NPSOL for this model
m1 = mxRun(m1 <- mxOption(m1, "Default optimizer", "NPSOL"))
testthat::expect_match(m1@runstate$compute$steps[1][[1]]$engine, "NPSOL")
# Error: m1@runstate$compute$steps[1][[1]]$engine does not match 'NPSOL'. Actual value: "CSOLNP"

# try global switch
mxOption(NULL, "Default optimizer", "NPSOL")
m1 = mxRun(mxOption(m1, "Default optimizer", "NPSOL"))
testthat::expect_match(m1@runstate$compute$steps[1][[1]]$engine, "NPSOL")
# all OK

Uh, users may have code that uses this option in the usual non-global way. Also, in the event that the compute path uses multiple optimization steps, might it not be inconvenient not to be able to set this at the model level?

Is this a necessary change, since fix with

m1 = mxRun(m1 <- mxOption(m1, "Default optimizer", "NPSOL"))

works in the released 2.0 Beta

> Also, in the event that the compute path uses multiple optimization steps, might it not be inconvenient not to be able to set this at the model level?

mxOption is the wrong way to control this in the first place. Take a look at the ifa-* tests in models/. Use a custom compute plan.

> Is this a necessary change, since fix with
> m1 = mxRun(m1 <- mxOption(m1, "Default optimizer", "NPSOL"))
> works in the released 2.0 Beta

I thought the whole point of this report was that it doesn't work and fails silently?

this used to work, but was disabled after the beta went live

m1 = mxOption(m1, "Default optimizer", "NPSOL")

I think either mxOption(m1, "Default optimizer", "NPSOL") should handle the case of setting the compute plan for a model, or the error should tell people how to do this easily.

As a start, we could submit this in MxOptions.R

if (key == "Default optimizer") {
stop(paste0(key, "is a global option and cannot be set on models",
"To switch optimizers globally, use, e.g.:\n",
"mxOption(m1, 'Default optimizer', 'CSOLNP')",
"To switch for just this model, use a custom compute plan.\n",
"See help(WHERE!!!) for an example."
))
}

Tim made this change. Thanks! I'm closing the ticket.