How to get ALL decision variables value?

Hi all,

I am new in Julia and JuMP.jl

I have many decision variables, like, x1, x1, …x999, …

if I want to obtain the value of all decision variables

now, I may only use the codes as follows:

x1 = value.(x1)
x2 = value.(x2)
....
x999 = value.(x999)

this may cost me too much time

Is there a “one-click” function to get all variable values? And copy them to their original variable names

I used to be a MATLAB/Yalmip user, in matlab, I can use this m-file to achieve the target above, as follows:

res = whos;
[nn, mm] = size(res);

for ii = 1:nn
    if strcmp(res(ii).class, 'sdpvar') || strcmp(res(ii).class, 'ndsdpvar')
        vars = res(ii).name;
        eval([vars, '=', 'value(', vars ,');']);
    end
end
clear vars

if JuMP.jl do not have this “one-click” function, who can tell me how to obtain the variables in the current workspace (Julia pro), like whos in MATLAB.

Thanks a lot!

You can use

value.(all_variables(model))

But a better way would be to structure your code to not use x1, x2, ..., x999. Use a vector like

@variable(model, x[1:999])

Then you can just go

value.(x)
3 Likes

Having a vector instead of x1, x2,… as suggested by @odow is likely better, but if for any reason you want to keep the same model structure as you have, you can (thanks to Julia metaprogramming capabilities) programmatically build the variable names and the for loop…

Hi odow,

Using vectors to create decision variables is a good idea, However, I may give a bad example.

In my mode, I want to obtain the value of all variables with completely different and irregular name.

value.(all_variables(model))

This code can indeed get the value of all variables, but it seems that it cannot replace the variable with the value of the variable, that is, the original name assigned to the variable

@variable(model, ashfjnbasdfgbkj[1:10, 1:10, 1:10], Bin)
@variable(model, jhsFADJNBGAH[1:10, 1:10, 1:10], Bin)
@variable(model, hdukfhiebfHB[1:10, 1:10, 1:10], Bin)
...
...
optimize!(model)
ashfjnbasdfgbkj = value.(ashfjnbasdfgbkj)
jhsFADJNBGAH = value.(jhsFADJNBGAH)
hdukfhiebfHB = value.(hdukfhiebfHB)

JuMP variables are just normal Julia bindings. You can do anything with them. You can also look them up using model[key].

@variable(model, x[1:10, 1:10, 1:10], Bin)
@variable(model, y[1:10, 1:10, 1:10], Bin)
@variable(model, z[1:10, 1:10, 1:10], Bin)
optimize!(model)
Z_val = Dict(v => value.(v) for v in [x, y, z])
Z_val = Dict(v => value.(model[v]) for v in [:x, :y, :z])

Another option is Models · JuMP

object_dictionary(model)

it returns a dictionary containing keys mapping to each JuMP object.

Hi all,
I may found the solutions. Thanks @odow for the tips!
This seems to be an inefficient method, but it is indeed effective for my code.
if anyone has a better way, please let me know, thanks! :blush:
I guess there may be a better way, but limited by my English level, it is difficult for me to search for a solution to my problem on Google. :sweat_smile:

dvar_string = string(keys(object_dictionary(model)))
# OUTPUT: dvar_string = "[:x, :y, :z, :p, :q,...]"
dvar = []
for i in 1:length(dvar_string)
    if dvar_string[i] == ':'
        I = i + 1
        for j = I:length(dvar_string)
            if dvar_string[j] == ','
                J = j-1
                push!(dvar, dvar_string[I:J])
                break
            end
        end
    end
end

for k in dvar
    eval(Meta.parse(k * "=value.(" * k * ")"))
end

You can also write it in a separate file, like : getAllJuMPValue.jl
and call this .jl-file after optimize!(model), as follows:

....
optimize!(model)
include("getAllJuMPValue.jl")
...

The above code is equivalently executed:

x = value.(x)
y = value.(y)
z = value.(z)
p = value.(p)
q = value.(q)
...

This is especially useful when there are many decision variables, and the decision variables are increased or decreased during the programming process for debugging.

In general, you should almost never need to use eval or Meta.parse. They’re easy to get wrong, and they don’t always do what you think they’re doing.

Do something like this instead:

solution = Dict(
    k => value.(model[k])
    for k in keys(object_dictionary(model))
)

and structure your code to not use the lots of lines like x = value.(x).