umx!

Constraints

There a many times in modeling that we need to set paths equal to values determined from other aspects of the model. Commonly this can be done using labels - simply giving the same labels to objects we wish to equate. This is computationally efficient. Another way to limit the values a path can take is via upper and lower bounds. There are times, however, when these two methods are insufficient. For instance equating a free path to a fixed path, or, constraining a value using an algebra. That’s when constraints are essential.

Constraints are implemented by providing an algebra to mxConstraint. e.g. , like mxConstraint(A < B[1,1] %*% 2)

Constrain K to take a value fixed in another matrix (no real use…)

Here’s an example in which we force the cells of matrix K to take the values of a second matrix limit. To do this we write an mxConstraint with the algebra K == limit. The constraint should ensure that K is [1,2; 3,4] - the values of limit.

m1 <- mxModel("constraint_test", 
    umxMatrix("limit", type = "Full", nrow = 2, ncol = 2, free = FALSE, values = 1:4), 
    umxMatrix("K"    , type = "Full", nrow = 2, ncol = 2, free = TRUE), 
    mxConstraint(K == limit, name = "Klimit_equality"), 
    mxAlgebra(min(K), name = "minK"), 
    mxFitFunctionAlgebra("minK") 
)
mxEval(K, m1)

You might try and do this using labels: but labels can only equate free parameters, not free and fixed parameters. So…

m1 = mxModel(model="con_test", 
    umxMatrix("limit", nrow = 2, ncol = 2, free = FALSE, labels = paste0("eq", 1:4), values = 1:4),
    umxMatrix("K"    , nrow = 2, ncol = 2, free = TRUE, labels = paste0("eq", 1:4)),
    mxAlgebra(min(K), name = "minK"), 
    mxAlgebraObjective("minK") 
)
m1 = mxRun(m1)
# Error: In model 'con_test' the name 'eq1' is used as a free parameter in 'con_test.K' and as a fixed parameter in 'con_test.limit'

Here’s another example. In this model, we will maximise the sum A + B, with the mxConstraint that A must exceed B, but also remain under the value 10. What do you think the answer will be?

m1 = mxModel("max_A_plus_B",
    umxMatrix("A", nrow = 1, ncol = 1, free = TRUE),
    umxMatrix("B", nrow = 1, ncol = 1, free = TRUE),
	mxConstraint(name = 'A_greaterthan_B', A > B),
	mxConstraint(name = 'Amax', A < 10),
    mxAlgebra(name = "C", A + B),
    mxAlgebra(name = "maxC", -C),
    mxFitFunctionAlgebra("maxC") 
)
m1 = mxRun(m1)

mxEval(c(A=A, B=B, C=C), m1)

#   [,1]
# A   10
# B   10
# C   20

Equate both free parameters of matrix D using labels (both are set to “eq”) but constrain one to take the value log(10)

m1 = mxModel("what",
	umxMatrix("D", "Full", nrow= 2, ncol= 1, free = TRUE, values = 1, labels = "eq"),
	mxConstraint(D[1,1] == log(10) , name = 'fix_cell_D_one'),	
    mxAlgebra(name = "maxD", -D[2,1]), 
    mxFitFunctionAlgebra("maxD")
)
m1 = mxRun(m1)
mxEval(D, m1)
#          [,1]
# [1,] 2.302585
# [2,] 2.302585