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

package
jump

#1

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


#2

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.


#3

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?


#4

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


#5

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

#6

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)

#7

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.


#8

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


#9

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.