From 84b60fc1ff1db9116b558ba7a2a915125dba7fca Mon Sep 17 00:00:00 2001 From: odow Date: Thu, 3 Jun 2021 14:18:39 +1200 Subject: [PATCH] WIP: breaking changes for MOI 0.10.0 --- Project.toml | 1 + src/MOI_wrapper.jl | 49 +++++++++++++++++------------------- test/MOI_wrapper.jl | 60 ++++++++++++++++++++------------------------- test/runtests.jl | 5 ++++ 4 files changed, 56 insertions(+), 59 deletions(-) diff --git a/Project.toml b/Project.toml index 83755fb..7b356ff 100644 --- a/Project.toml +++ b/Project.toml @@ -5,6 +5,7 @@ version = "0.2.1" [deps] HiGHS_jll = "8fd58aa0-07eb-5a78-9b36-339c94fd15ea" MathOptInterface = "b8f27783-ece8-5eb3-8dc8-9495eed66fee" +Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f" SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" [compat] diff --git a/src/MOI_wrapper.jl b/src/MOI_wrapper.jl index 02e05ac..4c37987 100644 --- a/src/MOI_wrapper.jl +++ b/src/MOI_wrapper.jl @@ -431,7 +431,7 @@ function MOI.get(model::Optimizer, ::MOI.NumberOfConstraints{F,S}) where {F,S} return length(MOI.get(model, MOI.ListOfConstraintIndices{F,S}())) end -function MOI.get(model::Optimizer, ::MOI.ListOfConstraints) +function MOI.get(model::Optimizer, ::MOI.ListOfConstraintTypesPresent) constraints = Set{Tuple{DataType,DataType}}() for info in values(model.variable_info) if info.bound == _BOUND_NONE @@ -464,13 +464,10 @@ function MOI.get(model::Optimizer, ::MOI.ListOfConstraints) end ### -### MOI.RawParameter +### MOI.RawOptimizerAttribute ### -function MOI.supports(model::Optimizer, param::MOI.RawParameter) - if !(param.name isa String) - return false - end +function MOI.supports(model::Optimizer, param::MOI.RawOptimizerAttribute) typeP = Ref{Cint}() return Highs_getOptionType(model, param.name, typeP) == 0 end @@ -498,7 +495,7 @@ function _set_option(model::Optimizer, option::String, value::String) return Highs_setStringOptionValue(model, option, value) end -function MOI.set(model::Optimizer, param::MOI.RawParameter, value) +function MOI.set(model::Optimizer, param::MOI.RawOptimizerAttribute, value) if !MOI.supports(model, param) throw(MOI.UnsupportedAttribute(param)) end @@ -540,7 +537,7 @@ function _get_string_option(model::Optimizer, option::String) end end -function MOI.get(model::Optimizer, param::MOI.RawParameter) +function MOI.get(model::Optimizer, param::MOI.RawOptimizerAttribute) if !(param.name isa String) throw(MOI.UnsupportedAttribute(param)) end @@ -567,15 +564,15 @@ end MOI.supports(::Optimizer, ::MOI.TimeLimitSec) = true function MOI.set(model::Optimizer, ::MOI.TimeLimitSec, ::Nothing) - return MOI.set(model, MOI.RawParameter("time_limit"), Inf) + return MOI.set(model, MOI.RawOptimizerAttribute("time_limit"), Inf) end function MOI.set(model::Optimizer, ::MOI.TimeLimitSec, limit::Real) - return MOI.set(model, MOI.RawParameter("time_limit"), Float64(limit)) + return MOI.set(model, MOI.RawOptimizerAttribute("time_limit"), Float64(limit)) end function MOI.get(model::Optimizer, ::MOI.TimeLimitSec) - return MOI.get(model, MOI.RawParameter("time_limit")) + return MOI.get(model, MOI.RawOptimizerAttribute("time_limit")) end ### @@ -779,7 +776,7 @@ function MOI.set( num_vars = length(model.variable_info) obj = zeros(Float64, num_vars) for term in f.terms - col = column(model, term.variable_index) + col = column(model, term.variable) obj[col+1] += term.coefficient end # TODO(odow): cache the mask. @@ -1256,7 +1253,7 @@ function _indices_and_coefficients( ) i = 1 for term in f.terms - indices[i] = column(model, term.variable_index) + indices[i] = column(model, term.variable) coefficients[i] = term.coefficient i += 1 end @@ -1534,9 +1531,9 @@ function MOI.set( # complains but it will require some upstream changes to introduce a faster # way of modifying a list of coefficients. old = MOI.get(model, MOI.ConstraintFunction(), c) - terms = Dict(x.variable_index => 0.0 for x in old.terms) + terms = Dict(x.variable => 0.0 for x in old.terms) for term in f.terms - terms[term.variable_index] = term.coefficient + terms[term.variable] = term.coefficient end r = row(model, c) for (k, v) in terms @@ -1676,7 +1673,7 @@ function MOI.get(model::Optimizer, ::MOI.RawStatusString) end function MOI.get(model::Optimizer, attr::MOI.PrimalStatus) - if attr.N != 1 + if attr.result_index != 1 return MOI.NO_SOLUTION elseif model.solution.has_primal_solution return MOI.FEASIBLE_POINT @@ -1687,7 +1684,7 @@ function MOI.get(model::Optimizer, attr::MOI.PrimalStatus) end function MOI.get(model::Optimizer, attr::MOI.DualStatus) - if attr.N != 1 + if attr.result_index != 1 return MOI.NO_SOLUTION elseif model.solution.has_dual_solution return MOI.FEASIBLE_POINT @@ -1718,7 +1715,7 @@ function MOI.get(model::Optimizer, ::MOI.ObjectiveBound) return sense == -1 ? max(primal, -p[]) : min(primal, p[]) end -function MOI.get(model::Optimizer, ::MOI.SolveTime) +function MOI.get(model::Optimizer, ::MOI.SolveTimeSec) return Highs_getRunTime(model) end @@ -2107,11 +2104,11 @@ function _extract_bound_data( MOI.get(src, MOI.ListOfConstraintIndices{MOI.SingleVariable,S}()) f = MOI.get(src, MOI.ConstraintFunction(), c_index) s = MOI.get(src, MOI.ConstraintSet(), c_index) - new_f = mapping.varmap[f.variable] + new_f = mapping[f.variable] info = _info(dest, new_f) _add_bounds(collower, colupper, info.column + 1, s) _update_info(info, s) - mapping.conmap[c_index] = + mapping[c_index] = MOI.ConstraintIndex{MOI.SingleVariable,S}(new_f.value) end return @@ -2129,13 +2126,13 @@ function _copy_to_columns(dest::Optimizer, src::MOI.ModelLike, mapping) info.name = MOI.get(dest, MOI.VariableName(), x_src[i]) info.index = index info.column = Cint(i - 1) - mapping.varmap[x_src[i]] = index + mapping[x_src[i]] = index end fobj = MOI.get(src, MOI.ObjectiveFunction{MOI.ScalarAffineFunction{Float64}}()) c = fill(0.0, numcols) for term in fobj.terms - i = mapping.varmap[term.variable_index].value + i = mapping[term.variable].value c[i] += term.coefficient end ret = Highs_changeObjectiveOffset(dest, fobj.constant) @@ -2180,7 +2177,7 @@ function _extract_row_data( ) dest.affine_constraint_info[key].row = Cint(length(dest.affine_constraint_info) - 1) - mapping.conmap[c_index] = + mapping[c_index] = MOI.ConstraintIndex{MOI.ScalarAffineFunction{Float64},S}(key.value) end _add_sizehint!(I, n_terms) @@ -2189,7 +2186,7 @@ function _extract_row_data( for f in fs for term in f.terms push!(I, row) - push!(J, Cint(mapping.varmap[term.variable_index].value)) + push!(J, Cint(mapping[term.variable].value)) push!(V, term.coefficient) end row += 1 @@ -2198,7 +2195,7 @@ function _extract_row_data( end function _check_input_data(dest::Optimizer, src::MOI.ModelLike) - for (F, S) in MOI.get(src, MOI.ListOfConstraints()) + for (F, S) in MOI.get(src, MOI.ListOfConstraintTypesPresent()) if !MOI.supports_constraint(dest, F, S) throw( MOI.UnsupportedConstraint{F,S}( @@ -2214,7 +2211,7 @@ function _check_input_data(dest::Optimizer, src::MOI.ModelLike) return end -MOI.Utilities.supports_default_copy_to(::Optimizer, ::Bool) = true +MOI.supports_incremental_interface(::Optimizer, ::Bool) = true function MOI.copy_to( dest::Optimizer, diff --git a/test/MOI_wrapper.jl b/test/MOI_wrapper.jl index 84e269f..ce0a463 100644 --- a/test/MOI_wrapper.jl +++ b/test/MOI_wrapper.jl @@ -413,28 +413,29 @@ end function test_HiGHS_custom_options(::Any, ::Any) model = HiGHS.Optimizer() - @test MOI.supports(model, MOI.RawParameter("solver")) - @test MOI.get(model, MOI.RawParameter("solver")) == "choose" - MOI.set(model, MOI.RawParameter("solver"), "simplex") - @test MOI.get(model, MOI.RawParameter("solver")) == "simplex" + @test MOI.supports(model, MOI.RawOptimizerAttribute("solver")) + @test MOI.get(model, MOI.RawOptimizerAttribute("solver")) == "choose" + MOI.set(model, MOI.RawOptimizerAttribute("solver"), "simplex") + @test MOI.get(model, MOI.RawOptimizerAttribute("solver")) == "simplex" @test MOI.get(model, MOI.RawParameter("output_flag")) == true MOI.set(model, MOI.RawParameter("output_flag"), false) @test MOI.get(model, MOI.RawParameter("output_flag")) == false - @test MOI.get(model, MOI.RawParameter("time_limit")) > 1000 - MOI.set(model, MOI.RawParameter("time_limit"), 1000.0) - @test MOI.get(model, MOI.RawParameter("time_limit")) == 1000.0 + @test MOI.get(model, MOI.RawOptimizerAttribute("time_limit")) > 1000 + MOI.set(model, MOI.RawOptimizerAttribute("time_limit"), 1000.0) + @test MOI.get(model, MOI.RawOptimizerAttribute("time_limit")) == 1000.0 # unsupported test - @test MOI.supports(model, MOI.RawParameter("wrong_param")) == false - @test_throws MOI.UnsupportedAttribute MOI.get( - model, - MOI.RawParameter("wrong_param"), + @test MOI.supports(model, MOI.RawOptimizerAttribute("wrong_param")) == false + @test_throws( + MOI.UnsupportedAttribute, + MOI.get(model, MOI.RawOptimizerAttribute("wrong_param")), ) for v in [false, 1, 1.0, "A"] @test_throws( MOI.UnsupportedAttribute, - MOI.set(model, MOI.RawParameter("wrong_param"), v) + MOI.set(model, MOI.RawOptimizerAttribute("wrong_param"), v) ) end + return end function test_Model_empty(model, ::Any) @@ -483,9 +484,9 @@ function test_options(model, ::Any) "presolve", # String ] for key in options - v = MOI.get(model, MOI.RawParameter(key)) - MOI.set(model, MOI.RawParameter(key), v) - v2 = MOI.get(model, MOI.RawParameter(key)) + v = MOI.get(model, MOI.RawOptimizerAttribute(key)) + MOI.set(model, MOI.RawOptimizerAttribute(key), v) + v2 = MOI.get(model, MOI.RawOptimizerAttribute(key)) @test v == v2 end return @@ -496,16 +497,7 @@ function test_option_invalid(model, ::Any) ErrorException( "Encountered an error in HiGHS: Check the log for details.", ), - MOI.set(model, MOI.RawParameter("time_limit"), -1.0), - ) - return -end - -function test_option_invalid(model, ::Any) - MOI.supports(model, MOI.RawParameter(:presolve)) == false - @test_throws MOI.UnsupportedAttribute MOI.get( - model, - MOI.RawParameter(:presolve), + MOI.set(model, MOI.RawOptimizerAttribute("time_limit"), -1.0), ) return end @@ -514,14 +506,16 @@ function test_option_unknown_option(model, ::Any) err = ErrorException( "Encountered an error in HiGHS: Check the log for details.", ) - @test_throws err MOI.set( - model, - MOI.RawParameter("write_solution_to_file"), - 1, + @test_throws( + err, + MOI.set(model, MOI.RawOptimizerAttribute("write_solution_to_file"), 1), + ) + @test_throws( + err, + MOI.set(model, MOI.RawOptimizerAttribute("simplex_strategy"), "on"), ) - @test_throws err MOI.set(model, MOI.RawParameter("simplex_strategy"), "on") - @test_throws err MOI.set(model, MOI.RawParameter("time_limit"), 1) - @test_throws err MOI.set(model, MOI.RawParameter("presolve"), 1) + @test_throws err MOI.set(model, MOI.RawOptimizerAttribute("time_limit"), 1) + @test_throws err MOI.set(model, MOI.RawOptimizerAttribute("presolve"), 1) return end @@ -545,7 +539,7 @@ c8: w + x in MathOptInterface.Interval(1.0, 2.0) dest = HiGHS.Optimizer() MOI.copy_to(dest, src) @test MOI.get(dest, MOI.NumberOfVariables()) == 4 - list = MOI.get(dest, MOI.ListOfConstraints()) + list = MOI.get(dest, MOI.ListOfConstraintTypesPresent()) @test length(list) == 8 for S in ( MOI.GreaterThan{Float64}, diff --git a/test/runtests.jl b/test/runtests.jl index cb1bed3..6eddf7c 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1,3 +1,8 @@ +if get(ENV, "GITHUB_ACTIONS", "") == "true" + import Pkg + Pkg.add(Pkg.PackageSpec(name = "MathOptInterface", rev = "master")) +end + using Test @testset "$(file)" for file in readdir(@__DIR__)