1 /* cplex.c (CPLEX-like interface to GLPK API) */
2
3 /***********************************************************************
4 * This code is part of GLPK (GNU Linear Programming Kit).
5 * Copyright (C) 2001-2013 Free Software Foundation, Inc.
6 * Written by Andrew Makhorin <mao@gnu.org>.
7 *
8 * GLPK is free software: you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * GLPK is distributed in the hope that it will be useful, but WITHOUT
14 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
16 * License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with GLPK. If not, see <http://www.gnu.org/licenses/>.
20 ***********************************************************************/
21
22 #include <ctype.h>
23 #include <stdarg.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <glpk.h>
28 #include "cplex.h"
29
30 struct CPXENV
31 { /* environment block */
32 CPXLP *list;
33 /* linked list of problem objects */
34 int *intparam; /* int intparam[]; */
35 /* integer control parameters */
36 double *dblparam; /* double dblparam[]; */
37 /* floating-point control parameters */
38 };
39
40 struct CPXLP
41 { /* problem object */
42 CPXENV *env;
43 /* pointer to environment block */
44 glp_prob *prob;
45 /* pointer to underlying GLPK problem object */
46 int rflen;
47 /* length of the array rflag */
48 char *rflag; /* char rflag[rflen]; */
49 /* rflag[i], i = 0,...,nrows-1, is a flag of i-th row: */
50 #define RF_NOT_RANGED 0 /* not ranged */
51 #define RF_RANGED_POS 1 /* ranged, RHS = lower bound */
52 #define RF_RANGED_NEG 2 /* ranged, RHS = upper bound */
53 int stat;
54 /* solution status reported by CPXgetstat; zero means no solution
55 exists */
56 int meth;
57 /* method indicator reported by CPXgetmethod */
58 int iwlen;
59 /* length of the working array */
60 int *iwork; /* int iwork[iwlen] */
61 /* working array initialized by binary zeros */
62 CPXLP *link;
63 /* pointer to another problem object */
64 };
65
66 struct intparam
67 { int which;
68 int defv;
69 int minv;
70 int maxv;
71 };
72
73 struct dblparam
74 { int which;
75 double defv;
76 double minv;
77 double maxv;
78 };
79
80 struct errstring
81 { int code;
82 const char *string;
83 };
84
85 #define BIGINT 2100000000
86 #define BIGDBL 1e75
87
88 static const struct intparam intparam[] =
89 { {CPX_PARAM_ADVIND, 0, 0, 2},
90 {CPX_PARAM_AGGIND, -1, -1, BIGINT},
91 {CPX_PARAM_DATACHECK, CPX_OFF, CPX_OFF, CPX_ON},
92 {CPX_PARAM_DPRIIND, CPX_DPRIIND_AUTO, CPX_DPRIIND_AUTO,
93 CPX_DPRIIND_DEVEX},
94 {CPX_PARAM_FASTMIP, CPX_OFF, CPX_OFF, CPX_ON}, /* ??? */
95 {CPX_PARAM_ITLIM, BIGINT, 0, BIGINT},
96 {CPX_PARAM_PERIND, CPX_OFF, CPX_OFF, CPX_ON},
97 {CPX_PARAM_PPRIIND, CPX_PPRIIND_AUTO, CPX_PPRIIND_PARTIAL,
98 CPX_PPRIIND_FULL},
99 {CPX_PARAM_PREIND, CPX_ON, CPX_OFF, CPX_ON},
100 {CPX_PARAM_REINV, 0, 0, 10000},
101 {CPX_PARAM_SCRIND, CPX_OFF, CPX_OFF, CPX_ON},
102 {CPX_PARAM_SIMDISPLAY, 1, 0, 2},
103 };
104
105 static const struct dblparam dblparam[] =
106 { {CPX_PARAM_EPOPT, 1e-6, 1e-9, 1e-1},
107 {CPX_PARAM_EPPER, 1e-6, 1e-8, BIGDBL},
108 {CPX_PARAM_EPRHS, 1e-6, 1e-9, 1e-1},
109 {CPX_PARAM_OBJLLIM, -BIGDBL, -BIGDBL, +BIGDBL},
110 {CPX_PARAM_OBJULIM, +BIGDBL, -BIGDBL, +BIGDBL},
111 };
112
113 static const struct errstring errstring[] =
114 { {CPXERR_ARRAY_NOT_ASCENDING, "Array entry %d not ascending"},
115 {CPXERR_BAD_ARGUMENT, "Invalid argument"},
116 {CPXERR_BAD_CTYPE, "Invalid ctype entry %d"},
117 {CPXERR_BAD_FILETYPE, "Invalid filetype"},
118 {CPXERR_BAD_LUB, "Invalid bound change indicator entry %d"},
119 {CPXERR_BAD_PARAM_NUM, "Invalid parameter number"},
120 {CPXERR_BAD_SENSE, "Invalid sense entry %d"},
121 {CPXERR_BAD_STATUS, "Invalid status entry %d for basis specificat"
122 "ion"},
123 {CPXERR_COL_INDEX_RANGE, "Column index %d out of range"},
124 {CPXERR_COUNT_RANGE, "Count entry %d negative or larger than allo"
125 "wed"},
126 {CPXERR_DUP_ENTRY, "Duplicate entry"},
127 {CPXERR_FAIL_OPEN_WRITE, "Could not open file '%s' for writing"},
128 {CPXERR_INDEX_RANGE, "Index is outside range of valid values"},
129 {CPXERR_NEGATIVE_SURPLUS, "Insufficient array length"},
130 {CPXERR_NO_BASIC_SOLN, "No basic solution exists"},
131 {CPXERR_NO_ENVIRONMENT, "No environment exists"},
132 {CPXERR_NO_FILENAME, "File name not specified"},
133 {CPXERR_NO_MEMORY, "Out of memory"},
134 {CPXERR_NO_PROBLEM, "No problem exists"},
135 {CPXERR_NO_SOLN, "No solution exists"},
136 {CPXERR_NOT_FIXED, "Only fixed variables are pivoted out"},
137 {CPXERR_NULL_NAME, "Null pointer %d in name array"},
138 {CPXERR_NULL_POINTER, "Null pointer for required data"},
139 {CPXERR_PARAM_TOO_BIG, "Parameter value too big"},
140 {CPXERR_PARAM_TOO_SMALL, "Parameter value too small"},
141 {CPXERR_ROW_INDEX_RANGE, "Row index %d out of range"},
142 };
143
144 /**********************************************************************/
145
146 #define xassert glp_assert
147 #define xprintf glp_printf
148 #define xmalloc glp_malloc
149 #define xcalloc glp_calloc
150 #define xfree glp_free
151
152 /**********************************************************************/
153
findintparam(int whichparam)154 static int findintparam(int whichparam)
155 { int k, card;
156 card = sizeof(intparam) / sizeof(struct intparam);
157 for (k = 0; k < card; k++)
158 if (intparam[k].which == whichparam) return k;
159 return -1;
160 }
161
getintparam(CPXENV * env,int whichparam)162 static int getintparam(CPXENV *env, int whichparam)
163 { int k;
164 xassert(env != NULL);
165 k = findintparam(whichparam);
166 xassert(k >= 0);
167 return env->intparam[k];
168 }
169
finddblparam(int whichparam)170 static int finddblparam(int whichparam)
171 { int k, card;
172 card = sizeof(dblparam) / sizeof(struct dblparam);
173 for (k = 0; k < card; k++)
174 if (dblparam[k].which == whichparam) return k;
175 return -1;
176 }
177
getdblparam(CPXENV * env,int whichparam)178 static double getdblparam(CPXENV *env, int whichparam)
179 { int k;
180 xassert(env != NULL);
181 k = finddblparam(whichparam);
182 xassert(k >= 0);
183 return env->dblparam[k];
184 }
185
finderrstring(int errcode)186 static const char *finderrstring(int errcode)
187 { int k, card;
188 card = sizeof(errstring) / sizeof(struct errstring);
189 for (k = 0; k < card; k++)
190 { if (errstring[k].code == errcode)
191 return errstring[k].string;
192 }
193 return NULL;
194 }
195
error(CPXENV * env,int errcode,...)196 static int error(CPXENV *env, int errcode, ...)
197 { va_list arg;
198 char buffer[510];
199 xassert(env != NULL);
200 if (getintparam(env, CPX_PARAM_SCRIND) == CPX_ON)
201 { xassert(CPXgeterrorstring(env, errcode, buffer) == buffer);
202 va_start(arg, errcode);
203 vprintf(buffer, arg);
204 va_end(arg);
205 }
206 return errcode;
207 }
208
checkenv(CPXENV * env)209 static int checkenv(CPXENV *env)
210 { int errcode;
211 if (env == NULL)
212 errcode = CPXERR_NO_ENVIRONMENT;
213 else
214 errcode = 0;
215 return errcode;
216 }
217
checklp(CPXENV * env,CPXLP * lp)218 static checklp(CPXENV *env, CPXLP *lp)
219 { int errcode;
220 errcode = checkenv(env);
221 if (errcode) goto done;
222 if (lp == NULL)
223 errcode = error(env, CPXERR_NO_PROBLEM);
224 done: return errcode;
225 }
226
invalidate(CPXLP * lp)227 static void invalidate(CPXLP *lp)
228 { lp->stat = 0;
229 lp->meth = CPX_ALG_NONE;
230 return;
231 }
232
enlargerflag(CPXLP * lp)233 static void enlargerflag(CPXLP *lp)
234 { int m;
235 xassert(lp != NULL);
236 m = glp_get_num_rows(lp->prob);
237 if (lp->rflen < m)
238 { int rflen = lp->rflen;
239 char *rflag = lp->rflag;
240 while (lp->rflen < m)
241 { lp->rflen += lp->rflen;
242 xassert(lp->rflen > 0);
243 }
244 lp->rflag = xcalloc(lp->rflen, sizeof(char));
245 memcpy(lp->rflag, rflag, rflen);
246 xfree(rflag);
247 }
248 return;
249 }
250
enlargeiwork(CPXLP * lp,int len)251 static void enlargeiwork(CPXLP *lp, int len)
252 { xassert(len >= 0);
253 if (lp->iwlen < len)
254 { xfree(lp->iwork);
255 while (lp->iwlen < len)
256 { lp->iwlen += lp->iwlen;
257 xassert(lp->iwlen > 0);
258 }
259 lp->iwork = xcalloc(lp->iwlen, sizeof(int));
260 memset(lp->iwork, 0, lp->iwlen * sizeof(int));
261 }
262 return;
263 }
264
265 /**********************************************************************/
266
CPXaddcols(CPXENV * env,CPXLP * lp,int ccnt,int nzcnt,const double obj[],const int cmatbeg[],const int cmatind[],const double cmatval[],const double lb[],const double ub[],char * colname[])267 int CPXaddcols(CPXENV *env, CPXLP *lp, int ccnt, int nzcnt,
268 const double obj[], const int cmatbeg[], const int cmatind[],
269 const double cmatval[], const double lb[], const double ub[],
270 char *colname[])
271 { int j, k, m, n, beg, end, type, errcode;
272 double lbnd, ubnd;
273 errcode = checklp(env, lp);
274 if (errcode) goto done;
275 if (ccnt < 0 || nzcnt < 0)
276 { errcode = error(env, CPXERR_BAD_ARGUMENT);
277 goto done;
278 }
279 if (ccnt > 0)
280 { if (cmatbeg == NULL || cmatind == NULL || cmatval == NULL)
281 { errcode = error(env, CPXERR_NULL_POINTER);
282 goto done;
283 }
284 }
285 m = glp_get_num_rows(lp->prob);
286 n = glp_get_num_cols(lp->prob);
287 enlargeiwork(lp, m);
288 for (j = 0; j < ccnt; j++)
289 { beg = cmatbeg[j];
290 if (j > 0 && !(cmatbeg[j-1] <= beg))
291 { errcode = error(env, CPXERR_ARRAY_NOT_ASCENDING, j);
292 goto done;
293 }
294 if (!(0 <= beg && beg <= nzcnt))
295 { errcode = error(env, CPXERR_INDEX_RANGE);
296 goto done;
297 }
298 end = (j < ccnt-1 ? cmatbeg[j+1] : nzcnt);
299 for (k = beg; k < end; k++)
300 { if (!(0 <= cmatind[k] && cmatind[k] < m))
301 { errcode = error(env, CPXERR_ROW_INDEX_RANGE, k);
302 goto done;
303 }
304 }
305 errcode = 0;
306 for (k = beg; k < end; k++)
307 { if (lp->iwork[cmatind[k]])
308 { errcode = error(env, CPXERR_DUP_ENTRY);
309 break;
310 }
311 lp->iwork[cmatind[k]] = 1;
312 }
313 for (k = beg; k < end; k++)
314 lp->iwork[cmatind[k]] = 0;
315 if (errcode) goto done;
316 if (colname != NULL)
317 { if (colname[j] == NULL)
318 { errcode = error(env, CPXERR_NULL_NAME, j);
319 goto done;
320 }
321 }
322 }
323 errcode = 0;
324 invalidate(lp);
325 if (ccnt > 0)
326 glp_add_cols(lp->prob, ccnt);
327 for (j = 0; j < ccnt; j++)
328 { if (colname != NULL)
329 glp_set_col_name(lp->prob, n+j+1, colname[j]);
330 lbnd = (lb == NULL ? 0.0 : lb[j]);
331 ubnd = (ub == NULL ? +CPX_INFBOUND : ub[j]);
332 if (lbnd <= -CPX_INFBOUND && ubnd >= +CPX_INFBOUND)
333 type = GLP_FR;
334 else if (ubnd >= +CPX_INFBOUND)
335 type = GLP_LO;
336 else if (lbnd <= -CPX_INFBOUND)
337 type = GLP_UP;
338 else if (lbnd != ubnd)
339 type = GLP_DB;
340 else
341 type = GLP_FX;
342 glp_set_col_bnds(lp->prob, n+j+1, type, lbnd, ubnd);
343 if (obj != NULL)
344 glp_set_obj_coef(lp->prob, n+j+1, obj[j]);
345 beg = cmatbeg[j];
346 end = (j < ccnt-1 ? cmatbeg[j+1] : nzcnt);
347 for (k = beg; k < end; k++)
348 lp->iwork[k-beg] = cmatind[k]+1;
349 glp_set_mat_col(lp->prob, n+j+1, end-beg, lp->iwork-1,
350 cmatval+beg-1);
351 for (k = beg; k < end; k++)
352 lp->iwork[k-beg] = 0;
353 }
354 done: return errcode;
355 }
356
CPXaddrows(CPXENV * env,CPXLP * lp,int ccnt,int rcnt,int nzcnt,const double rhs[],const char sense[],const int rmatbeg[],const int rmatind[],const double rmatval[],char * colname[],char * rowname[])357 int CPXaddrows(CPXENV *env, CPXLP *lp, int ccnt, int rcnt, int nzcnt,
358 const double rhs[], const char sense[], const int rmatbeg[],
359 const int rmatind[], const double rmatval[], char *colname[],
360 char *rowname[])
361 { int i, j, k, m, n, beg, end, type, errcode;
362 double temp;
363 errcode = checklp(env, lp);
364 if (errcode) goto done;
365 if (ccnt < 0 || rcnt < 0 || nzcnt < 0)
366 { errcode = error(env, CPXERR_BAD_ARGUMENT);
367 goto done;
368 }
369 if (rcnt > 0)
370 { if (rmatbeg == NULL || rmatind == NULL || rmatval == NULL)
371 { errcode = error(env, CPXERR_NULL_POINTER);
372 goto done;
373 }
374 }
375 m = glp_get_num_rows(lp->prob);
376 n = glp_get_num_cols(lp->prob);
377 enlargeiwork(lp, n+ccnt);
378 for (i = 0; i < rcnt; i++)
379 { if (sense != NULL)
380 { if (!(sense[i] == 'L' || sense[i] == 'E' ||
381 sense[i] == 'G' || sense[i] == 'R'))
382 { errcode = error(env, CPXERR_BAD_SENSE, i);
383 goto done;
384 }
385 }
386 beg = rmatbeg[i];
387 if (i > 0 && !(rmatbeg[i-1] <= beg))
388 { errcode = error(env, CPXERR_ARRAY_NOT_ASCENDING, i);
389 goto done;
390 }
391 if (!(0 <= beg && beg <= nzcnt))
392 { errcode = error(env, CPXERR_INDEX_RANGE);
393 goto done;
394 }
395 end = (i < rcnt-1 ? rmatbeg[i+1] : nzcnt);
396 for (k = beg; k < end; k++)
397 { if (!(0 <= rmatind[k] && rmatind[k] < n+ccnt))
398 { errcode = error(env, CPXERR_COL_INDEX_RANGE, k);
399 goto done;
400 }
401 }
402 errcode = 0;
403 for (k = beg; k < end; k++)
404 { if (lp->iwork[rmatind[k]])
405 { errcode = error(env, CPXERR_DUP_ENTRY);
406 break;
407 }
408 lp->iwork[rmatind[k]] = 1;
409 }
410 for (k = beg; k < end; k++)
411 lp->iwork[rmatind[k]] = 0;
412 if (errcode) goto done;
413 if (rowname != NULL)
414 { if (rowname[i] == NULL)
415 { errcode = error(env, CPXERR_NULL_NAME, i);
416 goto done;
417 }
418 }
419 }
420 for (j = 0; j < ccnt; j++)
421 { if (colname != NULL)
422 { if (colname[j] == NULL)
423 { errcode = error(env, CPXERR_NULL_NAME, j);
424 goto done;
425 }
426 }
427 }
428 errcode = 0;
429 invalidate(lp);
430 if (rcnt > 0)
431 glp_add_rows(lp->prob, rcnt);
432 if (ccnt > 0)
433 glp_add_cols(lp->prob, ccnt);
434 enlargerflag(lp);
435 for (i = 0; i < rcnt; i++)
436 { if (rowname != NULL)
437 glp_set_row_name(lp->prob, m+i+1, rowname[i]);
438 temp = (rhs == NULL ? 0.0 : rhs[i]);
439 if (sense == NULL || sense[i] == 'E')
440 { lp->rflag[m+i] = RF_NOT_RANGED;
441 type = GLP_FX;
442 }
443 else if (sense[i] == 'L')
444 { lp->rflag[m+i] = RF_NOT_RANGED;
445 type = GLP_UP;
446 }
447 else if (sense[i] == 'G')
448 { lp->rflag[m+i] = RF_NOT_RANGED;
449 type = GLP_LO;
450 }
451 else if (sense[i] == 'R')
452 { lp->rflag[m+i] = RF_RANGED_POS;
453 type = GLP_FX;
454 }
455 else
456 xassert(sense != sense);
457 glp_set_row_bnds(lp->prob, m+i+1, type, temp, temp);
458 beg = rmatbeg[i];
459 end = (i < rcnt-1 ? rmatbeg[i+1] : nzcnt);
460 for (k = beg; k < end; k++)
461 lp->iwork[k-beg] = rmatind[k]+1;
462 glp_set_mat_row(lp->prob, m+i+1, end-beg, lp->iwork-1,
463 rmatval+beg-1);
464 for (k = beg; k < end; k++)
465 lp->iwork[k-beg] = 0;
466 }
467 for (j = 0; j < ccnt; j++)
468 { if (colname != NULL)
469 glp_set_col_name(lp->prob, n+j+1, colname[j]);
470 glp_set_col_bnds(lp->prob, n+j+1, GLP_LO, 0.0, 0.0);
471 }
472 done: return errcode;
473 }
474
CPXbaropt(CPXENV * env,CPXLP * lp)475 int CPXbaropt(CPXENV *env, CPXLP *lp)
476 { xassert(env == env);
477 xassert(lp == lp);
478 xprintf("CPXbaropt: not implemented yet\n");
479 exit(EXIT_FAILURE);
480 return -1;
481 }
482
CPXbinvrow(CPXENV * env,CPXLP * lp,int i,double y[])483 int CPXbinvrow(CPXENV *env, CPXLP *lp, int i, double y[])
484 { xassert(env == env);
485 xassert(lp == lp);
486 xassert(i == i);
487 xassert(y == y);
488 xprintf("CPXbinvrow: not implemented yet\n");
489 exit(EXIT_FAILURE);
490 return -1;
491 }
492
CPXchgbds(CPXENV * env,CPXLP * lp,int cnt,const int indices[],const char lu[],const double bd[])493 int CPXchgbds(CPXENV *env, CPXLP *lp, int cnt, const int indices[],
494 const char lu[], const double bd[])
495 { int j, n, type, errcode;
496 double lbnd, ubnd;
497 errcode = checklp(env, lp);
498 if (errcode) goto done;
499 if (cnt < 0)
500 { errcode = error(env, CPXERR_BAD_ARGUMENT);
501 goto done;
502 }
503 if (cnt > 0)
504 { if (indices == NULL || lu == NULL || bd == NULL)
505 { errcode = error(env, CPXERR_NULL_POINTER);
506 goto done;
507 }
508 }
509 n = glp_get_num_cols(lp->prob);
510 for (j = 0; j < cnt; j++)
511 { if (!(0 <= indices[j] && indices[j] < n))
512 { errcode = error(env, CPXERR_COL_INDEX_RANGE, j);
513 goto done;
514 }
515 if (!(lu[j] == 'L' || lu[j] == 'U' || lu[j] == 'B'))
516 { errcode = error(env, CPXERR_BAD_LUB, j);
517 goto done;
518 }
519 }
520 errcode = 0;
521 invalidate(lp);
522 for (j = 0; j < cnt; j++)
523 { type = glp_get_col_type(lp->prob, indices[j]+1);
524 lbnd = glp_get_col_lb(lp->prob, indices[j]+1);
525 ubnd = glp_get_col_ub(lp->prob, indices[j]+1);
526 if (type == GLP_FR || type == GLP_UP)
527 lbnd = -CPX_INFBOUND;
528 if (type == GLP_FR || type == GLP_LO)
529 ubnd = +CPX_INFBOUND;
530 if (lu[j] == 'L')
531 lbnd = bd[j];
532 else if (lu[j] == 'U')
533 ubnd = bd[j];
534 else if (lu[j] == 'B')
535 lbnd = ubnd = bd[j];
536 else
537 xassert(lu != lu);
538 if (lbnd <= -CPX_INFBOUND && ubnd >= +CPX_INFBOUND)
539 type = GLP_FR;
540 else if (ubnd >= +CPX_INFBOUND)
541 type = GLP_LO;
542 else if (lbnd <= -CPX_INFBOUND)
543 type = GLP_UP;
544 else if (lbnd != ubnd)
545 type = GLP_DB;
546 else
547 type = GLP_FX;
548 glp_set_col_bnds(lp->prob, indices[j]+1, type, lbnd, ubnd);
549 }
550 done: return errcode;
551 }
552
CPXchgcoeflist(CPXENV * env,CPXLP * lp,int numcoefs,const int rowlist[],const int collist[],const double vallist[])553 int CPXchgcoeflist(CPXENV *env, CPXLP *lp, int numcoefs,
554 const int rowlist[], const int collist[], const double vallist[])
555 { int i, j, k, m, n, rcnt, ccnt, len, ptr, errcode;
556 int *head, *next, *ind;
557 double *val;
558 errcode = checklp(env, lp);
559 if (errcode) goto done;
560 if (numcoefs < 0)
561 { errcode = error(env, CPXERR_BAD_ARGUMENT);
562 goto done;
563 }
564 if (numcoefs == 0)
565 { errcode = 0;
566 goto done;
567 }
568 if (rowlist == NULL || collist == NULL || vallist == NULL)
569 { errcode = error(env, CPXERR_NULL_POINTER);
570 goto done;
571 }
572 /* check triplets and determine the number of rows and columns
573 to be changed */
574 m = glp_get_num_rows(lp->prob);
575 n = glp_get_num_cols(lp->prob);
576 enlargeiwork(lp, m);
577 enlargeiwork(lp, n);
578 rcnt = ccnt = 0;
579 for (k = 0; k < numcoefs; k++)
580 { i = rowlist[k];
581 if (!(0 <= i && i < m))
582 { errcode = error(env, CPXERR_ROW_INDEX_RANGE, i);
583 goto done;
584 }
585 if (!(lp->iwork[i] & 0x01))
586 rcnt++, lp->iwork[i] |= 0x01;
587 j = collist[k];
588 if (!(0 <= j && j < n))
589 { errcode = error(env, CPXERR_COL_INDEX_RANGE, j);
590 goto done;
591 }
592 if (!(lp->iwork[j] & 0x02))
593 ccnt++, lp->iwork[j] |= 0x02;
594 }
595 memset(lp->iwork, 0, m * sizeof(int));
596 memset(lp->iwork, 0, n * sizeof(int));
597 errcode = 0;
598 invalidate(lp);
599 if (rcnt <= ccnt)
600 { /* change the matrix by rows */
601 /* build the linked list of triplets:
602 head[i] is a pointer to first triplet for row i
603 next[k] is a pointer to next triplet for the same row */
604 head = xcalloc(m, sizeof(int));
605 for (i = 0; i < m; i++)
606 head[i] = -1;
607 next = xcalloc(numcoefs, sizeof(int));
608 for (k = 0; k < numcoefs; k++)
609 { i = rowlist[k];
610 next[k] = head[i];
611 head[i] = k;
612 }
613 /* check duplicate columns */
614 for (i = 0; i < m; i++)
615 { for (k = head[i]; k >= 0; k = next[k])
616 { j = collist[k];
617 if (lp->iwork[j])
618 { xfree(head);
619 xfree(next);
620 errcode = error(env, CPXERR_DUP_ENTRY);
621 goto done;
622 }
623 lp->iwork[j] = 1;
624 }
625 for (k = head[i]; k >= 0; k = next[k])
626 lp->iwork[collist[k]] = 0;
627 }
628 /* perform operation */
629 ind = xcalloc(1+n, sizeof(int));
630 val = xcalloc(1+n, sizeof(double));
631 for (i = 0; i < m; i++)
632 { if (head[i] < 0) continue;
633 len = glp_get_mat_row(lp->prob, i+1, ind, val);
634 for (ptr = 1; ptr <= len; ptr++)
635 { j = ind[ptr]-1;
636 xassert(lp->iwork[j] == 0);
637 lp->iwork[j] = ptr;
638 }
639 for (k = head[i]; k >= 0; k = next[k])
640 { j = collist[k];
641 if (lp->iwork[j] == 0)
642 lp->iwork[j] = ++len;
643 ptr = lp->iwork[j];
644 ind[ptr] = j+1, val[ptr] = vallist[k];
645 }
646 glp_set_mat_row(lp->prob, i+1, len, ind, val);
647 for (ptr = 1; ptr <= len; ptr++)
648 lp->iwork[ind[ptr]-1] = 0;
649 }
650 }
651 else
652 { /* change the matrix by columns */
653 /* build the linked lists of triplets:
654 head[j] is a pointer to first triplet for column j
655 next[k] is a pointer to next triplet for the same column */
656 head = xcalloc(n, sizeof(int));
657 for (j = 0; j < n; j++)
658 head[j] = -1;
659 next = xcalloc(numcoefs, sizeof(int));
660 for (k = 0; k < numcoefs; k++)
661 { j = collist[k];
662 next[k] = head[j];
663 head[j] = k;
664 }
665 /* check duplicate rows */
666 for (j = 0; j < n; j++)
667 { for (k = head[j]; k >= 0; k = next[k])
668 { i = rowlist[k];
669 if (lp->iwork[i])
670 { xfree(head);
671 xfree(next);
672 errcode = error(env, CPXERR_DUP_ENTRY);
673 goto done;
674 }
675 lp->iwork[i] = 1;
676 }
677 for (k = head[j]; k >= 0; k = next[k])
678 lp->iwork[rowlist[k]] = 0;
679 }
680 /* perform operation */
681 ind = xcalloc(1+m, sizeof(int));
682 val = xcalloc(1+m, sizeof(double));
683 for (j = 0; j < n; j++)
684 { if (head[j] < 0) continue;
685 len = glp_get_mat_col(lp->prob, j+1, ind, val);
686 for (ptr = 1; ptr <= len; ptr++)
687 { i = ind[ptr]-1;
688 xassert(lp->iwork[i] == 0);
689 lp->iwork[i] = ptr;
690 }
691 for (k = head[j]; k >= 0; k = next[k])
692 { i = rowlist[k];
693 if (lp->iwork[i] == 0)
694 lp->iwork[i] = ++len;
695 ptr = lp->iwork[i];
696 ind[ptr] = i+1, val[ptr] = vallist[k];
697 }
698 glp_set_mat_col(lp->prob, j+1, len, ind, val);
699 for (ptr = 1; ptr <= len; ptr++)
700 lp->iwork[ind[ptr]-1] = 0;
701 }
702 }
703 xfree(head);
704 xfree(next);
705 xfree(ind);
706 xfree(val);
707 done: return errcode;
708 }
709
CPXchgobjsen(CPXENV * env,CPXLP * lp,int maxormin)710 void CPXchgobjsen(CPXENV *env, CPXLP *lp, int maxormin)
711 { int errcode;
712 errcode = checklp(env, lp);
713 if (errcode) goto done;
714 if (!(maxormin == CPX_MIN || maxormin == CPX_MAX))
715 { errcode = error(env, CPXERR_BAD_ARGUMENT);
716 goto done;
717 }
718 errcode = 0;
719 invalidate(lp);
720 if (maxormin == CPX_MIN)
721 glp_set_obj_dir(lp->prob, GLP_MIN);
722 else
723 glp_set_obj_dir(lp->prob, GLP_MAX);
724 done: xassert(errcode == errcode);
725 return;
726 }
727
CPXchgsense(CPXENV * env,CPXLP * lp,int cnt,const int indices[],const char sense[])728 int CPXchgsense(CPXENV *env, CPXLP *lp, int cnt, const int indices[],
729 const char sense[])
730 { int i, m, type, errcode;
731 double rhs;
732 errcode = checklp(env, lp);
733 if (errcode) goto done;
734 if (cnt < 0)
735 { errcode = error(env, CPXERR_BAD_ARGUMENT);
736 goto done;
737 }
738 if (cnt > 0 && (indices == NULL || sense == NULL))
739 { errcode = error(env, CPXERR_NULL_POINTER);
740 goto done;
741 }
742 m = glp_get_num_rows(lp->prob);
743 for (i = 0; i < cnt; i++)
744 { if (!(0 <= indices[i] && indices[i] < m))
745 { errcode = error(env, CPXERR_ROW_INDEX_RANGE, i);
746 goto done;
747 }
748 if (!(sense[i] == 'L' || sense[i] == 'E' || sense[i] == 'G' ||
749 sense[i] == 'R'))
750 { errcode = error(env, CPXERR_BAD_SENSE, i);
751 goto done;
752 }
753 }
754 errcode = 0;
755 invalidate(lp);
756 for (i = 0; i < cnt; i++)
757 { type = glp_get_row_type(lp->prob, indices[i]+1);
758 if (lp->rflag[indices[i]] == RF_NOT_RANGED)
759 { if (type == GLP_LO || type == GLP_FX)
760 rhs = glp_get_row_lb(lp->prob, indices[i]+1);
761 else if (type == GLP_UP)
762 rhs = glp_get_row_ub(lp->prob, indices[i]+1);
763 else
764 xassert(type != type);
765 }
766 else if (lp->rflag[indices[i]] == RF_RANGED_POS)
767 { xassert(type == GLP_DB || type == GLP_FX);
768 rhs = glp_get_row_lb(lp->prob, indices[i]+1);
769 }
770 else if (lp->rflag[indices[i]] == RF_RANGED_NEG)
771 { xassert(type == GLP_DB);
772 rhs = glp_get_row_ub(lp->prob, indices[i]+1);
773 }
774 else
775 xassert(lp != lp);
776 if (sense[i] == 'L')
777 { lp->rflag[indices[i]] = RF_NOT_RANGED;
778 type = GLP_UP;
779 }
780 else if (sense[i] == 'E')
781 { lp->rflag[indices[i]] = RF_NOT_RANGED;
782 type = GLP_FX;
783 }
784 else if (sense[i] == 'G')
785 { lp->rflag[indices[i]] = RF_NOT_RANGED;
786 type = GLP_LO;
787 }
788 else if (sense[i] == 'R')
789 { lp->rflag[indices[i]] = RF_RANGED_POS;
790 type = GLP_FX;
791 }
792 else
793 xassert(sense != sense);
794 glp_set_row_bnds(lp->prob, indices[i]+1, type, rhs, rhs);
795 }
796 done: return errcode;
797 }
798
CPXcloseCPLEX(CPXENV ** _env)799 int CPXcloseCPLEX(CPXENV **_env)
800 { CPXENV *env;
801 CPXLP *lp;
802 int errcode;
803 if (_env == NULL)
804 { errcode = CPXERR_NULL_POINTER;
805 goto done;
806 }
807 env = *_env;
808 errcode = checkenv(env);
809 if (errcode) goto done;
810 while (env->list != NULL)
811 { lp = env->list;
812 errcode = CPXfreeprob(env, &lp);
813 xassert(!errcode);
814 }
815 xfree(env->intparam);
816 xfree(env->dblparam);
817 xfree(env);
818 *_env = NULL;
819 errcode = 0;
820 done: return errcode;
821 }
822
CPXcopybase(CPXENV * env,CPXLP * lp,const int cstat[],const int rstat[])823 int CPXcopybase(CPXENV *env, CPXLP *lp, const int cstat[],
824 const int rstat[])
825 { int i, j, m, n, stat, errcode;
826 errcode = checklp(env, lp);
827 if (errcode) goto done;
828 m = glp_get_num_rows(lp->prob);
829 n = glp_get_num_cols(lp->prob);
830 if (m > 0 && rstat == NULL || n > 0 && cstat == NULL)
831 { errcode = error(env, CPXERR_NULL_POINTER);
832 goto done;
833 }
834 for (i = 0; i < m; i++)
835 { if (!(rstat[i] == CPX_AT_LOWER || rstat[i] == CPX_BASIC ||
836 rstat[i] == CPX_AT_UPPER))
837 { errcode = error(env, CPXERR_BAD_STATUS, i);
838 goto done;
839 }
840 }
841 for (j = 0; j < n; j++)
842 { if (!(cstat[j] == CPX_AT_LOWER || cstat[j] == CPX_BASIC ||
843 cstat[j] == CPX_AT_UPPER || cstat[j] == CPX_FREE_SUPER))
844 { errcode = error(env, CPXERR_BAD_STATUS, j);
845 goto done;
846 }
847 }
848 errcode = 0;
849 invalidate(lp);
850 for (i = 0; i < m; i++)
851 { if (rstat[i] == CPX_AT_LOWER)
852 stat = GLP_NL;
853 else if (rstat[i] == CPX_BASIC)
854 stat = GLP_BS;
855 else if (rstat[i] == CPX_AT_UPPER)
856 stat = GLP_NU;
857 else
858 xassert(rstat != rstat);
859 glp_set_row_stat(lp->prob, i+1, stat);
860 }
861 for (j = 0; j < n; j++)
862 { if (cstat[j] == CPX_AT_LOWER)
863 stat = GLP_NL;
864 else if (cstat[j] == CPX_BASIC)
865 stat = GLP_BS;
866 else if (cstat[j] == CPX_AT_UPPER)
867 stat = GLP_NU;
868 else if (cstat[j] == CPX_FREE_SUPER)
869 stat = GLP_NF;
870 else
871 xassert(cstat != cstat);
872 glp_set_col_stat(lp->prob, j+1, stat);
873 }
874 done: return errcode;
875 }
876
CPXcopybasednorms(CPXENV * env,CPXLP * lp,const int cstat[],const int rstat[],const double dnorm[])877 int CPXcopybasednorms(CPXENV *env, CPXLP *lp, const int cstat[],
878 const int rstat[], const double dnorm[])
879 { int errcode;
880 errcode = CPXcopybase(env, lp, cstat, rstat);
881 xassert(dnorm == dnorm);
882 return errcode;
883 }
884
CPXcopylp(CPXENV * env,CPXLP * lp,int numcols,int numrows,int objsen,const double obj[],const double rhs[],const char sense[],const int matbeg[],const int matcnt[],const int matind[],const double matval[],const double lb[],const double ub[],const double rngval[])885 int CPXcopylp(CPXENV *env, CPXLP *lp, int numcols, int numrows,
886 int objsen, const double obj[], const double rhs[],
887 const char sense[], const int matbeg[], const int matcnt[],
888 const int matind[], const double matval[], const double lb[],
889 const double ub[], const double rngval[])
890 { int errcode;
891 errcode = CPXcopylpwnames(env, lp, numcols, numrows, objsen, obj,
892 rhs, sense, matbeg, matcnt, matind, matval, lb, ub, rngval,
893 NULL, NULL);
894 return errcode;
895 }
896
CPXcopylpwnames(CPXENV * env,CPXLP * lp,int numcols,int numrows,int objsen,const double obj[],const double rhs[],const char sense[],const int matbeg[],const int matcnt[],const int matind[],const double matval[],const double lb[],const double ub[],const double rngval[],char * colname[],char * rowname[])897 int CPXcopylpwnames(CPXENV *env, CPXLP *lp, int numcols, int numrows,
898 int objsen, const double obj[], const double rhs[],
899 const char sense[], const int matbeg[], const int matcnt[],
900 const int matind[], const double matval[], const double lb[],
901 const double ub[], const double rngval[], char *colname[],
902 char *rowname[])
903 { int i, j, k, beg, end, type, errcode;
904 double lbnd, ubnd;
905 char name[255+1];
906 errcode = checklp(env, lp);
907 if (errcode) goto done;
908 if (numcols < 0 || numrows < 0)
909 { errcode = error(env, CPXERR_BAD_ARGUMENT);
910 goto done;
911 }
912 if (!(objsen == CPX_MIN || objsen == CPX_MAX))
913 { errcode = error(env, CPXERR_BAD_ARGUMENT);
914 goto done;
915 }
916 if (numcols > 0)
917 { if (matbeg == NULL || matcnt == NULL || matind == NULL ||
918 matval == NULL)
919 { errcode = error(env, CPXERR_NULL_POINTER);
920 goto done;
921 }
922 }
923 for (i = 0; i < numrows; i++)
924 { if (sense != NULL)
925 { if (!(sense[i] == 'L' || sense[i] == 'E' ||
926 sense[i] == 'G' || sense[i] == 'R'))
927 { errcode = error(env, CPXERR_BAD_SENSE, i);
928 goto done;
929 }
930 }
931 if (rowname != NULL)
932 { if (rowname[i] == NULL)
933 { errcode = error(env, CPXERR_NULL_NAME, i);
934 goto done;
935 }
936 }
937 }
938 enlargeiwork(lp, numrows);
939 for (j = 0; j < numcols; j++)
940 { beg = matbeg[j];
941 if (j > 0 && !(matbeg[j-1] <= beg))
942 { errcode = error(env, CPXERR_ARRAY_NOT_ASCENDING, j);
943 goto done;
944 }
945 if (beg < 0)
946 { errcode = error(env, CPXERR_INDEX_RANGE);
947 goto done;
948 }
949 end = beg + matcnt[j];
950 if (!(beg <= end) || j < numcols-1 && !(end <= matbeg[j+1]))
951 { errcode = error(env, CPXERR_COUNT_RANGE, j);
952 goto done;
953 }
954 for (k = beg; k < end; k++)
955 { if (!(0 <= matind[k] && matind[k] < numrows))
956 { errcode = error(env, CPXERR_ROW_INDEX_RANGE, k);
957 goto done;
958 }
959 }
960 errcode = 0;
961 for (k = beg; k < end; k++)
962 { if (lp->iwork[matind[k]])
963 { errcode = error(env, CPXERR_DUP_ENTRY);
964 break;
965 }
966 lp->iwork[matind[k]] = 1;
967 }
968 for (k = beg; k < end; k++)
969 lp->iwork[matind[k]] = 0;
970 if (errcode) goto done;
971 if (colname != NULL)
972 { if (colname[j] != NULL)
973 { errcode = error(env, CPXERR_NULL_NAME, j);
974 goto done;
975 }
976 }
977 }
978 errcode = 0;
979 invalidate(lp);
980 if (glp_get_prob_name(lp->prob) == NULL)
981 name[0] = '\0';
982 else
983 strcpy(name, glp_get_prob_name(lp->prob));
984 glp_erase_prob(lp->prob);
985 glp_set_prob_name(lp->prob, name);
986 if (objsen == CPX_MIN)
987 glp_set_obj_dir(lp->prob, GLP_MIN);
988 else if (objsen == CPX_MAX)
989 glp_set_obj_dir(lp->prob, GLP_MAX);
990 else
991 xassert(objsen != objsen);
992 if (numrows > 0)
993 glp_add_rows(lp->prob, numrows);
994 enlargerflag(lp);
995 for (i = 0; i < numrows; i++)
996 { if (rowname != NULL)
997 glp_set_row_name(lp->prob, i+1, rowname[i]);
998 lbnd = ubnd = (rhs == NULL ? 0.0 : rhs[i]);
999 if (sense == NULL || sense[i] == 'E')
1000 { lp->rflag[i] = RF_NOT_RANGED;
1001 type = GLP_FX;
1002 }
1003 else if (sense[i] == 'L')
1004 { lp->rflag[i] = RF_NOT_RANGED;
1005 type = GLP_UP;
1006 }
1007 else if (sense[i] == 'G')
1008 { lp->rflag[i] = RF_NOT_RANGED;
1009 type = GLP_LO;
1010 }
1011 else if (sense[i] == 'R')
1012 { if (rngval == NULL || rngval[i] == 0.0)
1013 { lp->rflag[i] = RF_RANGED_POS;
1014 type = GLP_FX;
1015 }
1016 else if (rngval[i] > 0.0)
1017 { lp->rflag[i] = RF_RANGED_POS;
1018 type = GLP_DB;
1019 ubnd += rngval[i];
1020 }
1021 else /* rngval[i] < 0.0 */
1022 { lp->rflag[i] = RF_RANGED_NEG;
1023 type = GLP_DB;
1024 lbnd += rngval[i];
1025 }
1026 }
1027 else
1028 xassert(sense != sense);
1029 glp_set_row_bnds(lp->prob, i+1, type, lbnd, ubnd);
1030 }
1031 if (numcols > 0)
1032 glp_add_cols(lp->prob, numcols);
1033 for (j = 0; j < numcols; j++)
1034 { if (colname != NULL)
1035 glp_set_col_name(lp->prob, j+1, colname[j]);
1036 lbnd = (lb == NULL ? 0.0 : lb[j]);
1037 ubnd = (ub == NULL ? +CPX_INFBOUND : ub[j]);
1038 if (lbnd <= -CPX_INFBOUND && ubnd >= +CPX_INFBOUND)
1039 type = GLP_FR;
1040 else if (ubnd >= +CPX_INFBOUND)
1041 type = GLP_LO;
1042 else if (lbnd <= -CPX_INFBOUND)
1043 type = GLP_UP;
1044 else if (lbnd != ubnd)
1045 type = GLP_DB;
1046 else
1047 type = GLP_FX;
1048 glp_set_col_bnds(lp->prob, j+1, type, lbnd, ubnd);
1049 if (obj != NULL)
1050 glp_set_obj_coef(lp->prob, j+1, obj[j]);
1051 beg = matbeg[j];
1052 end = beg + matcnt[j];
1053 for (k = beg; k < end; k++)
1054 lp->iwork[k-beg] = matind[k]+1;
1055 glp_set_mat_col(lp->prob, j+1, end-beg, lp->iwork-1,
1056 matval+beg-1);
1057 for (k = beg; k < end; k++)
1058 lp->iwork[k-beg] = 0;
1059 }
1060 done: return errcode;
1061 }
1062
CPXcreateprob(CPXENV * env,int * status,const char * probname)1063 CPXLP *CPXcreateprob(CPXENV *env, int *status, const char *probname)
1064 { CPXLP *lp = NULL;
1065 int errcode;
1066 errcode = checkenv(env);
1067 if (errcode) goto done;
1068 lp = xmalloc(sizeof(struct CPXLP));
1069 lp->env = env;
1070 lp->prob = glp_create_prob();
1071 glp_set_prob_name(lp->prob, probname);
1072 lp->rflen = 100;
1073 lp->rflag = xcalloc(lp->rflen, sizeof(char));
1074 lp->iwlen = 100;
1075 lp->iwork = xcalloc(lp->iwlen, sizeof(int));
1076 memset(lp->iwork, 0, lp->iwlen * sizeof(int));
1077 lp->link = env->list;
1078 env->list = lp;
1079 invalidate(lp);
1080 done: if (status != NULL) *status = errcode;
1081 return lp;
1082 }
1083
CPXdelcols(CPXENV * env,CPXLP * lp,int begin,int end)1084 int CPXdelcols(CPXENV *env, CPXLP *lp, int begin, int end)
1085 { int j, n, errcode;
1086 errcode = checklp(env, lp);
1087 if (errcode) goto done;
1088 n = glp_get_num_cols(lp->prob);
1089 if (!(0 <= begin && begin <= end && end < n))
1090 { errcode = error(env, CPXERR_INDEX_RANGE);
1091 goto done;
1092 }
1093 errcode = 0;
1094 invalidate(lp);
1095 enlargeiwork(lp, end-begin+1);
1096 for (j = begin; j <= end; j++)
1097 lp->iwork[j-begin] = j+1;
1098 glp_del_cols(lp->prob, end-begin+1, lp->iwork-1);
1099 for (j = begin; j <= end; j++)
1100 lp->iwork[j-begin] = 0;
1101 done: return errcode;
1102 }
1103
CPXdelrows(CPXENV * env,CPXLP * lp,int begin,int end)1104 int CPXdelrows(CPXENV *env, CPXLP *lp, int begin, int end)
1105 { int i, m, errcode;
1106 errcode = checklp(env, lp);
1107 if (errcode) goto done;
1108 m = glp_get_num_rows(lp->prob);
1109 if (!(0 <= begin && begin <= end && end < m))
1110 { errcode = error(env, CPXERR_INDEX_RANGE);
1111 goto done;
1112 }
1113 errcode = 0;
1114 invalidate(lp);
1115 enlargeiwork(lp, end-begin+1);
1116 for (i = begin; i <= end; i++)
1117 lp->iwork[i-begin] = i+1;
1118 glp_del_rows(lp->prob, end-begin+1, lp->iwork-1);
1119 for (i = begin; i <= end; i++)
1120 lp->iwork[i-begin] = 0;
1121 for (i = end+1; i < m; i++)
1122 lp->rflag[i-(end-begin+1)] = lp->rflag[i];
1123 done: return errcode;
1124 }
1125
CPXdelsetcols(CPXENV * env,CPXLP * lp,int delstat[])1126 int CPXdelsetcols(CPXENV *env, CPXLP *lp, int delstat[])
1127 { xassert(env == env);
1128 xassert(lp == lp);
1129 xassert(delstat == delstat);
1130 xprintf("CPXdelsetcols: not implemented yet\n");
1131 exit(EXIT_FAILURE);
1132 return -1;
1133 }
1134
CPXdelsetrows(CPXENV * env,CPXLP * lp,int delstat[])1135 int CPXdelsetrows(CPXENV *env, CPXLP *lp, int delstat[])
1136 { int i, m, cnt, ind, errcode;
1137 errcode = checklp(env, lp);
1138 if (errcode) goto done;
1139 m = glp_get_num_rows(lp->prob);
1140 if (m > 0 && delstat == NULL)
1141 { errcode = error(env, CPXERR_NULL_POINTER);
1142 goto done;
1143 }
1144 errcode = 0;
1145 invalidate(lp);
1146 enlargeiwork(lp, m);
1147 cnt = ind = 0;
1148 for (i = 0; i < m; i++)
1149 { if (delstat[i] == 1)
1150 { delstat[i] = -1;
1151 lp->iwork[cnt++] = i+1;
1152 }
1153 else
1154 { delstat[i] = ind;
1155 lp->rflag[ind++] = lp->rflag[i];
1156 }
1157 }
1158 if (cnt > 0)
1159 glp_del_rows(lp->prob, cnt, lp->iwork-1);
1160 for (i = 0; i < cnt; i++)
1161 lp->iwork[i] = 0;
1162 done: return errcode;
1163 }
1164
1165 int CPXdualopt(CPXENV *env, CPXLP *lp);
1166
CPXfreeprob(CPXENV * env,CPXLP ** _lp)1167 int CPXfreeprob(CPXENV *env, CPXLP **_lp)
1168 { CPXLP *lp;
1169 int errcode;
1170 errcode = checkenv(env);
1171 if (errcode) goto done;
1172 if (_lp == NULL)
1173 { errcode = error(env, CPXERR_NULL_POINTER);
1174 goto done;
1175 }
1176 lp = *_lp;
1177 errcode = checklp(env, lp);
1178 if (errcode) goto done;
1179 errcode = 0;
1180 env = lp->env;
1181 if (env->list == lp)
1182 env->list = lp->link;
1183 else
1184 { CPXLP *pp;
1185 for (pp = env->list; pp != NULL; pp = pp->link)
1186 if (pp->link == lp) break;
1187 xassert(pp != NULL);
1188 pp->link = lp->link;
1189 }
1190 glp_delete_prob(lp->prob);
1191 xfree(lp->rflag);
1192 xfree(lp->iwork);
1193 xfree(lp);
1194 *_lp = NULL;
1195 done: return errcode;
1196 }
1197
CPXgetbase(CPXENV * env,CPXLP * lp,int cstat[],int rstat[])1198 int CPXgetbase(CPXENV *env, CPXLP *lp, int cstat[], int rstat[])
1199 { int i, j, m, n, stat, errcode;
1200 errcode = checklp(env, lp);
1201 if (errcode) goto done;
1202 if (!lp->stat)
1203 { errcode = error(env, CPXERR_NO_SOLN);
1204 goto done;
1205 }
1206 if (lp->meth == CPX_ALG_PRIMAL || lp->meth == CPX_ALG_DUAL)
1207 ;
1208 else
1209 { errcode = error(env, CPXERR_NO_BASIC_SOLN);
1210 goto done;
1211 }
1212 errcode = 0;
1213 if (rstat != NULL)
1214 { m = glp_get_num_rows(lp->prob);
1215 for (i = 0; i < m; i++)
1216 { stat = glp_get_row_stat(lp->prob, i+1);
1217 if (stat == GLP_BS)
1218 rstat[i] = CPX_BASIC;
1219 else if (lp->rflag[i] == RF_NOT_RANGED || stat != GLP_NU)
1220 rstat[i] = CPX_AT_LOWER;
1221 else
1222 rstat[i] = CPX_AT_UPPER;
1223 }
1224 }
1225 if (cstat != NULL)
1226 { n = glp_get_num_cols(lp->prob);
1227 for (j = 0; j < n; j++)
1228 { stat = glp_get_col_stat(lp->prob, j+1);
1229 if (stat == GLP_BS)
1230 cstat[j] = CPX_BASIC;
1231 else if (stat == GLP_NU)
1232 cstat[j] = CPX_AT_UPPER;
1233 else if (stat == GLP_NF)
1234 cstat[j] = CPX_FREE_SUPER;
1235 else
1236 cstat[j] = CPX_AT_LOWER;
1237 }
1238 }
1239 done: return errcode;
1240 }
1241
CPXgetbasednorms(CPXENV * env,CPXLP * lp,int cstat[],int rstat[],double dnorm[])1242 int CPXgetbasednorms(CPXENV *env, CPXLP *lp, int cstat[], int rstat[],
1243 double dnorm[])
1244 { int i, m, errcode;
1245 errcode = CPXgetbase(env, lp, cstat, rstat);
1246 if (errcode) goto done;
1247 if (dnorm != NULL)
1248 { m = glp_get_num_rows(lp->prob);
1249 for (i = 0; i < m; i++) dnorm[i] = 1.0;
1250 }
1251 done: return errcode;
1252 }
1253
CPXgetbhead(CPXENV * env,CPXLP * lp,int head[],double x[])1254 int CPXgetbhead(CPXENV *env, CPXLP *lp, int head[], double x[])
1255 { xassert(env == env);
1256 xassert(lp == lp);
1257 xassert(head == head);
1258 xassert(x == x);
1259 xprintf("CPXgetbhead: not implemented yet\n");
1260 exit(EXIT_FAILURE);
1261 return -1;
1262 }
1263
CPXgetdblparam(CPXENV * env,int whichparam,double * value)1264 int CPXgetdblparam(CPXENV *env, int whichparam, double *value)
1265 { int k, errcode;
1266 errcode = checkenv(env);
1267 if (errcode) goto done;
1268 k = finddblparam(whichparam);
1269 if (k < 0)
1270 { errcode = error(env, CPXERR_BAD_PARAM_NUM);
1271 goto done;
1272 }
1273 errcode = 0;
1274 if (value != NULL)
1275 *value = env->dblparam[k];
1276 done: return errcode;
1277 }
1278
CPXgetdj(CPXENV * env,CPXLP * lp,double dj[],int begin,int end)1279 int CPXgetdj(CPXENV *env, CPXLP *lp, double dj[], int begin, int end)
1280 { int j, n, errcode;
1281 errcode = checklp(env, lp);
1282 if (errcode) goto done;
1283 n = glp_get_num_cols(lp->prob);
1284 if (!(0 <= begin && begin <= end && end < n))
1285 { errcode = error(env, CPXERR_INDEX_RANGE);
1286 goto done;
1287 }
1288 if (!lp->stat)
1289 { errcode = error(env, CPXERR_NO_SOLN);
1290 goto done;
1291 }
1292 errcode = 0;
1293 if (lp->meth == CPX_ALG_PRIMAL || lp->meth == CPX_ALG_DUAL)
1294 { if (dj != NULL)
1295 { for (j = begin; j <= end; j++)
1296 dj[j-begin] = glp_get_col_dual(lp->prob, j+1);
1297 }
1298 }
1299 else
1300 xassert(lp != lp);
1301 done: return errcode;
1302 }
1303
CPXgeterrorstring(CPXENV * env,int errcode,char * buffer)1304 char *CPXgeterrorstring(CPXENV *env, int errcode, char *buffer)
1305 { const char *string;
1306 xassert(env == env);
1307 string = finderrstring(errcode);
1308 if (string == NULL)
1309 buffer = NULL;
1310 else
1311 sprintf(buffer, "CPLEX Error %5d: %s.\n", errcode, string);
1312 return buffer;
1313 }
1314
CPXgetijdiv(CPXENV * env,CPXLP * lp,int * idiv,int * jdiv)1315 int CPXgetijdiv(CPXENV *env, CPXLP *lp, int *idiv, int *jdiv)
1316 { xassert(env == env);
1317 xassert(lp == lp);
1318 xassert(idiv == idiv);
1319 xassert(jdiv == jdiv);
1320 xprintf("CPXgetijdiv: not implemented yet\n");
1321 exit(EXIT_FAILURE);
1322 return -1;
1323 }
1324
CPXgetintparam(CPXENV * env,int whichparam,int * value)1325 int CPXgetintparam(CPXENV *env, int whichparam, int *value)
1326 { int k, errcode;
1327 errcode = checkenv(env);
1328 if (errcode) goto done;
1329 k = findintparam(whichparam);
1330 if (k < 0)
1331 { errcode = error(env, CPXERR_BAD_PARAM_NUM);
1332 goto done;
1333 }
1334 errcode = 0;
1335 if (value != NULL)
1336 *value = env->intparam[k];
1337 done: return errcode;
1338 }
1339
CPXgetlb(CPXENV * env,CPXLP * lp,double lb[],int begin,int end)1340 int CPXgetlb(CPXENV *env, CPXLP *lp, double lb[], int begin, int end)
1341 { xassert(env == env);
1342 xassert(lp == lp);
1343 xassert(lb == lb);
1344 xassert(begin == begin);
1345 xassert(end == end);
1346 xprintf("CPXgetlb: not implemented yet\n");
1347 exit(EXIT_FAILURE);
1348 return -1;
1349 }
1350
CPXgetmethod(CPXENV * env,CPXLP * lp)1351 int CPXgetmethod(CPXENV *env, CPXLP *lp)
1352 { int method;
1353 if (checklp(env, lp))
1354 method = CPX_ALG_NONE;
1355 else
1356 method = lp->meth;
1357 return method;
1358 }
1359
CPXgetnumcols(CPXENV * env,CPXLP * lp)1360 int CPXgetnumcols(CPXENV *env, CPXLP *lp)
1361 { int numcols;
1362 if (checklp(env, lp))
1363 numcols = 0;
1364 else
1365 numcols = glp_get_num_cols(lp->prob);
1366 return numcols;
1367 }
1368
CPXgetnumnz(CPXENV * env,CPXLP * lp)1369 int CPXgetnumnz(CPXENV *env, CPXLP *lp)
1370 { int numnz;
1371 if (checklp(env, lp))
1372 numnz = 0;
1373 else
1374 numnz = glp_get_num_nz(lp->prob);
1375 return numnz;
1376 }
1377
CPXgetnumrows(CPXENV * env,CPXLP * lp)1378 int CPXgetnumrows(CPXENV *env, CPXLP *lp)
1379 { int numrows;
1380 if (checklp(env, lp))
1381 numrows = 0;
1382 else
1383 numrows = glp_get_num_rows(lp->prob);
1384 return numrows;
1385 }
1386
CPXgetobjval(CPXENV * env,CPXLP * lp,double * objval)1387 int CPXgetobjval(CPXENV *env, CPXLP *lp, double *objval)
1388 { int errcode;
1389 errcode = checklp(env, lp);
1390 if (errcode) goto done;
1391 if (!lp->stat)
1392 { errcode = error(env, CPXERR_NO_SOLN);
1393 goto done;
1394 }
1395 errcode = 0;
1396 if (lp->meth == CPX_ALG_PRIMAL || lp->meth == CPX_ALG_DUAL)
1397 { if (objval != NULL)
1398 *objval = glp_get_obj_val(lp->prob);
1399 }
1400 else
1401 xassert(lp != lp);
1402 done: return errcode;
1403 }
1404
CPXgetpi(CPXENV * env,CPXLP * lp,double pi[],int begin,int end)1405 int CPXgetpi(CPXENV *env, CPXLP *lp, double pi[], int begin, int end)
1406 { int i, m, errcode;
1407 errcode = checklp(env, lp);
1408 if (errcode) goto done;
1409 m = glp_get_num_rows(lp->prob);
1410 if (!(0 <= begin && begin <= end && end < m))
1411 { errcode = error(env, CPXERR_INDEX_RANGE);
1412 goto done;
1413 }
1414 if (!lp->stat)
1415 { errcode = error(env, CPXERR_NO_SOLN);
1416 goto done;
1417 }
1418 errcode = 0;
1419 if (lp->meth == CPX_ALG_PRIMAL || lp->meth == CPX_ALG_DUAL)
1420 { if (pi != NULL)
1421 { for (i = begin; i <= end; i++)
1422 pi[i-begin] = glp_get_row_dual(lp->prob, i+1);
1423 }
1424 }
1425 else
1426 xassert(lp != lp);
1427 done: return errcode;
1428 }
1429
CPXgetsense(CPXENV * env,CPXLP * lp,char sense[],int begin,int end)1430 int CPXgetsense(CPXENV *env, CPXLP *lp, char sense[], int begin,
1431 int end)
1432 { xassert(env == env);
1433 xassert(lp == lp);
1434 xassert(sense == sense);
1435 xassert(begin == begin);
1436 xassert(end == end);
1437 xprintf("CPXgetsense: not implemented yet\n");
1438 exit(EXIT_FAILURE);
1439 return -1;
1440 }
1441
CPXgetslack(CPXENV * env,CPXLP * lp,double slack[],int begin,int end)1442 int CPXgetslack(CPXENV *env, CPXLP *lp, double slack[], int begin,
1443 int end)
1444 { int i, m, type, errcode;
1445 double temp;
1446 errcode = checklp(env, lp);
1447 if (errcode) goto done;
1448 m = glp_get_num_rows(lp->prob);
1449 if (!(0 <= begin && begin <= end && end < m))
1450 { errcode = error(env, CPXERR_INDEX_RANGE);
1451 goto done;
1452 }
1453 if (!lp->stat)
1454 { errcode = error(env, CPXERR_NO_SOLN);
1455 goto done;
1456 }
1457 errcode = 0;
1458 if (lp->meth == CPX_ALG_PRIMAL || lp->meth == CPX_ALG_DUAL)
1459 { if (slack != NULL)
1460 { for (i = begin; i <= end; i++)
1461 { type = glp_get_row_type(lp->prob, i+1);
1462 temp = glp_get_row_prim(lp->prob, i+1);
1463 if (lp->rflag[i] == RF_NOT_RANGED)
1464 { if (type == GLP_LO || type == GLP_FX)
1465 slack[i-begin] =
1466 glp_get_row_lb(lp->prob, i+1) - temp;
1467 else if (type == GLP_UP)
1468 slack[i-begin] =
1469 glp_get_row_ub(lp->prob, i+1) - temp;
1470 else
1471 xassert(type != type);
1472 }
1473 else if (lp->rflag[i] == RF_RANGED_POS)
1474 { xassert(type == GLP_DB || type == GLP_FX);
1475 slack[i-begin] =
1476 temp - glp_get_row_lb(lp->prob, i+1);
1477 }
1478 else if (lp->rflag[i] == RF_RANGED_NEG)
1479 { xassert(type == GLP_DB);
1480 slack[i-begin] =
1481 temp - glp_get_row_ub(lp->prob, i+1);
1482 }
1483 else
1484 xassert(lp != lp);
1485 }
1486 }
1487 }
1488 else
1489 xassert(lp != lp);
1490 done: return errcode;
1491 }
1492
CPXgetstat(CPXENV * env,CPXLP * lp)1493 int CPXgetstat(CPXENV *env, CPXLP *lp)
1494 { int stat;
1495 if (checklp(env, lp))
1496 stat = 0;
1497 else
1498 stat = lp->stat;
1499 return stat;
1500 }
1501
CPXgetub(CPXENV * env,CPXLP * lp,double ub[],int begin,int end)1502 int CPXgetub(CPXENV *env, CPXLP *lp, double ub[], int begin, int end)
1503 { xassert(env == env);
1504 xassert(lp == lp);
1505 xassert(ub == ub);
1506 xassert(begin == begin);
1507 xassert(end == end);
1508 xprintf("CPXgetub: not implemented yet\n");
1509 exit(EXIT_FAILURE);
1510 return -1;
1511 }
1512
CPXgetweight(CPXENV * env,CPXLP * lp,int rcnt,const int rmatbeg[],const int rmatind[],const double rmatval[],double weight[],int dpriind)1513 int CPXgetweight(CPXENV *env, CPXLP *lp, int rcnt, const int rmatbeg[],
1514 const int rmatind[], const double rmatval[], double weight[],
1515 int dpriind)
1516 { xassert(env == env);
1517 xassert(lp == lp);
1518 xassert(rcnt == rcnt);
1519 xassert(rmatbeg == rmatbeg);
1520 xassert(rmatind == rmatind);
1521 xassert(rmatval == rmatval);
1522 xassert(weight == weight);
1523 xassert(dpriind == dpriind);
1524 xprintf("CPXgetweight: not implemented yet\n");
1525 exit(EXIT_FAILURE);
1526 return -1;
1527 }
1528
CPXgetx(CPXENV * env,CPXLP * lp,double x[],int begin,int end)1529 int CPXgetx(CPXENV *env, CPXLP *lp, double x[], int begin, int end)
1530 { int j, n, errcode;
1531 errcode = checklp(env, lp);
1532 if (errcode) goto done;
1533 n = glp_get_num_cols(lp->prob);
1534 if (!(0 <= begin && begin <= end && end < n))
1535 { errcode = error(env, CPXERR_INDEX_RANGE);
1536 goto done;
1537 }
1538 if (!lp->stat)
1539 { errcode = error(env, CPXERR_NO_SOLN);
1540 goto done;
1541 }
1542 errcode = 0;
1543 if (lp->meth == CPX_ALG_PRIMAL || lp->meth == CPX_ALG_DUAL)
1544 { if (x != NULL)
1545 { for (j = begin; j <= end; j++)
1546 x[j-begin] = glp_get_col_prim(lp->prob, j+1);
1547 }
1548 }
1549 else
1550 xassert(lp != lp);
1551 done: return errcode;
1552 }
1553
CPXinfodblparam(CPXENV * env,int whichparam,double * defvalue,double * minvalue,double * maxvalue)1554 int CPXinfodblparam(CPXENV *env, int whichparam, double *defvalue,
1555 double *minvalue, double *maxvalue)
1556 { int k, errcode;
1557 errcode = checkenv(env);
1558 if (errcode) goto done;
1559 k = finddblparam(whichparam);
1560 if (k < 0)
1561 { errcode = error(env, CPXERR_BAD_PARAM_NUM);
1562 goto done;
1563 }
1564 errcode = 0;
1565 if (defvalue != NULL)
1566 *defvalue = dblparam[k].defv;
1567 if (minvalue != NULL)
1568 *minvalue = dblparam[k].minv;
1569 if (maxvalue != NULL)
1570 *maxvalue = dblparam[k].maxv;
1571 done: return errcode;
1572 }
1573
CPXinfointparam(CPXENV * env,int whichparam,int * defvalue,int * minvalue,int * maxvalue)1574 int CPXinfointparam(CPXENV *env, int whichparam, int *defvalue,
1575 int *minvalue, int *maxvalue)
1576 { int k, errcode;
1577 errcode = checkenv(env);
1578 if (errcode) goto done;
1579 k = findintparam(whichparam);
1580 if (k < 0)
1581 { errcode = error(env, CPXERR_BAD_PARAM_NUM);
1582 goto done;
1583 }
1584 errcode = 0;
1585 if (defvalue != NULL)
1586 *defvalue = intparam[k].defv;
1587 if (minvalue != NULL)
1588 *minvalue = intparam[k].minv;
1589 if (maxvalue != NULL)
1590 *maxvalue = intparam[k].maxv;
1591 done: return errcode;
1592 }
1593
CPXmdleave(const CPXENV * env,CPXLP * lp,const int goodlist[],int goodlen,double downratio[],double upratio[])1594 int CPXmdleave(const CPXENV *env, CPXLP *lp, const int goodlist[],
1595 int goodlen, double downratio[], double upratio[])
1596 { int k;
1597 xassert(env == env);
1598 xassert(lp == lp);
1599 xassert(goodlist == goodlist);
1600 xassert(goodlen >= 0);
1601 xassert(downratio != NULL);
1602 xassert(upratio != NULL);
1603 /* not implemented yet */
1604 for (k = 0; k < goodlen; k++)
1605 downratio[k] = upratio[k] = 0.0;
1606 return 0;
1607 }
1608
CPXnewcols(CPXENV * env,CPXLP * lp,int ccnt,const double obj[],const double lb[],const double ub[],const char ctype[],char * colname[])1609 int CPXnewcols(CPXENV *env, CPXLP *lp, int ccnt, const double obj[],
1610 const double lb[], const double ub[], const char ctype[],
1611 char *colname[])
1612 { int j, n, kind, type, errcode;
1613 double lbnd, ubnd;
1614 errcode = checklp(env, lp);
1615 if (errcode) goto done;
1616 if (ccnt < 0)
1617 { errcode = error(env, CPXERR_BAD_ARGUMENT);
1618 goto done;
1619 }
1620 for (j = 0; j < ccnt; j++)
1621 { if (ctype != NULL)
1622 { if (!(ctype[j] == 'C' || ctype[j] == 'B' ||
1623 ctype[j] == 'I'))
1624 { errcode = error(env, CPXERR_BAD_CTYPE, j);
1625 goto done;
1626 }
1627 }
1628 if (colname != NULL)
1629 { if (colname[j] == NULL)
1630 { errcode = error(env, CPXERR_NULL_NAME, j);
1631 goto done;
1632 }
1633 }
1634 }
1635 errcode = 0;
1636 invalidate(lp);
1637 n = glp_get_num_cols(lp->prob);
1638 if (ccnt > 0)
1639 glp_add_cols(lp->prob, ccnt);
1640 for (j = 0; j < ccnt; j++)
1641 { if (colname != NULL)
1642 glp_set_col_name(lp->prob, n+j+1, colname[j]);
1643 if (obj != NULL)
1644 glp_set_obj_coef(lp->prob, n+j+1, obj[j]);
1645 lbnd = (lb == NULL ? 0.0 : lb[j]);
1646 ubnd = (ub == NULL ? 0.0 : ub[j]);
1647 if (lbnd <= -CPX_INFBOUND && ubnd >= +CPX_INFBOUND)
1648 type = GLP_FR;
1649 else if (ubnd >= +CPX_INFBOUND)
1650 type = GLP_LO;
1651 else if (lbnd <= -CPX_INFBOUND)
1652 type = GLP_UP;
1653 else if (lbnd != ubnd)
1654 type = GLP_DB;
1655 else
1656 type = GLP_FX;
1657 glp_set_col_bnds(lp->prob, n+j+1, type, lbnd, ubnd);
1658 if (ctype != NULL)
1659 { if (ctype[j] == 'C')
1660 kind = GLP_CV;
1661 else if (ctype[j] == 'B')
1662 kind = GLP_BV;
1663 else if (ctype[j] == 'I')
1664 kind = GLP_IV;
1665 else
1666 xassert(ctype != ctype);
1667 glp_set_col_kind(lp->prob, n+j+1, kind);
1668 }
1669 }
1670 done: return errcode;
1671 }
1672
CPXnewrows(CPXENV * env,CPXLP * lp,int rcnt,const double rhs[],const char sense[],const double rngval[],char * rowname[])1673 int CPXnewrows(CPXENV *env, CPXLP *lp, int rcnt, const double rhs[],
1674 const char sense[], const double rngval[], char *rowname[])
1675 { int i, m, type, errcode;
1676 double lbnd, ubnd;
1677 errcode = checklp(env, lp);
1678 if (errcode) goto done;
1679 if (rcnt < 0)
1680 { errcode = error(env, CPXERR_BAD_ARGUMENT);
1681 goto done;
1682 }
1683 for (i = 0; i < rcnt; i++)
1684 { if (sense != NULL)
1685 { if (!(sense[i] == 'L' || sense[i] == 'E' ||
1686 sense[i] == 'G' || sense[i] == 'R'))
1687 { errcode = error(env, CPXERR_BAD_SENSE, i);
1688 goto done;
1689 }
1690 }
1691 if (rowname != NULL)
1692 { if (rowname[i] == NULL)
1693 { errcode = error(env, CPXERR_NULL_NAME, i);
1694 goto done;
1695 }
1696 }
1697 }
1698 errcode = 0;
1699 invalidate(lp);
1700 m = glp_get_num_rows(lp->prob);
1701 if (rcnt > 0)
1702 glp_add_rows(lp->prob, rcnt);
1703 enlargerflag(lp);
1704 for (i = 0; i < rcnt; i++)
1705 { if (rowname != NULL)
1706 glp_set_row_name(lp->prob, m+i+1, rowname[i]);
1707 lbnd = ubnd = (rhs == NULL ? 0.0 : rhs[i]);
1708 if (sense == NULL || sense[i] == 'E')
1709 { lp->rflag[m+i] = RF_NOT_RANGED;
1710 type = GLP_FX;
1711 }
1712 else if (sense[i] == 'L')
1713 { lp->rflag[m+i] = RF_NOT_RANGED;
1714 type = GLP_UP;
1715 }
1716 else if (sense[i] == 'G')
1717 { lp->rflag[m+i] = RF_NOT_RANGED;
1718 type = GLP_LO;
1719 }
1720 else if (sense[i] == 'R')
1721 { if (rngval == NULL || rngval[i] == 0.0)
1722 { lp->rflag[m+i] = RF_RANGED_POS;
1723 type = GLP_FX;
1724 }
1725 else if (rngval[i] > 0.0)
1726 { lp->rflag[m+i] = RF_RANGED_POS;
1727 type = GLP_DB;
1728 ubnd += rngval[i];
1729 }
1730 else /* rngval[i] < 0.0 */
1731 { lp->rflag[m+i] = RF_RANGED_NEG;
1732 type = GLP_DB;
1733 lbnd += rngval[i];
1734 }
1735 }
1736 else
1737 xassert(sense != sense);
1738 glp_set_row_bnds(lp->prob, m+i+1, type, lbnd, ubnd);
1739 }
1740 done: return errcode;
1741 }
1742
CPXopenCPLEX(int * status)1743 CPXENV *CPXopenCPLEX(int *status)
1744 { CPXENV *env;
1745 int k, card;
1746 env = xmalloc(sizeof(CPXENV));
1747 env->list = NULL;
1748 card = sizeof(intparam) / sizeof(struct intparam);
1749 env->intparam = xcalloc(card, sizeof(int));
1750 for (k = 0; k < card; k++)
1751 env->intparam[k] = intparam[k].defv;
1752 card = sizeof(dblparam) / sizeof(struct dblparam);
1753 env->dblparam = xcalloc(card, sizeof(double));
1754 for (k = 0; k < card; k++)
1755 env->dblparam[k] = dblparam[k].defv;
1756 if (status != NULL) *status = 0;
1757 return env;
1758 }
1759
CPXpivotin(CPXENV * env,CPXLP * lp,const int rlist[],int rlen)1760 int CPXpivotin(CPXENV *env, CPXLP *lp, const int rlist[], int rlen)
1761 { int i, m, errcode;
1762 errcode = checklp(env, lp);
1763 if (errcode) goto done;
1764 if (rlen < 0)
1765 { errcode = error(env, CPXERR_BAD_ARGUMENT);
1766 goto done;
1767 }
1768 if (rlen > 0 && rlist == NULL)
1769 { errcode = error(env, CPXERR_NULL_POINTER);
1770 goto done;
1771 }
1772 m = glp_get_num_rows(lp->prob);
1773 for (i = 0; i < rlen; i++)
1774 { if (!(0 <= rlist[i] && rlist[i] < m))
1775 { errcode = error(env, CPXERR_ROW_INDEX_RANGE, i);
1776 goto done;
1777 }
1778 }
1779 errcode = 0;
1780 for (i = 0; i < rlen; i++)
1781 { if (glp_get_row_type(lp->prob, rlist[i]+1) != GLP_FX)
1782 { if (glp_get_row_stat(lp->prob, rlist[i]+1) != GLP_BS)
1783 { /* not implemented yet */
1784 break;
1785 }
1786 }
1787 }
1788 done: return errcode;
1789 }
1790
CPXpivotout(CPXENV * env,CPXLP * lp,const int clist[],int clen)1791 int CPXpivotout(CPXENV *env, CPXLP *lp, const int clist[], int clen)
1792 { int j, n, errcode;
1793 errcode = checklp(env, lp);
1794 if (errcode) goto done;
1795 if (clen < 0)
1796 { errcode = error(env, CPXERR_BAD_ARGUMENT);
1797 goto done;
1798 }
1799 if (clen > 0 && clist == NULL)
1800 { errcode = error(env, CPXERR_NULL_POINTER);
1801 goto done;
1802 }
1803 n = glp_get_num_cols(lp->prob);
1804 for (j = 0; j < clen; j++)
1805 { if (!(0 <= clist[j] && clist[j] < n))
1806 { errcode = error(env, CPXERR_COL_INDEX_RANGE, j);
1807 goto done;
1808 }
1809 if (glp_get_col_type(lp->prob, clist[j]+1) != GLP_FX)
1810 { errcode = error(env, CPXERR_NOT_FIXED);
1811 goto done;
1812 }
1813 }
1814 errcode = 0;
1815 for (j = 0; j < clen; j++)
1816 { if (glp_get_col_stat(lp->prob, clist[j]+1) == GLP_BS)
1817 { /* not implemented yet */
1818 break;
1819 }
1820 }
1821 done: return errcode;
1822 }
1823
1824 int CPXprimopt(CPXENV *env, CPXLP *lp);
1825
CPXsavwrite(CPXENV * env,CPXLP * lp,const char * filename)1826 int CPXsavwrite(CPXENV *env, CPXLP *lp, const char *filename)
1827 { xassert(env == env);
1828 xassert(lp == lp);
1829 xassert(filename == filename);
1830 xprintf("CPXsavwrite: not implemented yet\n");
1831 exit(EXIT_FAILURE);
1832 return -1;
1833 }
1834
CPXsetdblparam(CPXENV * env,int whichparam,double newvalue)1835 int CPXsetdblparam(CPXENV *env, int whichparam, double newvalue)
1836 { int k, errcode;
1837 errcode = checkenv(env);
1838 if (errcode) goto done;
1839 k = finddblparam(whichparam);
1840 if (k < 0)
1841 { errcode = error(env, CPXERR_BAD_PARAM_NUM);
1842 goto done;
1843 }
1844 if (newvalue < dblparam[k].minv)
1845 { errcode = error(env, CPXERR_PARAM_TOO_SMALL);
1846 goto done;
1847 }
1848 if (newvalue > dblparam[k].maxv)
1849 { errcode = error(env, CPXERR_PARAM_TOO_BIG);
1850 goto done;
1851 }
1852 errcode = 0;
1853 env->dblparam[k] = newvalue;
1854 done: return errcode;
1855 }
1856
CPXsetintparam(CPXENV * env,int whichparam,int newvalue)1857 int CPXsetintparam(CPXENV *env, int whichparam, int newvalue)
1858 { int k, errcode;
1859 errcode = checkenv(env);
1860 if (errcode) goto done;
1861 k = findintparam(whichparam);
1862 if (k < 0)
1863 { errcode = error(env, CPXERR_BAD_PARAM_NUM);
1864 goto done;
1865 }
1866 if (newvalue < intparam[k].minv)
1867 { errcode = error(env, CPXERR_PARAM_TOO_SMALL);
1868 goto done;
1869 }
1870 if (newvalue > intparam[k].maxv)
1871 { errcode = error(env, CPXERR_PARAM_TOO_BIG);
1872 goto done;
1873 }
1874 errcode = 0;
1875 env->intparam[k] = newvalue;
1876 done: return errcode;
1877 }
1878
CPXsolninfo(CPXENV * env,CPXLP * lp,int * solnmethod,int * solntype,int * pfeasind,int * dfeasind)1879 int CPXsolninfo(CPXENV *env, CPXLP *lp, int *solnmethod, int *solntype,
1880 int *pfeasind, int *dfeasind)
1881 { int type, pfeas, dfeas, errcode;
1882 errcode = checklp(env, lp);
1883 if (errcode) goto done;
1884 errcode = 0;
1885 if (!lp->stat)
1886 type = CPX_NO_SOLN, pfeas = dfeas = 0;
1887 else if (lp->meth == CPX_ALG_PRIMAL || lp->meth == CPX_ALG_DUAL)
1888 { type = CPX_BASIC_SOLN;
1889 pfeas = (glp_get_prim_stat(lp->prob) == GLP_FEAS);
1890 dfeas = (glp_get_dual_stat(lp->prob) == GLP_FEAS);
1891 }
1892 else
1893 xassert(lp != lp);
1894 if (solnmethod != NULL)
1895 *solnmethod = lp->meth;
1896 if (solntype != NULL)
1897 *solntype = type;
1898 if (pfeasind != NULL)
1899 *pfeasind = pfeas;
1900 if (dfeasind != NULL)
1901 *dfeasind = dfeas;
1902 done: return errcode;
1903 }
1904
CPXsolution(CPXENV * env,CPXLP * lp,int * lpstat,double * objval,double x[],double pi[],double slack[],double dj[])1905 int CPXsolution(CPXENV *env, CPXLP *lp, int *lpstat, double *objval,
1906 double x[], double pi[], double slack[], double dj[])
1907 { int m, n, errcode;
1908 errcode = checklp(env, lp);
1909 if (errcode) goto done;
1910 if (!lp->stat)
1911 { errcode = error(env, CPXERR_NO_SOLN);
1912 goto done;
1913 }
1914 errcode = 0;
1915 m = glp_get_num_rows(lp->prob);
1916 n = glp_get_num_cols(lp->prob);
1917 if (lp->meth == CPX_ALG_PRIMAL || lp->meth == CPX_ALG_DUAL)
1918 { if (lpstat != NULL)
1919 *lpstat = CPXgetstat(env, lp);
1920 if (objval != NULL)
1921 xassert(CPXgetobjval(env, lp, objval) == 0);
1922 if (x != NULL)
1923 xassert(CPXgetx(env, lp, x, 0, n-1) == 0);
1924 if (pi != NULL)
1925 xassert(CPXgetpi(env, lp, pi, 0, m-1) == 0);
1926 if (slack != NULL)
1927 xassert(CPXgetslack(env, lp, slack, 0, m-1) == 0);
1928 if (dj != NULL)
1929 xassert(CPXgetdj(env, lp, dj, 0, n-1) == 0);
1930 }
1931 else
1932 xassert(lp != lp);
1933 done: return errcode;
1934 }
1935
CPXstrongbranch(CPXENV * env,CPXLP * lp,const int goodlist[],int goodlen,double downpen[],double uppen[],int itlim)1936 int CPXstrongbranch(CPXENV *env, CPXLP *lp, const int goodlist[],
1937 int goodlen, double downpen[], double uppen[], int itlim)
1938 { int k;
1939 xassert(env == env);
1940 xassert(lp == lp);
1941 xassert(goodlist == goodlist);
1942 xassert(goodlen >= 0);
1943 xassert(downpen != NULL);
1944 xassert(uppen != NULL);
1945 xassert(itlim == itlim);
1946 /* not implemented yet */
1947 for (k = 0; k < goodlen; k++)
1948 downpen[k] = uppen[k] = 0.0;
1949 return 0;
1950 }
1951
xstrcasecmp(const char * s1,const char * s2)1952 static int xstrcasecmp(const char *s1, const char *s2)
1953 { int c1, c2;
1954 for (;;)
1955 { c1 = toupper((unsigned char)*s1++);
1956 c2 = toupper((unsigned char)*s2++);
1957 if (c1 == '\0' || c1 != c2) break;
1958 }
1959 return c1 - c2;
1960 }
1961
getfiletype(const char * filename,char type[3+1])1962 static void getfiletype(const char *filename, char type[3+1])
1963 { /* determine filetype from filename */
1964 int beg, end;
1965 beg = end = strlen(filename);
1966 while (beg > 0 && filename[beg-1] != '.' && end - beg < 3)
1967 beg--;
1968 if (beg > 0 && filename[beg-1] == '.' &&
1969 xstrcasecmp(&filename[beg], "gz") == 0)
1970 { end = --beg;
1971 while (beg > 0 && filename[beg-1] != '.' && end - beg < 3)
1972 beg--;
1973 }
1974 if (beg > 0 && filename[beg-1] == '.')
1975 { memcpy(type, &filename[beg], end - beg);
1976 type[end - beg] = '\0';
1977 }
1978 else
1979 type[0] = '\0';
1980 return;
1981 }
1982
CPXwriteprob(CPXENV * env,CPXLP * lp,const char * filename,const char * filetype)1983 int CPXwriteprob(CPXENV *env, CPXLP *lp, const char *filename,
1984 const char *filetype)
1985 { glp_prob *copy;
1986 int errcode;
1987 char type[3+1];
1988 errcode = checklp(env, lp);
1989 if (errcode) goto done;
1990 if (filename == NULL)
1991 { errcode = error(env, CPXERR_NO_FILENAME);
1992 goto done;
1993 }
1994 if (filetype == NULL)
1995 getfiletype(filename, type), filetype = type;
1996 if (xstrcasecmp(filetype, "MPS") == 0)
1997 { glp_term_out(GLP_OFF);
1998 errcode = glp_write_mps(lp->prob, GLP_MPS_FILE, NULL, filename)
1999 ;
2000 glp_term_out(GLP_ON);
2001 }
2002 else if (xstrcasecmp(filetype, "LP") == 0)
2003 { glp_term_out(GLP_OFF);
2004 errcode = glp_write_lp(lp->prob, NULL, filename);
2005 glp_term_out(GLP_ON);
2006 }
2007 else if (xstrcasecmp(filetype, "RMP") == 0 ||
2008 xstrcasecmp(filetype, "REW") == 0)
2009 { copy = glp_create_prob();
2010 glp_copy_prob(copy, lp->prob, GLP_OFF);
2011 glp_term_out(GLP_OFF);
2012 errcode = glp_write_mps(copy, GLP_MPS_DECK, NULL, filename);
2013 glp_term_out(GLP_ON);
2014 glp_delete_prob(copy);
2015 }
2016 else if (xstrcasecmp(filetype, "RLP") == 0)
2017 { copy = glp_create_prob();
2018 glp_copy_prob(copy, lp->prob, GLP_OFF);
2019 glp_term_out(GLP_OFF);
2020 errcode = glp_write_lp(copy, NULL, filename);
2021 glp_term_out(GLP_ON);
2022 glp_delete_prob(copy);
2023 }
2024 else
2025 { errcode = error(env, CPXERR_BAD_FILETYPE);
2026 goto done;
2027 }
2028 if (errcode)
2029 errcode = error(env, CPXERR_FAIL_OPEN_WRITE, filename);
2030 done: return errcode;
2031 }
2032
2033 /**********************************************************************/
2034
solvelp(CPXENV * env,CPXLP * lp,int meth)2035 static int solvelp(CPXENV *env, CPXLP *lp, int meth)
2036 { glp_smcp parm;
2037 int errcode;
2038 errcode = checklp(env, lp);
2039 if (errcode) goto done;
2040 errcode = 0;
2041 invalidate(lp);
2042 glp_init_smcp(&parm);
2043 switch (meth)
2044 { case CPX_ALG_PRIMAL:
2045 parm.meth = GLP_PRIMAL;
2046 break;
2047 case CPX_ALG_DUAL:
2048 parm.meth = GLP_DUAL;
2049 break;
2050 default:
2051 xassert(meth != meth);
2052 }
2053 switch (getintparam(env, CPX_PARAM_SIMDISPLAY))
2054 { case 0:
2055 parm.msg_lev = GLP_MSG_OFF;
2056 break;
2057 case 1:
2058 parm.msg_lev = GLP_MSG_ALL;
2059 break;
2060 case 2:
2061 parm.msg_lev = GLP_MSG_ALL;
2062 parm.out_frq = 1;
2063 break;
2064 default:
2065 xassert(env != env);
2066 }
2067 xassert(getdblparam == getdblparam);
2068 switch (getintparam(env, CPX_PARAM_ADVIND))
2069 { case 0:
2070 glp_term_out(GLP_OFF);
2071 glp_adv_basis(lp->prob, 0);
2072 glp_term_out(GLP_ON);
2073 break;
2074 case 1:
2075 case 2:
2076 break;
2077 default:
2078 xassert(env != env);
2079 }
2080 if (!glp_bf_exists(lp->prob))
2081 { if (glp_factorize(lp->prob) != 0)
2082 { glp_term_out(GLP_OFF);
2083 glp_adv_basis(lp->prob, 0);
2084 glp_term_out(GLP_ON);
2085 if (glp_factorize(lp->prob) != 0)
2086 glp_std_basis(lp->prob);
2087 }
2088 }
2089 xassert(glp_simplex(lp->prob, &parm) == 0);
2090 switch (glp_get_status(lp->prob))
2091 { case GLP_OPT:
2092 lp->stat = CPX_STAT_OPTIMAL;
2093 lp->meth = meth;
2094 break;
2095 case GLP_NOFEAS:
2096 lp->stat = CPX_STAT_INFEASIBLE;
2097 lp->meth = meth;
2098 break;
2099 case GLP_UNBND:
2100 lp->stat = CPX_STAT_UNBOUNDED;
2101 lp->meth = meth;
2102 break;
2103 default:
2104 xassert(lp != lp);
2105 }
2106 done: return errcode;
2107 }
2108
CPXprimopt(CPXENV * env,CPXLP * lp)2109 int CPXprimopt(CPXENV *env, CPXLP *lp)
2110 { int errcode;
2111 errcode = solvelp(env, lp, CPX_ALG_PRIMAL);
2112 return errcode;
2113 }
2114
CPXdualopt(CPXENV * env,CPXLP * lp)2115 int CPXdualopt(CPXENV *env, CPXLP *lp)
2116 { int errcode;
2117 errcode = solvelp(env, lp, CPX_ALG_DUAL);
2118 return errcode;
2119 }
2120
CPXlpopt(CPXENV * env,CPXLP * lp)2121 int CPXlpopt(CPXENV *env, CPXLP *lp)
2122 { int errcode;
2123 errcode = solvelp(env, lp, CPX_ALG_PRIMAL);
2124 return errcode;
2125 }
2126
2127 /* eof */
2128