# Second-order cone constraint in JuMP

**URL:** <https://discourse.julialang.org/t/second-order-cone-constraint-in-jump/130927>\
**Category:** Optimization (Mathematical)\
**Tags:** question, package, jump\
**Created:** [July 22, 2025, 2:49am UTC](https://discourse.julialang.org/t/second-order-cone-constraint-in-jump/130927 "2025-07-22T02:49:57Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![Z\_M](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/z_m/32/52830_2.png) [@Z\_M](https://discourse.julialang.org/u/Z_M)\
**Post date:** [July 22, 2025, 2:49am UTC](https://discourse.julialang.org/t/second-order-cone-constraint-in-jump/130927/1 "2025-07-22T02:49:57Z")

</div>

Hi guys!  
How to solve this constraint in Julia in JuMP, where the Q is a 2×2 Hessian matrix of a convex function, so it is a positive semidefinite matrix.

I know it can be reformulated as a second-order cone constraint, but I don’t know how to transfer.

Thank you very much!

 ![image](https://global.discourse-cdn.com/julialang/original/3X/8/c/8c0bade87db9d3f12bfa4e15420ee27c2bc4da6e.png)

---

<div class="post-metadata">

**Author:** ![WalterMadelim](https://avatars.discourse-cdn.com/v4/letter/w/3e96dc/32.png) [@WalterMadelim](https://discourse.julialang.org/u/WalterMadelim)\
**Post date:** [July 22, 2025, 6:07am UTC](https://discourse.julialang.org/t/second-order-cone-constraint-in-jump/130927/2 "2025-07-22T06:07:45Z")

</div>

If you are using Gurobi, you can just write it without reformulation.

If your `Q` is real:

1. if it is positive definite, then it is easy—a cholesky decomposition is sufficient.
2. if it is positive semidefinite, then maybe you can do a spectral decomposition

something like

```julia
# This `A` is a PSD matrix
A = [36 -26 -18 -24 -4; -26 59 -32 81 -15; -18 -32 62 -60 37; -24 81 -60 117 -30; -4 -15 37 -30 93]

using LinearAlgebra
vals, Q = eigen(A); # spectral decomposition
D = Diagonal(vals);
Q = Matrix(Q');
# @assert (Q'D)Q == A

# suppose you want to add this constr
t ≥ (x'A)x 
# you can define
JuMP.@expression(model, y, (Q)x)
# then the constr becomes
t ≥ (y'D)y
# since `D` is Diagonal, this constr can be converted to SOC form

```

Then after removing `0` entries in `D`, then followed by a cholesky decomposition, you can write the last constraint as a rotated second order cone [here](https://docs.mosek.com/modeling-cookbook/cqo.html#euclidean-norms).

Then you can in turn transform that rotated second order cone to a standard SOC.

* * *

**PS** to know whether a given symmetric matrix is positive definite, you can do `cholesky` directly, if success, then it is PD, otherwise you can do spectral decomposition as a recourse.

---

<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:** [July 22, 2025, 10:12pm UTC](https://discourse.julialang.org/t/second-order-cone-constraint-in-jump/130927/3 "2025-07-22T22:12:15Z")

</div>

Hi @Z_M,

Here’s the Cholesky version:

```julia
using JuMP
Q = [1.0 0.5; 0.5 3.0]
model = Model()
@variable(model, t)
@variable(model, x[i in 1:2])
@objective(model, Min, t)
QQ = LinearAlgebra.cholesky(Q)
# 2 * t * 1 >= || QQ.U * x ||_2^2
@constraint(model, [t; 1; QQ.U * x] in RotatedSecondOrderCone())

```

---

<div class="post-metadata">

**Author:** ![Z\_M](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/z_m/32/52830_2.png) [@Z\_M](https://discourse.julialang.org/u/Z_M)\
**Post date:** [July 23, 2025, 5:24am UTC](https://discourse.julialang.org/t/second-order-cone-constraint-in-jump/130927/4 "2025-07-23T05:24:58Z")

</div>

Thank you!  
I use Gurobi in JuMP, so how to write it without reformulation.  
In addition, if I have the JuMP.@expression(model, y, (Q)x) and then how to write a soc constraint in JuMP.

Thank you very much!

---

<div class="post-metadata">

**Author:** ![Z\_M](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/z_m/32/52830_2.png) [@Z\_M](https://discourse.julialang.org/u/Z_M)\
**Post date:** [July 23, 2025, 5:29am UTC](https://discourse.julialang.org/t/second-order-cone-constraint-in-jump/130927/5 "2025-07-23T05:29:19Z")

</div>

Thank you for your reply.  
When I run this code, for the constraint: _@constraint(model, [t; 1; QQ.U \* x] in RotatedSecondOrderCone())_

It always has an error:  
_MethodError: Cannot convert an object of type QuadExpr to an object of type AffExpr_

In addition, I use Gurobi in JuMP, so I wonder if Gurobi can solve the RotatedSecondOrderCone constraint.

---

<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:** [July 23, 2025, 6:19am UTC](https://discourse.julialang.org/t/second-order-cone-constraint-in-jump/130927/6 "2025-07-23T06:19:46Z")

</div>

Gurobi supports quadratic constraints. Just write it as:

```Julia
using JuMP
Q = [1.0 0.5; 0.5 3.0]
model = Model()
@variable(model, t)
@variable(model, x[i in 1:2])
@objective(model, Min, t)
@constraint(model, t >= 0.5 * x' * Q * x)

```

The second order cone equivalent is:

```julia
@constraint(model, [(t + 1) / sqrt(2); (t - 1) / sqrt(2); QQ.U * x] in SecondOrderCone())

```

(If it isn’t obvious why, try expanding out the SOC constraint to the quadratic form.)

---

<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:** [July 23, 2025, 6:20am UTC](https://discourse.julialang.org/t/second-order-cone-constraint-in-jump/130927/7 "2025-07-23T06:20:34Z")

</div>

> [@Z\_M](#):
>
> MethodError: Cannot convert an object of type QuadExpr to an object of type AffExpr

This error is not coming from the code I wrote. Can you provide a reproducible example?

---

<div class="post-metadata">

**Author:** ![Z\_M](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/z_m/32/52830_2.png) [@Z\_M](https://discourse.julialang.org/u/Z_M)\
**Post date:** [July 23, 2025, 7:45am UTC](https://discourse.julialang.org/t/second-order-cone-constraint-in-jump/130927/8 "2025-07-23T07:45:27Z")

</div>

I run the following code and get the error.

Q = [1.0 0.5; 0.5 3.0]

QQ = LinearAlgebra.cholesky(Q)

model = Model(Gurobi.Optimizer)

@variable(model, t)

@variable(model, x[i in 1:2])

@objective(model, Min, t)

# @constraint(model, t \>= 0.5 \* x’ \* Q \* x)

@constraint(model, [(t + 1) / sqrt(2); (t - 1) / sqrt(2); QQ.U \* x] in SecondOrderCone())

optimize!(model)

 ![image](https://global.discourse-cdn.com/julialang/original/3X/b/e/be768d84ce6190111a08881cc34fb3de33f2bb8a.png)

---

<div class="post-metadata">

**Author:** ![Z\_M](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/z_m/32/52830_2.png) [@Z\_M](https://discourse.julialang.org/u/Z_M)\
**Post date:** [July 23, 2025, 7:46am UTC](https://discourse.julialang.org/t/second-order-cone-constraint-in-jump/130927/9 "2025-07-23T07:46:15Z")

</div>

Thank you very much! I got it.

---

<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:** [July 24, 2025, 3:14am UTC](https://discourse.julialang.org/t/second-order-cone-constraint-in-jump/130927/10 "2025-07-24T03:14:58Z")

</div>

I can’t reproduce:

```julia
julia> using JuMP, Gurobi, LinearAlgebra

julia> Q = [1.0 0.5; 0.5 3.0]
2×2 Matrix{Float64}:
 1.0 0.5
 0.5 3.0

julia> model = Model(Gurobi.Optimizer)
Set parameter LicenseID to value 890341
A JuMP Model
├ solver: Gurobi
├ objective_sense: FEASIBILITY_SENSE
├ num_variables: 0
├ num_constraints: 0
└ Names registered in the model: none

julia> @variable(model, t)
t

julia> @variable(model, x[i in 1:2])
2-element Vector{VariableRef}:
 x[1]
 x[2]

julia> @objective(model, Min, t)
t

julia> QQ = LinearAlgebra.cholesky(Q)
Cholesky{Float64, Matrix{Float64}}
U factor:
2×2 UpperTriangular{Float64, Matrix{Float64}}:
 1.0 0.5
  ⋅ 1.65831

julia> @constraint(model, [(t + 1) / sqrt(2); (t - 1) / sqrt(2); QQ.U * x] in SecondOrderCone())
[0.7071067811865475 t + 0.7071067811865475, 0.7071067811865475 t - 0.7071067811865475, x[1] + 0.5 x[2], 1.6583123951777 x[2]] ∈ MathOptInterface.SecondOrderCone(4)

julia> optimize!(model)
Gurobi Optimizer version 12.0.2 build v12.0.2rc0 (mac64[x86] - Darwin 24.1.0 24B83)

CPU model: Intel(R) Core(TM) i5-8259U CPU @ 2.30GHz
Thread count: 4 physical cores, 8 logical processors, using up to 8 threads

Optimize a model with 4 rows, 7 columns and 9 nonzeros
Model fingerprint: 0x303d1a5d
Model has 1 quadratic constraint
Coefficient statistics:
  Matrix range [5e-01, 2e+00]
  QMatrix range [1e+00, 1e+00]
  Objective range [1e+00, 1e+00]
  Bounds range [0e+00, 0e+00]
  RHS range [7e-01, 7e-01]
Presolve removed 3 rows and 5 columns
Presolve time: 0.00s
Presolved: 1 rows, 2 columns, 2 nonzeros
Presolved model has 1 second-order cone constraint
Ordering time: 0.00s

Barrier statistics:
 AA' NZ : 0.000e+00
 Factor NZ : 1.000e+00
 Factor Ops : 1.000e+00 (less than 1 second per iteration)
 Threads : 1

                  Objective Residual
Iter Primal Dual Primal Dual Compl Time
   0 1.20979837e-02 0.00000000e+00 8.55e-03 7.04e-03 5.54e-03 0s
   1 1.31297546e-05 -1.79908716e-07 9.18e-06 7.46e-06 6.05e-06 0s
   2 1.44738910e-08 -1.63817071e-10 1.01e-08 8.26e-09 6.66e-09 0s

Barrier solved model in 2 iterations and 0.00 seconds (0.00 work units)
Optimal objective 1.44738910e-08

User-callback calls 62, time in user-callback 0.00 sec

```
