@@ -2907,13 +2907,33 @@ function MOI.optimize!(model::Optimizer)
2907
2907
_set_MIP_start (model)
2908
2908
end
2909
2909
start_time = time ()
2910
- if model. has_nlp_constraints
2911
- @checked Lib. XPRSnlpoptimize (model. inner, model. solve_method)
2912
- elseif is_mip (model)
2913
- @checked Lib. XPRSmipoptimize (model. inner, model. solve_method)
2910
+
2911
+ version = getversion ()
2912
+ # Verson 41.01 introduces XPRSoptimize as a more general optimization routine,
2913
+ # automatically selecting the algorithm based on the presence of mip entities and
2914
+ # nonlinear constraints
2915
+ if version >= v " 41.01"
2916
+ solvestatus = Ref {Int32} ()
2917
+ solstatus = Ref {Int32} ()
2918
+ @checked Lib. XPRSoptimize (
2919
+ model. inner,
2920
+ model. solve_method,
2921
+ solvestatus,
2922
+ solstatus,
2923
+ )
2924
+ opt_used = getattribute (model. inner, " XPRS_OPTIMIZETYPEUSED" )
2925
+ # 0: LP solver, 1: MIP solver, 2: Local nonlinear solver, 3: Global nonlinear solver
2926
+ model. has_nlp_constraints = (opt_used == 2 || opt_used == 3 )
2914
2927
else
2915
- @checked Lib. XPRSlpoptimize (model. inner, model. solve_method)
2928
+ if model. has_nlp_constraints
2929
+ @checked Lib. XPRSnlpoptimize (model. inner, model. solve_method)
2930
+ elseif is_mip (model)
2931
+ @checked Lib. XPRSmipoptimize (model. inner, model. solve_method)
2932
+ else
2933
+ @checked Lib. XPRSlpoptimize (model. inner, model. solve_method)
2934
+ end
2916
2935
end
2936
+
2917
2937
model. cached_solution. solve_time = time () - start_time
2918
2938
check_cb_exception (model)
2919
2939
# Should be almost a no-op if not needed. Might have minor overhead due to
@@ -2924,33 +2944,81 @@ function MOI.optimize!(model::Optimizer)
2924
2944
model. termination_status = _cache_termination_status (model)
2925
2945
model. primal_status = _cache_primal_status (model)
2926
2946
model. dual_status = _cache_dual_status (model)
2927
- # TODO : add @checked here - must review statuses
2928
- if model. has_nlp_constraints
2929
- Lib. XPRSgetnlpsol (
2947
+
2948
+ # XPRSgetnlpsol and XPRSgetmippsol are deprecated as of version 44.01
2949
+ # XPRSgetsolution is also recommended instead of XPRSgetlpsol also after solving LPs
2950
+ if version >= v " 44.01"
2951
+ sol_status = Ref {Int32} ()
2952
+ ncols = getattribute (model. inner, " XPRS_INPUTCOLS" )
2953
+ @checked Lib. XPRSgetsolution (
2930
2954
model. inner,
2955
+ sol_status,
2931
2956
model. cached_solution. variable_primal,
2932
- model. cached_solution. linear_primal,
2933
- model. cached_solution. linear_dual,
2934
- model. cached_solution. variable_dual,
2957
+ 0 ,
2958
+ ncols - 1 ,
2935
2959
)
2936
- elseif is_mip (model )
2937
- # TODO @checked (only works if not in [MOI.NO_SOLUTION, MOI.INFEASIBILITY_CERTIFICATE, MOI.INFEASIBLE_POINT] )
2938
- Lib. XPRSgetmipsol (
2960
+ slack_status = Ref {Int32} ( )
2961
+ nrows = getattribute (model . inner, " XPRS_INPUTROWS " )
2962
+ @checked Lib. XPRSgetslacks (
2939
2963
model. inner,
2940
- model . cached_solution . variable_primal ,
2964
+ slack_status ,
2941
2965
model. cached_solution. linear_primal,
2966
+ 0 ,
2967
+ nrows - 1 ,
2942
2968
)
2943
- fill! (model. cached_solution. linear_dual, NaN )
2944
- fill! (model. cached_solution. variable_dual, NaN )
2945
- else
2946
- Lib. XPRSgetlpsol (
2969
+ dual_status = Ref {Int32} ()
2970
+ @checked Lib. XPRSgetduals (
2947
2971
model. inner,
2948
- model. cached_solution. variable_primal,
2949
- model. cached_solution. linear_primal,
2972
+ dual_status,
2950
2973
model. cached_solution. linear_dual,
2974
+ 0 ,
2975
+ nrows - 1 ,
2976
+ )
2977
+ # Check if dual values are not available (MIP or global solves)
2978
+ if dual_status[] == Lib. XPRS_SOLSTATUS_NOTFOUND
2979
+ fill! (model. cached_solution. linear_dual, NaN )
2980
+ end
2981
+ redcost_status = Ref {Int32} ()
2982
+ @checked Lib. XPRSgetredcosts (
2983
+ model. inner,
2984
+ redcost_status,
2951
2985
model. cached_solution. variable_dual,
2986
+ 0 ,
2987
+ ncols - 1 ,
2952
2988
)
2989
+ if redcost_status[] == Lib. XPRS_SOLSTATUS_NOTFOUND
2990
+ fill! (model. cached_solution. variable_dual, NaN )
2991
+ end
2992
+ else
2993
+ # TODO : add @checked here - must review statuses
2994
+ if model. has_nlp_constraints
2995
+ Lib. XPRSgetnlpsol (
2996
+ model. inner,
2997
+ model. cached_solution. variable_primal,
2998
+ model. cached_solution. linear_primal,
2999
+ model. cached_solution. linear_dual,
3000
+ model. cached_solution. variable_dual,
3001
+ )
3002
+ elseif is_mip (model)
3003
+ # TODO @checked (only works if not in [MOI.NO_SOLUTION, MOI.INFEASIBILITY_CERTIFICATE, MOI.INFEASIBLE_POINT])
3004
+ Lib. XPRSgetmipsol (
3005
+ model. inner,
3006
+ model. cached_solution. variable_primal,
3007
+ model. cached_solution. linear_primal,
3008
+ )
3009
+ fill! (model. cached_solution. linear_dual, NaN )
3010
+ fill! (model. cached_solution. variable_dual, NaN )
3011
+ else
3012
+ Lib. XPRSgetlpsol (
3013
+ model. inner,
3014
+ model. cached_solution. variable_primal,
3015
+ model. cached_solution. linear_primal,
3016
+ model. cached_solution. linear_dual,
3017
+ model. cached_solution. variable_dual,
3018
+ )
3019
+ end
2953
3020
end
3021
+
2954
3022
model. cached_solution. linear_primal .=
2955
3023
rhs .- model. cached_solution. linear_primal
2956
3024
status = MOI. get (model, MOI. PrimalStatus ())
0 commit comments