Registering Expressions as JuMP variables in a loop

Hey guys, I have a project, where I create a model like this

m = @model begin
	@exogenous data
	@exogenous consumption
	production[1:71] := inv(I - data.Ω) * consumtion
	prices[1:71] := @maxc c(production) constraints(c)
end

This should then be converted into a JuMP Model, so production and prices should be a variable in this model. I store the expression on the LHS and RHS of the := operator in a Dict{Expr,Expr} and when building the JuMP Model I loop over them. Now here is the problem:

function build_jump_model(em::EconomicModel)
	m = Model(HiGHS.Optimizer)
	for (k,v) in em.maximisation_variables
		@info k
		@variable(m, eval(k))
	end
	return m
end

This errors on compilation and

function build_jump_model(em::EconomicModel)
   m = Model(HiGHS.Optimizer)
   for (k,v) in em.maximisation_variables
   	@info k
   	@variable(m, k)
   end
   return m
end

this just registers :k as a variable. (why is it :k and not just k tho?)
Is it even possible to correctly register the value of k? Thanks

Hi @theplatters :smile:

I don’t know what @model and @exogenous are, so I don’t know how much help I will be, but:

You probably need

function build_jump_model(em::EconomicModel)
	model = Model(HiGHS.Optimizer)
	for (k, v) in em.maximisation_variables
		model[k] = @variable(model)
	end
	return model
end

or

function build_jump_model(em::EconomicModel)
	model = Model(HiGHS.Optimizer)
	@variable(model, x[keys(em.maximisation_variables)])
	return model
end

You should almost never use eval.

I’ll point you to these parts of the JuMP documentation:

Happy to answer further questions after you’ve read.

I’ll caution you that if you’re writing the @model macro, then getting this to work can be very tricky. I’d encourage you to think of alternative approaches before you try to be too clever with the macros.

Thank you for the detailed reply.

The first code you provided solves the problem. Although I don’t like how JuMP changes the global state of variables.

What alternative approaches would you suggest? I want it to be as concise as possible, so that the user has to not worry about implementation details, that’s why I started writing it like this.

1 Like

Although I don’t like how JuMP changes the global state of variables

Unfortunately for you, then, this is a fundamental design decision in JuMP which will never change.

What alternative approaches would you suggest

I didn’t suggest anything because I don’t know what you are trying to achieve. One downside to making a DSL with macros is that simplifies the process for people who are already familiar with the domain, but it makes it harder for people unfamiliar to reason about what is happening. (As one example you yourself have already run into: @variable(model, x) does something very specific. And you cannot interpolate symbols or other variables into the x name.)