How to change the type from MOIU.CachingOptimizer{MOI.AbstractOptimizer,...} to MOI.AbstractoOptimizer

I want to make a solver looking for a feasibility solution. Therefore, I want to bring up the problem of mps format and treat constraints, variables, coefficients, etc. as follows.
The structure I want is the same structure as JuniperProblem in a package called Juniper.

mutable struct JuniperProblem
    nl_solver           :: Any
    nl_solver_options   :: Vector{Pair}
   
    model               :: JuMP.Model

    relaxation_status   :: MOI.TerminationStatusCode
    relaxation_objval   :: Float64
    relaxation_solution :: Vector{Float64}

    status              :: MOI.TerminationStatusCode
    objval              :: Float64
    best_bound          :: Float64

    x                   :: Vector{JuMP.VariableRef}
    primal_start        :: Vector{Real}
    num_constr          :: Int64
    num_nl_constr       :: Int64
    num_q_constr        :: Int64
    num_l_constr        :: Int64
    num_var             :: Int64
    l_var               :: Vector{Float64}
    u_var               :: Vector{Float64}

    has_nl_objective    :: Bool
    nlp_evaluator       :: MOI.AbstractNLPEvaluator

    objective           :: Union{SVF, SAF, SQF, Nothing}

    disc2var_idx        :: Vector{Int64}
    var2disc_idx        :: Vector{Int64}

    var_type            :: Vector{Symbol}
    obj_sense           :: Symbol
    num_disc_var        :: Int64

    solution            :: Vector{Float64}

    soltime             :: Float64
    options             :: SolverOptions
    solutions           :: Vector{SolutionObj}
    nsolutions          :: Int64

    mip_solver          :: Any
    mip_solver_options  :: Vector{Pair}

    relaxation_time     :: Float64
    start_time          :: Float64

    # Info  
    nintvars            :: Int64
    nbinvars            :: Int64
    nnodes              :: Int64
    ncuts               :: Int64
    nbranches           :: Int64
    nlevels             :: Int64

    fpump_info          :: Dict{Symbol,Float64}

    # debug 
    debugDict           :: Dict{Symbol,Any}

    JuniperProblem() = new()
end 

The main functions for entering values in JuniperProble are:

function init_juniper_problem!(jp::JuniperProblem, model::MOI.AbstractOptimizer)
    num_variables = length(model.variable_info)
    num_linear_le_constraints = length(model.linear_le_constraints)
    num_linear_ge_constraints = length(model.linear_ge_constraints)
    num_linear_eq_constraints = length(model.linear_eq_constraints)
    num_quadratic_le_constraints = length(model.quadratic_le_constraints)
    num_quadratic_ge_constraints = length(model.quadratic_ge_constraints)
    num_quadratic_eq_constraints = length(model.quadratic_eq_constraints)

    jp.status = MOI.OPTIMIZE_NOT_CALLED
    jp.relaxation_status = MOI.OPTIMIZE_NOT_CALLED
    jp.has_nl_objective = model.nlp_data.has_objective
    jp.nlp_evaluator = model.nlp_data.evaluator
    jp.objective = model.objective

    jp.objval = NaN
    jp.best_bound = NaN
    jp.solution = fill(NaN, num_variables)
    jp.nsolutions = 0
    jp.solutions = []
    jp.num_disc_var = 0
    jp.nintvars = 0
    jp.nbinvars = 0
    jp.nnodes = 1 # is set to one for the root node
    jp.ncuts = 0
    jp.nbranches = 0
    jp.nlevels = 1
    jp.relaxation_time = 0.0

    jp.start_time = time()

    jp.nl_solver = model.options.nl_solver
    nl_vec_opts = Vector{Pair}()
    if isa(jp.nl_solver, MOI.OptimizerWithAttributes)
        for arg in model.options.nl_solver.params
            push!(nl_vec_opts, arg)
        end
    end

    jp.nl_solver_options = nl_vec_opts

    if model.options.mip_solver !== nothing
        jp.mip_solver = model.options.mip_solver
        mip_vec_opts = Vector{Pair}()
        if isa(jp.mip_solver, MOI.OptimizerWithAttributes)
            for arg in model.options.mip_solver.params
                push!(mip_vec_opts, arg)
            end
        end
    
        jp.mip_solver_options = mip_vec_opts
    end
    jp.options = model.options    
    if model.sense == MOI.MIN_SENSE 
        jp.obj_sense = :Min
    else
        jp.obj_sense = :Max
    end
    jp.l_var = info_array_of_variables(model.variable_info, :lower_bound)
    jp.u_var = info_array_of_variables(model.variable_info, :upper_bound)
    integer_bool_arr = info_array_of_variables(model.variable_info, :is_integer)
    binary_bool_arr = info_array_of_variables(model.variable_info, :is_binary)
    primal_start_arr = info_array_of_variables(model.variable_info, :start)
    jp.primal_start = primal_start_arr
    jp.nintvars = sum(integer_bool_arr)
    jp.nbinvars = sum(binary_bool_arr)
    jp.num_disc_var = sum(integer_bool_arr)+sum(binary_bool_arr)
    jp.num_var = length(model.variable_info)
    jp.var_type = [:Cont for i in 1:jp.num_var]
    jp.var_type[integer_bool_arr .== true] .= :Int
    jp.var_type[binary_bool_arr .== true] .= :Bin
    jp.disc2var_idx = zeros(jp.num_disc_var)
    jp.var2disc_idx = zeros(jp.num_var)
    int_i = 1
    for i=1:jp.num_var
        if jp.var_type[i] != :Cont
            jp.disc2var_idx[int_i] = i
            jp.var2disc_idx[i] = int_i
            int_i += 1
        end
    end
    jp.num_l_constr = num_linear_le_constraints+num_linear_ge_constraints+num_linear_eq_constraints
    jp.num_q_constr = num_quadratic_le_constraints+num_quadratic_ge_constraints+num_quadratic_eq_constraints
    jp.num_nl_constr = length(model.nlp_data.constraint_bounds)
    jp.num_constr = jp.num_l_constr+jp.num_q_constr+jp.num_nl_constr
