1 /****************************************************************************/
2 /*                                                                          */
3 /*  This file is part of CONCORDE                                           */
4 /*                                                                          */
5 /*  (c) Copyright 1995--1999 by David Applegate, Robert Bixby,              */
6 /*  Vasek Chvatal, and William Cook                                         */
7 /*                                                                          */
8 /*  Permission is granted for academic research use.  For other uses,       */
9 /*  contact the authors for licensing options.                              */
10 /*                                                                          */
11 /*  Use at your own risk.  We make no guarantees about the                  */
12 /*  correctness or usefulness of this code.                                 */
13 /*                                                                          */
14 /****************************************************************************/
15 
16 /****************************************************************************/
17 /*                                                                          */
18 /*              Interface Routines to The CPLEX 6.0-7.0 LP Solvers          */
19 /*                                                                          */
20 /*  NOTE: Use this code in place of lp_none.c to access the Cplex 6.0-7.0   */
21 /*   libraries. You will also need to link the cplex library via the        */
22 /*   makefile.                                                              */
23 /*                                                                          */
24 /*                                                                          */
25 /*  Written by:  Applegate, Bixby, Chvatal, and Cook                        */
26 /*  Date: April 17, 1997                                                    */
27 /*        June 19, 1997 (bico, REB)                                         */
28 /*                                                                          */
29 /*  See the start of the file lp_none.c for a description of the            */
30 /*  functions exported by this file.                                        */
31 /*                                                                          */
32 /*                                                                          */
33 /*  NOTES:                                                                  */
34 /*                                                                          */
35 /****************************************************************************/
36 
37 
38 #include "machdefs.h"
39 #include "util.h"
40 #include "macrorus.h"
41 #include "lp.h"
42 #include <cplex.h>
43 
44 #undef  CC_CPLEX_DISPLAY
45 
46 #define CC_ONE_ENV
47 
48 #ifdef CC_ONE_ENV
49 static CPXENVptr CClp_cplex_env = (CPXENVptr) NULL;
50 static int CClp_env_count = 0;
51 
52 typedef struct CClp_parameters {
53     int    scrind;
54     int    simdisplay;
55     int    fastmip;
56     int    advind;
57     int    dpriind;
58     int    ppriind;
59     double epper;
60     double epopt;
61     double eprhs;
62     int perind;
63     int preind;
64     int aggind;
65 } CClp_parameters;
66 #endif
67 
68 struct CClp {
69     CPXENVptr cplex_env;
70     CPXLPptr  cplex_lp;
71 #ifdef CC_ONE_ENV
72     CClp_parameters cplex_params;
73 #endif
74 };
75 
76 struct CClp_warmstart {
77     int      rcount;
78     int      ccount;
79     int     *rstat;
80     int     *cstat;
81     double  *dnorm;
82 };
83 
84 struct CClp_info {
85     int  rcount;
86     int  ccount;
87     int *rstat;
88     int *cstat;
89 };
90 
91 #define SOLVER_WARMSTART_NAME "CPL5"
92 
93 
94 static int
95     primalopt (CClp *lp),
96     dualopt (CClp *lp),
97     baropt (CClp *lp),
98     getfarkasmultipliers (CClp *lp, double *y);
99 
100 #ifdef CC_ONE_ENV
101 static int
102     set_parameters (CPXENVptr cplex_env, CClp_parameters *params);
103 #endif
104 
105 
CClp_init(CClp ** lp)106 int CClp_init (CClp **lp)
107 {
108     int rval = 0;
109 
110     CClp_free (lp);
111 
112     (*lp) = CC_SAFE_MALLOC (1, CClp);
113     if ((*lp) == (CClp *) NULL) {
114         fprintf (stderr, "Out of memory in CClp_init\n");
115         rval = 1; goto CLEANUP;
116     }
117 
118     (*lp)->cplex_env = (CPXENVptr) NULL;
119     (*lp)->cplex_lp = (CPXLPptr) NULL;
120 
121 #ifdef CC_ONE_ENV
122     if (CClp_cplex_env == (CPXENVptr) NULL) {
123         CClp_cplex_env = CPXopenCPLEX (&rval);
124         if (rval) {
125             fprintf (stderr, "CPXopenCPLEX failed, return code %d\n", rval);
126             goto CLEANUP;
127         }
128         CClp_env_count = 0;
129     }
130     (*lp)->cplex_env = CClp_cplex_env;
131     CClp_env_count++;
132 #else /* CC_ONE_ENV */
133     (*lp)->cplex_env = CPXopenCPLEX (&rval);
134     if (rval) {
135         fprintf (stderr, "CPXopenCPLEX failed, return code %d\n", rval);
136         goto CLEANUP;
137     }
138 #endif /* CC_ONE_ENV */
139 
140 #ifdef CC_ONE_ENV
141 #ifdef CC_CPLEX_DISPLAY
142     (*lp)->cplex_params.scrind = 1;
143     (*lp)->cplex_params.simdisplay = 1;
144 #else
145     (*lp)->cplex_params.scrind = 0;
146     (*lp)->cplex_params.simdisplay = 0;
147 #endif
148     (*lp)->cplex_params.fastmip = 1;
149     (*lp)->cplex_params.advind = 1;
150     (*lp)->cplex_params.dpriind = CPX_DPRIIND_STEEP;
151     (*lp)->cplex_params.ppriind = CPX_PPRIIND_STEEP;
152     (*lp)->cplex_params.epper = 1.0E-6;
153     (*lp)->cplex_params.epopt = 1.0E-9;
154     (*lp)->cplex_params.eprhs = 1.0E-9;
155 
156     (*lp)->cplex_params.perind = 0;
157     (*lp)->cplex_params.preind = 1;
158     (*lp)->cplex_params.aggind = 1;
159 
160 #else /* CC_ONE_ENV */
161 
162 #ifdef CC_CPLEX_DISPLAY
163     /* the documentation doesn't say what the return value means */
164     rval = CPXsetintparam ((*lp)->cplex_env, CPX_PARAM_SCRIND, 1);
165     if (rval) {
166         fprintf (stderr, "CPXsetintparam CPX_PARAM_SCRIND failed\n");
167         goto CLEANUP;
168     }
169 
170     rval = CPXsetintparam ((*lp)->cplex_env, CPX_PARAM_SIMDISPLAY, 1);
171     if (rval) {
172         fprintf (stderr, "CPXsetintparam CPX_PARAM_SIMDISPLAY failed\n");
173         goto CLEANUP;
174     }
175 #endif
176 
177     rval = CPXsetintparam ((*lp)->cplex_env, CPX_PARAM_FASTMIP, 1);
178     if (rval) {
179         fprintf (stderr, "CPXsetintparam CPX_PARAM_FASTMIP failed\n");
180         goto CLEANUP;
181     }
182 
183     rval = CPXsetintparam ((*lp)->cplex_env, CPX_PARAM_ADVIND, 1);
184     if (rval) {
185         fprintf (stderr, "CPXsetintparam CPX_PARAM_ADVIND failed\n");
186         goto CLEANUP;
187     }
188     rval = CPXsetintparam ((*lp)->cplex_env, CPX_PARAM_DPRIIND,
189                            CPX_DPRIIND_STEEP);
190     if (rval) {
191         fprintf (stderr, "CPXsetintparam CPX_PARAM_DPRIIND failed\n");
192         goto CLEANUP;
193     }
194     rval = CPXsetintparam ((*lp)->cplex_env, CPX_PARAM_PPRIIND,
195                            CPX_PPRIIND_STEEP);
196     if (rval) {
197         fprintf (stderr, "CPXsetintparam CPX_PARAM_PPRIIND failed\n");
198         goto CLEANUP;
199     }
200 
201     /* REB, 14 October 1997:  The following three parameter settings
202        help fl3795 a bunch, and are probably not a bad idea in general */
203 
204     rval = CPXsetdblparam ((*lp)->cplex_env, CPX_PARAM_EPPER, 1.0E-6);
205     if (rval) {
206         fprintf (stderr, "CPXsetdblparam CPX_PARAM_EPPER failed\n");
207         goto CLEANUP;
208     }
209     rval = CPXsetdblparam ((*lp)->cplex_env, CPX_PARAM_EPOPT, 1.0E-9);
210     if (rval) {
211         fprintf (stderr, "CPXsetdblparam CPX_PARAM_EPOPT failed\n");
212         goto CLEANUP;
213     }
214     rval = CPXsetdblparam ((*lp)->cplex_env, CPX_PARAM_EPRHS, 1.0E-9);
215     if (rval) {
216         fprintf (stderr, "CPXsetdblparam CPX_PARAM_EPRHS failed\n");
217         goto CLEANUP;
218     }
219 
220 #endif /* CC_ONE_ENV */
221 
222 CLEANUP:
223 
224     if (rval) {
225         CClp_free (lp);
226     }
227 
228     return rval;
229 }
230 
CClp_force_perturb(CClp * lp)231 int CClp_force_perturb (CClp *lp)
232 {
233     int rval = 0;
234 
235 #ifdef CC_ONE_ENV
236     lp->cplex_params.perind = 1;
237 #else /* CC_ONE_ENV */
238     rval = CPXsetintparam (lp->cplex_env, CPX_PARAM_PERIND, 1);
239     if (rval) {
240         fprintf (stderr, "CPXsetintparam CPX_PARAM_PERIND failed\n");
241     }
242 #endif /* CC_ONE_ENV */
243     return rval;
244 }
245 
CClp_tune_small(CClp * lp)246 int CClp_tune_small (CClp *lp)
247 {
248 #ifdef CC_ONE_ENV
249     lp->cplex_params.dpriind = CPX_DPRIIND_FULL;
250     lp->cplex_params.ppriind = CPX_PPRIIND_AUTO;
251 #else /* CC_ONE_ENV */
252     int rval;
253 
254     rval = CPXsetintparam (lp->cplex_env, CPX_PARAM_DPRIIND,
255                            CPX_DPRIIND_FULL);
256     if (rval) {
257         fprintf (stderr, "CPXsetintparam CPX_PARAM_DPRIIND failed\n");
258         return rval;
259     }
260     rval = CPXsetintparam (lp->cplex_env, CPX_PARAM_PPRIIND,
261                            CPX_PPRIIND_AUTO);
262     if (rval) {
263         fprintf (stderr, "CPXsetintparam CPX_PARAM_PPRIIND failed\n");
264         return rval;
265     }
266 #endif /* CC_ONE_ENV */
267     return 0;
268 }
269 
CClp_disable_presolve(CClp * lp)270 int CClp_disable_presolve (CClp *lp)
271 {
272 #ifdef CC_ONE_ENV
273     lp->cplex_params.preind = CPX_OFF;
274     lp->cplex_params.aggind = 0;
275 #else /* CC_ONE_ENV */
276     if (CPXsetintparam (lp->cplex_env, CPX_PARAM_PREIND, CPX_OFF)) {
277         fprintf (stderr, "CPXsetintparam CPX_PARAM_PREIND failed\n");
278         return 1;
279     }
280     if (CPXsetintparam (lp->cplex_env, CPX_PARAM_AGGIND, 0)) {
281         fprintf (stderr, "CPXsetintparam CPX_PARAM_AGGIND failed\n");
282         return 1;
283     }
284 #endif /* CC_ONE_ENV */
285     return 0;
286 }
287 
CClp_free(CClp ** lp)288 void CClp_free (CClp **lp)
289 {
290     if (*lp) {
291         if ((*lp)->cplex_env) {
292             if ((*lp)->cplex_lp) {
293                 CPXfreeprob ((*lp)->cplex_env, &((*lp)->cplex_lp));
294             }
295 #ifdef CC_ONE_ENV
296             (*lp)->cplex_env = (CPXENVptr) NULL;
297             CClp_env_count--;
298             if (CClp_env_count == 0) {
299                 CPXcloseCPLEX (&CClp_cplex_env);
300                 CClp_cplex_env = (CPXENVptr) NULL;
301             }
302 #else
303             CPXcloseCPLEX (&((*lp)->cplex_env));
304 #endif
305         }
306         CC_FREE (*lp, CClp);
307     }
308 }
309 
CClp_freelp(CClp ** lp)310 void CClp_freelp (CClp **lp)
311 {
312     if (*lp) {
313         if ((*lp)->cplex_lp) {
314             CPXfreeprob ((*lp)->cplex_env, &((*lp)->cplex_lp));
315         }
316     }
317 }
318 
CClp_loadlp(CClp * lp,const char * name,int ncols,int nrows,int objsense,double * obj,double * rhs,char * sense,int * matbeg,int * matcnt,int * matind,double * matval,double * lb,double * ub)319 int CClp_loadlp (CClp *lp, const char *name, int ncols, int nrows,
320         int objsense, double *obj, double *rhs, char *sense, int *matbeg,
321         int *matcnt, int *matind, double *matval, double *lb, double *ub)
322 {
323     int rval = 0;
324     char nambuf[32];
325 
326     /* We copy the name since CPXcreateprob doesn't declare name as const */
327     strncpy (nambuf, name, sizeof (nambuf));
328     nambuf[sizeof(nambuf)-1] = '\0';
329 
330     lp->cplex_lp = CPXcreateprob (lp->cplex_env, &rval, nambuf);
331     if (!lp->cplex_lp || rval) {
332        fprintf (stderr, "CPXcreateprob failed, return code %d\n", rval);
333        return 1;
334     }
335 
336     rval = CPXcopylp (lp->cplex_env, lp->cplex_lp, ncols, nrows,
337                       objsense, obj, rhs, sense, matbeg, matcnt,
338                       matind, matval, lb, ub, (double *) NULL);
339     if (rval) {
340        fprintf (stderr, "CPXcopylp failed, return code %d\n", rval);
341        return 1;
342     }
343 
344     return 0;
345 }
346 
CClp_create(CClp * lp,const char * name)347 int CClp_create (CClp *lp, const char *name)
348 {
349     int rval;
350     char nambuf[32];
351 
352     /* We copy the name since CPXcreateprob doesn't declare name as const */
353     strncpy (nambuf, name, sizeof (nambuf));
354     nambuf[sizeof(nambuf)-1] = '\0';
355 
356     lp->cplex_lp = CPXcreateprob (lp->cplex_env, &rval, nambuf);
357     if (!lp->cplex_lp || rval) {
358        fprintf (stderr, "CPXcreateprob failed, return code %d\n", rval);
359        return 1;
360     }
361     return 0;
362 }
363 
CClp_new_row(CClp * lp,char sense,double rhs)364 int CClp_new_row (CClp *lp, char sense, double rhs)
365 {
366     int rval;
367     char asense[1];
368     double arhs[1];
369 
370     asense[0] = sense;
371     arhs[0] = rhs;
372 
373     rval = CPXnewrows (lp->cplex_env, lp->cplex_lp, 1, arhs, asense,
374                        (double *) NULL, (char **) NULL);
375     if (rval) {
376         fprintf (stderr, "CPXnewrows failed\n");
377         return rval;
378     }
379     return 0;
380 }
381 
CClp_change_sense(CClp * lp,int row,char sense)382 int CClp_change_sense (CClp *lp, int row, char sense)
383 {
384     int xindex[1];
385     char asense[1];
386     int rval;
387 
388     xindex[0] = row;
389     asense[0] = sense;
390     rval = CPXchgsense (lp->cplex_env, lp->cplex_lp, 1, xindex, asense);
391     if (rval) {
392         fprintf (stderr, "CPXchgsense failed\n");
393         return rval;
394     }
395     return 0;
396 }
397 
CClp_opt(CClp * lp,int method)398 int CClp_opt (CClp *lp, int method)
399 {
400     int  rval = 0;
401 
402 #ifdef CC_ONE_ENV
403     if (set_parameters (lp->cplex_env, &lp->cplex_params)) {
404         fprintf (stderr, "Unable to set optimization parameters\n");
405     }
406 #endif
407 
408     switch (method) {
409         case CClp_METHOD_PRIMAL:
410             rval = primalopt (lp);
411             break;
412         case CClp_METHOD_DUAL:
413             rval = dualopt (lp);
414             break;
415         case CClp_METHOD_BARRIER:
416             rval = baropt (lp);
417             break;
418         default:
419             rval = 1;
420             fprintf (stderr, "Nonexistent method in CClp_opt\n");
421             break;
422     }
423     return rval;
424 }
425 
primalopt(CClp * lp)426 static int primalopt (CClp *lp)
427 {
428     int rval;
429     int solstat;
430 #ifdef  CC_CPLEX_WRITE_PRIMAL
431     static int  probcnt = 0;
432     char probname[100];
433 
434     sprintf (probname, "prim%d.sav", probcnt);
435     probcnt++;
436     printf ("Writing %s\n", probname);
437     CPXsavwrite (lp->cplex_env, lp->cplex_lp, probname);
438 #endif
439 
440     rval = CPXprimopt (lp->cplex_env, lp->cplex_lp);
441     if (rval) {
442         if (rval == CPX_STAT_INForUNBD) {
443             int old, oldagg;
444             printf ("Cplex presolve failed, switch to simplex\n");
445             fflush (stdout);
446             if (CPXgetintparam (lp->cplex_env, CPX_PARAM_PREIND, &old)) {
447                 fprintf (stderr, "CPXgetintparam CPX_PARAM_PREIND failed\n");
448                 return 1;
449             }
450             if (CPXsetintparam (lp->cplex_env, CPX_PARAM_PREIND, CPX_OFF)) {
451                 fprintf (stderr, "CPXsetintparam CPX_PARAM_PREIND failed\n");
452                 return 1;
453             }
454             if (CPXgetintparam (lp->cplex_env, CPX_PARAM_AGGIND, &oldagg)) {
455                 fprintf (stderr, "CPXgetintparam CPX_PARAM_AGGIND failed\n");
456                 return 1;
457             }
458             if (CPXsetintparam (lp->cplex_env, CPX_PARAM_AGGIND, 0)) {
459                 fprintf (stderr, "CPXsetintparam CPX_PARAM_AGGIND failed\n");
460                 return 1;
461             }
462             rval = CPXprimopt (lp->cplex_env, lp->cplex_lp);
463             if (rval) {
464                 fprintf (stderr, "CPXprimopt failed, return code %d\n", rval);
465                 return 1;
466             }
467             if (CPXsetintparam (lp->cplex_env, CPX_PARAM_PREIND, old)) {
468                 fprintf (stderr, "CPXsetintparam CPX_PARAM_PREIND failed\n");
469                 return 1;
470             }
471             if (CPXsetintparam (lp->cplex_env, CPX_PARAM_AGGIND, oldagg)) {
472                 fprintf (stderr, "CPXsetintparam CPX_PARAM_AGGIND failed\n");
473                 return 1;
474             }
475         } else {
476             fprintf (stderr, "CPXprimopt failed, return code %d\n", rval);
477             return 1;
478         }
479     }
480     solstat = CPXgetstat (lp->cplex_env, lp->cplex_lp);
481     if (solstat == CPX_STAT_INFEASIBLE) {
482         return 2;
483     } else if (solstat != CPX_STAT_OPTIMAL       &&
484                solstat != CPX_STAT_OPTIMAL_INFEAS  ) {
485         fprintf (stderr, "Cplex optimization status %d\n", solstat);
486         return 1;
487     }
488     return 0;
489 }
490 
dualopt(CClp * lp)491 static int dualopt (CClp *lp)
492 {
493     int rval;
494     int solstat;
495 #ifdef  CC_CPLEX_WRITE_DUAL
496     static int  probcnt = 0;
497     char probname[100];
498 
499     sprintf (probname, "dual%d.sav", probcnt);
500     probcnt++;
501     printf ("Writing %s\n", probname);
502     CPXsavwrite (lp->cplex_env, lp->cplex_lp, probname);
503 #endif
504 
505     rval = CPXdualopt (lp->cplex_env, lp->cplex_lp);
506     if (rval) {
507         if (rval == CPX_STAT_INForUNBD) {
508             int old, oldagg;
509             printf ("Cplex presolve failed, switch to simplex\n");
510             fflush (stdout);
511             if (CPXgetintparam (lp->cplex_env, CPX_PARAM_PREIND, &old)) {
512                 fprintf (stderr, "CPXgetintparam CPX_PARAM_PREIND failed\n");
513                 return 1;
514             }
515             if (CPXsetintparam (lp->cplex_env, CPX_PARAM_PREIND, CPX_OFF)) {
516                 fprintf (stderr, "CPXsetintparam CPX_PARAM_PREIND failed\n");
517                 return 1;
518             }
519             if (CPXgetintparam (lp->cplex_env, CPX_PARAM_AGGIND, &oldagg)) {
520                 fprintf (stderr, "CPXgetintparam CPX_PARAM_AGGIND failed\n");
521                 return 1;
522             }
523             if (CPXsetintparam (lp->cplex_env, CPX_PARAM_AGGIND, 0)) {
524                 fprintf (stderr, "CPXsetintparam CPX_PARAM_AGGIND failed\n");
525                 return 1;
526             }
527             rval = CPXdualopt (lp->cplex_env, lp->cplex_lp);
528             if (rval) {
529                 fprintf (stderr, "CPXdualopt failed, return code %d\n", rval);
530                 return 1;
531             }
532             if (CPXsetintparam (lp->cplex_env, CPX_PARAM_PREIND, old)) {
533                 fprintf (stderr, "CPXsetintparam CPX_PARAM_PREIND failed\n");
534                 return 1;
535             }
536             if (CPXsetintparam (lp->cplex_env, CPX_PARAM_AGGIND, oldagg)) {
537                 fprintf (stderr, "CPXsetintparam CPX_PARAM_AGGIND failed\n");
538                 return 1;
539             }
540         } else {
541             fprintf (stderr, "CPXdualopt failed, return code %d\n", rval);
542             return 1;
543         }
544     }
545     solstat = CPXgetstat (lp->cplex_env, lp->cplex_lp);
546     if (solstat == CPX_STAT_INFEASIBLE) {
547         return 2;
548     } else if (solstat != CPX_STAT_OPTIMAL       &&
549                solstat != CPX_STAT_OPTIMAL_INFEAS  ) {
550         fprintf (stderr, "Cplex optimization status %d\n", solstat);
551         if (solstat == CPX_STAT_ABORT_IT_LIM) {
552             int itlim;
553             rval = CPXgetintparam (lp->cplex_env, CPX_PARAM_ITLIM, &itlim);
554             if (!rval) {
555                 printf ("cplex iteration limit: %d\n", itlim);
556                 fflush (stdout);
557             }
558         }
559         return 1;
560     }
561     return 0;
562 }
563 
baropt(CClp * lp)564 static int baropt (CClp *lp)
565 {
566     int rval;
567     int solstat;
568 #ifdef CC_CPLEX_WRITE_BARRIER
569     static int  probcnt = 0;
570     char probname[100];
571 
572     sprintf (probname, "barrier%d.sav", probcnt);
573     probcnt++;
574     printf ("Writing %s\n", probname);
575     CPXsavwrite (lp->cplex_env, lp->cplex_lp, probname);
576 #endif
577 
578     rval = CPXbaropt (lp->cplex_env, lp->cplex_lp);
579     if (rval) {
580         printf ("CPXbaropt failed, return code %d, calling CPXdualopt\n",
581                 rval);
582         return dualopt (lp);
583     }
584     solstat = CPXgetstat (lp->cplex_env, lp->cplex_lp);
585     if (solstat != CPX_STAT_OPTIMAL) {
586         printf ("CPXbaropt returned non-optimal solution, calling CPXdualopt\n");
587         return dualopt (lp);
588     }
589     return 0;
590 }
591 
592 #define CC_MAX_REFACTORFREQ  150
593 
CClp_limited_dualopt(CClp * lp,int iterationlim,int * status,double * objupperlim)594 int CClp_limited_dualopt (CClp *lp, int iterationlim, int *status,
595                           double *objupperlim)
596 {
597     int rval = 0;
598     int sval = 0;
599     int solstat;
600     int dfeasind;
601 
602     int got_iterationlim = 0;
603     int got_presolveind  = 0;
604     int got_aggregateind = 0;
605     int got_objupperlim  = 0;
606     int got_refactorfreq = 0;
607     int got_perind       = 0;
608 
609     int    old_iterationlim;
610     int    old_presolveind;
611     int    old_aggregateind;
612     double old_objupperlim;
613     int    old_refactorfreq;
614     int    old_perind;
615 
616 #ifdef CC_ONE_ENV
617     if (set_parameters (lp->cplex_env, &lp->cplex_params)) {
618         fprintf (stderr, "Unable to set optimization parameters\n");
619     }
620 #endif
621 
622     /* REB, 14 October 1997:  If perturbation has been turned on elsewhere,
623        we need to turn it off for branch selection */
624 
625     rval = CPXgetintparam (lp->cplex_env, CPX_PARAM_PERIND, &old_perind);
626     if (rval) {
627          fprintf (stderr, "CPXgetintparam CPX_PARAM_PERIND failed\n");
628          goto CLEANUP;
629     }
630     got_perind = 1;
631 
632     rval = CPXgetintparam (lp->cplex_env, CPX_PARAM_ITLIM, &old_iterationlim);
633     if (rval) {
634         fprintf (stderr, "CPXgetintparam CPX_PARAM_ITLIM failed\n");
635         goto CLEANUP;
636     }
637     got_iterationlim = 1;
638 
639     rval = CPXgetdblparam (lp->cplex_env, CPX_PARAM_OBJULIM, &old_objupperlim);
640     if (rval) {
641         fprintf (stderr, "CPXgetdblparam CPX_PARAM_OBJULIM failed\n");
642         goto CLEANUP;
643     }
644     got_objupperlim = 1;
645 
646     rval = CPXgetintparam (lp->cplex_env, CPX_PARAM_PREIND, &old_presolveind);
647     if (rval) {
648         fprintf (stderr, "CPXgetintparam CPX_PARAM_PREIND failed\n");
649         goto CLEANUP;
650     }
651     got_presolveind = 1;
652 
653     rval = CPXgetintparam (lp->cplex_env, CPX_PARAM_AGGIND, &old_aggregateind);
654     if (rval) {
655         fprintf (stderr, "CPXgetintparam CPX_PARAM_AGGIND failed\n");
656         goto CLEANUP;
657     }
658     got_aggregateind = 1;
659 
660     rval = CPXgetintparam (lp->cplex_env, CPX_PARAM_REINV, &old_refactorfreq);
661     if (rval) {
662         fprintf (stderr, "CPXgetintparam CPX_PARAM_REINV failed\n");
663         goto CLEANUP;
664     }
665     got_refactorfreq = 1;
666 
667     rval = CPXsetintparam (lp->cplex_env, CPX_PARAM_PERIND, 0);
668     if (rval) {
669          fprintf (stderr, "CPXsetintparam CPX_PARAM_PERIND failed\n");
670          goto CLEANUP;
671     }
672 
673     rval = CPXsetintparam (lp->cplex_env, CPX_PARAM_ITLIM, iterationlim);
674     if (rval) {
675         fprintf (stderr, "CPXsetintparam CPX_PARAM_ITLIM failed\n");
676         goto CLEANUP;
677     }
678 
679     if ( iterationlim < CC_MAX_REFACTORFREQ ) {
680         rval = CPXsetintparam (lp->cplex_env, CPX_PARAM_REINV, iterationlim+1);
681         if (rval) {
682             fprintf (stderr, "CPXsetintparam CPX_PARAM_REINV failed\n");
683             goto CLEANUP;
684         }
685     }
686 
687     if (objupperlim) {
688         rval = CPXsetdblparam (lp->cplex_env, CPX_PARAM_OBJULIM, *objupperlim);
689         if (rval) {
690             fprintf (stderr, "CPXsetdblparam CPX_PARAM_OBJULIM failed\n");
691             goto CLEANUP;
692         }
693     }
694 
695     rval = CPXdualopt (lp->cplex_env, lp->cplex_lp);
696     if (rval) {
697         if (rval == CPX_STAT_INForUNBD) {
698             printf ("Cplex presolve failed, force simplex\n");
699             fflush (stdout);
700 
701             if (CPXsetintparam (lp->cplex_env, CPX_PARAM_PREIND, CPX_OFF)) {
702                 fprintf (stderr, "CPXsetintparam CPX_PARAM_PREIND failed\n");
703                 goto CLEANUP;
704             }
705             if (CPXsetintparam (lp->cplex_env, CPX_PARAM_AGGIND, 0)) {
706                 fprintf (stderr, "CPXsetintparam CPX_PARAM_AGGIND failed\n");
707                 goto CLEANUP;
708             }
709             rval = CPXdualopt (lp->cplex_env, lp->cplex_lp);
710             if (rval) {
711                 fprintf (stderr, "CPXdualopt failed, return code %d\n", rval);
712                 goto CLEANUP;
713             }
714         } else {
715             fprintf (stderr, "CPXdualopt failed, return code %d\n", rval);
716             goto CLEANUP;
717         }
718     }
719     solstat = CPXgetstat (lp->cplex_env, lp->cplex_lp);
720     rval = CPXsolninfo (lp->cplex_env, lp->cplex_lp, NULL, NULL, NULL,
721 		        &dfeasind);
722     if ( rval ) {
723         fprintf (stderr, "CPXsolninfo dfeasind failed\n");
724 	goto CLEANUP;
725     }
726     if ( solstat==CPX_STAT_ABORT_IT_LIM &&
727          !dfeasind                        ) {
728         rval = CPXsetdblparam (lp->cplex_env, CPX_PARAM_OBJULIM, -1.0E75);
729         if (rval) {
730             fprintf (stderr, "CPXsetdblparam CPX_PARAM_OBJULIM failed\n");
731             goto CLEANUP;
732         }
733         /* We could be even more aggressive here and make the iteration
734            limit infinite, but that approach seems contrary to the
735            intent of this function.  Hence, the repeat test for
736            CPX_IT_LIM_INFEAS below -- REB, 1 July 97 */
737         rval = CPXdualopt (lp->cplex_env, lp->cplex_lp);
738         if (rval) {
739             fprintf (stderr, "CPXdualopt failed, return code %d\n", rval);
740             goto CLEANUP;
741         }
742         solstat = CPXgetstat (lp->cplex_env, lp->cplex_lp);
743         rval = CPXsolninfo (lp->cplex_env, lp->cplex_lp, NULL, NULL, NULL,
744 		            &dfeasind);
745         if ( rval ) {
746             fprintf (stderr, "CPXsolninfo dfeasind failed\n");
747     	    goto CLEANUP;
748         }
749     }
750 
751     if (solstat == CPX_STAT_INFEASIBLE) {
752         printf ("Infeasible in CPXdualopt\n"); fflush (stdout);
753         if (status) *status = CClp_INFEASIBLE;
754     } else if (solstat == CPX_STAT_ABORT_IT_LIM &&
755                !dfeasind                          ) {
756         printf ("LP infeasible after the limited number of iterations\n");
757         fflush (stdout);
758         if (status) *status = CClp_UNKNOWN;
759     } else if (solstat != CPX_STAT_OPTIMAL          &&
760                solstat != CPX_STAT_OPTIMAL_INFEAS   &&
761                solstat != CPX_STAT_ABORT_OBJ_LIM    &&
762                (solstat != CPX_STAT_ABORT_IT_LIM ||
763 	        !dfeasind                          )  ) {
764         fprintf (stderr, "Cplex optimization status %d\n", solstat);
765         if (status) *status = CClp_FAILURE;
766     } else {
767         if (status) *status = CClp_SUCCESS;
768     }
769 
770 CLEANUP:
771 
772     if (got_iterationlim == 1) {
773         sval = CPXsetintparam (lp->cplex_env, CPX_PARAM_ITLIM,
774                                old_iterationlim);
775         if (sval) {
776             fprintf (stderr, "CPXsetintparam CPX_PARAM_ITLIM failed\n");
777             rval = 1;
778         }
779     }
780 
781     if (got_objupperlim == 1) {
782         sval = CPXsetdblparam (lp->cplex_env, CPX_PARAM_OBJULIM,
783                                old_objupperlim);
784         if (sval) {
785             fprintf (stderr, "CPXsetdblparam CPX_PARAM_OBJULIM failed\n");
786             rval = 1;
787         }
788     }
789 
790     if (got_presolveind == 1) {
791         sval = CPXsetintparam (lp->cplex_env, CPX_PARAM_PREIND,
792                                old_presolveind);
793         if (sval) {
794             fprintf (stderr, "CPXsetintparam CPX_PARAM_PREIND failed\n");
795             rval = 1;
796         }
797     }
798 
799     if (got_aggregateind == 1) {
800         sval = CPXsetintparam (lp->cplex_env, CPX_PARAM_AGGIND,
801                                old_aggregateind);
802         if (sval) {
803             fprintf (stderr, "CPXsetintparam CPX_PARAM_AGGIND failed\n");
804             rval = 1;
805         }
806     }
807 
808     if (got_refactorfreq == 1) {
809         sval = CPXsetintparam (lp->cplex_env, CPX_PARAM_REINV,
810                                old_refactorfreq);
811         if (sval) {
812             fprintf (stderr, "CPXsetintparam CPX_PARAM_REINV failed\n");
813             rval = 1;
814         }
815     }
816 
817     if (got_perind == 1) {
818         sval = CPXsetintparam (lp->cplex_env, CPX_PARAM_PERIND, old_perind);
819         if (sval) {
820             fprintf (stderr, "CPXsetintparam CPX_PARAM_PERIND failed\n");
821             rval = 1;;
822         }
823     }
824 
825     if (rval && status) {
826         *status = CClp_FAILURE;
827     }
828 
829     return rval;
830 }
831 
CClp_addrows(CClp * lp,int newrows,int newnz,double * rhs,char * sense,int * rmatbeg,int * rmatind,double * rmatval)832 int CClp_addrows (CClp *lp, int newrows, int newnz, double *rhs, char *sense,
833                   int *rmatbeg, int *rmatind, double *rmatval)
834 {
835     int rval = 0;
836 
837     rval = CPXaddrows (lp->cplex_env, lp->cplex_lp, 0, newrows, newnz,
838                        rhs, sense, rmatbeg, rmatind, rmatval,
839                        (char **) NULL, (char **) NULL);
840     if (rval) fprintf (stderr, "CPXaddrows failed\n");
841     return rval;
842 }
843 
CClp_addcols(CClp * lp,int newcols,int newnz,double * obj,int * cmatbeg,int * cmatind,double * cmatval,double * lb,double * ub)844 int CClp_addcols (CClp *lp, int newcols, int newnz, double *obj,
845                   int *cmatbeg, int *cmatind, double *cmatval,
846                   double *lb, double *ub)
847 {
848     int rval = 0;
849 
850     rval = CPXaddcols (lp->cplex_env, lp->cplex_lp, newcols, newnz, obj,
851                    cmatbeg, cmatind, cmatval, lb, ub, (char **) NULL);
852     if (rval) fprintf (stderr, "CPXaddcols failed\n");
853     return rval;
854 }
855 
CClp_delete_row(CClp * lp,int i)856 int CClp_delete_row (CClp *lp, int i)
857 {
858     int rval = 0;
859     int locali[1];
860 
861 #ifdef CC_ONE_ENV
862     if (set_parameters (lp->cplex_env, &lp->cplex_params)) {
863         fprintf (stderr, "Unable to set optimization parameters\n");
864     }
865 #endif
866 
867     locali[0] = i;
868     if (CPXpivotin (lp->cplex_env, lp->cplex_lp, locali, 1)) {
869         fprintf (stderr, "CPXpivotin failed, continuing anyway\n");
870     }
871     rval = CPXdelrows (lp->cplex_env, lp->cplex_lp, i, i);
872     if (rval) fprintf (stderr, "CPXdelrows failed\n");
873     return rval;
874 }
875 
CClp_delete_set_of_rows(CClp * lp,int * delstat)876 int CClp_delete_set_of_rows (CClp *lp, int *delstat)
877 {
878     int rval = 0;
879     int *dellist = (int *) NULL;
880     int delcnt = 0;
881     int i;
882     int j;
883     int rcnt = CPXgetnumrows (lp->cplex_env, lp->cplex_lp);
884 
885 #ifdef CC_ONE_ENV
886     if (set_parameters (lp->cplex_env, &lp->cplex_params)) {
887         fprintf (stderr, "Unable to set optimization parameters\n");
888     }
889 #endif
890 
891     for (i=0; i<rcnt; i++) {
892         if (delstat[i]) delcnt++;
893     }
894     if (delcnt == 0) {
895         fprintf (stderr, "delete_set_of_rows with no deleted rows\n");
896         return 0;
897     }
898     dellist = CC_SAFE_MALLOC (delcnt, int);
899     if (dellist == (int *) NULL) {
900         fprintf (stderr, "Out of memory in delete_set_of_rows\n");
901         return 1;
902     }
903     for (i=0, j=0; i<rcnt; i++) {
904         if (delstat[i]) {
905             dellist[j++] = i;
906         }
907     }
908     if (j != delcnt) {
909         fprintf (stderr, "Lost some deleted rows\n");
910         CC_FREE (dellist, int);
911         return 1;
912     }
913 
914     if (CPXpivotin (lp->cplex_env, lp->cplex_lp, dellist, delcnt)) {
915         fprintf (stderr, "CPXpivotin failed, continuing anyway\n");
916     }
917     CC_FREE (dellist, int);
918 
919     rval = CPXdelsetrows (lp->cplex_env, lp->cplex_lp, delstat);
920     if (rval) fprintf (stderr, "CPXdelsetrows failed\n");
921     return rval;
922 }
923 
CClp_delete_column(CClp * lp,int i)924 int CClp_delete_column (CClp *lp, int i)
925 {
926     int rval = 0;
927     int locali[1];
928     char lu[1];
929     double bd[1];
930 
931 #ifdef CC_ONE_ENV
932     if (set_parameters (lp->cplex_env, &lp->cplex_params)) {
933         fprintf (stderr, "Unable to set optimization parameters\n");
934     }
935 #endif
936 
937     locali[0] = i;
938     lu[0] = 'B';
939     bd[0] = 0.0;
940 
941     if (CPXchgbds (lp->cplex_env, lp->cplex_lp, 1, locali, lu, bd)) {
942         fprintf (stderr, "CPXchgbds failed, continuing anyway\n");
943     }
944 
945     if (CPXdualopt (lp->cplex_env, lp->cplex_lp)) {
946         fprintf (stderr, "CPXdualopt failed, continuing anyway\n");
947     }
948 
949     if (CPXpivotout (lp->cplex_env, lp->cplex_lp, locali, 1)) {
950         fprintf (stderr, "CPXpivotout failed, continuing anyway\n");
951     }
952 
953     rval = CPXdelcols (lp->cplex_env, lp->cplex_lp, i, i);
954     if (rval) fprintf (stderr, "CPXdelcols failed\n");
955     return rval;
956 }
957 
CClp_delete_set_of_columns(CClp * lp,int * delstat)958 int CClp_delete_set_of_columns (CClp *lp, int *delstat)
959 {
960     int rval = 0;
961     int *dellist = (int *) NULL;
962     char *lu = (char *) NULL;
963     double *bd = (double *) NULL;
964     int delcnt = 0;
965     int i;
966     int j;
967     int ccnt = CPXgetnumcols (lp->cplex_env, lp->cplex_lp);
968 
969 #ifdef CC_ONE_ENV
970     if (set_parameters (lp->cplex_env, &lp->cplex_params)) {
971         fprintf (stderr, "Unable to set optimization parameters\n");
972     }
973 #endif
974 
975     for (i=0; i<ccnt; i++) {
976         if (delstat[i]) delcnt++;
977     }
978     if (delcnt == 0) {
979         fprintf (stderr, "delete_set_of_columns with no deleted columns\n");
980         return 0;
981     }
982     dellist = CC_SAFE_MALLOC (delcnt, int);
983     lu = CC_SAFE_MALLOC (delcnt, char);
984     bd = CC_SAFE_MALLOC (delcnt, double);
985     if (dellist == (int *) NULL ||
986         lu == (char *) NULL ||
987         bd == (double *) NULL) {
988         fprintf (stderr, "Out of memory in delete_set_of_columns\n");
989         CC_IFFREE (dellist, int);
990         CC_IFFREE (lu, char);
991         CC_IFFREE (bd, double);
992         return 1;
993     }
994     for (i=0, j=0; i<ccnt; i++) {
995         if (delstat[i]) {
996             lu[j] = 'B';
997             bd[j] = 0.0;
998             dellist[j++] = i;
999         }
1000     }
1001     if (j != delcnt) {
1002         fprintf (stderr, "Lost some deleted columns\n");
1003         CC_FREE (dellist, int);
1004         CC_FREE (lu, char);
1005         CC_FREE (bd, double);
1006         return 1;
1007     }
1008 
1009     if (CPXchgbds (lp->cplex_env, lp->cplex_lp, delcnt, dellist, lu, bd)) {
1010         fprintf (stderr, "CPXchgbds failed, stumbling on anyway\n");
1011     }
1012 
1013     if (CPXdualopt (lp->cplex_env, lp->cplex_lp)) {
1014         fprintf (stderr, "CPXdualopt failed, continuing anyway\n");
1015     }
1016 
1017     if (CPXpivotout (lp->cplex_env, lp->cplex_lp, dellist, delcnt)) {
1018         fprintf (stderr, "CPXpivotout failed, continuing anyway\n");
1019     }
1020 
1021     CC_FREE (dellist, int);
1022     CC_FREE (lu, char);
1023     CC_FREE (bd, double);
1024 
1025     rval = CPXdelsetcols (lp->cplex_env, lp->cplex_lp, delstat);
1026     if (rval) fprintf (stderr, "CPXdelsetcols failed\n");
1027     return rval;
1028 }
1029 
CClp_setbnd(CClp * lp,int col,char lower_or_upper,double bnd)1030 int CClp_setbnd (CClp *lp, int col, char lower_or_upper, double bnd)
1031 {
1032     int cindex[1];
1033     double bd[1];
1034     char lu[1];
1035     int rval;
1036 
1037     cindex[0] = col;
1038     lu[0] = lower_or_upper;
1039     bd[0] = bnd;
1040 
1041     rval = CPXchgbds (lp->cplex_env, lp->cplex_lp, 1, cindex, lu, bd);
1042     if (rval) {
1043         fprintf (stderr, "Couldn't set bnd on variable %d in cplex\n", col);
1044         return rval;
1045     }
1046     return 0;
1047 }
1048 
CClp_get_warmstart(CClp * lp,CClp_warmstart ** w)1049 int CClp_get_warmstart (CClp *lp, CClp_warmstart **w)
1050 {
1051     int rval = 0;
1052 
1053     CClp_free_warmstart (w);
1054 
1055     (*w) = CC_SAFE_MALLOC (1, CClp_warmstart);
1056     if ((*w) == (CClp_warmstart *) NULL) {
1057         fprintf (stderr, "Out of memory in CClp_get_warmstart\n");
1058         rval = 1; goto CLEANUP;
1059     }
1060 
1061     (*w)->ccount = 0;
1062     (*w)->rcount = 0;
1063     (*w)->cstat  = (int *) NULL;
1064     (*w)->rstat  = (int *) NULL;
1065     (*w)->dnorm  = (double *) NULL;
1066 
1067     (*w)->ccount = CPXgetnumcols (lp->cplex_env, lp->cplex_lp);
1068     if ((*w)->ccount == 0) {
1069         fprintf (stderr, "No columns in LP\n");
1070         rval = 1; goto CLEANUP;
1071     }
1072     (*w)->rcount = CPXgetnumrows (lp->cplex_env, lp->cplex_lp);
1073     if ((*w)->rcount == 0) {
1074         fprintf (stderr ,"No rows in LP\n");
1075         rval = 1; goto CLEANUP;
1076     }
1077 
1078     (*w)->cstat = CC_SAFE_MALLOC ((*w)->ccount, int);
1079     (*w)->rstat = CC_SAFE_MALLOC ((*w)->rcount, int);
1080     (*w)->dnorm = CC_SAFE_MALLOC ((*w)->rcount, double);
1081     if (!(*w)->cstat || !(*w)->rstat || !(*w)->dnorm) {
1082         fprintf (stderr, "out of memory in CClp_get_warmstart\n");
1083         rval = 1; goto CLEANUP;
1084     }
1085 
1086     rval = CPXgetbasednorms (lp->cplex_env, lp->cplex_lp, (*w)->cstat,
1087                              (*w)->rstat, (*w)->dnorm);
1088     if (rval) {
1089         fprintf (stderr, "CPXgetbasednorms failed, trying to get basis\n");
1090         CC_IFFREE ((*w)->dnorm, double);
1091         rval = CPXgetbase (lp->cplex_env, lp->cplex_lp, (*w)->cstat,
1092                            (*w)->rstat);
1093         if (rval) {
1094             fprintf (stderr, "CPXgetbase failed\n"); goto CLEANUP;
1095         }
1096     }
1097 
1098     return 0;
1099 
1100 CLEANUP:
1101 
1102     CClp_free_warmstart (w);
1103     return rval;
1104 }
1105 
CClp_load_warmstart(CClp * lp,CClp_warmstart * w)1106 int CClp_load_warmstart (CClp *lp, CClp_warmstart *w)
1107 {
1108     int rval = 0;
1109 
1110     if (w->cstat && w->rstat && w->dnorm) {
1111         rval = CPXcopybasednorms (lp->cplex_env, lp->cplex_lp, w->cstat,
1112                                   w->rstat, w->dnorm);
1113         if (rval) {
1114             fprintf (stderr, "CPXcopybasednorms failed\n"); goto CLEANUP;
1115         }
1116     } else if (w->cstat && w->rstat) {
1117         rval = CPXcopybase (lp->cplex_env, lp->cplex_lp, w->cstat, w->rstat);
1118         if (rval) {
1119             fprintf (stderr, "CPXcopybase failed\n"); goto CLEANUP;
1120         }
1121     } else {
1122         printf ("WARNING: No basis in call to load_warmstart\n");
1123         fflush (stdout);
1124     }
1125 
1126 CLEANUP:
1127 
1128     return rval;
1129 }
1130 
CClp_build_warmstart(CClp_warmstart ** w,CClp_info * i)1131 int CClp_build_warmstart (CClp_warmstart **w, CClp_info *i)
1132 {
1133     int rval = 0;
1134     int j;
1135 
1136     CClp_free_warmstart (w);
1137 
1138     (*w) = CC_SAFE_MALLOC (1, CClp_warmstart);
1139     if ((*w) == (CClp_warmstart *) NULL) {
1140         fprintf (stderr, "Out of memory in CClp_get_warmstart\n");
1141         rval = 1; goto CLEANUP;
1142     }
1143 
1144     (*w)->ccount = 0;
1145     (*w)->rcount = 0;
1146     (*w)->cstat = (int *) NULL;
1147     (*w)->rstat = (int *) NULL;
1148     (*w)->dnorm = (double *) NULL;
1149 
1150     (*w)->ccount = i->ccount;
1151     if ((*w)->ccount == 0) {
1152         fprintf (stderr, "No columns in CClp_info\n");
1153         rval = 1; goto CLEANUP;
1154     }
1155     (*w)->rcount = i->rcount;
1156     if ((*w)->rcount == 0) {
1157         fprintf (stderr, "No rows in CClp_info\n");
1158         rval = 1; goto CLEANUP;
1159     }
1160 
1161     (*w)->cstat = CC_SAFE_MALLOC ((*w)->ccount, int);
1162     (*w)->rstat = CC_SAFE_MALLOC ((*w)->rcount, int);
1163     if (!(*w)->cstat || !(*w)->rstat) {
1164         fprintf (stderr, "out of memory in CClp_get_warmstart\n");
1165         rval = 1; goto CLEANUP;
1166     }
1167 
1168     for (j=0; j<(*w)->ccount; j++) {
1169         (*w)->cstat[j] = i->cstat[j];
1170     }
1171     for (j=0; j<(*w)->rcount; j++) {
1172         (*w)->rstat[j] = i->rstat[j];
1173     }
1174 
1175     return 0;
1176 
1177   CLEANUP:
1178     CClp_free_warmstart (w);
1179     return rval;
1180 }
1181 
CClp_free_warmstart(CClp_warmstart ** w)1182 void CClp_free_warmstart (CClp_warmstart **w)
1183 {
1184     if (*w != (CClp_warmstart *) NULL) {
1185         CC_IFFREE ((*w)->cstat, int);
1186         CC_IFFREE ((*w)->rstat, int);
1187         CC_IFFREE ((*w)->dnorm, double);
1188         CC_FREE (*w, CClp_warmstart);
1189     }
1190 }
1191 
CClp_sread_warmstart(CC_SFILE * f,CClp_warmstart ** w)1192 int CClp_sread_warmstart (CC_SFILE *f, CClp_warmstart **w)
1193 {
1194     char name[5];
1195     int i;
1196     int ccount;
1197     int rcount;
1198     int has_dnorms;
1199 
1200     CClp_free_warmstart (w);
1201 
1202     for (i=0; i<4; i++) {
1203         if (CCutil_sread_char (f, &name[i])) goto CLEANUP;
1204     }
1205     name[4] = '\0';
1206 
1207     if (strncmp (name, SOLVER_WARMSTART_NAME, 4)) {
1208         fprintf (stderr, "warmstart for another solver (%s) ignored\n", name);
1209         return 0;
1210     }
1211 
1212     if (CCutil_sread_int (f, &ccount)) goto CLEANUP;
1213     if (CCutil_sread_int (f, &rcount)) goto CLEANUP;
1214 
1215     (*w) = CC_SAFE_MALLOC (1, CClp_warmstart);
1216     if ((*w) == (CClp_warmstart *) NULL) {
1217         fprintf (stderr, "Out of memory in CClp_sread_warmstart\n");
1218         goto CLEANUP;
1219     }
1220 
1221     (*w)->ccount = 0;
1222     (*w)->rcount = 0;
1223     (*w)->cstat  = (int *) NULL;
1224     (*w)->rstat  = (int *) NULL;
1225     (*w)->dnorm  = (double *) NULL;
1226 
1227     (*w)->cstat = CC_SAFE_MALLOC (ccount, int);
1228     (*w)->rstat = CC_SAFE_MALLOC (rcount, int);
1229     if ((*w)->cstat == (int *) NULL ||
1230         (*w)->rstat == (int *) NULL) {
1231         fprintf (stderr, "out of memory in CClp_sread_warmstart\n");
1232         goto CLEANUP;
1233     }
1234     for (i = 0; i < ccount; i++) {
1235         if (CCutil_sread_bits (f, &(((*w)->cstat)[i]), 2))
1236             goto CLEANUP;
1237     }
1238     for (i = 0; i < rcount; i++) {
1239         if (CCutil_sread_bits (f, &(((*w)->rstat)[i]), 1))
1240             goto CLEANUP;
1241     }
1242 
1243     if (CCutil_sread_int (f, &has_dnorms)) goto CLEANUP;
1244 
1245     if (has_dnorms) {
1246         (*w)->dnorm = CC_SAFE_MALLOC (rcount, double);
1247         if ((*w)->dnorm == (double *) NULL) {
1248             fprintf (stderr, "out of memory in CClp_sread_warmstart\n");
1249             goto CLEANUP;
1250         }
1251         for (i = 0; i < rcount; i++) {
1252             if (CCutil_sread_double (f, &(((*w)->dnorm)[i]))) goto CLEANUP;
1253         }
1254     }
1255 
1256     (*w)->ccount = ccount;
1257     (*w)->rcount = rcount;
1258 
1259     return 0;
1260 
1261 CLEANUP:
1262 
1263     CClp_free_warmstart (w);
1264     return 1;
1265 }
1266 
CClp_swrite_warmstart(CC_SFILE * f,CClp_warmstart * w)1267 int CClp_swrite_warmstart (CC_SFILE *f, CClp_warmstart *w)
1268 {
1269     int i;
1270     const char *name = SOLVER_WARMSTART_NAME;
1271 
1272     for (i=0; i<4; i++) {
1273         if (CCutil_swrite_char (f, name[i])) return 1;
1274     }
1275 
1276     if (CCutil_swrite_int (f, w->ccount)) return 1;
1277     if (CCutil_swrite_int (f, w->rcount)) return 1;
1278 
1279     for (i = 0; i < w->ccount; i++) {
1280         if (CCutil_swrite_bits (f, w->cstat[i], 2)) return 1;
1281     }
1282 
1283     for (i = 0; i < w->rcount; i++) {
1284         if (CCutil_swrite_bits (f, w->rstat[i], 1)) return 1;
1285     }
1286 
1287     if (w->dnorm == (double *) NULL) {
1288         if (CCutil_swrite_int (f, 0)) return 1;
1289     } else {
1290         if (CCutil_swrite_int (f, 1)) return 1;
1291         for (i = 0; i < w->rcount; i++) {
1292             if (CCutil_swrite_double (f, w->dnorm[i])) return 1;
1293         }
1294     }
1295 
1296     return 0;
1297 }
1298 
CClp_get_info(CClp * lp,CClp_info ** i)1299 int CClp_get_info (CClp *lp, CClp_info **i)
1300 {
1301     int rval = 0;
1302 
1303     CClp_free_info (i);
1304 
1305     (*i) = CC_SAFE_MALLOC (1, CClp_info);
1306     if ((*i) == (CClp_info *) NULL) {
1307         fprintf (stderr, "Out of memory in CClp_get_info\n");
1308         rval = 1; goto CLEANUP;
1309     }
1310 
1311     (*i)->ccount = 0;
1312     (*i)->rcount = 0;
1313     (*i)->cstat = (int *) NULL;
1314     (*i)->rstat = (int *) NULL;
1315 
1316     (*i)->ccount = CPXgetnumcols (lp->cplex_env, lp->cplex_lp);
1317     if ((*i)->ccount == 0) {
1318         fprintf (stderr, "No columns in CClp_get_info\n");
1319         rval = 1; goto CLEANUP;
1320     }
1321     (*i)->rcount = CPXgetnumrows (lp->cplex_env, lp->cplex_lp);
1322     if ((*i)->rcount == 0) {
1323         fprintf (stderr ,"No rows in CClp_get_info\n");
1324         rval = 1; goto CLEANUP;
1325     }
1326 
1327     (*i)->cstat = CC_SAFE_MALLOC ((*i)->ccount, int);
1328     (*i)->rstat = CC_SAFE_MALLOC ((*i)->rcount, int);
1329     if (!(*i)->cstat || !(*i)->rstat) {
1330         fprintf (stderr, "out of memory in CClp_get_info\n");
1331         rval = 1; goto CLEANUP;
1332     }
1333 
1334     rval = CPXgetbase (lp->cplex_env, lp->cplex_lp, (*i)->cstat, (*i)->rstat);
1335     if (rval) {
1336         fprintf (stderr, "CPXgetbase failed\n"); goto CLEANUP;
1337     }
1338 
1339     return 0;
1340 
1341 CLEANUP:
1342 
1343     CClp_free_info (i);
1344     return rval;
1345 }
1346 
CClp_create_info(CClp_info ** i,int rcount,int ccount)1347 int CClp_create_info (CClp_info **i, int rcount, int ccount)
1348 {
1349     int rval = 0;
1350     int j;
1351 
1352     CClp_free_info (i);
1353 
1354     (*i) = CC_SAFE_MALLOC (1, CClp_info);
1355     if ((*i) == (CClp_info *) NULL) {
1356         fprintf (stderr, "Out of memory in CClp_create_info\n");
1357         rval = 1; goto CLEANUP;
1358     }
1359 
1360     (*i)->ccount = 0;
1361     (*i)->rcount = 0;
1362     (*i)->cstat = (int *) NULL;
1363     (*i)->rstat = (int *) NULL;
1364 
1365     (*i)->ccount = ccount;
1366     if (ccount == 0) {
1367         fprintf (stderr, "No columns in CClp_create_info\n");
1368         rval = 1; goto CLEANUP;
1369     }
1370     (*i)->rcount = rcount;
1371     if (rcount == 0) {
1372         fprintf (stderr, "No rows in CClp_create_info\n");
1373         rval = 1; goto CLEANUP;
1374     }
1375 
1376     (*i)->cstat = CC_SAFE_MALLOC ((*i)->ccount, int);
1377     (*i)->rstat = CC_SAFE_MALLOC ((*i)->rcount, int);
1378     if (!(*i)->cstat || !(*i)->rstat) {
1379         fprintf (stderr, "out of memory in CClp_create_info\n");
1380         rval = 1; goto CLEANUP;
1381     }
1382 
1383     for (j=0; j<ccount; j++) {
1384         (*i)->cstat[j] = 0;
1385     }
1386     for (j=0; j<rcount; j++) {
1387         (*i)->rstat[j] = 0;
1388     }
1389 
1390     return 0;
1391 
1392   CLEANUP:
1393     CClp_free_info (i);
1394     return rval;
1395 }
1396 
CClp_is_col_active(CClp_info * i,int c)1397 int CClp_is_col_active (CClp_info *i, int c)
1398 {
1399     if (c < 0 || c >= i->ccount) return 0;
1400     return i->cstat[c] == 1 || i->cstat[c] == 2;
1401 }
1402 
CClp_is_row_active(CClp_info * i,int r)1403 int CClp_is_row_active (CClp_info *i, int r)
1404 {
1405     if (r < 0 || r >= i->rcount) return 0;
1406     return i->rstat[r] == 0;
1407 }
1408 
CClp_set_col_active(CClp_info * i,int c)1409 void CClp_set_col_active (CClp_info *i, int c)
1410 {
1411     if (c >= 0 && c < i->ccount) i->cstat[c] = 1;
1412 }
1413 
CClp_set_col_inactive(CClp_info * i,int c)1414 void CClp_set_col_inactive (CClp_info *i, int c)
1415 {
1416     if (c >= 0 && c < i->ccount) i->cstat[c] = 0;
1417 }
1418 
CClp_set_col_upper(CClp_info * i,int c)1419 void CClp_set_col_upper (CClp_info *i, int c)
1420 {
1421     if (c >= 0 && c < i->ccount) i->cstat[c] = 2;
1422 }
1423 
CClp_set_row_active(CClp_info * i,int r)1424 void CClp_set_row_active (CClp_info *i, int r)
1425 {
1426     if (r >= 0 && r < i->rcount) i->rstat[r] = 0;
1427 }
1428 
CClp_set_row_inactive(CClp_info * i,int r)1429 void CClp_set_row_inactive (CClp_info *i, int r)
1430 {
1431     if (r >= 0 && r < i->rcount) i->rstat[r] = 1;
1432 }
1433 
CClp_free_info(CClp_info ** i)1434 void CClp_free_info (CClp_info **i)
1435 {
1436     if ((*i) != (CClp_info *) NULL) {
1437         CC_IFFREE ((*i)->cstat, int);
1438         CC_IFFREE ((*i)->rstat, int);
1439         CC_FREE (*i, CClp_info);
1440     }
1441 }
1442 
CClp_x(CClp * lp,double * x)1443 int CClp_x (CClp *lp, double *x)
1444 {
1445     int rval = 0;
1446     int ncols;
1447 
1448     ncols = CPXgetnumcols (lp->cplex_env, lp->cplex_lp);
1449     if (ncols == 0) {
1450         fprintf (stderr, "No columns in LP\n");
1451         return 1;
1452     }
1453     rval = CPXgetx (lp->cplex_env, lp->cplex_lp, x, 0, ncols - 1);
1454     if (rval) {
1455         fprintf (stderr, "CPXgetx failed\n");
1456         return rval;
1457     }
1458     return 0;
1459 }
1460 
CClp_rc(CClp * lp,double * rc)1461 int CClp_rc (CClp *lp, double *rc)
1462 {
1463     int rval = 0;
1464     int ncols;
1465 
1466     ncols = CPXgetnumcols (lp->cplex_env, lp->cplex_lp);
1467     if (ncols == 0) {
1468         fprintf (stderr, "No columns in LP\n"); return 1;
1469     }
1470     rval = CPXgetdj (lp->cplex_env, lp->cplex_lp, rc, 0, ncols - 1);
1471     if (rval) {
1472         fprintf (stderr, "CPXgetdj failed\n"); return rval;
1473     }
1474     return 0;
1475 }
1476 
CClp_pi(CClp * lp,double * pi)1477 int CClp_pi (CClp *lp, double *pi)
1478 {
1479     int rval = 0;
1480     int nrows;
1481 
1482     if ( CPXgetmethod (lp->cplex_env, lp->cplex_lp) == CPX_ALG_DUAL       &&
1483          CPXgetstat (lp->cplex_env, lp->cplex_lp )  == CPX_STAT_INFEASIBLE  ) {
1484         rval = getfarkasmultipliers (lp, pi);
1485         if (rval) {
1486             fprintf (stderr, "getfarkasmultipliers failed\n"); return rval;
1487         }
1488         return 0;
1489     }
1490 
1491     nrows = CPXgetnumrows (lp->cplex_env, lp->cplex_lp);
1492     if (nrows == 0) {
1493         fprintf (stderr, "No rows in LP\n"); return 1;
1494     }
1495     rval = CPXgetpi (lp->cplex_env, lp->cplex_lp, pi, 0, nrows - 1);
1496     if (rval) {
1497         fprintf (stderr, "CPXgetpi failed\n"); return rval;
1498     }
1499     return 0;
1500 }
1501 
CClp_objval(CClp * lp,double * obj)1502 int CClp_objval (CClp *lp, double *obj)
1503 {
1504     int rval;
1505 
1506     rval = CPXgetobjval (lp->cplex_env, lp->cplex_lp, obj);
1507     if (rval) {
1508         fprintf (stderr, "CPXgetobjval failed\n");
1509         return rval;
1510     }
1511     return 0;
1512 }
1513 
CClp_nrows(CClp * lp)1514 int CClp_nrows (CClp *lp)
1515 {
1516     return CPXgetnumrows (lp->cplex_env, lp->cplex_lp);
1517 }
1518 
CClp_ncols(CClp * lp)1519 int CClp_ncols (CClp *lp)
1520 {
1521     return CPXgetnumcols (lp->cplex_env, lp->cplex_lp);
1522 }
1523 
CClp_nnonzeros(CClp * lp)1524 int CClp_nnonzeros (CClp *lp)
1525 {
1526     return CPXgetnumnz (lp->cplex_env, lp->cplex_lp);
1527 }
1528 
CClp_status(CClp * lp,int * status)1529 int CClp_status (CClp *lp, int *status)
1530 {
1531     int solmethod, solstat;
1532 
1533 #ifdef CC_ONE_ENV
1534     if (set_parameters (lp->cplex_env, &lp->cplex_params)) {
1535         fprintf (stderr, "Unable to set optimization parameters\n");
1536     }
1537 #endif
1538 
1539     solmethod = CPXgetmethod (lp->cplex_env, lp->cplex_lp);
1540     if (solmethod == CPX_ALG_PRIMAL || solmethod == CPX_ALG_DUAL) {
1541         solstat = CPXgetstat (lp->cplex_env, lp->cplex_lp);
1542         if (solstat == CPX_STAT_OPTIMAL || solstat == CPX_STAT_OPTIMAL_INFEAS) {
1543             *status = 0;
1544             return 0;
1545         } else if (solstat == CPX_STAT_INFEASIBLE && solmethod==CPX_ALG_DUAL) {
1546             *status = 1;
1547             return 0;
1548         } else {
1549             fprintf (stderr, "lp in an unknown state: %d %d\n",
1550                            solmethod, solstat);
1551             *status = -1;
1552             return 1;
1553         }
1554     } else {
1555         fprintf (stderr, "lp not solved by usual methods: %d\n", solmethod);
1556         *status = -2;
1557         return 1;
1558     }
1559 }
1560 
CClp_getweight(CClp * lp,int nrows,int * rmatbeg,int * rmatind,double * rmatval,double * weight)1561 int CClp_getweight (CClp *lp, int nrows, int *rmatbeg, int *rmatind,
1562                     double *rmatval, double *weight)
1563 {
1564     int rval = 0;
1565 
1566 #ifdef CC_ONE_ENV
1567     if (set_parameters (lp->cplex_env, &lp->cplex_params)) {
1568         fprintf (stderr, "Unable to set optimization parameters\n");
1569     }
1570 #endif
1571 
1572     rval = CPXgetweight (lp->cplex_env, lp->cplex_lp, nrows,
1573                          rmatbeg, rmatind, rmatval, weight, CPX_DPRIIND_STEEP);
1574     if (rval) {
1575         fprintf (stderr, "CPXgetweight failed\n");
1576     }
1577     return rval;
1578 }
1579 
CClp_dump_lp(CClp * lp,const char * fname)1580 int CClp_dump_lp (CClp *lp, const char *fname)
1581 {
1582     int rval = 0;
1583     char nambuf[32];
1584 
1585     /* We copy the name since CPXsavwrite doesn't declare fname as const */
1586     strncpy (nambuf, fname, sizeof (nambuf));
1587     nambuf[sizeof(nambuf)-1] = '\0';
1588 
1589     rval = CPXsavwrite (lp->cplex_env, lp->cplex_lp, nambuf);
1590     if (rval) {
1591         fprintf (stderr, "CPXsavwrite failed\n");
1592     }
1593     return rval;
1594 }
1595 
1596 #define OURCPLEXZERO    (1.0E-10)
1597 #define OURCPLEX_INTTOL (0.0001)
1598 
CClp_getgoodlist(CClp * lp,int * goodlist,int * goodlen_p,double * downpen,double * uppen)1599 int CClp_getgoodlist (CClp *lp, int *goodlist, int *goodlen_p,
1600                       double *downpen, double *uppen)
1601 {
1602     int  rval = 0;
1603     int  ncols, i, k;
1604     int  *cstat = (int *) NULL;
1605     double *x = (double *) NULL;
1606 
1607     /* Call CPXdualopt and verify optimality */
1608 
1609 #ifdef CC_ONE_ENV
1610     if (set_parameters (lp->cplex_env, &lp->cplex_params)) {
1611         fprintf (stderr, "Unable to set optimization parameters\n");
1612     }
1613 #endif
1614 
1615     rval = CPXdualopt (lp->cplex_env, lp->cplex_lp);
1616     if (rval) {
1617         fprintf (stderr, "CPXdualopt failed, return code %d\n", rval);
1618         rval = 1; goto CLEANUP;
1619     }
1620 
1621     ncols = CPXgetnumcols (lp->cplex_env, lp->cplex_lp);
1622     if ( ncols == 0 ) {
1623         fprintf (stderr, "No columns in LP\n");
1624         rval = 1; goto CLEANUP;
1625     }
1626 
1627     x = CC_SAFE_MALLOC (ncols, double);
1628     if (x == (double *) NULL) {
1629         fprintf (stderr, "out of memory in branch_getgoodlist\n");
1630         rval = 1; goto CLEANUP;
1631     }
1632     if (CPXgetx (lp->cplex_env, lp->cplex_lp, x, 0, ncols-1)) {
1633         fprintf (stderr, "CPXgetx failed\n");
1634         rval = 1; goto CLEANUP;
1635     }
1636 
1637     cstat = CC_SAFE_MALLOC (ncols, int);
1638     if ( cstat == (int *) NULL ) {
1639         fprintf (stderr, "Out of memory\n");
1640         rval = 1; goto CLEANUP;
1641     }
1642 
1643     /* Get basis */
1644 
1645     if ( CPXgetbase (lp->cplex_env, lp->cplex_lp, cstat, (int *) NULL) ) {
1646         fprintf (stderr, "CPXgetbase failed\n");
1647         rval = 1; goto CLEANUP;
1648     }
1649 
1650     /* Make initial goodlist and goodlen */
1651 
1652     *goodlen_p = 0;
1653     for (i = 0; i < ncols; i++) {
1654        if ( cstat[i] == 1 ) {
1655           goodlist[(*goodlen_p)++] = i;
1656        }
1657     }
1658 
1659     /* Call CPXmdleave */
1660 
1661     if ( CPXmdleave (lp->cplex_env, lp->cplex_lp, goodlist, *goodlen_p,
1662                      downpen, uppen)) {
1663        fprintf (stderr, "CPXmdleave failed\n");
1664        rval = 1; goto CLEANUP;
1665     }
1666 
1667     /* Keep only the nondegenerate ones */
1668 
1669     k = *goodlen_p;
1670     *goodlen_p = 0;
1671     for (i = 0; i < k; i++) {
1672        if ( CC_OURABS (downpen[i]) > OURCPLEXZERO   &&
1673             CC_OURABS (uppen[i])   > OURCPLEXZERO   &&
1674             x[goodlist[i]] >= OURCPLEX_INTTOL      &&
1675             x[goodlist[i]] <= 1.0 - OURCPLEX_INTTOL  ) {
1676           goodlist[*goodlen_p]  = goodlist[i];
1677           downpen[*goodlen_p]   = x[goodlist[i]] * downpen[i];
1678           uppen[*goodlen_p]     = (1.0 - x[goodlist[i]]) * uppen[i];
1679           (*goodlen_p)++;
1680        }
1681     }
1682 
1683     if (*goodlen_p == 0) {
1684         /* All edges have degenerate pivots */
1685         for (i = 0; i < k; i++) {
1686             if (x[goodlist[i]] >= OURCPLEX_INTTOL &&
1687                 x[goodlist[i]] <= 1.0 - OURCPLEX_INTTOL) {
1688                 goodlist[*goodlen_p] = goodlist[i];
1689                 downpen[*goodlen_p]  = x[goodlist[i]];
1690                 uppen[*goodlen_p]    = 1.0 - x[goodlist[i]];
1691                 (*goodlen_p)++;
1692             }
1693         }
1694     }
1695 
1696     rval = 0;
1697 
1698 CLEANUP:
1699 
1700     CC_IFFREE (cstat, int);
1701     CC_IFFREE (x, double);
1702     return rval;
1703 }
1704 
CClp_strongbranch(CClp * lp,int * candidatelist,int ncand,double * downpen,double * uppen,int iterations,double upperbound)1705 int CClp_strongbranch (CClp *lp, int *candidatelist, int ncand,
1706                        double *downpen, double *uppen, int iterations,
1707                        double upperbound)
1708 {
1709     double oldupperbound;
1710     int rval = 0;
1711     int sval = 0;
1712     int old_perind;
1713     int i;
1714 
1715 #ifdef CC_ONE_ENV
1716     if (set_parameters (lp->cplex_env, &lp->cplex_params)) {
1717         fprintf (stderr, "Unable to set optimization parameters\n");
1718     }
1719 #endif
1720 
1721     rval = CPXgetdblparam (lp->cplex_env, CPX_PARAM_OBJULIM,
1722                            &oldupperbound);
1723     if (rval) {
1724         fprintf (stderr, "CPXgetdblparam failed\n"); return rval;
1725     }
1726     rval = CPXsetdblparam (lp->cplex_env, CPX_PARAM_OBJULIM,
1727                            upperbound);
1728     if (rval) {
1729         fprintf (stderr, "CPXsetdblparam failed\n"); return rval;
1730     }
1731 
1732     /* REB, 14 October 1997:  If perturbation has been turned on elsewhere,
1733        we need to turn it off for branch selection */
1734 
1735     rval = CPXgetintparam (lp->cplex_env, CPX_PARAM_PERIND, &old_perind);
1736     if (rval) {
1737          fprintf (stderr, "CPXgetintparam failed\n"); return rval;
1738     }
1739 
1740     rval = CPXsetintparam (lp->cplex_env, CPX_PARAM_PERIND, 0);
1741     if (rval) {
1742          fprintf (stderr, "CPXsetintparam failed\n"); return rval;
1743     }
1744 
1745     rval = CPXstrongbranch (lp->cplex_env, lp->cplex_lp, candidatelist,
1746                             ncand, downpen, uppen, iterations);
1747 
1748     if (rval) {
1749         fprintf (stderr, "CPXstrongbranch failed, return code %d\n", rval);
1750         sval = CPXsetdblparam (lp->cplex_env, CPX_PARAM_OBJULIM,
1751                                oldupperbound);
1752         if (sval) {
1753             fprintf (stderr,
1754                      "CPXsetdblparam failed with return code %d\n",
1755                      sval);
1756         }
1757         return rval;
1758     }
1759 
1760     rval = CPXsetintparam (lp->cplex_env, CPX_PARAM_PERIND, old_perind);
1761     if (rval) {
1762          fprintf (stderr, "CPXsetintparam failed\n"); return rval;
1763     }
1764 
1765     rval = CPXsetdblparam (lp->cplex_env, CPX_PARAM_OBJULIM,
1766                            oldupperbound);
1767     if (rval) {
1768         fprintf (stderr, "CPXsetdblparam failed\n"); return rval;
1769     }
1770 
1771     for (i=0; i<ncand; i++) {
1772         if (downpen[i] > upperbound) downpen[i] = upperbound;
1773         if (uppen[i] > upperbound) uppen[i] = upperbound;
1774     }
1775 
1776     return 0;
1777 }
1778 
getfarkasmultipliers(CClp * lp,double * y)1779 static int getfarkasmultipliers (CClp *lp, double *y)
1780 {
1781     int  rval = 0;
1782 
1783     int  i = 0, nrows, idiv, jdiv;
1784     double  val, lb, ub;
1785     int  *bhead =  (int *) NULL;
1786     char  *sense = (char *) NULL;
1787 
1788 #ifdef CC_ONE_ENV
1789     if (set_parameters (lp->cplex_env, &lp->cplex_params)) {
1790         fprintf (stderr, "Unable to set optimization parameters\n");
1791     }
1792 #endif
1793 
1794     if ( lp->cplex_env == (struct cpxenv *) NULL ||
1795          lp->cplex_lp  == (struct cpxlp *)  NULL) {
1796         rval = 1;  fprintf (stderr, "env object or lp object is NULL\n");
1797         goto CLEANUP;
1798     }
1799 
1800     if ( CPXgetmethod (lp->cplex_env, lp->cplex_lp) != CPX_ALG_DUAL  ||
1801          CPXgetstat (lp->cplex_env, lp->cplex_lp )  != CPX_STAT_INFEASIBLE  ) {
1802         rval = 1;  fprintf (stderr, "Incorrect solution type\n");
1803         goto CLEANUP;
1804     }
1805 
1806     if ( CPXgetijdiv (lp->cplex_env, lp->cplex_lp, &idiv, &jdiv) ) {
1807         rval = 1;  fprintf (stderr, "CPXgetijdiv failed\n");
1808         goto CLEANUP;
1809     }
1810 
1811     if ( (jdiv == -1  &&  idiv == -1) ||
1812          (jdiv != -1  &&  idiv != -1)   ) {
1813         rval = 1;  fprintf (stderr, "CPLEX returned illegal indices\n");
1814         goto CLEANUP;
1815     }
1816 
1817     nrows = CPXgetnumrows (lp->cplex_env, lp->cplex_lp);
1818     if ( nrows == 0 ) {
1819         rval = 1;  fprintf (stderr, "lp->cplex_lp has no rows\n");
1820         goto CLEANUP;
1821     }
1822 
1823     bhead = CC_SAFE_MALLOC (nrows, int);
1824     sense = CC_SAFE_MALLOC (nrows, char);
1825     if ( bhead == (int *) NULL ||
1826          sense == (char *) NULL   ) {
1827         rval = -1;  fprintf (stderr, "Out of memory\n");
1828         goto CLEANUP;
1829     }
1830 
1831     if ( CPXgetbhead (lp->cplex_env, lp->cplex_lp, bhead, NULL) ) {
1832         rval = 1;  fprintf (stderr, "CPXgetbhead failed\n");
1833         goto CLEANUP;
1834     }
1835 
1836     if ( CPXgetsense (lp->cplex_env, lp->cplex_lp, sense, 0, nrows-1) ) {
1837         rval = 1;  fprintf (stderr, "CPXgetsense failed\n");
1838         goto CLEANUP;
1839     }
1840 
1841     if ( jdiv >= 0 ) {
1842         for (i = 0; i < nrows; i++) {
1843             if ( bhead[i] == jdiv )  break;
1844         }
1845         if ( i == nrows ) {
1846             rval = 1;  fprintf (stderr, "Basis index not found\n");
1847             goto CLEANUP;
1848         }
1849         if ( CPXgetx (lp->cplex_env, lp->cplex_lp, &val, jdiv, jdiv) ) {
1850             rval = 1;  fprintf (stderr, "CPXgetx failed\n");
1851             goto CLEANUP;
1852         }
1853         if ( CPXgetlb (lp->cplex_env, lp->cplex_lp, &lb, jdiv, jdiv) ) {
1854             rval = 1;  fprintf (stderr, "CPXgetlb failed\n");
1855             goto CLEANUP;
1856         }
1857         if ( CPXgetub (lp->cplex_env, lp->cplex_lp, &ub, jdiv, jdiv) ) {
1858             rval = 1;  fprintf (stderr, "CPXgetub failed\n");
1859             goto CLEANUP;
1860         }
1861     } else {
1862         for (i = 0; i < nrows; i++) {
1863             if ( bhead[i] ==  -idiv-1 )  break;
1864         }
1865         if ( i == nrows ) {
1866             rval = 1;  fprintf (stderr, "Basis index not found\n");
1867             goto CLEANUP;
1868         }
1869         if ( CPXgetslack (lp->cplex_env, lp->cplex_lp, &val, idiv, idiv) ) {
1870             rval = 1;  fprintf (stderr, "CPXgetslack failed\n");
1871             goto CLEANUP;
1872         }
1873         lb = 0.0;
1874         if ( sense[idiv] == 'E' )  ub = 0.0;
1875         else                       ub = CPX_INFBOUND;
1876         if ( sense[idiv] == 'G' )  val *= -1.0;
1877     }
1878 
1879     if ( CPXbinvrow (lp->cplex_env, lp->cplex_lp, i, y) ) {
1880         rval = 1;  fprintf (stderr, "CPXbinvrow failed\n");
1881         goto CLEANUP;
1882     }
1883 
1884     if ( val < lb ) {
1885         for (i = 0; i < nrows; i++)  y[i] *= -1.0;
1886     }
1887 
1888     for (i = 0; i < nrows; i++) {
1889         if ( sense[i] == 'L'  &&  y[i] > 0.0 )  y[i] = 0.0;
1890         if ( sense[i] == 'G'  &&  y[i] < 0.0 )  y[i] = 0.0;
1891     }
1892 
1893 CLEANUP:
1894 
1895     CC_IFFREE (bhead, int);
1896     CC_IFFREE (sense, char);
1897 
1898     return rval;
1899 }
1900 
1901 #ifdef CC_ONE_ENV
1902 
set_parameters(CPXENVptr cplex_env,CClp_parameters * params)1903 static int set_parameters (CPXENVptr cplex_env, CClp_parameters *params)
1904 {
1905     int rval;
1906 
1907     /* the documentation doesn't say what the return value means */
1908     rval = CPXsetintparam (cplex_env, CPX_PARAM_SCRIND, params->scrind);
1909     if (rval) {
1910         fprintf (stderr, "CPXsetintparam CPX_PARAM_SCRIND failed\n");
1911         goto CLEANUP;
1912     }
1913 
1914     rval = CPXsetintparam (cplex_env, CPX_PARAM_SIMDISPLAY,
1915                            params->simdisplay);
1916     if (rval) {
1917         fprintf (stderr, "CPXsetintparam CPX_PARAM_SIMDISPLAY failed\n");
1918         goto CLEANUP;
1919     }
1920 
1921     rval = CPXsetintparam (cplex_env, CPX_PARAM_FASTMIP, params->fastmip);
1922     if (rval) {
1923         fprintf (stderr, "CPXsetintparam CPX_PARAM_FASTMIP failed\n");
1924         goto CLEANUP;
1925     }
1926     rval = CPXsetintparam (cplex_env, CPX_PARAM_ADVIND, params->advind);
1927     if (rval) {
1928         fprintf (stderr, "CPXsetintparam CPX_PARAM_ADVIND failed\n");
1929         goto CLEANUP;
1930     }
1931     rval = CPXsetintparam (cplex_env, CPX_PARAM_DPRIIND, params->dpriind);
1932     if (rval) {
1933         fprintf (stderr, "CPXsetintparam CPX_PARAM_DPRIIND failed\n");
1934         goto CLEANUP;
1935     }
1936     rval = CPXsetintparam (cplex_env, CPX_PARAM_PPRIIND, params->ppriind);
1937     if (rval) {
1938         fprintf (stderr, "CPXsetintparam CPX_PARAM_PPRIIND failed\n");
1939         goto CLEANUP;
1940     }
1941 
1942     rval = CPXsetdblparam (cplex_env, CPX_PARAM_EPPER, params->epper);
1943     if (rval) {
1944         fprintf (stderr, "CPXsetdblparam CPX_PARAM_EPPER failed\n");
1945         goto CLEANUP;
1946     }
1947     rval = CPXsetdblparam (cplex_env, CPX_PARAM_EPOPT, params->epopt);
1948     if (rval) {
1949         fprintf (stderr, "CPXsetdblparam CPX_PARAM_EPOPT failed\n");
1950         goto CLEANUP;
1951     }
1952     rval = CPXsetdblparam (cplex_env, CPX_PARAM_EPRHS, params->eprhs);
1953     if (rval) {
1954         fprintf (stderr, "CPXsetdblparam CPX_PARAM_EPRHS failed\n");
1955         goto CLEANUP;
1956     }
1957 
1958     rval = CPXsetintparam (cplex_env, CPX_PARAM_PERIND, params->perind);
1959     if (rval) {
1960         fprintf (stderr, "CPXsetintparam CPX_PARAM_PERIND failed\n");
1961         goto CLEANUP;
1962     }
1963 
1964     rval = CPXsetintparam (cplex_env, CPX_PARAM_PREIND, params->preind);
1965     if (rval) {
1966         fprintf (stderr, "CPXsetintparam CPX_PARAM_PREIND failed\n");
1967         goto CLEANUP;
1968     }
1969 
1970     rval = CPXsetintparam (cplex_env, CPX_PARAM_AGGIND, params->aggind);
1971     if (rval) {
1972         fprintf (stderr, "CPXsetintparam CPX_PARAM_AGGIND failed\n");
1973         goto CLEANUP;
1974     }
1975 
1976     rval = 0;
1977   CLEANUP:
1978     return rval;
1979 }
1980 #endif /* CC_ONE_ENV */
1981