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

Fixed optimize! to handle @constraint and @NLconstraint at the same time #208

Closed
wants to merge 112 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
112 commits
Select commit Hold shift + click to select a range
b4950e9
Adding to_str to utils
RaphMota Mar 23, 2023
0b10a40
Xpress NLP structures and functions
RaphMota Mar 30, 2023
27fdb95
solving PR issues
RaphMota Apr 3, 2023
9e09d15
to_str modified for SLP
RaphMota Apr 5, 2023
8e8f4dd
adding constraint_to_expr
RaphMota Apr 5, 2023
5589d75
to_str modified for nlp right format
RaphMota Apr 10, 2023
c2c55fb
New version of Xpress
RaphMota Apr 10, 2023
ea37e58
removing to_str in optimize!
RaphMota Apr 10, 2023
07b1bfb
to_constraint_set added
RaphMota Apr 12, 2023
3ab2aa6
objective_value update
RaphMota Apr 12, 2023
d512edb
nlp case added to status
RaphMota Apr 12, 2023
2bf2300
getnlpsol edited
RaphMota Apr 12, 2023
63df39e
corrections
RaphMota Apr 12, 2023
3ff7d96
corrections
RaphMota Apr 12, 2023
a8c51e8
reset_cached_solution updated
RaphMota Apr 12, 2023
cc11ada
getnlpsol updated
RaphMota Apr 12, 2023
e69116b
correcting indentation
RaphMota Apr 12, 2023
22100fa
Status issue solved
RaphMota Apr 13, 2023
32cfbea
Status issue corrections
RaphMota Apr 13, 2023
e25e37c
solving shadow price issue
RaphMota Apr 13, 2023
31a2544
nlp updated
RaphMota Apr 13, 2023
a1e1d1b
NonlinearConstraintRef added
RaphMota Apr 13, 2023
522ca95
NonlinearConstraintRef added
RaphMota Apr 13, 2023
51dbd76
NonlinearConstraintRef added
RaphMota Apr 13, 2023
622bcc9
corrections shadow price
RaphMota Apr 13, 2023
485d9c4
corrections shadow price
RaphMota Apr 13, 2023
beb7116
Objective value and value fixed
RaphMota Apr 13, 2023
466400c
Objective value and value fixed
RaphMota Apr 13, 2023
d3f2342
get NLPBlockDual added
RaphMota Apr 13, 2023
dcc274e
nlp.jl fixed
RaphMota Apr 13, 2023
618c077
cleaning constraints before optimizing
RaphMota Apr 14, 2023
c8b1269
cleaning constraints before optimizing
RaphMota Apr 14, 2023
2d02097
cleaning constraints before optimizing
RaphMota Apr 14, 2023
4094685
cleaning constraints before optimizing
RaphMota Apr 14, 2023
2b7d691
cleaning constraints before optimizing
RaphMota Apr 14, 2023
8f80430
cleaning constraints before optimizing
RaphMota Apr 14, 2023
2719ba3
removing useless functions from nlp.jl
RaphMota Apr 17, 2023
8910845
solving dict issue
RaphMota Apr 17, 2023
69d2fd8
Solving importation issues
RaphMota Apr 17, 2023
3fd5da3
Fixing dual
RaphMota Apr 17, 2023
04341a3
tests added
RaphMota Apr 17, 2023
d2913b0
module issue solved
RaphMota Apr 17, 2023
a707d00
solving tests issues
RaphMota Apr 17, 2023
4c7c230
solving tests issues
RaphMota Apr 17, 2023
55ec895
Solving test issues
RaphMota Apr 18, 2023
6ca4f47
Case with only NLObjective
RaphMota Apr 18, 2023
91972d8
Case with only NLObjective
RaphMota Apr 18, 2023
8b814ff
Case with only NLObjective
RaphMota Apr 18, 2023
bc9f86a
cached primal updated
RaphMota Apr 18, 2023
2a01dbb
solving problems
RaphMota Apr 18, 2023
5221cd9
solving problems
RaphMota Apr 18, 2023
94ccd54
solving problems
RaphMota Apr 18, 2023
e18202d
test dummy nlp fixed
RaphMota Apr 18, 2023
d6e5c7c
test dummy nlp fixed
RaphMota Apr 18, 2023
b368806
Importations
RaphMota Apr 18, 2023
59c093e
Importations
RaphMota Apr 18, 2023
bddf6a8
set_bounds fixed
RaphMota Apr 18, 2023
951129a
Solving add_constraints
RaphMota Apr 18, 2023
6b7eddd
Fixing warnings
RaphMota Apr 19, 2023
b023647
Fixing warnings
RaphMota Apr 19, 2023
db6046f
fix warnings
RaphMota Apr 19, 2023
01d9b71
fix warnings
RaphMota Apr 19, 2023
fe35d6d
Removing useless functions
RaphMota Apr 19, 2023
6beaf0a
Removing useless functions
RaphMota Apr 19, 2023
72e6b27
Removing useless functions
RaphMota Apr 19, 2023
8f8ce60
Dual issue fixed
RaphMota Apr 19, 2023
1187bc9
Dual issue fixed
RaphMota Apr 19, 2023
54d5a7c
Editing optimize!
RaphMota Apr 19, 2023
5a4c16d
Editing optimize!
RaphMota Apr 19, 2023
6ba1623
Editing optimize!
RaphMota Apr 19, 2023
a2252ed
Editing optimize!
RaphMota Apr 19, 2023
f55b323
Editing optimize!
RaphMota Apr 19, 2023
fbaf3e3
Invalid Evaluator case fixing
RaphMota Apr 20, 2023
003785d
Invalid Evaluator case fixing
RaphMota Apr 20, 2023
bb5011b
Invalid Evaluator case fixing
RaphMota Apr 20, 2023
b7aa2f5
testing XPRSnlpoptimize
RaphMota Apr 20, 2023
263a075
testing XPRSnlpoptimize
RaphMota Apr 20, 2023
ab54b2e
changing runtests
RaphMota Apr 20, 2023
d162414
changing runtests
RaphMota Apr 20, 2023
5f71dac
changing runtests
RaphMota Apr 20, 2023
efb41b8
changing runtests
RaphMota Apr 20, 2023
34bb185
fixing empty!
RaphMota Apr 20, 2023
24f5736
Removing test_temp
RaphMota Apr 20, 2023
308359b
Removing test_temp
RaphMota Apr 20, 2023
fd7313f
Removing test_temp
RaphMota Apr 20, 2023
9666414
Solving callbacks issues
RaphMota Apr 20, 2023
1c9bb87
Solving callbacks issues
RaphMota Apr 20, 2023
b6f4d71
Updating Base.Show
RaphMota Apr 24, 2023
b8489b4
Updating Base.Show
RaphMota Apr 24, 2023
87486ca
callbacks issues
RaphMota Apr 24, 2023
3b5f717
callbacks issues
RaphMota Apr 24, 2023
a40a8dc
callbacks issues
RaphMota Apr 24, 2023
b32d870
callbacks issues
RaphMota Apr 24, 2023
3dfb750
callbacks issues
RaphMota Apr 24, 2023
23274ee
callbacks issues
RaphMota Apr 24, 2023
7ac249b
callbacks issues
RaphMota Apr 24, 2023
7e2fe52
callbacks issues
RaphMota Apr 24, 2023
95cb037
callbacks issues
RaphMota Apr 24, 2023
c1f109f
callbacks issues
RaphMota Apr 24, 2023
c3fb08e
callbacks issues
RaphMota Apr 24, 2023
715b265
callbacks issues
RaphMota Apr 24, 2023
7361241
callbacks issues
RaphMota Apr 24, 2023
2aff439
callbacks issues
RaphMota Apr 24, 2023
01c3263
callbacks issues
RaphMota Apr 24, 2023
e98be7f
callbacks tests
RaphMota Apr 24, 2023
014ed0b
callbacks tests
RaphMota Apr 24, 2023
13bcade
Updating helper
RaphMota Apr 24, 2023
cec749b
Updating helper
RaphMota Apr 24, 2023
7f0da88
Base show updated
RaphMota Apr 24, 2023
7f67de0
Merge branch 'jg/nlp' into master
joaquimg May 17, 2023
0085605
Fixing case with L and NL constraints
RaphMota May 26, 2023
8f37452
Merge branch 'master' of https://github.com/RaphMota/Xpress.jl-Lib
RaphMota May 26, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ version = "0.16.1"
Libdl = "8f399da3-3557-5675-b5ff-fb832c97cbdb"
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
MathOptInterface = "b8f27783-ece8-5eb3-8dc8-9495eed66fee"
Revise = "295af30f-e4ad-537b-8983-00126c2a3abe"
SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"
XpressPSR = "3a57e2e4-7268-4354-91dd-d57606666fa4"

