# How to pass the domain of a variable to a function in a general manner?

**URL:** <https://discourse.julialang.org/t/how-to-pass-the-domain-of-a-variable-to-a-function-in-a-general-manner/111824>\
**Category:** Optimization (Mathematical)\
**Tags:** question, jump, optimization, algorithm\
**Created:** [March 19, 2024, 3:01pm UTC](https://discourse.julialang.org/t/how-to-pass-the-domain-of-a-variable-to-a-function-in-a-general-manner/111824 "2024-03-19T15:01:34Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![WuSiren](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/wusiren/32/42529_2.png) [@WuSiren](https://discourse.julialang.org/u/WuSiren)\
**Post date:** [March 19, 2024, 3:01pm UTC](https://discourse.julialang.org/t/how-to-pass-the-domain-of-a-variable-to-a-function-in-a-general-manner/111824/1 "2024-03-19T15:01:34Z")

</div>

I plan to implement some certain algorithm that is designed for a class of some type of optimization problems with one of whose decision variables x required to be in the domain F\_x\subseteq \mathbb{R}\_+^n.

I decide to write a function for this algorithm so that the users can pass the necessary parameters of any instance to it to obtain the optimal solution. Suppose the name of the function is `MyAlgorithm(Fx, other_params)`.

Now my question is how should I pass the domain F\_x to the function in a general way? For example, if in an instance of this type of problem we have F\_x=\{0,1\}^m\times\mathbb{R}\_+^n, what should I write at the position of `Fx` when invoking the function `MyAlgorithm(Fx, other_params)`? And furthermore, how can the function recognize and resolve it with the help of `JuMP`?

Many thanks!

---

<div class="post-metadata">

**Author:** ![odow](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/odow/32/28685_2.png) [@odow](https://discourse.julialang.org/u/odow)\
**Post date:** [March 19, 2024, 7:42pm UTC](https://discourse.julialang.org/t/how-to-pass-the-domain-of-a-variable-to-a-function-in-a-general-manner/111824/2 "2024-03-19T19:42:09Z")

</div>

Take a read of the tutorial: [Design patterns for larger models · JuMP](https://jump.dev/JuMP.jl/stable/tutorials/getting_started/design_patterns_for_larger_models/)

You could do something like:

```Julia
struct BinaryNonnegative
    m::Int
    n::Int
end

function create_variables(Fx::BinaryNonnegative, model)
    @variable(model, x[1:Fx.m], Bin)
    @variable(model, y[1:Fx.n] >= 0)
    return [x; y]
end

function MyAlgorithm(Fx, params)
    model = Model()
    x = create_variables(Fx, model)
    return model
end

Fx = BinaryNonnegative(3, 7)
params = nothing
model = MyAlgorithm(Fx, params)

```

---

<div class="post-metadata">

**Author:** ![WuSiren](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/wusiren/32/42529_2.png) [@WuSiren](https://discourse.julialang.org/u/WuSiren)\
**Post date:** [March 20, 2024, 1:58am UTC](https://discourse.julialang.org/t/how-to-pass-the-domain-of-a-variable-to-a-function-in-a-general-manner/111824/3 "2024-03-20T01:58:38Z")

</div>

> [@odow](#):
>
> ```julia
> function MyAlgorithm(Fx, params)
> model = Model()
> x = create_variables(Fx, model)
> return model
> end
> 
> ```

Yes, thanks! It does work, but what if F\_x is other arbitrary domain such as F\_x = \{0,1\}^m\times\mathbb{R}\_+^n\times\mathbb{Z}\_+^k\subseteq\mathbb{R}\_+^{m+n+k}? I mean I don’t want the function `MyAlgorithm` to depend on another fixed function like `create_variables`.

---

<div class="post-metadata">

**Author:** ![odow](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/odow/32/28685_2.png) [@odow](https://discourse.julialang.org/u/odow)\
**Post date:** [March 20, 2024, 2:14am UTC](https://discourse.julialang.org/t/how-to-pass-the-domain-of-a-variable-to-a-function-in-a-general-manner/111824/4 "2024-03-20T02:14:56Z")

</div>

> but what if Fx is other arbitrary domain  
> I mean I don’t want the function `MyAlgorithm` to depend on another fixed function like `create_variables` .

JuMP doesn’t work by defining a single vector of decision variables that lives in a Cartesian product of domains. If you want something like that, you’ll need to code it yourself.

How about:

```Julia
julia> using JuMP

julia> abstract type AbstractDomain end

julia> struct ZeroOne <: AbstractDomain; n::Int end

julia> add_variables(d::ZeroOne, model) = @variable(model, [1:d.n], Bin)
add_variables (generic function with 1 method)

julia> struct Rplus <: AbstractDomain; n::Int end

julia> add_variables(d::Rplus, model) = @variable(model, [1:d.n], lower_bound = 0)
add_variables (generic function with 2 methods)

julia> struct Zplus <: AbstractDomain; n::Int end

julia> add_variables(d::Zplus, model) = @variable(model, [1:d.n], lower_bound = 0, Int)
add_variables (generic function with 3 methods)

julia> function MyAlgorithm(Fx::Vector{<:AbstractDomain}, params)
           model = Model()
           x = reduce(vcat, add_variables.(Fx, model))
           return model, x
       end
MyAlgorithm (generic function with 1 method)

julia> model, x = MyAlgorithm([ZeroOne(3), Rplus(2), Zplus(3)], nothing)
(A JuMP Model
Feasibility problem with:
Variables: 8
`VariableRef`-in-`MathOptInterface.GreaterThan{Float64}`: 5 constraints
`VariableRef`-in-`MathOptInterface.Integer`: 3 constraints
`VariableRef`-in-`MathOptInterface.ZeroOne`: 3 constraints
Model mode: AUTOMATIC
CachingOptimizer state: NO_OPTIMIZER
Solver name: No optimizer attached., VariableRef[_[1], _[2], _[3], _[4], _[5], _[6], _[7], _[8]])

julia> model
A JuMP Model
Feasibility problem with:
Variables: 8
`VariableRef`-in-`MathOptInterface.GreaterThan{Float64}`: 5 constraints
`VariableRef`-in-`MathOptInterface.Integer`: 3 constraints
`VariableRef`-in-`MathOptInterface.ZeroOne`: 3 constraints
Model mode: AUTOMATIC
CachingOptimizer state: NO_OPTIMIZER
Solver name: No optimizer attached.

julia> x
8-element Vector{VariableRef}:
 _[1]
 _[2]
 _[3]
 _[4]
 _[5]
 _[6]
 _[7]
 _[8]

```

You could also get people to pass you a vector of lower bounds, upper bounds, and whether the variable is integer.

Perhaps:

```Julia
julia> struct Domain
           lower::Float64
           upper::Float64
           discrete::Bool
       end

julia> function MyAlgorithm(Fx::Vector{Domain}, params)
           model = Model()
           @variable(
               model,
               Fx[i].lower <= x[i in 1:length(Fx)] <= Fx[i].upper,
               integer = Fx[i].discrete,
           )
           return model, x
       end
MyAlgorithm (generic function with 2 methods)

julia> Fx = vcat(
           fill(Domain(0.0, 1.0, true), 3),
           fill(Domain(0.0, Inf, false), 2),
           fill(Domain(0.0, Inf, true), 3),
       )
8-element Vector{Domain}:
 Domain(0.0, 1.0, true)
 Domain(0.0, 1.0, true)
 Domain(0.0, 1.0, true)
 Domain(0.0, Inf, false)
 Domain(0.0, Inf, false)
 Domain(0.0, Inf, true)
 Domain(0.0, Inf, true)
 Domain(0.0, Inf, true)

julia> model, x = MyAlgorithm(Fx, nothing)
(A JuMP Model
Feasibility problem with:
Variables: 8
`VariableRef`-in-`MathOptInterface.GreaterThan{Float64}`: 8 constraints
`VariableRef`-in-`MathOptInterface.LessThan{Float64}`: 3 constraints
`VariableRef`-in-`MathOptInterface.Integer`: 6 constraints
Model mode: AUTOMATIC
CachingOptimizer state: NO_OPTIMIZER
Solver name: No optimizer attached.
Names registered in the model: x, VariableRef[x[1], x[2], x[3], x[4], x[5], x[6], x[7], x[8]])

```

A key benefit of JuMP is that you are free to construct the most appropriate data structure for your problem. You do not need to use built-in constructs. A downside is that choosing the most appropriate data structure can be difficult.

---

<div class="post-metadata">

**Author:** ![WuSiren](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/wusiren/32/42529_2.png) [@WuSiren](https://discourse.julialang.org/u/WuSiren)\
**Post date:** [March 20, 2024, 2:17am UTC](https://discourse.julialang.org/t/how-to-pass-the-domain-of-a-variable-to-a-function-in-a-general-manner/111824/5 "2024-03-20T02:17:19Z")

</div>

Thank you very much ! I’ll read your code carefully.
