Custom R fit function with algebras - possible?

2 replies [Last post]
CharlesD's picture
Offline
Joined: 04/30/2013

My attempts to specify a custom R objective function with mxFitFunctionR (using latest build from the git mirror) are not working, because it seems as though the model that gets passed into the fitfunction is with all the algebras unevaluated. Am I doing something wrong, or thinking about this completely wrong? Is there a way I can achieve similar with the algebras evaluated? Below is a minimal example modified from the mxFitFunctionR example. Thanks!

A <- mxMatrix(nrow = 4, ncol = 1, values = c(6:9), free = TRUE, name = 'A')
B <- mxMatrix(nrow = 4, ncol = 1, values = c(10:13), free = FALSE, labels=paste0("testalg[",1:4,",1]"),name = 'B')
testalg<-mxAlgebra(A%x%2,name="testalg")
squared <- function(x) { x ^ 2 }

# Define the objective function in R

objFunction <- function(model, state) {
# browser()
values <- model[['B']]@values
print("i")
return(squared(values[1,1] - 4) + squared(values[2,1] + 3)+
squared(values[3,1] - 30)+squared(values[4,1] - 2))
}

# Define the expectation function

fitFunction <- mxFitFunctionR(objFunction)

# Define the model

tmpModel <- mxModel('exampleModel', A, B,testalg, fitFunction)

# Fit the model and print a summary

tmpModelOut <- mxRun(tmpModel)
summary(tmpModelOut)

mhunter's picture
Offline
Joined: 07/31/2009
mxEval your algebra

Hi Charles,

I'll give you some code that works, and then explain the key difference from the code that did not work. Here's the code.

require(OpenMx)
 
A <- mxMatrix(nrow = 4, ncol = 1, values = c(6:9), free = TRUE, name = 'A')
B <- mxMatrix(nrow = 4, ncol = 1, values = c(10:13), free = FALSE, labels=paste("testalg[",1:4,",1]", sep=''),name = 'B')
testalg<-mxAlgebra(A%x%2,name="testalg")
squared <- function(x) { x ^ 2 }
 
# Define the objective function in R
 
objFunction <- function(model, state) {
# browser()
#values <- model[['B']]@values
values <- mxEval(B, model=model, compute=TRUE)  #### Key Difference
print("i")
return(squared(values[1,1] - 4) + squared(values[2,1] + 3)+
squared(values[3,1] - 30)+squared(values[4,1] - 2))
}
 
# Define the expectation function
 
fitFunction <- mxFitFunctionR(objFunction)
 
# Define the model
 
tmpModel <- mxModel('exampleModel', A, B,testalg, fitFunction)
 
# Fit the model and print a summary
 
tmpModelOut <- mxRun(tmpModel)
summary(tmpModelOut)

The key difference is using mxEval. This is the preferred method for getting the values of a mxMatrix or the result of an mxAlgebra. OpenMx does not automatically evaluate mxAlgebras in the frontend, or when you use R fit functions. OpenMx has a system of knowing in the backend when mxAlgebras need to be evaluated and when they can be left alone. So, when you're using mxAlgebra's with an R fit function, the R fit function should probably use mxEval with compute=TRUE.

CharlesD's picture
Offline
Joined: 04/30/2013
Took me a while to get back

Took me a while to get back to this, but fantastic, cheers Mike!