[compat]
MathOptInterface = "1"
Expand Down
261 changes: 231 additions & 30 deletions src/MOI/MOI_wrapper.jl

Large diffs are not rendered by default.

223 changes: 223 additions & 0 deletions src/MOI/nlp.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,223 @@
MOI.supports(::Optimizer, ::MOI.NLPBlock) = true

function walk_and_strip_variable_index!(expr::Expr)
for i in 1:length(expr.args)
if expr.args[i] isa MOI.VariableIndex
expr.args[i] = expr.args[i].value
end
walk_and_strip_variable_index!(expr.args[i])
end
return
end

walk_and_strip_variable_index!(not_expr) = nothing

function MOI.set(model::Optimizer, ::MOI.NLPBlock, nlp_data::MOI.NLPBlockData)
if model.nlp_block_data !== nothing
model.nlp_block_data = nothing
# error("Nonlinear block already set; cannot overwrite. Create a new model instead.")
end
model.nlp_block_data = nlp_data

nlp_eval = nlp_data.evaluator

MOI.initialize(nlp_eval, [:ExprGraph])

if nlp_data.has_objective
# according to test: test_nonlinear_objective_and_moi_objective_test
# from MOI 0.10.9, linear objectives are just ignores if the noliena exists
# if model.inner.objective_expr !== nothing
# error("Two objectives set: One linear, one nonlinear.")
# end
obj = verify_support(MOI.objective_expr(nlp_eval))
walk_and_strip_variable_index!(obj)
if obj == :NaN
model.objective_expr = 0.0
model.termination_status = MOI.INVALID_MODEL
else
model.objective_expr = obj
end
model.objective_type = NLP_OBJECTIVE
else
model.objective_expr = 0.0
end

