# Convert a nonlinear model defined by JuMP's legacy version to latest version

**URL:** https://discourse.julialang.org/t/convert-a-nonlinear-model-defined-by-jumps-legacy-version-to-latest-version/129542
**Category:** Optimization (Mathematical)
**Created:** [June 1, 2025, 9:59pm UTC](https://discourse.julialang.org/t/convert-a-nonlinear-model-defined-by-jumps-legacy-version-to-latest-version/129542 "2025-06-01T21:59:36Z")
**Posts on this page:** 8
**Page:** 1

<div class="post-metadata">

### Author: ![zhu266](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/zhu266/32/217099_2.png) [@zhu266](https://discourse.julialang.org/u/zhu266)
#### Post date: [June 1, 2025, 9:59pm UTC](https://discourse.julialang.org/t/convert-a-nonlinear-model-defined-by-jumps-legacy-version-to-latest-version/129542/1 "2025-06-01T21:59:36Z")

</div>

Hi everyone, I am fetching models from `MINLPLib.jl`, and I guess they use “Nonlinear Modeling (Legacy)” to define nonlinear constraints/objectives. I am curious if there is any way to transform a nonlinear model defined by legacy version to a model defined by latest version “Nonlinear Modeling”?

---

<div class="post-metadata">

### Author: ![zhu266](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/zhu266/32/217099_2.png) [@zhu266](https://discourse.julialang.org/u/zhu266)
#### Post date: [June 1, 2025, 10:32pm UTC](https://discourse.julialang.org/t/convert-a-nonlinear-model-defined-by-jumps-legacy-version-to-latest-version/129542/2 "2025-06-01T22:32:36Z")

</div>

@odow I tested using .nl file from MINLPLib organization and julia package. Both throw an error

> ERROR: MethodError: no method matching operate(::typeof(\*), ::Type{Float64}, ::Float64, ::Nothing)  
> The function `operate` exists, but no method is defined for this combination of argument types.

when I set

> new\_model = JuMP.read\_from\_file(“minlplib/nl/4stufen.nl”; use\_nlp\_block = false)

But output a model when I set

> m\_new = JuMP.read\_from\_file(“minlplib/nl/4stufen.nl”; use\_nlp\_block = true)

---

<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: [June 1, 2025, 10:43pm UTC](https://discourse.julialang.org/t/convert-a-nonlinear-model-defined-by-jumps-legacy-version-to-latest-version/129542/3 "2025-06-01T22:43:04Z")

</div>

Hi @zhu266, thanks for posting over here.

Yes, I was just trying this locally as well and I found the same bug. I’m just about to push a fix. I’ll update this post with the link when it’s ready: [[FileFormats.NL] fix try\_scalar\_affine\_function by odow · Pull Request #2766 · jump-dev/MathOptInterface.jl · GitHub](https://github.com/jump-dev/MathOptInterface.jl/pull/2766)

One approach will be:

```julia
using MINLPLib
using JuMP
function convert_legacy_to_new(model)
    path = mktempdir()
    filename = joinpath(path, "model.nl")
    write_to_file(model, filename)
    return read_from_file(filename; use_nlp_block = false)
end

model = fetch_model("minlp/4stufen")
model = convert_legacy_to_new(model)

```

The other approach is:

```Julia
using JuMP
import Downloads
function download_model(name; kwargs...)
    io = IOBuffer()
    Downloads.download("https://www.minlplib.org/nl/$(name).nl", io)
    seekstart(io)
    return read(
        io,
        Model;
        use_nlp_block = false,
        format = MOI.FileFormats.FORMAT_NL,
    )
end
model = download_model("4stufen")

```

---

<div class="post-metadata">

### Author: ![zhu266](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/zhu266/32/217099_2.png) [@zhu266](https://discourse.julialang.org/u/zhu266)
#### Post date: [June 2, 2025, 12:29am UTC](https://discourse.julialang.org/t/convert-a-nonlinear-model-defined-by-jumps-legacy-version-to-latest-version/129542/4 "2025-06-02T00:29:06Z")

</div>

Great, thank you!

---

<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: [June 2, 2025, 12:55am UTC](https://discourse.julialang.org/t/convert-a-nonlinear-model-defined-by-jumps-legacy-version-to-latest-version/129542/5 "2025-06-02T00:55:15Z")

</div>

I’m just preparing a new release of MathOptInterface, [Prep for v1.40.2 by odow · Pull Request #2767 · jump-dev/MathOptInterface.jl · GitHub](https://github.com/jump-dev/MathOptInterface.jl/pull/2767), so this should be fixed in a few hours.

---

<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: [June 2, 2025, 3:22am UTC](https://discourse.julialang.org/t/convert-a-nonlinear-model-defined-by-jumps-legacy-version-to-latest-version/129542/6 "2025-06-02T03:22:51Z")

</div>

Just chiming back in to say that this now fixed. Sorry for the bug!

```julia
(minlp) pkg> st
Status `/private/tmp/minlp/Project.toml`
  [4076af6c] JuMP v1.26.0
  [c36e90e8] MINLPLib v0.1.0 `https://github.com/lanl-ansi/MINLPLib.jl#master`
  [b8f27783] MathOptInterface v1.40.2

julia> using JuMP

julia> import Downloads

julia> function download_model(name; kwargs...)
           io = IOBuffer()
           Downloads.download("https://www.minlplib.org/nl/$(name).nl", io)
           seekstart(io)
           return read(
               io,
               Model;
               use_nlp_block = false,
               format = MOI.FileFormats.FORMAT_NL,
           )
       end
download_model (generic function with 1 method)

julia> model = download_model("4stufen")
A JuMP Model
├ solver: none
├ objective_sense: MIN_SENSE
│ └ objective_function_type: AffExpr
├ num_variables: 149
├ num_constraints: 351
│ ├ NonlinearExpr in MOI.EqualTo{Float64}: 34
│ ├ AffExpr in MOI.EqualTo{Float64}: 60
│ ├ AffExpr in MOI.GreaterThan{Float64}: 4
│ ├ VariableRef in MOI.GreaterThan{Float64}: 149
│ ├ VariableRef in MOI.LessThan{Float64}: 56
│ └ VariableRef in MOI.ZeroOne: 48
└ Names registered in the model: none

```

---

<div class="post-metadata">

### Author: ![zhu266](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/zhu266/32/217099_2.png) [@zhu266](https://discourse.julialang.org/u/zhu266)
#### Post date: [June 2, 2025, 3:37am UTC](https://discourse.julialang.org/t/convert-a-nonlinear-model-defined-by-jumps-legacy-version-to-latest-version/129542/7 "2025-06-02T03:37:54Z")

</div>

I really appreciate your efforts! Also, I mention that the model returned by convert\_legacy\_to\_new(model) has anonymous variable. Suppose \_[i] corresponding to x, is the index i the VariableIndex of x?

---

<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: [June 2, 2025, 3:44am UTC](https://discourse.julialang.org/t/convert-a-nonlinear-model-defined-by-jumps-legacy-version-to-latest-version/129542/8 "2025-06-02T03:44:00Z")

</div>

If you want to maintain names, use [MathOptFormat | Specification and description of the MathOptFormat file format](https://jump.dev/MathOptFormat) instead:

```julia
function convert_legacy_to_new(model)
    path = mktempdir()
    filename = joinpath(path, "model.mof.json")
    write_to_file(model, filename)
    return read_from_file(filename; use_nlp_block = false)
end

```

This won’t keep the JuMP-level structures like `model[:x]`, but you can look things up by their `name`:

```julia
julia> variable_by_name(model, "x[13]")
x[13]

```
