diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 71c16b36..df632052 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -32,9 +32,9 @@ jobs: ${{ runner.os }}- - uses: julia-actions/julia-buildpkg@v1 env: - SECRET_XPRS_WIN_8110: ${{ secrets.XPRS_WIN_8110 }} - SECRET_XPRL_WIN_8110: ${{ secrets.XPRL_WIN_8110 }} - SECRET_XPRA_WIN_8130: ${{ secrets.XPAUTH_XPR }} + SECRET_XPRS_WIN: ${{ secrets.XPRS_WIN_900 }} + SECRET_XPRL_WIN: ${{ secrets.XPRL_WIN_900 }} + SECRET_XPRA_WIN: ${{ secrets.XPAUTH_XPR }} - uses: julia-actions/julia-runtest@v1 - uses: julia-actions/julia-processcoverage@v1 - uses: codecov/codecov-action@v1 diff --git a/deps/build.jl b/deps/build.jl index 2d5ac54f..95ef3ce4 100644 --- a/deps/build.jl +++ b/deps/build.jl @@ -66,9 +66,9 @@ end function ci_installation() files = if Sys.iswindows() [ - (ENV["SECRET_XPRS_WIN_8110"], "xprs.dll") - (ENV["SECRET_XPRL_WIN_8110"], "xprl.dll") - (ENV["SECRET_XPRA_WIN_8130"], "xpauth.xpr") + (ENV["SECRET_XPRS_WIN"], "xprs.dll") + (ENV["SECRET_XPRL_WIN"], "xprl.dll") + (ENV["SECRET_XPRA_WIN"], "xpauth.xpr") ] end for (url, file) in files @@ -84,12 +84,11 @@ function ci_installation() end end - if haskey(ENV, "XPRESS_JL_SKIP_LIB_CHECK") # Skip! elseif get(ENV, "JULIA_REGISTRYCI_AUTOMERGE", "false") == "true" write_depsfile("julia_registryci_automerge") -elseif get(ENV, "SECRET_XPRS_WIN_8110", "") != "" +elseif get(ENV, "SECRET_XPRS_WIN", "") != "" ci_installation() else local_installation() diff --git a/src/MOI/MOI_callbacks.jl b/src/MOI/MOI_callbacks.jl index 48edf36f..2fbb53e8 100644 --- a/src/MOI/MOI_callbacks.jl +++ b/src/MOI/MOI_callbacks.jl @@ -236,7 +236,7 @@ function MOI.submit( count += 1 end mipsolcol = Cint.(mipsolcol) - mipsolval = Cfloat.(mipsolval) + mipsolval = Cdouble.(mipsolval) if ilength == MOI.get(model, MOI.NumberOfVariables()) mipsolcol = C_NULL end diff --git a/src/MOI/MOI_wrapper.jl b/src/MOI/MOI_wrapper.jl index a169a365..8e520318 100644 --- a/src/MOI/MOI_wrapper.jl +++ b/src/MOI/MOI_wrapper.jl @@ -4275,6 +4275,9 @@ end function _pass_variable_names_to_solver(model::Xpress.Optimizer; warn = true) NAMELENGTH = 64 n_variables = length(model.variable_info) + if n_variables == 0 + return nothing + end var_names = String[string('C', i) for i in 1:n_variables] duplicate_check = Set{String}() for variable in values(model.variable_info) @@ -4308,6 +4311,9 @@ end function _pass_constraint_names_to_solver(model::Xpress.Optimizer; warn = true) NAMELENGTH = 64 n_constraints = length(model.affine_constraint_info) + if n_constraints == 0 + return nothing + end con_names = String[string('R', i) for i in 1:n_constraints] duplicate_check = Set{String}() for constraint in values(model.affine_constraint_info) diff --git a/test/MathOptInterface/MOI_callbacks.jl b/test/MathOptInterface/MOI_callbacks.jl index d32298f3..a64b6919 100644 --- a/test/MathOptInterface/MOI_callbacks.jl +++ b/test/MathOptInterface/MOI_callbacks.jl @@ -7,8 +7,9 @@ const MOI = MathOptInterface function callback_simple_model() model = Xpress.Optimizer( - HEURSTRATEGY = 0, - OUTPUTLOG = 0 + HEURSTRATEGY = 0, # before v41 + HEUREMPHASIS = 0, + OUTPUTLOG = 0, ) MOI.Utilities.loadfromstring!(model, """ @@ -26,8 +27,15 @@ end function callback_knapsack_model() model = Xpress.Optimizer( - HEURSTRATEGY = 0, - OUTPUTLOG = 0 + OUTPUTLOG = 0, + HEURSTRATEGY = 0, # before v41 + HEUREMPHASIS = 0, + CUTSTRATEGY = 0, + PRESOLVE = 0, + MIPPRESOLVE = 0, + PRESOLVEOPS = 0, + MIPTHREADS = 1, + THREADS = 1, ) MOI.set(model, MOI.NumberOfThreads(), 2) diff --git a/test/MathOptInterface/MOI_wrapper.jl b/test/MathOptInterface/MOI_wrapper.jl index f0d62749..49a6f728 100644 --- a/test/MathOptInterface/MOI_wrapper.jl +++ b/test/MathOptInterface/MOI_wrapper.jl @@ -891,6 +891,91 @@ function test_name_empty_names() return nothing end +function test_dummy_nlp() + model = Xpress.Optimizer(OUTPUTLOG = 0); + x = MOI.add_variables(model, 2); + c = [1.0, 2.0] + MOI.set( + model, + MOI.ObjectiveFunction{MOI.ScalarAffineFunction{Float64}}(), + MOI.ScalarAffineFunction(MOI.ScalarAffineTerm.(c, x), 0.0), + ); + + MOI.set(model, MOI.VariableName(), x, ["x1", "x2"]) + + Xpress._pass_variable_names_to_solver(model) + + MOI.set(model, MOI.ObjectiveSense(), MOI.MIN_SENSE) + + b1 = MOI.add_constraint.( + model, + x, + MOI.GreaterThan(0.0), + ) + b1 = MOI.add_constraint.( + model, + x, + MOI.LessThan(10.0), + ) + + c1 = MOI.add_constraint( + model, + MOI.ScalarAffineFunction(MOI.ScalarAffineTerm.([1.0, 0.0], x), 0.0), + MOI.EqualTo(0.0), + ) + + c3 = MOI.add_constraint( + model, + MOI.ScalarAffineFunction(MOI.ScalarAffineTerm.([0.0, 1.0], x), 0.0), + MOI.GreaterThan(10.0), + ) + + MOI.optimize!(model) + + x_sol = MOI.get.(model, MOI.VariablePrimal(), x) + @test x_sol == [0.0, 10.0] + + ret = Xpress.Lib.XPRSnlpchgformulastring(model.inner, Cint(0), "- 5 * x1 - 3") + @test ret == 0 + ret = Xpress.Lib.XPRSnlpchgformulastring(model.inner, Cint(0), "- 3.14") + @test ret == 0 + + solvestatus = Ref{Cint}(0) + solstatus = Ref{Cint}(0) + ret = Xpress.Lib.XPRSoptimize(model.inner, "", solvestatus, solstatus) + @test ret == 0 + + xx = Array{Float64}(undef, 2) + slack = Array{Float64}(undef, 2) + duals = Array{Float64}(undef, 2) + djs = Array{Float64}(undef, 2) + ret = Xpress.Lib.XPRSgetnlpsol(model.inner, xx, slack, duals, djs) + @test ret == 0 + @test xx == [3.14, 10] + @test slack == [0, 0] + + ret = Xpress.Lib.XPRSnlpchgformulastring(model.inner, Cint(0), "- 0.5 * x1 - 3") + @test ret == 0 + + # to optimize NLPs we need: XPRSoptimize + solvestatus = Ref{Cint}(0) + solstatus = Ref{Cint}(0) + ret = Xpress.Lib.XPRSoptimize(model.inner, "", solvestatus, solstatus) + @test ret == 0 + + # to get solution values from NLP we need: XPRSgetnlpsol + xx = Array{Float64}(undef, 2) + slack = Array{Float64}(undef, 2) + duals = Array{Float64}(undef, 2) + djs = Array{Float64}(undef, 2) + ret = Xpress.Lib.XPRSgetnlpsol(model.inner, xx, slack, duals, djs) + @test ret == 0 + @test xx == [6, 10] + @test slack == [0, 0] + + return nothing +end + end TestMOIWrapper.runtests()