for i in 1:length(nlp_data.constraint_bounds)
expr = verify_support(MOI.constraint_expr(nlp_eval, i))
println(i)

@assert expr.head == :call
lb = nlp_data.constraint_bounds[i].lower
ub = nlp_data.constraint_bounds[i].upper
@assert expr.head == :call
if expr.args[1] == :(==)
@assert lb == ub == expr.args[3]
elseif expr.args[1] == :(<=)
@assert lb == -Inf
lb = nothing
@assert ub == expr.args[3]
elseif expr.args[1] == :(>=)
@assert lb == expr.args[3]
@assert ub == Inf
ub = nothing
else
error("Unexpected expression $expr.")
end
expr = expr.args[2]
walk_and_strip_variable_index!(expr)
push!(model.nlp_constraint_info, Xpress.NLPConstraintInfo(expr, lb, ub, nothing))
end
return
end

# Converting expressions in strings adapted to chgformulastring and chgobjformulastring
wrap_with_parens(x::String) = string("( ", x, " )")

to_str(x) = string(x)

function to_str(c::Expr)
if c.head == :comparison
if length(c.args) == 3
return join([to_str(c.args[1]), " ", c.args[2], " ", c.args[3]])
elseif length(c.args) == 5
return join([c.args[1], " ", c.args[2], " ", to_str(c.args[3]), " ",
c.args[4], " ", c.args[5]])
else
throw(UnrecognizedExpressionException("comparison", c))
end
elseif c.head == :call
if c.args[1] in (:<=,:>=,:(==))
if length(c.args) == 3
return join([to_str(c.args[2]), " ", to_str(c.args[1]), " ", to_str(c.args[3])])
elseif length(c.args) == 5
return join([to_str(c.args[1]), " ", to_str(c.args[2]), " ", to_str(c.args[3]), " ", to_str(c.args[4]), " ", to_str(c.args[5])])
else
throw(UnrecognizedExpressionException("comparison", c))
end
elseif c.args[1] in (:+,:-,:*,:/)
if all(d->isa(d, Real), c.args[2:end]) # handle unary case
return wrap_with_parens(string(eval(c)))
elseif c.args[1] == :- && length(c.args) == 2
return wrap_with_parens(string("( - $(to_str(c.args[2])) )"))
else
return wrap_with_parens(string(join([to_str(d) for d in c.args[2:end]], join([" ",string(c.args[1]), " "]))))
end
elseif c.args[1] == :^
if length(c.args) != 3
throw(UnrecognizedExpressionException("function call", c))
end
return wrap_with_parens(join([to_str(c.args[2]), " ",to_str(c.args[1]), " ",to_str(c.args[3])]))
elseif c.args[1] in (:exp,:log,:sin,:cos,:abs,:tan,:sqrt)
if length(c.args) != 2
throw(UnrecognizedExpressionException("function call", c))
end
return wrap_with_parens(string(join([uppercase(string(c.args[1])), " "]), wrap_with_parens(to_str(c.args[2]))))
else
throw(UnrecognizedExpressionException("function call", c))
end
elseif c.head == :ref
if c.args[1] == :x
idx = c.args[2]
@assert isa(idx, Int)
# TODO decide is use use defined names
# might be messy becaus a use can call his variable "sin"
return "x$idx"
else
throw(UnrecognizedExpressionException("reference", c))
end
end
end

