Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

adding relative & absolute mip gaps #17

Merged
merged 13 commits into from
Nov 3, 2023
42 changes: 41 additions & 1 deletion src/SolverAPI.jl
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,17 @@ function response(
res["solve_time_sec"] = Float64(MOI.get(model, MOI.SolveTimeSec()))

result_count = MOI.get(model, MOI.ResultCount())

try
res["relative_gap"]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove this line?

rel_gap = Float64(MOI.get(model, MOI.RelativeGap()))
if !isinf(rel_gap)
res["relative_gap"] = rel_gap # Inf cannot be serialized to JSON
end
catch
# ignore if solver does not support relative gap
end

results = [Dict{String,Any}() for _ in 1:result_count]
var_names = [string('\"', v, '\"') for v in json.variables]
var_idxs = MOI.get(model, MOI.ListOfVariableIndices())
Expand Down Expand Up @@ -398,8 +409,37 @@ function set_options!(model::MOI.ModelLike, options::JSON3.Object)#::Nothing
MOI.set(model, MOI.TimeLimitSec(), Float64(get(options, :time_limit_sec, 300.0)))
end

if MOI.supports(model, MOI.RelativeGapTolerance()) &&
haskey(options, :relative_gap_tolerance)
# Set relative gap tolerance
rel_gap_tol = Float64(options[:relative_gap_tolerance])
if rel_gap_tol < 0 || rel_gap_tol > 1
throw(Error(NotAllowed, "Relative gap tolerance must be within [0,1]."))
end

MOI.set(model, MOI.RelativeGapTolerance(), rel_gap_tol)
end

if MOI.supports(model, MOI.AbsoluteGapTolerance()) &&
haskey(options, :absolute_gap_tolerance)
# Set absolute gap tolerance
abs_gap_tol = Float64(options[:absolute_gap_tolerance])
if abs_gap_tol < 0
throw(Error(NotAllowed, "Absolute gap tolerance must be non-negative."))
end

MOI.set(model, MOI.AbsoluteGapTolerance(), abs_gap_tol)
end

for (key, val) in options
if key in [:solver, :print_format, :print_only, :time_limit_sec]
if key in [
:solver,
:print_format,
:print_only,
:time_limit_sec,
:relative_gap_tolerance,
:absolute_gap_tolerance,
]
# Skip - these are handled elsewhere.
continue
elseif key == :silent
Expand Down
4 changes: 4 additions & 0 deletions test/all_tests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,10 @@ end
("feas_with_obj", "InvalidFormat"),
# no objective function specified for a minimization problem
("min_no_obj", "InvalidFormat"),
# absolute_gap_tolerance out of range, e.g., -0.1
("abs_gap_out_of_range", "NotAllowed"),
# relative_gap_tolerance must be within [0,1]
("rel_gap_out_of_range", "NotAllowed"),
# unsupported sense such as 'feasibility'
("unsupported_sense", "InvalidFormat"),
# range: wrong number of args
Expand Down
1 change: 1 addition & 0 deletions test/inputs/abs_gap_out_of_range.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"version":"0.1","sense":"min","variables":["x","y"],"constraints":[["and",["==",["+","x",["*",3,"y"]],1],[">=",["+","x","y"],1]],["and",["Int","x"],["Nonneg","x"]],["Int","y"]],"objectives":[["+",["*",2,"x"],"y"]],"options":{"solver":"HIGHS", "absolute_gap_tolerance":-0.1}}
1 change: 1 addition & 0 deletions test/inputs/rel_gap_out_of_range.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"version":"0.1","sense":"min","variables":["x","y"],"constraints":[["and",["==",["+","x",["*",3,"y"]],1],[">=",["+","x","y"],1]],["and",["Int","x"],["Nonneg","x"]],["Int","y"]],"objectives":[["+",["*",2,"x"],"y"]],"options":{"solver":"HIGHS", "relative_gap_tolerance":1.1}}
Loading