# JuMP docs on SDP replace \`logdet\` with \`tr\`—is this correct?

**URL:** <https://discourse.julialang.org/t/jump-docs-on-sdp-replace-logdet-with-tr-is-this-correct/79324>\
**Category:** Optimization (Mathematical)\
**Created:** [April 11, 2022, 2:52am UTC](https://discourse.julialang.org/t/jump-docs-on-sdp-replace-logdet-with-tr-is-this-correct/79324 "2022-04-11T02:52:22Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![maxkapur](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/maxkapur/32/21208_2.png) [@maxkapur](https://discourse.julialang.org/u/maxkapur)\
**Post date:** [April 11, 2022, 2:52am UTC](https://discourse.julialang.org/t/jump-docs-on-sdp-replace-logdet-with-tr-is-this-correct/79324/1 "2022-04-11T02:52:22Z")

</div>

[The JuMP documentation](https://jump.dev/JuMP.jl/stable/tutorials/conic/min_ellipse/) gives, as an example of a semidefinite program, the problem of finding the minimum-volume ellipse that contains a given list of ellipses centered at the origin:

```julia
minimize trace(WX)
subject to X >= A_i, i = 1,...,m
            X PSD

```

where the weight matrix `W` is ttaken as simply the identity matrix.

The reference for this problem is Boyd and Vandenberghe’s _Convex Optimization,_ sec. 8.4.1. But if you consult this text, it is clear that the correct statement of the problem is

```julia
minimize log(det(WX))
subject to X >= A_i, i = 1,...,m
            X PSD

```

instead, because the volume of an ellipsoid is proportional to the _product_ of its axis lengths, which in turn are proportional to the eigenvalues of the matrix. Now, since \det A = \prod \lambda\_i and \operatorname{tr} A = \sum \lambda \_i, where \lambda\_i are the eigenvalues of A, for a well-conditioned A, these problems are good approximations of one another. But I don’t think that they are quite the same.

Further evidence: The Matlab code for this problem given on the CVX website (which is, as I understand it, a semiofficial supplement to the _Convex Optimization_ book)

```matlab
cvx_begin sdp
    variable Asqr(n,n) symmetric
    variable btilde(n)
    variable t(m)
    maximize( det_rootn( Asqr ) )
    subject to
        t >= 0;
        for i = 1:m
            [ -(Asqr - t(i)*As{i}), -(btilde - t(i)*bs{i}), zeros(n,n);
              -(btilde - t(i)*bs{i})', -(- 1 - t(i)*cs{i}), -btilde';
               zeros(n,n), -btilde, Asqr] >= 0;
        end
cvx_end

```

uses the function `det_rootn()` which is a monotonic transformation of \log \det and not of the trace.

Anyhow, I would really like to use Julia’s `LinearAlgebra.logdet()` function here, but it hasn’t been implemented for JuMP variables yet. Here is an adaptation of the `example_min_ellipse()` function from the JuMP docs I linked above, which uses `logdet` instead of `tr`:

```julia
using JuMP
import LinearAlgebra
import SCS

function example_min_ellipse_logdet()
    # We will use three ellipses: two "simple" ones, and a random one.
    As = [
        [2.0 0.0; 0.0 1.0],
        [1.0 0.0; 0.0 3.0],
        [2.86715 1.60645; 1.60645 1.12639],
    ]
    # We change the weights to see different solutions, if they exist
    weights = [1.0 0.0; 0.0 1.0]
    model = Model(SCS.Optimizer)
    set_silent(model)
    @variable(model, X[i = 1:2, j = 1:2], PSD)
    @objective(model, Min, logdet(weights * X))
    @constraint(model, [As_i in As], X >= As_i, PSDCone())
    optimize!(model)
    return objective_value(model)
end

example_min_ellipse_logdet()

```

gives

```julia
MethodError: Cannot `convert` an object of type AffExpr to an object of type Float64

```

**Questions:**

- Am I correct to suspect that objective function used in the JuMP docs is wrong?
- Is there a way to get JuMP/SCS to accept a `logdet` term in the objective function?

---

<div class="post-metadata">

**Author:** ![jd-foster](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jd-foster/32/35824_2.png) [@jd-foster](https://discourse.julialang.org/u/jd-foster)\
**Post date:** [April 11, 2022, 3:39am UTC](https://discourse.julialang.org/t/jump-docs-on-sdp-replace-logdet-with-tr-is-this-correct/79324/2 "2022-04-11T03:39:18Z")

</div>

See here too:

> [@Log determinant objective](https://discourse.julialang.org/t/log-determinant-objective/23927/6):
>
> How does one use this? Here’s an example, but it isn’t supported by Ipopt or NLopt, you’ll need to reformulate your entire problem as a conic optimization problem and use a solver like Mosek or SCS. [https://jump.dev/MathOptInterface.jl/stable/reference/standard\_form/#MathOptInterface.LogDetConeSquare](https://jump.dev/MathOptInterface.jl/stable/reference/standard_form/#MathOptInterface.LogDetConeSquare) # max log(det(x)) # # is equivalent to # max t # s.t. t \<= log(det(X)) model = Model() @variable(model, X[1:3, 1:3]) @variable(model, t) @constraint(model, [t; 1; vec(X)] in MOI.LogDetConeSqua…

---

<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:** [April 11, 2022, 3:46am UTC](https://discourse.julialang.org/t/jump-docs-on-sdp-replace-logdet-with-tr-is-this-correct/79324/3 "2022-04-11T03:46:45Z")

</div>

> Am I correct to suspect that objective function used in the JuMP docs is wrong?

Sure. This is example is [very old](https://github.com/jump-dev/JuMP.jl/blame/2c9116ede89ce8402ecc0b6af5beab16a8170269/examples/minellipse.jl), so I assume it was just added with the `trace` as the relaxation because we didn’t have `LogDet` support at the time.

> Is there a way to get JuMP/SCS to accept a `logdet` term in the objective function?

Based on their transformation to root-det, you probably want something like:

```julia
model = Model()
@variable(model, X[1:2, 1:2], PSD)
@variable(model, t)
@objective(model, Max, t)
X_tri = [X[i, j] for i in 1:2 for j in i:2]
@constraint(model, [t; X_tri...] in MOI.RootDetConeTriangle(2))

```

If you get something working, you can edit this file [https://github.com/jump-dev/JuMP.jl/blob/master/docs/src/tutorials/conic/min\_ellipse.jl](https://github.com/jump-dev/JuMP.jl/blob/master/docs/src/tutorials/conic/min_ellipse.jl) to make a pull request updating JuMP’s documentation.

---

<div class="post-metadata">

**Author:** ![maxkapur](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/maxkapur/32/21208_2.png) [@maxkapur](https://discourse.julialang.org/u/maxkapur)\
**Post date:** [April 11, 2022, 6:18am UTC](https://discourse.julialang.org/t/jump-docs-on-sdp-replace-logdet-with-tr-is-this-correct/79324/4 "2022-04-11T06:18:21Z")

</div>

I got it working:

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

And submitted a PR:  
[https://github.com/jump-dev/JuMP.jl/pull/2945](https://github.com/jump-dev/JuMP.jl/pull/2945)

---

<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:** [April 11, 2022, 6:28am UTC](https://discourse.julialang.org/t/jump-docs-on-sdp-replace-logdet-with-tr-is-this-correct/79324/5 "2022-04-11T06:28:49Z")

</div>

Great! I’ll take a look.