verify_support(c) = c

function verify_support(c::Real)
if isfinite(c) # blocks NaN and +/-Inf
return c
end
error("Expected number but got $c")
end

function verify_support(c::Expr)
if c.head == :comparison
map(verify_support, c.args)
return c
end
if c.head == :call
if c.args[1] in (:+, :-, :*, :/, :exp, :log)
return c
elseif c.args[1] in (:<=, :>=, :(==))
map(verify_support, c.args[2:end])
return c
elseif c.args[1] == :^
@assert isa(c.args[2], Real) || isa(c.args[3], Real)
return c
else # TODO: do automatic transformation for x^y, |x|
error("Unsupported expression $c")
end
end
return c
end

function set_lower_bound(info::NLPConstraintInfo, value::Union{Number, Nothing})
if value !== nothing
info.lower_bound !== nothing && throw(ArgumentError("Lower bound has already been set"))
info.lower_bound = value
end
return
end

function set_upper_bound(info::NLPConstraintInfo, value::Union{Number, Nothing})
if value !== nothing
info.upper_bound !== nothing && throw(ArgumentError("Upper bound has already been set"))
info.upper_bound = value
end
return
end

function set_bounds(info::NLPConstraintInfo, set::MOI.EqualTo)
set_lower_bound(info, set.value)
set_upper_bound(info, set.value)
end

function set_bounds(info::NLPConstraintInfo, set::MOI.GreaterThan)
set_lower_bound(info, set.lower)
end

function set_bounds(info::NLPConstraintInfo, set::MOI.LessThan)
set_upper_bound(info, set.upper)
end

function set_bounds(info::NLPConstraintInfo, set::MOI.Interval)
set_lower_bound(info, set.lower)
set_upper_bound(info, set.upper)
end

# Transforming NLconstraints in constraint sets used for affine functions creation in optimize!
function to_constraint_set(c::Xpress.NLPConstraintInfo)
if c.lower_bound !== nothing || c.upper_bound !== nothing
if c.upper_bound === nothing
return [MOI.GreaterThan(c.lower_bound)]
elseif c.lower_bound === nothing
return [MOI.LessThan(c.upper_bound)]
elseif c.lower_bound==c.upper_bound
return [MOI.EqualTo(c.lower_bound)]
else
return MOI.GreaterThan(c.lower_bound), MOI.LessThan(c.upper_bound)
end
end
end

# The problem is Nonlinear if a NLPBlockData has been defined
function is_nlp(model)
return model.nlp_block_data !== nothing
end

MOI.supports(::Optimizer, ::MOI.NLPBlockDual) = true

function MOI.get(model::Optimizer, attr::MOI.NLPBlockDual)
MOI.check_result_index_bounds(model, attr)
s = _dual_multiplier(model)
return s .*model.cached_solution.linear_dual[(1:length(model.nlp_constraint_info))]
end


1 change: 1 addition & 0 deletions src/api.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4964,3 +4964,4 @@ end
function _bo_validate(obranch, p_status)
@checked Lib.XPRS_bo_validate(obranch, p_status)
end

