# Nonconvex and Matrix Variables

Is there any way to deal with matrix variables with Nonconvex lib ?
I tried something like:

``````using Nonconvex

f(x) = sqrt(x[2,2])
g(x, a, b) = (a*x[1,2] + b)^3 - x[2,1]

model = Model(f)
add_ineq_constraint!(model, x -> g(x, 2, 0))
add_ineq_constraint!(model, x -> g(x, -1, 1))

alg = IpoptAlg()
options = IpoptOptions(first_order = true, tol = 1e-7)
r = optimize(model, alg, [[1.0,1.0],[1.0, 1.0]], options = options)
``````

but I got the following error:

``````Stacktrace:
[1] getindex
@ ./array.jl:862 [inlined]
[2] g(x::Vector{Vector{Float64}}, a::Int64, b::Int64)
@ Main ~/Nextcloud/Dauphine/OptiForm/Julia/Nonconvex/test.jl:5
[3] (::var"#1#2")(x::Vector{Vector{Float64}})
@ Main ~/Nextcloud/Dauphine/OptiForm/Julia/Nonconvex/test.jl:9
[4] add_ineq_constraint!(m::Model{Vector{Any}}, f::var"#1#2", s::Float64) (repeats 2 times)
@ NonconvexCore ~/.julia/packages/NonconvexCore/uZAVo/src/models/model.jl:160
[5] top-level scope
@ ~/Nextcloud/Dauphine/OptiForm/Julia/Nonconvex/test.jl:9
``````

Just reshape them to/from vectors passing them as optimization parameters to/from Nonconvex.

Your decision variables are a vector of vectors so you need `x[1][2]` not `x[1,2]`. Nonconvex supports vectors of mostly arbitrary data structures as decision variables.

``````using Nonconvex

f(x) = sqrt(x[2][2])
g(x, a, b) = (a*x[1][2] + b)^3 - x[2][1]

model = Model(f)
add_ineq_constraint!(model, x -> g(x, 2, 0))
add_ineq_constraint!(model, x -> g(x, -1, 1))

alg = IpoptAlg()
options = IpoptOptions(first_order = true, tol = 1e-7)
r = optimize(model, alg, [[1.0,1.0],[1.0, 1.0]], options = options)
``````
1 Like

Oh, I didnâ€™t notice this.

If @chupin actually wants a â€śmatrixâ€ť variable, then I should remind them that Julia has actual 2d arrays â€” you donâ€™t need `[[0.0, 0.0],[0.0,0.0]]` arrays-of-arrays as you would in Python.

1 Like

In fact, I want Matrix variables because in my more complex code, I use the very usefull `ones`, `zeros`, `rand`, etc., that produce matrices.
I tried to convert the toy example:

``````using Nonconvex
f(x) = sqrt(x[2,2])
g(x, a, b) = (a*x[1,2] + b)^3 - x[2,1]

model = Model(f)
addvar!(model, [1e-4 1e-4 ;  1e-4 1e-4], [10.0 10.0 ; 10.0 10.0])
add_ineq_constraint!(model, x -> g(x, 2, 0))
add_ineq_constraint!(model, x -> g(x, -1, 1))

alg = IpoptAlg()
options = IpoptOptions(first_order = true, tol = 1e-7)
r = optimize(model, alg, [1.0 1.0 ; 1.0 1.0], options = options
``````

but I got the error:

``````ERROR: LoadError: BoundsError: attempt to access 1-element Vector{Matrix{Float64}} at index [1, 2]
Stacktrace:
[1] getindex
@ ./array.jl:862 [inlined]
[2] g(x::Vector{Matrix{Float64}}, a::Int64, b::Int64)
@ Main ~/Nextcloud/Dauphine/OptiForm/Julia/Nonconvex/test.jl:18
[3] (::var"#1#2")(x::Vector{Matrix{Float64}})
@ Main ~/Nextcloud/Dauphine/OptiForm/Julia/Nonconvex/test.jl:22
[4] add_ineq_constraint!(m::Model{Vector{Any}}, f::var"#1#2", s::Float64) (repeats 2 times)
@ NonconvexCore ~/.julia/packages/NonconvexCore/uZAVo/src/models/model.jl:160
[5] top-level scope
@ ~/Nextcloud/Dauphine/OptiForm/Julia/Nonconvex/test.jl:22
in expression starting at /home/mc/Nextcloud/Dauphine/OptiForm/Julia/Nonconvex/test.jl:22
``````

The decision variables `x` is always a vector of things. In your case, you are adding a single matrix decision variable. So to get it in the function you should use `x[1]`.

``````add_ineq_constraint!(model, x -> g(x[1], 2, 0))
add_ineq_constraint!(model, x -> g(x[1], -1, 1))
``````

Thanks, but unfortunately, the following code gives a lot of errors (beginning with Zigote)

``````using Nonconvex

f(x) = sqrt(x[2,2])
g(x, a, b) = (a*x[1,2] + b)^3 - x[2,1]

model = Model(f)
addvar!(model, [1e-4 1e-4 ;  1e-4 1e-4], [10.0 10.0 ; 10.0 10.0])
add_ineq_constraint!(model, x -> g(x[1], 2, 0))
add_ineq_constraint!(model, x -> g(x[1], -1, 1))

alg = IpoptAlg()
options = IpoptOptions(first_order = true, tol = 1e-7)
r = optimize(model, alg, [1.0 1.0 ; 1.0 1.0], options = options)
``````

That seems to be the best way. Thanks