1/* BEGIN LICENSE BLOCK 2 * Version: CMPL 1.1 3 * 4 * The contents of this file are subject to the Cisco-style Mozilla Public 5 * License Version 1.1 (the "License"); you may not use this file except 6 * in compliance with the License. You may obtain a copy of the License 7 * at www.eclipse-clp.org/license. 8 * 9 * Software distributed under the License is distributed on an "AS IS" 10 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See 11 * the License for the specific language governing rights and limitations 12 * under the License. 13 * 14 * The Original Code is The ECLiPSe Constraint Logic Programming System. 15 * The Initial Developer of the Original Code is Cisco Systems, Inc. 16 * Portions created by the Initial Developer are 17 * Copyright (C) 1995-2012 Cisco Systems, Inc. All Rights Reserved. 18 * 19 * Contributor(s): Joachim Schimpf, Kish Shen and Andrew Eremin, IC-Parc 20 * 21 * END LICENSE BLOCK */ 22 23/* 24 * ECLiPSe/CPLEX interface (for inclusion in eplex.c) 25 */ 26 27/* Hack needed for Cplex 12.3: to select the correct definitions, pretend to be the MSC compiler. */ 28#if defined(_WIN32) && !defined(_MSC_VER) /* Note that _WIN32 is also defined for _WIN_64 */ 29#define _MSC_VER 30#include "cplex.h" /* CPLEX declarations */ 31#undef _MSC_VER 32#else 33#include "cplex.h" /* CPLEX declarations */ 34#endif 35 36/* The values CPX_VERSION_VERSION and CPX_VERSION_RELEASE were introduced in CPLEX 12.3. 37 * For earlier versions, we compute them from the 4-digit CPX_VERSION. 38 */ 39#ifndef CPX_VERSION_VERSION 40#define CPX_VERSION_VERSION (CPX_VERSION/100) 41#endif 42#ifndef CPX_VERSION_RELEASE 43#define CPX_VERSION_RELEASE ((CPX_VERSION/10)%10) 44#endif 45 46#if (CPLEX == 0) 47#define CPLEX CPX_VERSION_VERSION 48#elif (CPLEX != CPX_VERSION_VERSION) 49Version mismatch! 50#endif 51 52#ifndef CPLEXMINOR 53#define CPLEXMINOR CPX_VERSION_RELEASE 54#elif (CPLEXMINOR != CPX_VERSION_RELEASE) 55Version mismatch! 56#endif 57 58#ifndef CPXPUBLIC 59#define CPXPUBLIC 60#endif 61 62typedef int param_id_t; 63typedef char sostype_t; 64 65#include "eplex.h" /* needs declarations above! */ 66 67 68#define SOLVER_SHORT_NAME CPX 69#define SOLVER_ATOMIC_NAME "cplex" 70#define SOLVER_VERSION_INT (10*CPLEX+CPLEXMINOR) 71#define SOLVER_HAS_STR_PARAMS 72#define STRBUFFERSIZE CPX_STR_PARAM_MAX /* size of string parameter buffer size */ 73 74 75#define SOLVER_SENSE_LE 'L' 76#define SOLVER_SENSE_GE 'G' 77#define SOLVER_SENSE_EQ 'E' 78 79#define SOLVER_SOS_TYPE1 '1' 80#define SOLVER_SOS_TYPE2 '2' 81 82# define CPX_COL_AT_LOWER CPX_AT_LOWER 83# define CPX_COL_AT_UPPER CPX_AT_UPPER 84# define CPX_COL_BASIC CPX_BASIC 85# define CPX_COL_FREE_SUPER CPX_FREE_SUPER 86/* next two not tested */ 87# define CPX_COL_NONBASIC_ZERO_BOUNDED CPX_COL_AT_LOWER 88# define CPX_COL_NONBASIC_ZERO_UNBOUNDED CPX_COL_FREE_SUPER 89 90#define SUPPORT_IIS 91 92#if CPLEX >= 9 93#define HAS_CONCURRENT 94#endif 95 96#if CPLEX >= 12 97#define HAS_INDICATOR_CONSTRAINTS 98#endif 99 100#if CPLEX >= 10 101/* CPLEX 10+ has more generic error for no solution state and the more general conflict set 102 rather than IIS (which is for LP only) for infeasible analyses 103*/ 104# define CPXERR_NO_INT_SOLN CPXERR_NO_SOLN 105 106# define HAS_GENERAL_CONFLICT_REFINER 107 108# define Find_Conflict(Res, L, NRows, NCols) Res = CPXrefineconflict(cpx_env, L, &(NRows), &(NCols)) 109 110# define Get_Conflict(L, Status, RowIdxs, RowStat, NRows_p, ColIdxs, ColStat, NCols_p) \ 111 CPXgetconflict(cpx_env, L, &(Status), RowIdxs, RowStat, NRows_p, ColIdxs, ColStat, NCols_p) 112 113#else 114 115/* mapping the calls to find a conflict set to the older and less general routines (LP only) to get 116 the IIS 117*/ 118# define Find_Conflict(Res, L, NRows, NCols) Res = CPXfindiis(cpx_env, L, &(NRows), &(NCols)) 119 120# define Get_Conflict(L, Status, RowIdxs, RowStat, NRows_p, ColIdxs, ColStat, NCols_p) \ 121 CPXgetiis(cpx_env, L, &(Status), RowIdxs, RowStat, NRows_p, ColIdxs, ColStat, NCols_p) 122 123# define CPX_CONFLICT_LB CPXIIS_AT_LOWER 124# define CPX_CONFLICT_UB CPXIIS_AT_UPPER 125# define CPX_STAT_CONFLICT_MINIMAL CPXIIS_COMPLETE 126 127#endif 128 129#if CPLEX >= 7 130# define CPX_HAS_LPOPT 131#endif 132 133#if CPLEX < 9 134/* CPLEX 8 and older has no valid bestobjval for an optimal MIP solution! 135 cutoff 136*/ 137# define NO_MIPBESTBOUND_IF_OPTIMAL 138#endif 139 140#if (CPLEX >= 8) 141 142/* uniform treatment of solution status (independent of primal/dual) */ 143# define UNIFORM_SOL_STAT 144# define HAS_SIFT 145# define CPX_HAS_DEFAULTALG /* has way of specifying `default' method without 146 naming method, for all LP/MIP/QP */ 147# define HAS_MIQP 148 149# define SetCPXAlg(cpx_env, method) { \ 150 CPXsetintparam(cpx_env, CPX_PARAM_LPMETHOD, method);\ 151 CPXsetintparam(cpx_env, CPX_PARAM_STARTALG, method);\ 152 if (method != CPX_ALG_SIFTING) \ 153 CPXsetintparam(cpx_env, CPX_PARAM_QPMETHOD, method);\ 154 else \ 155 CPXsetintparam(cpx_env, CPX_PARAM_QPMETHOD, CPX_ALG_AUTOMATIC);\ 156} 157 158# define SetSiftAlg(cpx_env, meth) { \ 159 switch (meth) \ 160 { \ 161 case METHOD_AUTO: \ 162 CPXsetintparam(cpx_env, CPX_PARAM_SIFTALG, CPX_ALG_AUTOMATIC); \ 163 break; \ 164 case METHOD_PRIMAL: \ 165 CPXsetintparam(cpx_env, CPX_PARAM_SIFTALG, CPX_ALG_PRIMAL); \ 166 break; \ 167 case METHOD_DUAL: \ 168 CPXsetintparam(cpx_env, CPX_PARAM_SIFTALG, CPX_ALG_DUAL); \ 169 break; \ 170 case METHOD_BAR: \ 171 CPXsetintparam(cpx_env, CPX_PARAM_SIFTALG, CPX_ALG_BARRIER); \ 172 break; \ 173 case METHOD_NET: \ 174 CPXsetintparam(cpx_env, CPX_PARAM_SIFTALG, CPX_ALG_NET); \ 175 break; \ 176 default: \ 177 /* use error stream as warning stream unavailable */ \ 178 Fprintf(Current_Error, "Eplex warning: aux. method chosen for" \ 179 " sifting is unavailable. Using default instead\n"); \ 180 ec_flush(Current_Error); \ 181 meth = METHOD_DEFAULT; \ 182 case METHOD_DEFAULT: \ 183 break; \ 184 } \ 185} 186 187#else /* CPLX < 8 */ 188 189/* pre-CPLEX 8 names */ 190# define CPXPROB_MILP CPXPROB_MIP 191# define CPXPROB_FIXEDMILP CPXPROB_FIXED 192 193# define CPX_STAT_OPTIMAL CPX_OPTIMAL 194# define CPX_STAT_INFEASIBLE CPX_INFEASIBLE 195# define CPX_STAT_OPTIMAL_INFEAS CPX_OPTIMAL_INFEAS 196# define CPX_STAT_UNBOUNDED CPX_UNBOUNDED 197# define CPX_STAT_INForUNBD CPX_INForUNBD 198# define CPX_STAT_OPTIMAL_FACE_UNBOUNDED CPX_OPTIMAL_FACE_UNBOUNDED 199 200# define CPXqpopt(A,B) CPXbaropt(A,B) /* no CPXqpopt() */ 201 202/* DualMethod(lpd,m,am) should be true for methods that require different 203 * interpretation of the optimization result code */ 204 205# define DualMethod(lpd,m,am) \ 206 (((lpd)->prob_type == PROBLEM_LP || (lpd)->prob_type == PROBLEM_RELAXEDL) && \ 207 ((m) == METHOD_DUAL || ((m) == METHOD_NET && (am) == METHOD_DUAL)) ) 208 209# define CPX_HAS_RELAXEDLP 210 211# if (CPLEX >= 7) /* CPLEX 7 only */ 212 213# define SetCPXAlg(cpx_env, method) { \ 214 CPXsetintparam(cpx_env, CPX_PARAM_LPMETHOD, method);\ 215 CPXsetintparam(cpx_env, CPX_PARAM_STARTALG, method);\ 216} 217 218# elif (CPLEX >= 6) /* CPLEX 6 only */ 219 220# define CPX_ALG_NET CPX_NODEALG_HYBNETOPT 221 222# define HAS_NO_BARCROSSOVER /* does not have `no crossover' for barrier */ 223 224# define SetCPXAlg(cpx_env, method) { \ 225 CPXsetintparam(cpx_env, CPX_PARAM_STARTALG, method);\ 226} 227 228# endif 229 230#endif /* CPLEX >= 8 */ 231 232#if CPLEX > 12 || (CPLEX == 12 && CPLEXMINOR >= 3) 233#define IfAtLeast123(X) (X) 234#else 235#define IfAtLeast123(X) 0 236#endif 237 238#define SuccessState(d) ( \ 239 (d)->sol_state == CPX_STAT_OPTIMAL || \ 240 (d)->sol_state == CPX_STAT_OPTIMAL_INFEAS || \ 241 (d)->sol_state == CPX_STAT_OPTIMAL_FACE_UNBOUNDED || \ 242 IfAtLeast123((d)->sol_state == CPX_STAT_FIRSTORDER) || \ 243 MIPSuccessState(d)) 244 245#define MIPSuccessState(d) ( \ 246 (d)->sol_state == CPXMIP_OPTIMAL || \ 247 (d)->sol_state == CPXMIP_OPTIMAL_TOL || \ 248 (d)->sol_state == CPXMIP_OPTIMAL_INFEAS) 249 250#define FailState(d) ( \ 251 (d)->sol_state == CPX_STAT_INFEASIBLE || \ 252 (d)->sol_state == CPXMIP_INFEASIBLE) 253 254#if CPLEX >= 8 255#define UnboundedState(d) ( \ 256 (d)->sol_state == CPX_STAT_UNBOUNDED || \ 257 (d)->sol_state == CPXMIP_UNBOUNDED) 258 259#define MaybeFailState(d) ( \ 260 (d)->sol_state == CPX_STAT_INForUNBD || \ 261 (d)->sol_state == CPXMIP_INForUNBD || \ 262 (d)->sol_state == CPXERR_PRESLV_INForUNBD ) 263 264#define LPAbortedState(d) ( \ 265 (d)->sol_state == CPX_STAT_ABORT_IT_LIM || \ 266 (d)->sol_state == CPX_STAT_ABORT_TIME_LIM || \ 267 IfAtLeast123((d)->sol_state == CPX_STAT_ABORT_DETTIME_LIM) || \ 268 (d)->sol_state == CPX_STAT_ABORT_OBJ_LIM || \ 269 (d)->sol_state == CPX_STAT_ABORT_USER || \ 270 (d)->sol_state == CPX_STAT_NUM_BEST || \ 271 (d)->sol_state == CPX_STAT_ABORT_PRIM_OBJ_LIM || \ 272 (d)->sol_state == CPX_STAT_ABORT_DUAL_OBJ_LIM ) 273 274#else 275 276/* aborted with no feasible (primal/dual) solution */ 277#define LPAbortedNoSolState(d) ( \ 278 (d)->sol_state == CPX_IT_LIM_INFEAS || \ 279 (d)->sol_state == CPX_TIME_LIM_INFEAS || \ 280 (d)->sol_state == CPX_NUM_BEST_INFEAS || \ 281 (d)->sol_state == CPX_ABORT_INFEAS ) 282 283/* aborted with feasible solution */ 284#define LPAbortedSolState(d) ( \ 285 (d)->sol_state == CPX_OBJ_LIM || \ 286 (d)->sol_state == CPX_IT_LIM_FEAS || \ 287 (d)->sol_state == CPX_TIME_LIM_FEAS || \ 288 (d)->sol_state == CPX_NUM_BEST_FEAS || \ 289 (d)->sol_state == CPX_NUM_BEST_PRIM_DUAL_FEAS || \ 290 (d)->sol_state == CPX_ABORT_FEAS ) 291 292#define LPAbortedState(d) ( \ 293 LPAbortedSolState(d) || LPAbortedNoSolState(d) ) 294 295#define UnboundedState(d) ( \ 296 (d)->sol_state == CPX_STAT_UNBOUNDED ) 297 298#if CPLEX > 6 || ( CPLEX == 6 && CPLEXMINOR > 0 ) 299#define MaybeFailState(d) ( \ 300 (d)->sol_state == CPX_STAT_INForUNBD || \ 301 (d)->sol_state == CPXERR_PRESLV_INForUNBD ) 302#else 303#define MaybeFailState(d) 0 304#endif 305 306#endif 307 308#if CPLEX >= 7 309# define MIPSemiFailState(d) ( \ 310 (d)->sol_state == CPXMIP_NODE_LIM_INFEAS || \ 311 (d)->sol_state == CPXMIP_TIME_LIM_INFEAS || \ 312 IfAtLeast123((d)->sol_state == CPXMIP_DETTIME_LIM_INFEAS) || \ 313 (d)->sol_state == CPXMIP_FAIL_INFEAS || \ 314 (d)->sol_state == CPXMIP_MEM_LIM_INFEAS || \ 315 (d)->sol_state == CPXMIP_ABORT_INFEAS || \ 316 (d)->sol_state == CPXMIP_FAIL_INFEAS_NO_TREE) 317 318# define MIPSemiSuccessState(d) ( \ 319 (d)->sol_state == CPXMIP_SOL_LIM || \ 320 (d)->sol_state == CPXMIP_NODE_LIM_FEAS || \ 321 (d)->sol_state == CPXMIP_TIME_LIM_FEAS || \ 322 IfAtLeast123((d)->sol_state == CPXMIP_DETTIME_LIM_FEAS) || \ 323 (d)->sol_state == CPXMIP_FAIL_FEAS || \ 324 (d)->sol_state == CPXMIP_MEM_LIM_FEAS || \ 325 (d)->sol_state == CPXMIP_ABORT_FEAS || \ 326 (d)->sol_state == CPXMIP_FAIL_FEAS_NO_TREE) 327#else 328# define MIPSemiFailState(d) ( \ 329 (d)->sol_state == CPXMIP_NODE_LIM_INFEAS || \ 330 (d)->sol_state == CPXMIP_TIME_LIM_INFEAS || \ 331 (d)->sol_state == CPXMIP_FAIL_INFEAS || \ 332 (d)->sol_state == CPXMIP_MEM_LIM_INFEAS || \ 333 (d)->sol_state == CPXMIP_ABORT_INFEAS || \ 334 (d)->sol_state == CPXMIP_FAIL_INFEAS_NO_TREE || \ 335 (d)->sol_state == CPXMIP_NODE_FILE_LIM_INFEAS) 336 337# define MIPSemiSuccessState(d) ( \ 338 (d)->sol_state == CPXMIP_SOL_LIM || \ 339 (d)->sol_state == CPXMIP_NODE_LIM_FEAS || \ 340 (d)->sol_state == CPXMIP_TIME_LIM_FEAS || \ 341 (d)->sol_state == CPXMIP_FAIL_FEAS || \ 342 (d)->sol_state == CPXMIP_MEM_LIM_FEAS || \ 343 (d)->sol_state == CPXMIP_ABORT_FEAS || \ 344 (d)->sol_state == CPXMIP_FAIL_FEAS_NO_TREE || \ 345 (d)->sol_state == CPXMIP_NODE_FILE_LIM_FEAS) 346#endif 347 348 349#define SetPreSolve(state) \ 350{\ 351 Log1(CPXsetintparam(cpx_env, CPX_PARAM_PREIND, %d), state); \ 352 CPXsetintparam(cpx_env, CPX_PARAM_PREIND, state); \ 353} 354 355#define CPXupdatemodel(LP) 356 357#define Get_Feasibility_Tolerance(E,L,T) CPXgetdblparam(E,CPX_PARAM_EPRHS,T) 358 359#define Get_Int_Param(E,L,A1,A2) CPXgetintparam(E,A1,A2) 360#define Get_Dbl_Param(E,L,A1,A2) CPXgetdblparam(E,A1,A2) 361#define Get_Str_Param(E,L,A1,A2) CPXgetstrparam(E,A1,A2) 362#define Set_Int_Param(E,L,A1,A2) CPXsetintparam(E,A1,A2) 363#define Set_Dbl_Param(E,L,A1,A2) CPXsetdblparam(E,A1,A2) 364#define Set_Str_Param(E,L,A1,A2) CPXsetstrparam(E,A1,A2) 365 366# define Get_LP_Objval(A1,A2) CPXgetobjval(cpx_env,(A1)->lp,A2) 367# define Get_Best_Objbound(A1, A2) CPXgetbestobjval(cpx_env,A1,A2) 368 369#define Get_MIPCutOff(d, v) \ 370 ((d)->sense == SENSE_MIN ? CPXgetdblparam(cpx_env, CPX_PARAM_CUTUP, v) : CPXgetdblparam(cpx_env, CPX_PARAM_CUTLO, v)) 371 372#define UsingBarrierNoCrossOver(d) (CPXgetmethod(cpx_env, (d)) == CPX_ALG_BARRIER) 373#define Get_Bar_Primal_Obj(d, obj) CPXgetdblquality(cpx_env, (d), obj, CPX_PRIMAL_OBJ) 374#define Get_Bar_Dual_Obj(d, obj) CPXgetdblquality(cpx_env, (d), obj, CPX_DUAL_OBJ) 375 376#define HAS_QUADRATIC 377#define SOLVER_MAT_BASE 0 378#define SOLVER_MAT_OFFSET 1 379 380#define HAS_LIMITED_MIP_RESULTS 381