Splatting keyword arguments to @variable macro in JuMP

I have a function which returns a particular variable, but defines it differently depending on my model type. I’ve recreated a MWE below.

using JuMP

function get_z_kwargs(m::Model)
    if m.ext[:model_type] == "binary"
        kwargs = (binary=true)
    elseif m.ext[:model_type] == "integer"
        kwargs = (integer=true, lower_bound=0)
    elseif m.ext[:model_type] == "relaxed"
        kwargs = (lower_bound=0)
    end
end

function make_z_variable(m::Model)
    kwargs = get_z_kwargs(m)
    return z = @variable(m, [1:10], base_name="z", kwargs...)
end


m = Model()
m.ext[:model_type] = "integer"
make_z_variable(m)

This produces an error. I can get around this by doing this:

function get_z_kwargs(m::Model)
    if m.ext[:model_type] == "binary"
        kwargs = (binary=true, integer=false, lower_bound=0)
    elseif m.ext[:model_type] == "integer"
        kwargs = (binary=false, integer=true, lower_bound=0)
    elseif m.ext[:model_type] == "relaxed"
        kwargs = (binary=false, integer=false, lower_bound=0)
    end
end

function make_z_variable(m::Model)
    kwargs = get_z_kwargs(m)
    return z = @variable(m, [1:10], base_name="z",
        binary=kwargs[1], integer=kwargs[2], lower_bound=kwargs[3]
    )
end

make_z_variable(m)

But I’m curious to know whether I could adapt my original code to do what I want.

No, splatting keyword arguments doesn’t work with the JuMP macros. Do this instead:

function apply_model_type(v, m::Model)
    if m.ext[:model_type] == "binary"
        set_binary.(v)
    elseif m.ext[:model_type] == "integer"
        set_integer.(v)
        set_lower_bound.(v, 0)
    elseif m.ext[:model_type] == "relaxed"
        set_lower_bound.(v, 0)
    end
end

function make_z_variable(m::Model)
    z = @variable(m, [1:10], base_name="z")
    apply_model_type(z, m)
    return z
end
2 Likes

Thanks! That’s much nicer :slight_smile: