# How to extend the JuMP @variable so that it can construct a sparse array which can be used as a full matrix?

Hi all

In fact, this question is a derivative of my last question.

I want to create a 4x4 array variables, but it only has a value at the index (1, 2), (2, 1), (2, 3), (3, 2) and the rest is 0.

@blegat provide several solutions, one of which best meets my expectations, as follows:

``````model = Model()
x = zeros(AffExpr, 3, 3)
x[1, 1] = @variable(model, base_name = "x[1, 1]")
x[2, 2] = @variable(model, base_name = "x[2, 2]")
x[1, 3] = @variable(model, base_name = "x[1, 3]")
x[3, 1] = @variable(model, base_name = "x[3, 1]")
x[3, 3] = @variable(model, base_name = "x[3, 3]")

julia> x
3Ă—3 Matrix{AffExpr}:
x[1, 1]  0        x[1, 3]
0        x[2, 2]  0
x[3, 1]  0        x[3, 3]
``````

After my simple test, the â€śsparseâ€ť array variable `x` can be used as a â€śfullâ€ť matrix.

For example, the most concerned am I is matrix multiplication and indexing:

``````julia> rand(3, 3) * x
3Ă—3 Matrix{AffExpr}:
0.39383698459321326 x[1, 1] + 0.48046499431872314 x[3, 1]  0.1500480109188398 x[2, 2]  0.39383698459321326 x[1, 3] + 0.48046499431872314 x[3, 3]
0.9024020538088555 x[1, 1] + 0.21740175234965387 x[3, 1]   0.7251245455266802 x[2, 2]  0.9024020538088555 x[1, 3] + 0.21740175234965387 x[3, 3]
0.47900776569507086 x[1, 1] + 0.9605059975897137 x[3, 1]   0.832551981599313 x[2, 2]   0.47900776569507086 x[1, 3] + 0.9605059975897137 x[3, 3]

julia> x[1, 1] + x[1, 2]
x[1, 1]
``````

Thank you very much for the help provided by @blegat

Now, what I want to do is to make these codes more generic. I think I can extend `@variable`

In the following link, there is a very simple example to teach me how to extend `@variable`
https://jump.dev/JuMP.jl/v0.21.8/developers/extensions/

Maybe itâ€™s because my level is too low. I cannot follow it very well. (To be honest, I am confused about it.)

So, I want to study exactly how `@variable` works, but I am prevented from accessing both `JuMP.add_variable` and `JuMP.build_variable` functions because of Macros.

For example, when I create a JuMP variable

``````@variable(model, x[1:3, 1:3])
``````

How does JuMP identify `x` as a â€śnameâ€ť, and identify `[1:3, 1:3]` as a â€śdimensionâ€ť, â€¦?

What information should I refer to, in order to achieve my idea? like the form shown as follows:

``````@variable(model, x[1:3, 1:3], Sparse, row=[1, 2, 2, 3], col=[2, 1, 3, 2])
``````

I hope you wonâ€™t get bored with my long descriptions

Thanks a lot!

1 Like

Iâ€™ve recently improved this in the dev documentation: Variables Â· JuMP.

Namely: donâ€™t extend JuMP, just use regular Julia data structures:

``````using JuMP, SparseArrays
model = Model()
x = @variable(model, [1:4])

julia> X = sparse([1, 2, 2, 3], [2, 1, 3, 2], x)
3Ă—3 SparseMatrixCSC{VariableRef, Int64} with 4 stored entries:
â‹…       noname  â‹…
noname  â‹…       noname
â‹…       noname  â‹…

julia> b = [1, 2, 3];

julia> X * b
3-element Vector{AffExpr}:
2 noname
noname + 3 noname
2 noname
``````

Now you might run into some weirdness, because of how `zero(VariableRef)` works (it is not the type `VariableRef`!).

So things like

``````julia> X .* X
3Ă—3 SparseMatrixCSC{QuadExpr, Int64} with 9 stored entries:
0        nonameÂ˛  0
nonameÂ˛  0        nonameÂ˛
0        nonameÂ˛  0
``````

Will become dense.