JuMP.NormOneCone()

Can this NormOneCone be made easier? as SecondOrderCone is?
It will find it use in linear programming.
In my code, I now write something like

nm1e = JuMP.@variable(outer)
nm1c = JuMP.@constraint(outer, [nm1e; vec(outer_β - β)] ∈ JuMP.MOI.NormOneCone(1+length(β)))

I wish I could write

nm1c = JuMP.@constraint(outer, [nm1e; vec(outer_β - β)] ∈ JuMP.NormOneCone())

in the future. Will this be okay?

1 Like

There are arguments for and against this.

For:

  • it’s clearly simpler

Against:

  • The main reason for a “JuMP” cone that is different to the MOI cone is to manage shapes. That’s why we have PSDCone() etc, so that we can convert between the vector in MOI and the symmetric matrix in JuMP. That doesn’t apply here.
  • A second reason is historical. We added SecondOrderCone because we did. Mainly because it is quite commonly used. I don’t know that I would add it if I could choose again today.
  • If we add JuMP.NormOneCone, what about all the other MOI cones? I don’t really want to have so much duplication, especially just to save a few characters of typing.

We have NormOneCone documented here: Tips and tricks · JuMP. I think I’d prefer to make it really clear that you can use MOI cones directly in JuMP. They’re not second class citizens.

Note that if you do import MathOptInterface as MOI you don’t need JuMP.MOI.

Perhaps one could redefine the MOI cones to not need to give the size of the input as a argument then?

That is a reasonable suggestion but it would be very breaking so its not going to happen.

How would it be breaking? I’m suggesting to make giving the input size optional, not removing it entirely. One can still use it for error checking.

It is breaking because various codes assume you can call MOI.dimension(set).

You can add a new optional data attribute. You can’t take away a previously required attribute.

One would still create the set with the appropriate dimension, and it would still be readable with MOI.dimension. It would just be computed from the given input vector instead of given explicitly as an argument.

Thats exactly the behavior of the JuMP Abstract Set. Which we can do. But then there are two copies of every set. One nondimensional in JuMP and a dimensional set in MOI. For the sake of a few characters, id prefer we had less code in JuMP.

I still don’t see the difficulty with creating a dimensional set without giving it the dimension explicitly. @variable and @constraint are macros, they can handle the necessary rewriting.

Otherwise MOI sets are in fact second-class citizens.

There is no difficulty. It’s what JuMP.AbstractSet already supports: Extensions · JuMP

The code required would be:

struct NormOneCone <: JuMP.AbstractVectorSet end

moi_set(set::NormOneCone, dim::Int) = MOI.NormOneCone(dim)

but then I need to implement, test, document and maintain two copies of every set. Just so people don’t have to specify the dimension in their JuMP model. That’s certainly a worthy trade-off up for discussion. But the costs (to me) don’t seem to outweigh the minimal costs to users.

Otherwise MOI sets are in fact second-class citizens.

My point is that they aren’t.

You just need to write MOI.NormOneCone(3) instead of JuMP.NormOneCone().

We should teach people that they can use any MOI set, not just a subset of ones that have a corresponding JuMP.AbstractSet.

Having two copies of each set would indeed be silly. But I’m certain that there is a sensible way to implement this feature, either by redefining the MOI sets themselves, or redefining the macros.

In any case, there is no point in arguing, since you’re clearly not interested in doing it and I’m not going to do it myself.