# Convex.jl norm of multiple variables

I would like to use Convex.jl to solve a problem along the lines of

``````using Convex
x = Variable(1)
y = Variable(1)
z = Variable(1)
problem = minimize(x+y+z,norm([x,y,z])<=1)
``````

However, when I run this code, I get the error

``````MethodError: no method matching AbstractFloat(::Convex.MaxAtom)

Closest candidates are:
(::Type{T})(::AbstractChar) where T<:Union{AbstractChar, Number}
@ Base char.jl:50
(::Type{T})(::Base.TwicePrecision) where T<:Number
@ Base twiceprecision.jl:266
(::Type{T})(::Complex) where T<:Real
@ Base complex.jl:44
...

Stacktrace:
 float(x::Convex.MaxAtom)
@ Base ./float.jl:294
 generic_normInf(x::Vector{Variable})
@ LinearAlgebra ~/.julia/juliaup/julia-1.9.0-rc2+0.x64.linux.gnu/share/julia/stdlib/v1.9/LinearAlgebra/src/generic.jl:453
 normInf
@ ~/.julia/juliaup/julia-1.9.0-rc2+0.x64.linux.gnu/share/julia/stdlib/v1.9/LinearAlgebra/src/generic.jl:527 [inlined]
 generic_norm2(x::Vector{Variable})
@ LinearAlgebra ~/.julia/juliaup/julia-1.9.0-rc2+0.x64.linux.gnu/share/julia/stdlib/v1.9/LinearAlgebra/src/generic.jl:463
 norm2
@ ~/.julia/juliaup/julia-1.9.0-rc2+0.x64.linux.gnu/share/julia/stdlib/v1.9/LinearAlgebra/src/generic.jl:529 [inlined]
 norm(itr::Vector{Variable}, p::Int64)
@ LinearAlgebra ~/.julia/juliaup/julia-1.9.0-rc2+0.x64.linux.gnu/share/julia/stdlib/v1.9/LinearAlgebra/src/generic.jl:598
 norm(itr::Vector{Variable})
@ LinearAlgebra ~/.julia/juliaup/julia-1.9.0-rc2+0.x64.linux.gnu/share/julia/stdlib/v1.9/LinearAlgebra/src/generic.jl:596
 top-level scope
@ In:5
``````

From this I understand that the `norm` function can only be used on multi-dimensional variables, not multiple variables. Is there a way to combine multiple one-dimensional variables into a multi-dimensional variable so that this works?

Can you just formulate your problem with a single vector variable from the start?

I suppose in principle this is always possible, but it would improve readability etc to be able to use multiple names for conceptually different variables.

I think you might have better luck by defining the vector variable first and then giving individual names to new variables which you constrain to be equal to the vector components?

You can combine scalar variables into a vector-valued variable using `hcat` or `vcat`.

``````julia> using Convex

julia> import SCS

julia> x = Variable(1)
Variable
size: (1, 1)
sign: real
vexity: affine
id: 351…156

julia> y = Variable(1)
Variable
size: (1, 1)
sign: real
vexity: affine
id: 464…161

julia> z = Variable(1)
Variable
size: (1, 1)
sign: real
vexity: affine
id: 749…425

julia> problem = minimize(x + y + z, norm(hcat(x, y, z)) <= 1)
minimize
└─ + (affine; real)
├─ real variable (id: 351…156)
├─ real variable (id: 464…161)
└─ real variable (id: 749…425)
subject to
└─ <= constraint (convex)
├─ norm2 (convex; positive)
│  └─ hcat (affine; real)
│     ├─ …
│     ├─ …
│     └─ …
└─ 1

status: `solve!` not called yet

julia> solve!(problem, SCS.Optimizer)
------------------------------------------------------------------
SCS v3.2.3 - Splitting Conic Solver
(c) Brendan O'Donoghue, Stanford University, 2012
------------------------------------------------------------------
problem:  variables n: 5, constraints m: 6
cones: 	  z: primal zero / dual free vars: 1
l: linear vars: 1
q: soc vars: 4, qsize: 1
settings: eps_abs: 1.0e-04, eps_rel: 1.0e-04, eps_infeas: 1.0e-07
alpha: 1.50, scale: 1.00e-01, adaptive_scale: 1
max_iters: 100000, normalize: 1, rho_x: 1.00e-06
acceleration_lookback: 10, acceleration_interval: 10
lin-sys:  sparse-direct-amd-qdldl
nnz(A): 9, nnz(P): 0
------------------------------------------------------------------
iter | pri res | dua res |   gap   |   obj   |  scale  | time (s)
------------------------------------------------------------------
0| 1.68e+01  1.68e+00  6.00e+01 -3.00e+01  1.00e-01  8.72e-05
50| 3.30e-06  1.39e-09  2.86e-06 -1.73e+00  1.00e-01  1.17e-04
------------------------------------------------------------------
status:  solved
timings: total: 1.19e-04s = setup: 6.81e-05s + solve: 5.12e-05s
lin-sys: 9.65e-06s, cones: 5.73e-06s, accel: 2.43e-06s
------------------------------------------------------------------
objective = -1.732052
------------------------------------------------------------------

julia> evaluate(x), evaluate(y), evaluate(z)
(-0.5773512251810479, -0.5773512251810479, -0.5773512251810479)
``````
3 Likes

Thank you! Of course this perfectly answers my question. Thanks also @gdalle ; what you suggest would work as well I think but it is very nice to be able to write things using multiple variables when this is convenient.