Use Dictionary value in objective function

Hello,

I’m trying to be able to use values put in a Dictionary to weight the variables that are going to be minimized in a JuMP objective function.

The dictionnary is implemented as follow :

Dicopond = Dict(0=> 1, 1 => 2, 2 => 4, 3 => 8,
4 => 16, 5 => 32, 6 => 64, 7 => 128)

The variable :

@variable(model, absolute[y=1:endclassNb])

And the objective function :

@objective(model, Min, sum((absolute[y])*Dicopond[(absolute[y])] for y=1:endclassNb))

Absolute[y] will only take the values between 0 and 7.

However, I get the Error “LoadError: KeyError: key absolute[1] not found
in expression starting at…”

Is there a way to make him get the actual value corresponding to the value that will be assigned to absolute[y] ?

I’ve tried different ways to be able to put a weight to the decision variable and this was the one that seemed to be the most likely to work.

Thank you for your help!

EDIT : cross-posted on variables - Julia : use dictionary value in objective function? - Stack Overflow

Hi @rox, welcome to Julia and JuMP!

absolute is a JuMP decision variable and it can not be used as an index of any collection (including dictionaries).

You will have to come up with a different formulation of the problem.

Can you give more details on the problem you are trying to solve?

1 Like

Hey,

Thank you for your answer !

I’m trying to put an exponential ponderation to the “absolute” variable (the point of the code is putting students in a class. A class can have more or less student than an ideal class size, but the further away that number is from the ideal size the more it should weight so that the minimum function will favour a number of student around the ideal-class size).

As i have to use Linear Programming, i can’t put directly abs2(absolute) to get the value sqared. I’m then trying to go around that problem.

Do you think there’s a way to make it work somehow?

You should start writing your formulation in terms of equations.
You cant start with a regular absolute value penalty, and from that you can evolve to a piecewise linear penalty.

I’m sorry, could you elaborate on the equation part ?
Do you mean put an equation in the objective value ?
My main problem here is that the penality (what was in my dictionnary) depends directly from the value that the variable takes. I can’t put in advance that, for example, absolute[1] has to be multiplied by x.
Thanks!

Then you cannot have a linear formulation. If you need to multiply one variable by another then you have a quadratic formulation.

The standard way to represent this is to use a binary expansion (I haven’t tested the code, there might be typos):

Dicopond = Dict(
    0 => 1, 
    1 => 2, 
    2 => 4, 
    3 => 8,
    4 => 16, 
    5 => 32, 
    6 => 64, 
    7 => 128,
)
endclassNb = 3
model = Model()
@variable(model, absolute[1:endclassNb])
@variable(model, z[1:7, 1:endclassNb], Bin)
@constraint(model, sum(z) == 1)
@constraint(model, [y=1:endclassNb], absolute[y] == sum(a * z[a] for a=1:7))
@expression(moodel, da[y = 1:endclassNb], sum(z[i] * Dicopond[i] for i in 1:7))
@objective(model, Min, sum(absolute[y] * da[y] for y in 1:endclassNb))

That stills leaves you with a mixed-integer quadratic program, so you will need to use a commercial solver like Gurobi.

Cross posted: variables - Julia : use dictionary value in objective function? - Stack Overflow. @pszufe gave nicer answers than me.

2 Likes

@Henrique_Becker @joaquimg
Thank you for your help. I guess i won’t really have a choice to give up the linear aspect here.

1 Like

@odow Thank you a lot for the code and your help ! I’ll try with a mixed-integer solver if i can. And sorry about not mentionning the cross-post.

3 Likes