end

I built the model like this:

using JuMP, Cbc, Juniper, Ipopt,Random
model = read_from_file("/HDD/Workspace/CLT/mps/data/R100701005_2_cplex.mps")
nl_solver= optimizer_with_attributes(Ipopt.Optimizer, "print_level" => 0)
mip_solver = optimizer_with_attributes(Cbc.Optimizer, "logLevel" => 0 , "seconds" => 100, "feasibilityPump" => "on","maxSolutions" => 1)
optimizer = optimizer_with_attributes(Juniper.Optimizer, "nl_solver"=>nl_solver, "mip_solver"=>mip_solver)
set_optimizer(model, optimizer)

As an input value of init_juniper_problem, the model needs the MOI.AbstractOptimizer type. However, the model created with the read_from_file command is MOIU.CachingOptimizer {MOI.AbstractOptimizer, ...} as follows.

julia> typeof(backend(model))
MathOptInterface.Utilities.CachingOptimizer{MathOptInterface.AbstractOptimizer,MathOptInterface.Utilities.UniversalFallback{MathOptInterface.Utilities.Model{Float64}}}

There seems to be a way to use the MOI.AbstractOptimizer I need, but I don’t know.

Here are the results I tried:

Julia>Juniper.init_juniper_problem!(Juniper.JuniperProblem(), backend(model))

ERROR: type CachingOptimizer has no field variable_info
Stacktrace:
 [1] getproperty(::Any, ::Symbol) at ./sysimg.jl:18
 [2] init_juniper_problem!(::Juniper.JuniperProblem, ::MathOptInterface.Utilities.CachingOptimizer{MathOptInterface.AbstractOptimizer,MathOptInterface.Utilities.UniversalFallback{MathOptInterface.Utilities.Model{Float64}}}) at /HDD/sugyeong/github/FP_test.jl/src/bb_inits_and_defaults.jl:126
 [3] top-level scope at none:0

I am not friendly with Julia. Please ask for a lot of advice.

Hey,
I’m the main developer of Juniper maybe I can help you out. I’m not extremely sure what you’re trying to achieve. Are you trying to use Juniper for your problem or implement your own solver?

Normally one does not use the internal functions of a solver but instead JuMP or MOI.

If you’re still interested feel free to reach out via slack (Wikunia/Ole Kröger) or just ask here again.