# Convex.jl matrix constraints interface : How can i supply this matrix?

**URL:** <https://discourse.julialang.org/t/convex-jl-matrix-constraints-interface-how-can-i-supply-this-matrix/63753>\
**Category:** Optimization (Mathematical)\
**Created:** [June 29, 2021, 1:36pm UTC](https://discourse.julialang.org/t/convex-jl-matrix-constraints-interface-how-can-i-supply-this-matrix/63753 "2021-06-29T13:36:31Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![lrnv](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lrnv/32/19373_2.png) [@lrnv](https://discourse.julialang.org/u/lrnv)\
**Post date:** [June 29, 2021, 1:36pm UTC](https://discourse.julialang.org/t/convex-jl-matrix-constraints-interface-how-can-i-supply-this-matrix/63753/1 "2021-06-29T13:36:31Z")

</div>

Hi,

I want to constraint some matrix that is given as a linear functions of the variables to be semi-definite positive. However, I found something strange :

```julia
function get_hankels(s,a,b)
    m = length(s)-1
    if iseven(m)
        # m = 2n
        n = Int(m//2)
        H_low = [s[i+j-1] for i in 1:n+1,j in 1:n+1]
        H_up = [(a+b)*s[i+j] - s[i+j+1] - a*b*s[i+j-1] for i in 1:n,j in 1:n]
    else
        # m = 2n+1
        n = Int((m-1)//2)
        H_low = [s[i+j] - a*s[i+j-1] for i in 1:n+1,j in 1:n+1]
        H_up = [b*s[i+j-1] - s[i+j] for i in 1:n+1,j in 1:n+1]
    end
    return H_low,H_up
end

# To see the matrices I want to use : 
using DynamicPolynomials
m=6
@polyvar x[1:m+1]
H_low,H_up = get_hankels(x,0,1)
display(H_low)
display(H_up)

# Now with convex variables, I want to build the constraints : 
using Convex
m=6
s = Variable(m+1)
H_low, H_up = get_hankels(s,0,1) # works

cstr1 = (H_low ⪰ 0) # does not work. 
cstr1 = ([s[1] s[2] s[3] s[4]; s[2] s[3] s[4] s[5]; s[3] s[4] s[5] s[6]; s[4] s[5] s[6] s[7]] ⪰ 0) # works

# Same for H_up 
cstr2 = (H_up ⪰ 0)

```

I have the follwoing error message :

```julia
julia> cstr1 = (H_low ⪰ 0) # does not work.
ERROR: MethodError: no method matching ⪰(::Matrix{Convex.IndexAtom}, ::Int64)
Closest candidates are:
  ⪰(::Convex.AbstractExpr, ::Union{Number, AbstractArray}) at C:\Users\u009192\.julia\packages\Convex\ubaUN\src\constraints\sdp_constraints.jl:115
  ⪰(::Union{Number, AbstractArray}, ::Convex.AbstractExpr) at C:\Users\u009192\.julia\packages\Convex\ubaUN\src\constraints\sdp_constraints.jl:124
Stacktrace:
 [1] top-level scope
   @ REPL[58]:1

julia> 

```

Indeed, the type is not the same :

```julia
julia> typeof([s[1] s[2] s[3] s[4]; s[2] s[3] s[4] s[5]; s[3] s[4] s[5] s[6]; s[4] s[5] s[6] s[7]])
Convex.TransposeAtom

julia> typeof(H_low)
Matrix{Convex.IndexAtom} (alias for Array{Convex.IndexAtom, 2})

julia> 

```

Is there a way to build this `H_low` matrix automatically in the right type ? The size of the problem might change from a run to the other…

@ericphanson Do you now the right syntax ?

---

<div class="post-metadata">

**Author:** ![ericphanson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ericphanson/32/215186_2.png) [@ericphanson](https://discourse.julialang.org/u/ericphanson)\
**Post date:** [June 29, 2021, 5:28pm UTC](https://discourse.julialang.org/t/convex-jl-matrix-constraints-interface-how-can-i-supply-this-matrix/63753/2 "2021-06-29T17:28:19Z")

</div>

Yeah, this is something Convex struggles with, which is that it wants e.g. a 2x2 matrix to be `Variable(2,2)`, not `Matrix{Variable}`. In other words, Convex works with vector/matrix-valuned variables but can’t work with vectors/matrices of variables directly. One workaround is to do

```julia
function convert_to_variable(arr::AbstractMatrix{<:AbstractVariable})
    x = Variable(size(arr))
    for i = 1:size(arr, 1), j = 1:size(arr, 2)
        add_constraint!(x, x[i,j] == arr[i,j])
    end
    return x
end

```

(untested), and then do `H_low_variable = convert_to_variable(H_low)` and use `H_low_variable` from then on.

This might not be very efficient though, as it creates a new variable with one constraint per variable in your matrix. For Convex.jl, a more efficient approach would be to rewrite `get_hankels` in a “vectorized” way, i.e. try to write it something like a matrix multiplication (of a non-variable matrix) onto your variable vector `s`. In other words, try to avoid indexing into `s` and create `H_low` by a function of `s` that doesn’t need to index into it.

Since JuMP works on a scalar level, that might be a better approach for this kind of problem.

---

<div class="post-metadata">

**Author:** ![lrnv](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lrnv/32/19373_2.png) [@lrnv](https://discourse.julialang.org/u/lrnv)\
**Post date:** [June 29, 2021, 5:32pm UTC](https://discourse.julialang.org/t/convex-jl-matrix-constraints-interface-how-can-i-supply-this-matrix/63753/3 "2021-06-29T17:32:36Z")

</div>

I only changed the `AbstractVariable` to `AbstractExprOrValue` as is :

```julia
function convert_to_variable(arr::AbstractMatrix{<:Convex.AbstractExprOrValue})
    x = Variable(size(arr))
    for i = 1:size(arr, 1), j = 1:size(arr, 2)
        add_constraint!(x, x[i,j] == arr[i,j])
    end
    return x
end

```

I had `Matrix{Convex.IndexAtom}`, and `Convex.IndexAtom <: Convex.AbstractVariable` is false but `Convex.IndexAtom <: Convex.AbstractExprOrValue` is true.

Works like a charm, thanks a lot @ericphanson !

Edit: I’ll try rewriting it as matrix-vector product, as it is clearly possible in this case. It was just easier to reason about with indexing. Jump is out-of-scope since I need arbitrary precision 😉
