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.