4 changes: 1 addition & 3 deletions src/common.jl
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,6 @@ const XPRS_DUALIZE = 8144
const XPRS_DUALGRADIENT = 8145
const XPRS_SBITERLIMIT = 8146
const XPRS_SBBEST = 8147
const XPRS_MAXCUTTIME = 8149 # kept for compatibility (removed in v41)
const XPRS_ACTIVESET = 8152 # kept for compatibility (removed in v41)
const XPRS_BARINDEFLIMIT = 8153
const XPRS_HEURSTRATEGY = 8154 # kept for compatibility (removed in v41)
Expand Down Expand Up @@ -297,7 +296,6 @@ const XPRS_TUNERMODE = 8359
const XPRS_TUNERMETHOD = 8360
const XPRS_TUNERTARGET = 8362
const XPRS_TUNERTHREADS = 8363
const XPRS_TUNERMAXTIME = 8364 # kept for compatibility (removed in v41)
const XPRS_TUNERHISTORY = 8365
const XPRS_TUNERPERMUTE = 8366
const XPRS_TUNERROOTALG = 8367 # kept for compatibility (removed in v41)
Expand Down Expand Up @@ -418,8 +416,8 @@ const XPRS_BRANCHVAR = 1036
const XPRS_MIPTHREADID = 1037
const XPRS_ALGORITHM = 1049
const XPRS_SOLSTATUS = 1053
const XPRS_TIME = 1122 # kept for compatibility (removed in v41)
const XPRS_ORIGINALROWS = 1124
const NLPORIGINALROWS = 1125
const XPRS_CALLBACKCOUNT_OPTNODE = 1136
const XPRS_CALLBACKCOUNT_CUTMGR = 1137
const XPRS_ORIGINALQELEMS = 1157
Expand Down
35 changes: 34 additions & 1 deletion src/helper.jl
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,7 @@ n_quadratic_elements(prob::XpressProblem) = @_invoke Lib.XPRSgetintattrib(prob,
n_quadratic_row_coefficients(prob::XpressProblem) = @_invoke Lib.XPRSgetintattrib(prob, Lib.XPRS_ORIGINALQCELEMS, _)::Int
n_entities(prob::XpressProblem) = @_invoke Lib.XPRSgetintattrib(prob, Lib.XPRS_ORIGINALMIPENTS, _)::Int
n_setmembers(prob::XpressProblem) = @_invoke Lib.XPRSgetintattrib(prob, Lib.XPRS_ORIGINALSETMEMBERS, _)::Int
n_nonlinear_coefs(prob::XpressProblem) = @_invoke Lib.XPRSgetintattrib(prob, Lib.XPRS_SLPCOEFFICIENTS, _)::Int

n_original_variables(prob::XpressProblem) = @_invoke Lib.XPRSgetintattrib(prob, Lib.XPRS_ORIGINALCOLS, _)::Int
n_original_constraints(prob::XpressProblem) = @_invoke Lib.XPRSgetintattrib(prob, Lib.XPRS_ORIGINALROWS, _)::Int
Expand All @@ -243,11 +244,17 @@ objective_sense(prob::XpressProblem) = obj_sense(prob) == Lib.XPRS_OBJ_MINIMIZE

# derived attribute functions

"""
n_nonlinear_constraints(prob::XpressProblem)
Return the number of nonlinear contraints in the XpressProblem
"""
n_nonlinear_constraints(prob::XpressProblem) = max(n_nonlinear_coefs(prob) - 1,0)

"""
n_linear_constraints(prob::XpressProblem)
Return the number of purely linear contraints in the XpressProblem
"""
n_linear_constraints(prob::XpressProblem) = n_constraints(prob) - n_quadratic_constraints(prob)
n_linear_constraints(prob::XpressProblem) =n_constraints(prob) - n_quadratic_constraints(prob)-n_nonlinear_constraints(prob)

"""
is_qcp(prob::XpressProblem)
Expand All @@ -261,6 +268,12 @@ Return `true` if there are integer entities in the XpressProblem
"""
is_mixedinteger(prob::XpressProblem) = (n_entities(prob) + n_special_ordered_sets(prob)) > 0

"""
is_nonlinear(prob::XpressProblem)
Return `true` if there are nonlinear strings in the XpressProblem
"""
is_nonlinear(prob::XpressProblem) = n_nonlinear_coefs(prob) > 0

"""
is_quadratic_objective(prob::XpressProblem)
Return `true` if there are quadratic terms in the objective in the XpressProblem
Expand All @@ -273,6 +286,7 @@ Return a symbol enconding the type of the problem.]
Options are: `:LP`, `:QP` and `:QCP`
"""
function problem_type(prob::XpressProblem)
is_nonlinear(prob) ? (:NLP) :
is_quadratic_constraints(prob) ? (:QCP) :
is_quadratic_objective(prob) ? (:QP) : (:LP)
end
Expand All @@ -293,12 +307,31 @@ function Base.show(io::IO, prob::XpressProblem)
println(io, " number of linear constraints = $(n_linear_constraints(prob))")
println(io, " number of quadratic constraints = $(n_quadratic_constraints(prob))")
println(io, " number of sos constraints = $(n_special_ordered_sets(prob))")
println(io, " number of nonlinear constraints = $(n_nonlinear_constraints(prob))")
println(io, " number of non-zero coeffs = $(n_non_zero_elements(prob))")
println(io, " number of non-zero qp objective terms = $(n_quadratic_elements(prob))")
println(io, " number of non-zero qp constraint terms = $(n_quadratic_row_coefficients(prob))")
println(io, " number of integer entities = $(n_entities(prob))")
end

const NLPSTATUS_STRING = Dict{Int,String}(
Lib.XPRS_NLPSTATUS_UNSTARTED => "0 Unstarted ( XPRS_NLPSTATUS_UNSTARTED).",
Lib.XPRS_NLPSTATUS_SOLUTION => "1 Global search incomplete - an integer solution has been found ( XPRS_NLPSTATUS_SOLUTION).",
Lib.XPRS_NLPSTATUS_OPTIMAL => "2 Optimal ( XPRS_NLPSTATUS_OPTIMAL).",
Lib.XPRS_NLPSTATUS_NOSOLUTION => "3 Global search complete - No solution found ( XPRS_NLPSTATUS_NOSOLUTION).",
Lib.XPRS_NLPSTATUS_INFEASIBLE => "4 Infeasible ( XPRS_NLPSTATUS_INFEASIBLE).",
Lib.XPRS_NLPSTATUS_UNBOUNDED => "5 Unbounded ( XPRS_NLPSTATUS_UNBOUNDED).",
Lib.XPRS_NLPSTATUS_UNFINISHED => "6 Unfinished ( XPRS_NLPSTATUS_UNFINISHED).",
Lib.XPRS_NLPSTATUS_UNSOLVED => "7 Problem could not be solved due to numerical issues. ( XPRS_NLPSTATUS_UNSOLVED).",
)

function nlp_solve_complete(stat)
stat in [Lib.XPRS_NLPSTATUS_INFEASIBLE, Lib.XPRS_NLPSTATUS_OPTIMAL]
end
function nlp_solve_stopped(stat)
stat in [Lib.XPRS_NLPSTATUS_INFEASIBLE, Lib.XPRS_NLPSTATUS_OPTIMAL]
end

const MIPSTATUS_STRING = Dict{Int,String}(
Lib.XPRS_MIP_NOT_LOADED => "0 Problem has not been loaded ( XPRS_MIP_NOT_LOADED).",
Lib.XPRS_MIP_LP_NOT_OPTIMAL => "1 Global search incomplete - the initial continuous relaxation has not been solved and no integer solution has been found ( XPRS_MIP_LP_NOT_OPTIMAL).",
Expand Down
9 changes: 9 additions & 0 deletions src/lib.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2419,3 +2419,12 @@ end
function XPRSremovecbgloballog(prob, globallog, data)
ccall((:XPRSremovecbgloballog, libxprs), Cint, (XPRSprob, Ptr{Cvoid}, Ptr{Cvoid}), prob, globallog, data)
end

function XSLPcreateprob(prob, _probholder)
ccall((:XSLPcreateprob, libxprs), Cint, (XPRSprob, Ptr{XPRSprob},), prob, _probholder)
end

function XSLPinit()
ccall((:XSLPinit, libxprs), Cint, ())
end

2 changes: 1 addition & 1 deletion src/utils.jl
Original file line number Diff line number Diff line change
Expand Up @@ -144,4 +144,4 @@ function _check(prob, val::Cint)
throw(XpressError(val, "Xpress internal error:\n\n$e.\n"))
end
return nothing
end
end
6 changes: 3 additions & 3 deletions test/MathOptInterface/MOI_callbacks.jl
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ const MOI = MathOptInterface

function callback_simple_model()
model = Xpress.Optimizer(
HEURSTRATEGY = 0, # before v41
HEURSTRATEGY = 0,
HEUREMPHASIS = 0,
OUTPUTLOG = 0,
OUTPUTLOG = 0
)

MOI.Utilities.loadfromstring!(model, """
Expand All @@ -28,7 +28,7 @@ end
function callback_knapsack_model()
model = Xpress.Optimizer(
OUTPUTLOG = 0,
HEURSTRATEGY = 0, # before v41
HEURSTRATEGY = 0,
HEUREMPHASIS = 0,
CUTSTRATEGY = 0,
PRESOLVE = 0,
Expand Down
Loading