# Modular implementation of optimization problems with JuMP

**URL:** <https://discourse.julialang.org/t/modular-implementation-of-optimization-problems-with-jump/116261>\
**Category:** Optimization (Mathematical)\
**Tags:** jump, energy\
**Created:** [June 26, 2024, 2:06pm UTC](https://discourse.julialang.org/t/modular-implementation-of-optimization-problems-with-jump/116261 "2024-06-26T14:06:27Z")\
**Posts on this page:** 1\
**Showing post:** 4

<div class="post-metadata">

**Author:** ![pierre-haessig](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pierre-haessig/32/217129_2.png) [@pierre-haessig](https://discourse.julialang.org/u/pierre-haessig)\
**Post date:** [July 4, 2024, 12:33pm UTC](https://discourse.julialang.org/t/modular-implementation-of-optimization-problems-with-jump/116261/4 "2024-07-04T12:33:14Z")

</div>

I just came across the 2019 post [Pyomo style "blocks" in JuMP](https://discourse.julialang.org/t/pyomo-style-blocks-in-jump/31849) by @jonmat because the more I dig into it, the more I realize that I’m indeed in search of the **“namespace”** feature mentioned here (and I didn’t know that Pyomo provides this). Indeed, for some other project, I’m may be looking for a Modelica-style object/component oriented structuring of JuMP model.

Now, I understand that in the present state of JuMP it’s indeed possible to implement such things using anonymous variables. However, looking at my “add\_variable” wrapper of the classical `@variable` macro (see below), I feel like I’m just creating a more cumbersome version of `@variable` (see e.g. the presence of `lb` and `ub` keyword args since I cannot use the nice `lb <= x <= ub` syntax without a macro), for the only reason that I want to store the `VariableRef` in my container of choice (see `model_data::Dict{String,Any}`) rather than in the existing global `Model` container of registered variables.

So my question is: what would be the difficulty to bake this “reference storage hijacking” directly in the `@variable` macro? Or should I copy-paste the [`@variable` source code](https://github.com/jump-dev/JuMP.jl/blob/master/src/macros/%40variable.jl) and try to adapt it for my use case?

## my “add\_variable” wrapper

This is the present state of my custom “add\_variable” wrapper around `@variable` (early version discussed in [Using anonymous and or symbols to create dynamic variable names? - #3 by pierre-haessig](https://discourse.julialang.org/t/using-anonymous-and-or-symbols-to-create-dynamic-variable-names/83095/3)). Main features are:

- uses anonymous variables to avoid registration in the global namespace of `Model`
- but instead store the `VariableRef` in a `Dict`
- and then returns the `VariableRef` to make it easy to bind it to a similarly name Julia variable in the caller.

but to get these features, as said above, I have to pay the price of a much worse API compared to the original `@variable`.

```julia-auto
"""
    add_var!(model_data::Dict{String,Any}, name::String;
             lb=nothing, ub=nothing, fix=nothing, K::Int=1, stage="")

add a variable to the JuMP `Model` `model_data["model"]` and store the reference
to that variable in `model_data[name]`.

Returns the variable reference.

`name` is also used as the `base_name` of the JuMP variable (used for printing),
with the optional `stage` argument (`Int`, `String`...) used as a suffix.

# Other optional arguments:
- lower and/or upper bounds can be set with `lb` and `ub`
- equal bounds can be set with `fix`
- the variable can be a Vector of length `K` if `K` >1 (timeseries).
"""
function add_var!(model_data::Dict{String,Any}, name::String;
                  lb=nothing, ub=nothing, fix=nothing, K::Int=1, stage="")
    model = model_data["model"]
    name_suffix = "$name$stage"
    
    if K==1
        v = @variable(model, base_name=name_suffix)
    elseif K>1
        v = @variable(model, [1:K], base_name=name_suffix)
    else
        throw(ArgumentError("`K` array size parameter should be >=1"))
    end
    model_data[name] = v

    # Bounds:
    if (lb!==nothing || ub!==nothing) && fix!==nothing
        throw(ArgumentError("`lb` and `ub` bounds cannot be used in conjunction with `fix`"))
    end
    if fix !==nothing
        fix.(v)
    end
    if lb !==nothing
        set_lower_bound.(v, lb)
    end
    if ub !==nothing
        set_upper_bound.(v, ub)
    end
    
    return v
end

```

which is to be used as

```julia-auto
# One shot model setup
md = Dict{String,Any}()
md["model"] = Model(HiGHS.Optimizer)
# add piles of variables:
x = add_var!(model_data, "x", lb=0.0, ub=power_rated_gen_max)
y = add_var!(model_data, "y", lb=0.0, ub=power_rated_gen_max)

```

---

_[View the full topic](https://discourse.julialang.org/t/modular-implementation-of-optimization-problems-with-jump/116261)._
