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