How to pass auxiliary variables and constraints as "Defined variables" of AMPL in JuMP?

I am considering how to pass auxiliary variables as “Defined variables” of AMPL in JuMP.
Sample code

model = JuMP.Model(optimizer_with_attributes(Ipopt.Optimizer))
@variable(model, x)
@variable(model, y)
@variable(model, z) #an auxiliary variable
@objective(model, Max, 0)
@constraint(model, 2*x+y==1)
@constraint(model, z==2*x) #an auxiliary constraint
@constraint(model, x+2*z==1)
@time optimize!(model)
JuMP.value.(x) 
JuMP.value.(y) 
JuMP.value.(z) 

This problem solves a simple linear system of equations for 2 variables under 2 constraints theoretically. However, I introduce an auxiliary variable z as VariableRef by @variable and related constraint (z==2*x) as ConstraintRef. Thus, JuMP recognizes 3 variables and 3 constraints. For such a simple setting, the number of variables and constraints will not affect optimization results. However, if the problem has 100 control variables, 2000 auxiliary variables, and 2100 nonlinear equality constraints, JuMP optimization often fails or find an incorrect solution for some reasons.

On the other hand, AMPL allows users to define the auxiliary variable in the following format.

var z = 2*x

Then, z is recognized as “Defined variables”(AMPL) in A.8.1 (https://mathopt.de/AMPL/AMPL-RefMan.pdf), not as a control variable for chosen solver such as KNITRO and Ipopt. By using this feature, AMPL recognizes 2 variables and 2 constraints.

Are there any good ideas to specify control variables in JuMP to make a solver recognize only control variables while ignoring auxiliary variables and constraints?
For large-scale and complex optimizations, ignoring auxiliary variables and constraints is critical, like AMPL.

Use @expression:

model = JuMP.Model(optimizer_with_attributes(Ipopt.Optimizer))
@variable(model, x)
@variable(model, y)
@expression(model, z, 2 * x) #an auxiliary variable
@objective(model, Max, 0)
@constraint(model, 2*x+y==1)
# @constraint(model, z==2*x) #an auxiliary constraint
@constraint(model, x+2*z==1)
@time optimize!(model)
JuMP.value.(x) 
JuMP.value.(y) 
JuMP.value.(z) 

docs: Expressions · JuMP

4 Likes

Thank you. I did not know what really happens in @expression for optimization, but this is what I want to use here.

1 Like