# Set\_normalized\_coefficient in JuMP.jl is slow

**URL:** https://discourse.julialang.org/t/set-normalized-coefficient-in-jump-jl-is-slow/112533
**Category:** Optimization (Mathematical)
**Tags:** jump, performance
**Created:** [April 4, 2024, 4:35pm UTC](https://discourse.julialang.org/t/set-normalized-coefficient-in-jump-jl-is-slow/112533 "2024-04-04T16:35:05Z")
**Posts on this page:** 7
**Page:** 1

<div class="post-metadata">

### Author: ![PaterPen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/paterpen/32/27985_2.png) [@PaterPen](https://discourse.julialang.org/u/PaterPen)
#### Post date: [April 4, 2024, 4:35pm UTC](https://discourse.julialang.org/t/set-normalized-coefficient-in-jump-jl-is-slow/112533/1 "2024-04-04T16:35:05Z")

</div>

Hi, I wonder why `set_normalized_coefficient` takes about as long as the actual optimization in my MWE:

```julia
using JuMP, HiGHS

function create_solver(solver, l, C, d, lb)
    model = direct_model(optimizer_with_attributes(solver))
    @variable(model, x[i = eachindex(lb)].>=lb[i])
    @objective(model, Min, sum(x[i] * l[i] for i in eachindex(lb)))
    @constraint(model, con, C * x.≥d)
    set_silent(model)
    return model
end

function modify_coefficients!(model, variable, C)
    for j in axes(C, 2) # Loop over the columns of C (each variable)
        set_normalized_coefficient.(model[:con], variable[j], vec(C[:, j]))
    end
end

function test(n)
    l = rand(72)'
    C = rand(36, 72)
    d = rand(36)
    lb = zeros(72)

    solver = HiGHS.Optimizer
    model = create_solver(solver, l, C, d, lb)
    for _ in 1:n
        C = rand(36, 72)
        modify_coefficients!(model, model[:x], C)
        optimize!(model) # min l * x s.t. C * x ≥ d AND x ≥ lb
    end
end

@profview test(100)

```

My use case solves this problem for an `n` of about 40000, therefore the overhead from setting parameters is kinda annoying. Am I doing it inefficiently?

---

<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 4, 2024, 10:51pm UTC](https://discourse.julialang.org/t/set-normalized-coefficient-in-jump-jl-is-slow/112533/2 "2024-04-04T22:51:20Z")

</div>

I think part of the problem is that you’re trying to modify every constraint coefficient one-by-one, and that the constraints are dense. The “modify and re-solve” approach is really intended for small changes between solves.

I would just do:

```julia
using JuMP, HiGHS

function create_solver(solver, c::Vector, A::Matrix, b::Vector, l::Vector)
    n = length(c)
    @assert n == size(A, 2) == length(l)
    @assert size(A, 1) == length(b)
    model = Model(solver)
    set_silent(model)
    @variable(model, x[i = 1:n] >= l[i])
    @objective(model, Min, c' * x)
    @constraint(model, A * x .>= b)
    optimize!(model)
    @assert is_solved_and_feasible(model)
    return value.(x)
end

function test(n)
    c = rand(72)
    A = rand(36, 72)
    b = rand(36)
    l = zeros(72)
    for _ in 1:n
        A = rand(36, 72)
        x = create_solver(HiGHS.Optimizer, c, A, b, l)
    end
end

@time test(100)

```

---

<div class="post-metadata">

### Author: ![PaterPen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/paterpen/32/27985_2.png) [@PaterPen](https://discourse.julialang.org/u/PaterPen)
#### Post date: [April 5, 2024, 5:02am UTC](https://discourse.julialang.org/t/set-normalized-coefficient-in-jump-jl-is-slow/112533/3 "2024-04-05T05:02:21Z")

</div>

Yeah, the one-by-one modification clearly is inefficient. However, my approach is about twice as fast as your implementation (0.7s vs 1.5s) on my machine – that’s why I switched to “modify and re-solve” in the first place.

---

<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 5, 2024, 5:33am UTC](https://discourse.julialang.org/t/set-normalized-coefficient-in-jump-jl-is-slow/112533/4 "2024-04-05T05:33:37Z")

</div>

What is the real problem you are trying to solve? Do you want to modify the entire dense constraint matrix? Is the performance a bottleneck? You might consider instead [Parallelism · JuMP](https://jump.dev/JuMP.jl/stable/tutorials/algorithms/parallelism/#Using-parallelism-the-right-way)

Do you have a comparison for why the set\_normalized\_coefficient is “slow”? What would you expect to happen? We’re essentially throwing away the entire internal model and rebuilding from scratch. We can save some memory, but all internal data structures (presolve, factorizations, etc) need to be recomputed.

---

<div class="post-metadata">

### Author: ![PaterPen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/paterpen/32/27985_2.png) [@PaterPen](https://discourse.julialang.org/u/PaterPen)
#### Post date: [April 5, 2024, 6:07am UTC](https://discourse.julialang.org/t/set-normalized-coefficient-in-jump-jl-is-slow/112533/5 "2024-04-05T06:07:16Z")

</div>

My problem requires to adjust the matrix `C = B - (1+r)A` over a grid of 0 \leq r\_1 \leq ... \leq r\_n and solve the corresponding linear problem (where A \in \mathbb{R}\_{+}^{36 \times 72} and `B = [I(36) I(36)]`.

Since performance is the bottleneck, I will indeed use some threading.

I didn’t expect a speedup of more than ~30% but still I was wondering why the setup took that long compared to the actual solution. However, I am not aware of the internals of JuMP.jl / HiGHS.jl. Thanks for your help!

---

<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 5, 2024, 6:18am UTC](https://discourse.julialang.org/t/set-normalized-coefficient-in-jump-jl-is-slow/112533/6 "2024-04-05T06:18:54Z")

</div>

`r` is a scalar?

How about something like:

```julia
    model = direct_model(HiGHS.Optimizer())
    set_silent(model)
    @variable(model, x[i = 1:N] >= lb[i])
    @variable(model, y[i = 1:N])
    @objective(model, Min, l' * x)
    @constraint(model, con[i in 1:N], 1 * x[i] - y[i] == 0)
    @constraint(model, B * x - A * y .>= d)
    for r in range(0, 1, length = n)
        set_normalized_coefficient(con, x, fill(1 + r, N))
        optimize!(model)
    end

```

Now you only need to modify `N` coefficients in each step.

---

<div class="post-metadata">

### Author: ![PaterPen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/paterpen/32/27985_2.png) [@PaterPen](https://discourse.julialang.org/u/PaterPen)
#### Post date: [April 5, 2024, 9:29pm UTC](https://discourse.julialang.org/t/set-normalized-coefficient-in-jump-jl-is-slow/112533/7 "2024-04-05T21:29:01Z")

</div>

That’s dope and what I should have tried in the first place. Thanks!!
