Skip to content

Ternary operator inside macros #324

@joaquimg

Description

@joaquimg

Many users use the ternary operator (? :) inside @expresion and @constraint.
A very common usage is optional slack variables.

The following example illustrates that usage.
JuMP has options to do it efficiently, writing different expressions in a loop or using add_to_expression!. But:

  • The downside of writing separate expressions is that there might be much more code replication if the constraint is more complicated.
  • The downside of add_to_expression! is readability.
  • ifelse is not an option as the variable frequently does not exist in this cases.

--

As an alternative to:
@expression(model, 2x[1] + (iseven(j) ? 3x[j] : 0))

Maybe we can to something more clever? such as:

@expression(model, 2x[1] + @zero_if_not(iseven(j), 3x[j]))

--

Here is the example:

using JuMP
function test1()
    model = Model()
    N = 1_000_000
    @variable(model, x[1:N])
    _zero_exp = JuMP.AffExpr(0.0)
    for i in 1:5
        @show i
        GC.gc()
        GC.gc()
        @time for j in 1:N
            if iseven(j)
                @expression(model, 2x[1] + 3x[j])
            else
                @expression(model, 2x[1])
            end
        end
        GC.gc()
        GC.gc()
        @time for j in 1:N
            e = @expression(model, 2x[1])
            if iseven(j)
                add_to_expression!(e, 3, x[j])
            end
        end
        GC.gc()
        GC.gc()
        @time for j in 1:N
            @expression(model, 2x[1] + (iseven(j) ? 3x[j] : 0))
        end
    end
end
test1()

Which results in:

i = 1
  0.415310 seconds (7.00 M allocations: 549.316 MiB)
  0.424566 seconds (7.00 M allocations: 549.316 MiB)
  0.584483 seconds (10.50 M allocations: 823.975 MiB, 19.22% gc time)
i = 2
  0.337471 seconds (7.00 M allocations: 549.316 MiB)
  0.446796 seconds (7.00 M allocations: 549.316 MiB)
  0.591993 seconds (10.50 M allocations: 823.975 MiB, 21.81% gc time)
i = 3
  0.417391 seconds (7.00 M allocations: 549.316 MiB)
  0.437248 seconds (7.00 M allocations: 549.316 MiB)
  0.595859 seconds (10.50 M allocations: 823.975 MiB, 18.18% gc time)
i = 4
  0.329041 seconds (7.00 M allocations: 549.316 MiB)
  0.345533 seconds (7.00 M allocations: 549.316 MiB)
  0.670093 seconds (10.50 M allocations: 823.975 MiB, 23.70% gc time)
i = 5
  0.424246 seconds (7.00 M allocations: 549.316 MiB)
  0.324499 seconds (7.00 M allocations: 549.316 MiB)
  0.749065 seconds (10.50 M allocations: 823.975 MiB, 15.93% gc time)

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions