How to write .NL file containing JuMP problem using AmplNLWriter.jl

I’m looking for ways to write a jump model to my hard drive so that it can be solved on another machine.

julia> using JuMP, AmplNLWriter
julia> m = Model(solver=AmplNLSolver("bonmin"))
julia> @variable(m,x[1:2])
julia> @objective(m,Min,dot(x,x))

I’ve tried: AmplNLsolver.write_nl_file(open(“/tmp/Problem.nl”,“w”),m)

but that didn’t work for me.

Any suggestions?
Thanks,
Lars

See the code between here and here. I think a PR to refactor this so that you can easily write an NL file from a model without solving it would be welcome.

Thanks, I got one step further, I think. See this code.

function mywrite_nl_file(f::IO, mj::JuMP.Model)
    JuMP.build(mj)
    
    m = internalmodel(mj)
    m.status = :NotSolved
    m.solve_exitcode = -1
    m.solve_result_num = -1
    m.solve_result = "?"
    m.solve_message = ""

    # There is no non-linear binary type, only non-linear discrete, so make
    # sure binary vars have bounds in [0, 1]
    for i in 1:m.nvar
        if m.vartypes[i] == :Bin
            if m.x_l[i] < 0
                m.x_l[i] = 0
            end
            if m.x_u[i] > 1
                m.x_u[i] = 1
            end
        end
    end
    AmplNLWriter.make_var_index!(m)
    AmplNLWriter.make_con_index!(m)

    AmplNLWriter.write_nl_file(f, m.inner)
end

Using this function, I can write the example provided in the package even without solving them. However, for my own example things don’t work. Here it is:

using JuMP, AmplNLWriter

U  = randn(10,6)
ft = [1;0;1;0;1;0]
dobs = U*ft


m = Model(solver=AmplNLSolver("bonmin"))
@variable(m, f[1:6], Bin )
@objective(m, Min, dot(U*f-dobs, U*f-dobs));

io = open("/tmp/myExample.nl","w")
mywrite_nl_file(io,m)
close(io)

I’m getting the following error

ERROR: LoadError: Solver does not support quadratic objectives
 in setquadobjterms!(::AmplNLWriter.AmplNLLinearQuadraticModel, ::Array{Int32,1}, ::Array{Int32,1}, ::Array{Float64,1}) at ~/.julia/v0.5/MathProgBase/src/SolverInterface/LinearQuadratic.jl:71
 in addQuadratics(::JuMP.Model) at ~/.julia/v0.5/JuMP/src/solvers.jl:484
 in #build#114(::Bool, ::Bool, ::JuMP.ProblemTraits, ::Function, ::JuMP.Model) at ~/.julia/v0.5/JuMP/src/solvers.jl:422
 in write_nl_file(::IOStream, ::JuMP.Model) at ~/.julia/v0.5/ConvDiff/src/io.jl:3
 in include_from_node1(::String) at ./loading.jl:488
 in include_from_node1(::String) at ~/Software/julia-0.5/usr/lib/julia/sys.dylib:?
while loading ~/.julia/v0.5/AmplNLWriter/examples/myEx.jl, in expression starting on line 14

I tried also with other solvers, like Ipopt and without the binary constraints… no success…

Any clue?

AmplNLWriter doesn’t support quadratic objectives, you will need to add the objective via @NLobjective for it to work.

Okay. Is there a reason why AmplNLWriter doesn’t support QPs?

Tried that, but I ran into a new problem since in order to use @NLobjective I need to register a new function, right? Here is a minimal example

using JuMP, AmplNLWriter

mysquare(x) = x^2
mj = Model(solver=AmplNLSolver("bonmin"))
JuMP.register(mj, :mysquare, 1, mysquare, autodiff=true)
@variable(mj, x)
@NLobjective(mj, Min, mysquare(x))

io = open("/tmp/myExample.nl","w")
JuMP.build(mj)
m = mj.internalModel.inner
m.status = :NotSolved
m.solve_exitcode = -1
m.solve_result_num = -1
m.solve_result = "?"
m.solve_message = ""

# There is no non-linear binary type, only non-linear discrete, so make
# sure binary vars have bounds in [0, 1]
for i in 1:m.nvar
    if m.vartypes[i] == :Bin
        if m.x_l[i] < 0
            m.x_l[i] = 0
        end
        if m.x_u[i] > 1
            m.x_u[i] = 1
        end
    end
end
AmplNLWriter.make_var_index!(m)
AmplNLWriter.make_con_index!(m)

AmplNLWriter.write_nl_file(io, m)
close(io)

This gives the following error:

ERROR: LoadError: KeyError: key :mysquare not found

There is no reason it can’t support the quadratic interface, it just hasn’t been added yet. PRs would be welcome if anybody requires this functionality.

You can’t use user-provided functions with AmplNLWriter. You have to write the nonlinear terms as a sequence of elementary operations. Your example works with the following:

using JuMP, AmplNLWriter

mj = Model(solver=AmplNLSolver("bonmin"))
@variable(mj, x)
@NLobjective(mj, Min, x^2)

io = open("/tmp/myExample.nl","w")
JuMP.build(mj)
m = mj.internalModel.inner
m.status = :NotSolved
m.solve_exitcode = -1
m.solve_result_num = -1
m.solve_result = "?"
m.solve_message = ""

# There is no non-linear binary type, only non-linear discrete, so make
# sure binary vars have bounds in [0, 1]
for i in 1:m.nvar
    if m.vartypes[i] == :Bin
        if m.x_l[i] < 0
            m.x_l[i] = 0
        end
        if m.x_u[i] > 1
            m.x_u[i] = 1
        end
    end
end
AmplNLWriter.make_var_index!(m)
AmplNLWriter.make_con_index!(m)

AmplNLWriter.write_nl_file(io, m)
close(io)

Thanks, but writing my actual problem out with elementary operations is probably infeasible.

Can you give me some clues what needs to be done to support quadratic programs? I have no feeling how complicated adding this is. There definitely is interest in it.

See previous discussion at https://github.com/JuliaOpt/AmplNLWriter.jl/issues/49.

Thanks for sharing this, Miles. Looks like some work is required here, but I think it’ll be worth it. Note sure if I’ll have time to work on it in the next months though.