Using MathOptInterface.AbstractOptimizer in parametric type declaration

Hi all,

I have a question regarding using the MathOptInterface.AbstractOptimizer for parametric type declaration when defining a composite type. For example, take the type definition below:

using JuMP # JuMP reexports MathOptInterface as MOI
using Ipopt

struct TestType{U <: MOI.AbstractOptimizer}
    test::U
end

my_test = TestType(Ipopt.Optimizer)

The idea here is that the user can pass a number of possible solvers to instantiate the composite type; however, the snippet above gives me the following error:

ERROR: MethodError: no method matching TestType(::Type{Ipopt.Optimizer})
The type `TestType` exists, but no method is defined for this combination of argument types when trying to construct it.

Closest candidates are:
  TestType(::U) where U<:MathOptInterface.AbstractOptimizer
   @ Main c:\Users\...\minexample.jl:5

Stacktrace:
 [1] top-level scope
   @ c:\Users\...\minexample.jl:8

I thought that U <: MOI.AbstractOptimizer would be a valid type declaration because Ipopt.Optimizer is a subtype of MOI.AbstractOptimizer, for example:

julia> Ipopt.Optimizer <:  MOI.AbstractOptimizer
true

What is the correct way to declare the type parameter for U in the struct TestType? Thank you in advance for the help!

The issue is that TestType(Ipopt.Optimizer) is passing in the type of an optimizer, not an instance of it.

You either need TestType(Ipopt.Optimizer()), or you need something like:

julia> struct TestType{U<:Real}
           test::Type{U}
       end

julia> TestType(Int)
TestType{Int64}(Int64)

julia> TestType(1)
ERROR: MethodError: no method matching TestType(::Int64)

Closest candidates are:
  TestType(::Type{U}) where U<:Real
   @ Main REPL[1]:2

Stacktrace:
 [1] top-level scope
   @ REPL[3]:1

It might help your understanding to try examples with Real instead of MOI.AbstractOptimizer:

julia> struct TestType{U<:Real}
           test::U
       end

julia> TestType(Int)
ERROR: MethodError: no method matching TestType(::Type{Int64})

Closest candidates are:
  TestType(::U) where U<:Real
   @ Main REPL[1]:2

Stacktrace:
 [1] top-level scope
   @ REPL[2]:1

julia> TestType(1)
TestType{Int64}(1)

However, from a JuMP perspective, you probably just want to make this:

struct TestType
    test::Any
end

This would support

GRB_ENV = Gurobi.Env()
TestType(() -> Gurobi.Optimizer(GRB_ENV))

and

TestType(optimizer_with_attributes(Ipopt.Optimizer, "tol" => 1e-8))

JuMP’s optimizer constructors do to need to be <:MOI.AbstractOptimizer.

1 Like