Skip to content

Commit

Permalink
Refactor and simplify src/helper.jl (#237)
Browse files Browse the repository at this point in the history
  • Loading branch information
odow authored Mar 19, 2024
1 parent 232bd38 commit 3842900
Show file tree
Hide file tree
Showing 7 changed files with 444 additions and 393 deletions.
104 changes: 74 additions & 30 deletions src/MOI/MOI_wrapper.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1152,7 +1152,11 @@ function MOI.get(
model::Optimizer,
::MOI.ObjectiveFunction{MOI.ScalarAffineFunction{Float64}},
)
ncols = n_variables(model.inner)
ncols = @_invoke Lib.XPRSgetintattrib(
model.inner,
Lib.XPRS_ORIGINALCOLS,
_,
)::Int
first = 0
last = ncols - 1
_dobj = Vector{Float64}(undef, ncols)
Expand Down Expand Up @@ -1199,8 +1203,14 @@ function MOI.get(
::MOI.ObjectiveFunction{MOI.ScalarQuadraticFunction{Float64}},
)
dest = zeros(length(model.variable_info))
nnz = n_quadratic_elements(model.inner)
n = n_variables(model.inner)
nnz = @_invoke(
Lib.XPRSgetintattrib(model.inner, Lib.XPRS_ORIGINALQELEMS, _)::Int
)
n = @_invoke Lib.XPRSgetintattrib(
model.inner,
Lib.XPRS_ORIGINALCOLS,
_,
)::Int
nels = Ref{Cint}(nnz)
mstart = Array{Cint}(undef, n + 1)
mclind = Array{Cint}(undef, nnz)
Expand Down Expand Up @@ -2330,7 +2340,8 @@ end

function _get_affine_terms(model::Optimizer, c::MOI.ConstraintIndex)
row = _info(model, c).row
nzcnt_max = n_non_zero_elements(model.inner)
nzcnt_max =
@_invoke Lib.XPRSgetintattrib(model.inner, Lib.XPRS_ELEMS, _)::Int

_nzcnt = Ref(Cint(0))
@checked Lib.XPRSgetrows(
Expand Down Expand Up @@ -2635,10 +2646,15 @@ function MOI.add_constraint(
indices .-= 1,#Cint.(_mrwind::Vector{Int}),
coefficients,#_dmatval
)
ncons = @_invoke Lib.XPRSgetintattrib(
model.inner,
Lib.XPRS_ORIGINALROWS,
_,
)::Int
@checked Lib.XPRSsetindicators(
model.inner,
1,
Ref{Cint}(n_constraints(model.inner) - 1),
Ref{Cint}(ncons - 1),
Ref{Cint}(con_value - 1),
Ref{Cint}(indicator_activation(Val{A})),
)
Expand Down Expand Up @@ -2720,9 +2736,14 @@ function MOI.add_constraint(
V .*= 0.5 # only for constraints
I .-= 1
J .-= 1
ncons = @_invoke Lib.XPRSgetintattrib(
model.inner,
Lib.XPRS_ORIGINALROWS,
_,
)::Int
@checked Lib.XPRSaddqmatrix(
model.inner,
n_constraints(model.inner) - 1,
ncons - 1,
Cint(length(I)),
I,
J,
Expand Down Expand Up @@ -2867,9 +2888,19 @@ function MOI.delete(
end

function _get_sparse_sos(model)
nnz = n_setmembers(model.inner)
nsos = n_special_ordered_sets(model.inner)
n = n_variables(model.inner)
nnz = @_invoke(
Lib.XPRSgetintattrib(model.inner, Lib.XPRS_ORIGINALSETMEMBERS, _)::Int
)
nsos = @_invoke Lib.XPRSgetintattrib(
model.inner,
Lib.XPRS_ORIGINALSETS,
_,
)::Int
n = @_invoke Lib.XPRSgetintattrib(
model.inner,
Lib.XPRS_ORIGINALCOLS,
_,
)::Int

settypes = Array{Cchar}(undef, nsos)
setstart = Array{Cint}(undef, nsos + 1)
Expand Down Expand Up @@ -2963,7 +2994,15 @@ function check_cb_exception(model::Optimizer)
return
end

is_mip(model) = is_mixedinteger(model.inner) && !model.solve_relaxation
function is_mip(model::Optimizer)
n = @_invoke(
Lib.XPRSgetintattrib(model.inner, Lib.XPRS_ORIGINALMIPENTS, _)::Int,
)
nsos = @_invoke(
Lib.XPRSgetintattrib(model.inner, Lib.XPRS_ORIGINALSETS, _)::Int,
)
return !model.solve_relaxation && n + nsos > 0
end

function _set_MIP_start(model)
colind, solval = Cint[], Cdouble[]
Expand All @@ -2984,22 +3023,24 @@ function MOI.optimize!(model::Optimizer)
# Initialize callbacks if necessary.
if check_moi_callback_validity(model)
if model.moi_warnings &&
getcontrol(model.inner, Lib.XPRS_HEURSTRATEGY) != 0
@warn "Callbacks in XPRESS might not work correctly with HEURSTRATEGY != 0"
getcontrol(model.inner, "XPRS_HEURSTRATEGY") != 0
@warn(
"Callbacks in XPRESS might not work correctly with HEURSTRATEGY != 0",
)
end
MOI.set(model, CallbackFunction(), default_moi_callback(model))
model.has_generic_callback = false # because it is set as true in the above
end
pre_solve_reset(model)
# cache rhs: must be done before hand because it cant be
# properly queried if the problem ends up in a presolve state
rhs = Vector{Float64}(undef, n_constraints(model.inner))
@checked Lib.XPRSgetrhs(
ncons = @_invoke Lib.XPRSgetintattrib(
model.inner,
rhs,
Cint(0),
Cint(n_constraints(model.inner) - 1),
)
Lib.XPRS_ORIGINALROWS,
_,
)::Int
rhs = Vector{Float64}(undef, ncons)
@checked Lib.XPRSgetrhs(model.inner, rhs, Cint(0), Cint(ncons - 1))
if !model.ignore_start && is_mip(model)
_set_MIP_start(model)
end
Expand Down Expand Up @@ -4205,9 +4246,14 @@ function MOI.add_constraint(
C_NULL,
C_NULL,
)
ncons = @_invoke Lib.XPRSgetintattrib(
model.inner,
Lib.XPRS_ORIGINALROWS,
_,
)::Int
@checked Lib.XPRSaddqmatrix(
model.inner,
n_constraints(model.inner) - 1,
ncons - 1,
Cint(length(I)),
I,
I,
Expand Down Expand Up @@ -4297,14 +4343,12 @@ function MOI.add_constraint(
C_NULL,
C_NULL,
)
@checked Lib.XPRSaddqmatrix(
ncons = @_invoke Lib.XPRSgetintattrib(
model.inner,
n_constraints(model.inner) - 1,
length(I),
I,
J,
V,
)
Lib.XPRS_ORIGINALROWS,
_,
)::Int
@checked Lib.XPRSaddqmatrix(model.inner, ncons - 1, length(I), I, J, V)
model.last_constraint_index += 1
model.affine_constraint_info[model.last_constraint_index] =
ConstraintInfo(length(model.affine_constraint_info) + 1, s, RSOC)
Expand Down Expand Up @@ -4904,11 +4948,11 @@ end
MOI.supports(::Optimizer, ::MOI.RelativeGapTolerance) = true

function MOI.get(model::Optimizer, ::MOI.RelativeGapTolerance)
return getcontrol(model.inner, Lib.XPRS_MIPRELSTOP)
return getcontrol(model.inner, "XPRS_MIPRELSTOP")
end

function MOI.set(model::Optimizer, ::MOI.RelativeGapTolerance, value::Float64)
setcontrol!(model.inner, Lib.XPRS_MIPRELSTOP, value)
setcontrol!(model.inner, "XPRS_MIPRELSTOP", value)
return
end

Expand All @@ -4919,10 +4963,10 @@ end
MOI.supports(::Optimizer, ::MOI.AbsoluteGapTolerance) = true

function MOI.get(model::Optimizer, ::MOI.AbsoluteGapTolerance)
return getcontrol(model.inner, Lib.XPRS_MIPABSSTOP)
return getcontrol(model.inner, "XPRS_MIPABSSTOP")
end

function MOI.set(model::Optimizer, ::MOI.AbsoluteGapTolerance, value::Float64)
setcontrol!(model.inner, Lib.XPRS_MIPABSSTOP, value)
setcontrol!(model.inner, "XPRS_MIPABSSTOP", value)
return
end
1 change: 0 additions & 1 deletion src/Xpress.jl
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ include("Lib/Lib.jl")

include("utils.jl")
include("helper.jl")
include("attributes_controls.jl")
include("api.jl")
include("xprs_callbacks.jl")
include("license.jl")
Expand Down
165 changes: 165 additions & 0 deletions src/api.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6777,3 +6777,168 @@ end
function _bo_validate(obranch, p_status)
@checked Lib.XPRS_bo_validate(obranch, p_status)
end

#=
Other methods that we have deprecated
=#

function mip_solve_complete(stat)
return stat in [Lib.XPRS_MIP_INFEAS, Lib.XPRS_MIP_OPTIMAL]
end

function mip_solve_stopped(stat)
return stat in [Lib.XPRS_MIP_INFEAS, Lib.XPRS_MIP_OPTIMAL]
end

function fixinfinity(val::Float64)
if val == Inf
return Lib.XPRS_PLUSINFINITY
elseif val == -Inf
return Lib.XPRS_MINUSINFINITY
else
return val
end
end

function fixinfinity!(vals::Vector{Float64})
return map!(fixinfinity, vals, vals)
end

function is_quadratic_constraints(prob::XpressProblem)
return n_quadratic_constraints(prob) > 0
end

is_quadratic_objective(prob::XpressProblem) = n_quadratic_elements(prob) > 0

function obj_sense(prob::XpressProblem)
@_invoke Lib.XPRSgetdblattrib(prob, Lib.XPRS_OBJSENSE, _)::Float64
end

function objective_sense(prob::XpressProblem)
return obj_sense(prob) == Lib.XPRS_OBJ_MINIMIZE ? :minimize : :maximize
end

function n_original_variables(prob::XpressProblem)
@_invoke Lib.XPRSgetintattrib(prob, Lib.XPRS_ORIGINALCOLS, _)::Int
end

function n_original_constraints(prob::XpressProblem)
@_invoke Lib.XPRSgetintattrib(prob, Lib.XPRS_ORIGINALROWS, _)::Int
end

get_version_raw() = @_invoke Lib.XPRSgetversion(_)::String

function problem_type(prob::XpressProblem)
if n_quadratic_constraints(prob) > 0
return :QCP
elseif n_quadratic_elements(prob) > 0
return :QP
else
return :LP
end
end

function n_linear_constraints(prob::XpressProblem)
return n_constraints(prob) - n_quadratic_constraints(prob)
end

function n_setmembers(prob::XpressProblem)
@_invoke Lib.XPRSgetintattrib(prob, Lib.XPRS_ORIGINALSETMEMBERS, _)::Int
end

function n_quadratic_row_coefficients(prob::XpressProblem)
@_invoke Lib.XPRSgetintattrib(prob, Lib.XPRS_ORIGINALQCELEMS, _)::Int
end

function n_quadratic_elements(prob::XpressProblem)
@_invoke Lib.XPRSgetintattrib(prob, Lib.XPRS_ORIGINALQELEMS, _)::Int
end

function n_non_zero_elements(prob::XpressProblem)
@_invoke Lib.XPRSgetintattrib(prob, Lib.XPRS_ELEMS, _)::Int
end

function n_variables(prob::XpressProblem)
@_invoke Lib.XPRSgetintattrib(prob, Lib.XPRS_ORIGINALCOLS, _)::Int
end

function n_quadratic_constraints(prob::XpressProblem)
@_invoke Lib.XPRSgetintattrib(prob, Lib.XPRS_ORIGINALQCONSTRAINTS, _)::Int
end

function n_entities(prob::XpressProblem)
@_invoke Lib.XPRSgetintattrib(prob, Lib.XPRS_ORIGINALMIPENTS, _)::Int
end

function n_special_ordered_sets(prob::XpressProblem)
@_invoke Lib.XPRSgetintattrib(prob, Lib.XPRS_ORIGINALSETS, _)::Int
end

function n_constraints(prob::XpressProblem)
@_invoke Lib.XPRSgetintattrib(prob, Lib.XPRS_ORIGINALROWS, _)::Int
end

include("attributes_controls.jl")

function get_control_or_attribute(prob::XpressProblem, control::Int32)
if control in INTEGER_CONTROLS_VALUES
return @_invoke Lib.XPRSgetintcontrol(prob, control, _)::Int
elseif control in DOUBLE_CONTROLS_VALUES
return @_invoke Lib.XPRSgetdblcontrol(prob, control, _)::Float64
elseif control in STRING_CONTROLS_VALUES
return @_invoke Lib.XPRSgetstrcontrol(prob, control, _)::String
elseif control in INTEGER_ATTRIBUTES_VALUES
return @_invoke Lib.XPRSgetintattrib(prob, control, _)::Int
elseif control in DOUBLE_ATTRIBUTES_VALUES
return @_invoke Lib.XPRSgetdblattrib(prob, control, _)::Float64
elseif control in STRING_ATTRIBUTES_VALUES
return @_invoke Lib.XPRSgetstrattrib(prob, control, _)::String
end
return error("Unrecognized parameter: $(control).")
end

function get_control_or_attribute(prob::XpressProblem, control::Integer)
return get_control_or_attribute(prob, Int32(control))
end

function getcontrol(prob::XpressProblem, control::Int32)
if control in INTEGER_CONTROLS_VALUES
return @_invoke Lib.XPRSgetintcontrol(prob, control, _)::Int
elseif control in DOUBLE_CONTROLS_VALUES
return @_invoke Lib.XPRSgetdblcontrol(prob, control, _)::Float64
elseif control in STRING_CONTROLS_VALUES
return @_invoke Lib.XPRSgetstrcontrol(prob, control, _)::String
end
return error("Unrecognized control: $(control).")
end

function getcontrol(prob::XpressProblem, control::Integer)
return getcontrol(prob, Int32(control))
end

function setcontrol!(prob::XpressProblem, control::Int32, val)
if control in INTEGER_CONTROLS_VALUES
if !isinteger(val)
error("Expected and integer and got $val")
end
Lib.XPRSsetintcontrol(prob, Cint(control), Int32(val))
elseif control in DOUBLE_CONTROLS_VALUES
Lib.XPRSsetdblcontrol(prob, control, Float64(val))
elseif control in STRING_CONTROLS_VALUES
Lib.XPRSsetstrcontrol(prob, control, val)
else
error("Unrecognized control parameter: $(control).")
end
return
end

function setcontrol!(prob::XpressProblem, control::Integer, val)
return setcontrol!(prob, Cint(control), val)
end

function setcontrols!(prob::XpressProblem; kwargs...)
for (control, val) in kwargs
setcontrol!(prob, String(control), val)
end
return
end
Loading

0 comments on commit 3842900

Please sign in to comment.