1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/examples/cplex/cplex.c Mon Dec 06 13:09:21 2010 +0100
1.3 @@ -0,0 +1,2130 @@
1.4 +/* cplex.c (CPLEX-like interface to GLPK API) */
1.5 +
1.6 +/***********************************************************************
1.7 +* This code is part of GLPK (GNU Linear Programming Kit).
1.8 +*
1.9 +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
1.10 +* 2009, 2010 Andrew Makhorin, Department for Applied Informatics,
1.11 +* Moscow Aviation Institute, Moscow, Russia. All rights reserved.
1.12 +* E-mail: <mao@gnu.org>.
1.13 +*
1.14 +* GLPK is free software: you can redistribute it and/or modify it
1.15 +* under the terms of the GNU General Public License as published by
1.16 +* the Free Software Foundation, either version 3 of the License, or
1.17 +* (at your option) any later version.
1.18 +*
1.19 +* GLPK is distributed in the hope that it will be useful, but WITHOUT
1.20 +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
1.21 +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
1.22 +* License for more details.
1.23 +*
1.24 +* You should have received a copy of the GNU General Public License
1.25 +* along with GLPK. If not, see <http://www.gnu.org/licenses/>.
1.26 +***********************************************************************/
1.27 +
1.28 +#include <ctype.h>
1.29 +#include <stdarg.h>
1.30 +#include <stdio.h>
1.31 +#include <stdlib.h>
1.32 +#include <string.h>
1.33 +#include <glpk.h>
1.34 +#include "cplex.h"
1.35 +
1.36 +struct CPXENV
1.37 +{ /* environment block */
1.38 + CPXLP *list;
1.39 + /* linked list of problem objects */
1.40 + int *intparam; /* int intparam[]; */
1.41 + /* integer control parameters */
1.42 + double *dblparam; /* double dblparam[]; */
1.43 + /* floating-point control parameters */
1.44 +};
1.45 +
1.46 +struct CPXLP
1.47 +{ /* problem object */
1.48 + CPXENV *env;
1.49 + /* pointer to environment block */
1.50 + glp_prob *prob;
1.51 + /* pointer to underlying GLPK problem object */
1.52 + int rflen;
1.53 + /* length of the array rflag */
1.54 + char *rflag; /* char rflag[rflen]; */
1.55 + /* rflag[i], i = 0,...,nrows-1, is a flag of i-th row: */
1.56 +#define RF_NOT_RANGED 0 /* not ranged */
1.57 +#define RF_RANGED_POS 1 /* ranged, RHS = lower bound */
1.58 +#define RF_RANGED_NEG 2 /* ranged, RHS = upper bound */
1.59 + int stat;
1.60 + /* solution status reported by CPXgetstat; zero means no solution
1.61 + exists */
1.62 + int meth;
1.63 + /* method indicator reported by CPXgetmethod */
1.64 + int iwlen;
1.65 + /* length of the working array */
1.66 + int *iwork; /* int iwork[iwlen] */
1.67 + /* working array initialized by binary zeros */
1.68 + CPXLP *link;
1.69 + /* pointer to another problem object */
1.70 +};
1.71 +
1.72 +struct intparam
1.73 +{ int which;
1.74 + int defv;
1.75 + int minv;
1.76 + int maxv;
1.77 +};
1.78 +
1.79 +struct dblparam
1.80 +{ int which;
1.81 + double defv;
1.82 + double minv;
1.83 + double maxv;
1.84 +};
1.85 +
1.86 +struct errstring
1.87 +{ int code;
1.88 + const char *string;
1.89 +};
1.90 +
1.91 +#define BIGINT 2100000000
1.92 +#define BIGDBL 1e75
1.93 +
1.94 +static const struct intparam intparam[] =
1.95 +{ {CPX_PARAM_ADVIND, 0, 0, 2},
1.96 + {CPX_PARAM_AGGIND, -1, -1, BIGINT},
1.97 + {CPX_PARAM_DATACHECK, CPX_OFF, CPX_OFF, CPX_ON},
1.98 + {CPX_PARAM_DPRIIND, CPX_DPRIIND_AUTO, CPX_DPRIIND_AUTO,
1.99 + CPX_DPRIIND_DEVEX},
1.100 + {CPX_PARAM_FASTMIP, CPX_OFF, CPX_OFF, CPX_ON}, /* ??? */
1.101 + {CPX_PARAM_ITLIM, BIGINT, 0, BIGINT},
1.102 + {CPX_PARAM_PERIND, CPX_OFF, CPX_OFF, CPX_ON},
1.103 + {CPX_PARAM_PPRIIND, CPX_PPRIIND_AUTO, CPX_PPRIIND_PARTIAL,
1.104 + CPX_PPRIIND_FULL},
1.105 + {CPX_PARAM_PREIND, CPX_ON, CPX_OFF, CPX_ON},
1.106 + {CPX_PARAM_REINV, 0, 0, 10000},
1.107 + {CPX_PARAM_SCRIND, CPX_OFF, CPX_OFF, CPX_ON},
1.108 + {CPX_PARAM_SIMDISPLAY, 1, 0, 2},
1.109 +};
1.110 +
1.111 +static const struct dblparam dblparam[] =
1.112 +{ {CPX_PARAM_EPOPT, 1e-6, 1e-9, 1e-1},
1.113 + {CPX_PARAM_EPPER, 1e-6, 1e-8, BIGDBL},
1.114 + {CPX_PARAM_EPRHS, 1e-6, 1e-9, 1e-1},
1.115 + {CPX_PARAM_OBJLLIM, -BIGDBL, -BIGDBL, +BIGDBL},
1.116 + {CPX_PARAM_OBJULIM, +BIGDBL, -BIGDBL, +BIGDBL},
1.117 +};
1.118 +
1.119 +static const struct errstring errstring[] =
1.120 +{ {CPXERR_ARRAY_NOT_ASCENDING, "Array entry %d not ascending"},
1.121 + {CPXERR_BAD_ARGUMENT, "Invalid argument"},
1.122 + {CPXERR_BAD_CTYPE, "Invalid ctype entry %d"},
1.123 + {CPXERR_BAD_FILETYPE, "Invalid filetype"},
1.124 + {CPXERR_BAD_LUB, "Invalid bound change indicator entry %d"},
1.125 + {CPXERR_BAD_PARAM_NUM, "Invalid parameter number"},
1.126 + {CPXERR_BAD_SENSE, "Invalid sense entry %d"},
1.127 + {CPXERR_BAD_STATUS, "Invalid status entry %d for basis specificat"
1.128 + "ion"},
1.129 + {CPXERR_COL_INDEX_RANGE, "Column index %d out of range"},
1.130 + {CPXERR_COUNT_RANGE, "Count entry %d negative or larger than allo"
1.131 + "wed"},
1.132 + {CPXERR_DUP_ENTRY, "Duplicate entry"},
1.133 + {CPXERR_FAIL_OPEN_WRITE, "Could not open file '%s' for writing"},
1.134 + {CPXERR_INDEX_RANGE, "Index is outside range of valid values"},
1.135 + {CPXERR_NEGATIVE_SURPLUS, "Insufficient array length"},
1.136 + {CPXERR_NO_BASIC_SOLN, "No basic solution exists"},
1.137 + {CPXERR_NO_ENVIRONMENT, "No environment exists"},
1.138 + {CPXERR_NO_FILENAME, "File name not specified"},
1.139 + {CPXERR_NO_MEMORY, "Out of memory"},
1.140 + {CPXERR_NO_PROBLEM, "No problem exists"},
1.141 + {CPXERR_NO_SOLN, "No solution exists"},
1.142 + {CPXERR_NOT_FIXED, "Only fixed variables are pivoted out"},
1.143 + {CPXERR_NULL_NAME, "Null pointer %d in name array"},
1.144 + {CPXERR_NULL_POINTER, "Null pointer for required data"},
1.145 + {CPXERR_PARAM_TOO_BIG, "Parameter value too big"},
1.146 + {CPXERR_PARAM_TOO_SMALL, "Parameter value too small"},
1.147 + {CPXERR_ROW_INDEX_RANGE, "Row index %d out of range"},
1.148 +};
1.149 +
1.150 +/**********************************************************************/
1.151 +
1.152 +#define xassert glp_assert
1.153 +#define xprintf glp_printf
1.154 +#define xmalloc glp_malloc
1.155 +#define xcalloc glp_calloc
1.156 +#define xfree glp_free
1.157 +
1.158 +/**********************************************************************/
1.159 +
1.160 +static int findintparam(int whichparam)
1.161 +{ int k, card;
1.162 + card = sizeof(intparam) / sizeof(struct intparam);
1.163 + for (k = 0; k < card; k++)
1.164 + if (intparam[k].which == whichparam) return k;
1.165 + return -1;
1.166 +}
1.167 +
1.168 +static int getintparam(CPXENV *env, int whichparam)
1.169 +{ int k;
1.170 + xassert(env != NULL);
1.171 + k = findintparam(whichparam);
1.172 + xassert(k >= 0);
1.173 + return env->intparam[k];
1.174 +}
1.175 +
1.176 +static int finddblparam(int whichparam)
1.177 +{ int k, card;
1.178 + card = sizeof(dblparam) / sizeof(struct dblparam);
1.179 + for (k = 0; k < card; k++)
1.180 + if (dblparam[k].which == whichparam) return k;
1.181 + return -1;
1.182 +}
1.183 +
1.184 +static double getdblparam(CPXENV *env, int whichparam)
1.185 +{ int k;
1.186 + xassert(env != NULL);
1.187 + k = finddblparam(whichparam);
1.188 + xassert(k >= 0);
1.189 + return env->dblparam[k];
1.190 +}
1.191 +
1.192 +static const char *finderrstring(int errcode)
1.193 +{ int k, card;
1.194 + card = sizeof(errstring) / sizeof(struct errstring);
1.195 + for (k = 0; k < card; k++)
1.196 + { if (errstring[k].code == errcode)
1.197 + return errstring[k].string;
1.198 + }
1.199 + return NULL;
1.200 +}
1.201 +
1.202 +static int error(CPXENV *env, int errcode, ...)
1.203 +{ va_list arg;
1.204 + char buffer[510];
1.205 + xassert(env != NULL);
1.206 + if (getintparam(env, CPX_PARAM_SCRIND) == CPX_ON)
1.207 + { xassert(CPXgeterrorstring(env, errcode, buffer) == buffer);
1.208 + va_start(arg, errcode);
1.209 + vprintf(buffer, arg);
1.210 + va_end(arg);
1.211 + }
1.212 + return errcode;
1.213 +}
1.214 +
1.215 +static int checkenv(CPXENV *env)
1.216 +{ int errcode;
1.217 + if (env == NULL)
1.218 + errcode = CPXERR_NO_ENVIRONMENT;
1.219 + else
1.220 + errcode = 0;
1.221 + return errcode;
1.222 +}
1.223 +
1.224 +static checklp(CPXENV *env, CPXLP *lp)
1.225 +{ int errcode;
1.226 + errcode = checkenv(env);
1.227 + if (errcode) goto done;
1.228 + if (lp == NULL)
1.229 + errcode = error(env, CPXERR_NO_PROBLEM);
1.230 +done: return errcode;
1.231 +}
1.232 +
1.233 +static void invalidate(CPXLP *lp)
1.234 +{ lp->stat = 0;
1.235 + lp->meth = CPX_ALG_NONE;
1.236 + return;
1.237 +}
1.238 +
1.239 +static void enlargerflag(CPXLP *lp)
1.240 +{ int m;
1.241 + xassert(lp != NULL);
1.242 + m = glp_get_num_rows(lp->prob);
1.243 + if (lp->rflen < m)
1.244 + { int rflen = lp->rflen;
1.245 + char *rflag = lp->rflag;
1.246 + while (lp->rflen < m)
1.247 + { lp->rflen += lp->rflen;
1.248 + xassert(lp->rflen > 0);
1.249 + }
1.250 + lp->rflag = xcalloc(lp->rflen, sizeof(char));
1.251 + memcpy(lp->rflag, rflag, rflen);
1.252 + xfree(rflag);
1.253 + }
1.254 + return;
1.255 +}
1.256 +
1.257 +static void enlargeiwork(CPXLP *lp, int len)
1.258 +{ xassert(len >= 0);
1.259 + if (lp->iwlen < len)
1.260 + { xfree(lp->iwork);
1.261 + while (lp->iwlen < len)
1.262 + { lp->iwlen += lp->iwlen;
1.263 + xassert(lp->iwlen > 0);
1.264 + }
1.265 + lp->iwork = xcalloc(lp->iwlen, sizeof(int));
1.266 + memset(lp->iwork, 0, lp->iwlen * sizeof(int));
1.267 + }
1.268 + return;
1.269 +}
1.270 +
1.271 +/**********************************************************************/
1.272 +
1.273 +int CPXaddcols(CPXENV *env, CPXLP *lp, int ccnt, int nzcnt,
1.274 + const double obj[], const int cmatbeg[], const int cmatind[],
1.275 + const double cmatval[], const double lb[], const double ub[],
1.276 + char *colname[])
1.277 +{ int j, k, m, n, beg, end, type, errcode;
1.278 + double lbnd, ubnd;
1.279 + errcode = checklp(env, lp);
1.280 + if (errcode) goto done;
1.281 + if (ccnt < 0 || nzcnt < 0)
1.282 + { errcode = error(env, CPXERR_BAD_ARGUMENT);
1.283 + goto done;
1.284 + }
1.285 + if (ccnt > 0)
1.286 + { if (cmatbeg == NULL || cmatind == NULL || cmatval == NULL)
1.287 + { errcode = error(env, CPXERR_NULL_POINTER);
1.288 + goto done;
1.289 + }
1.290 + }
1.291 + m = glp_get_num_rows(lp->prob);
1.292 + n = glp_get_num_cols(lp->prob);
1.293 + enlargeiwork(lp, m);
1.294 + for (j = 0; j < ccnt; j++)
1.295 + { beg = cmatbeg[j];
1.296 + if (j > 0 && !(cmatbeg[j-1] <= beg))
1.297 + { errcode = error(env, CPXERR_ARRAY_NOT_ASCENDING, j);
1.298 + goto done;
1.299 + }
1.300 + if (!(0 <= beg && beg <= nzcnt))
1.301 + { errcode = error(env, CPXERR_INDEX_RANGE);
1.302 + goto done;
1.303 + }
1.304 + end = (j < ccnt-1 ? cmatbeg[j+1] : nzcnt);
1.305 + for (k = beg; k < end; k++)
1.306 + { if (!(0 <= cmatind[k] && cmatind[k] < m))
1.307 + { errcode = error(env, CPXERR_ROW_INDEX_RANGE, k);
1.308 + goto done;
1.309 + }
1.310 + }
1.311 + errcode = 0;
1.312 + for (k = beg; k < end; k++)
1.313 + { if (lp->iwork[cmatind[k]])
1.314 + { errcode = error(env, CPXERR_DUP_ENTRY);
1.315 + break;
1.316 + }
1.317 + lp->iwork[cmatind[k]] = 1;
1.318 + }
1.319 + for (k = beg; k < end; k++)
1.320 + lp->iwork[cmatind[k]] = 0;
1.321 + if (errcode) goto done;
1.322 + if (colname != NULL)
1.323 + { if (colname[j] == NULL)
1.324 + { errcode = error(env, CPXERR_NULL_NAME, j);
1.325 + goto done;
1.326 + }
1.327 + }
1.328 + }
1.329 + errcode = 0;
1.330 + invalidate(lp);
1.331 + if (ccnt > 0)
1.332 + glp_add_cols(lp->prob, ccnt);
1.333 + for (j = 0; j < ccnt; j++)
1.334 + { if (colname != NULL)
1.335 + glp_set_col_name(lp->prob, n+j+1, colname[j]);
1.336 + lbnd = (lb == NULL ? 0.0 : lb[j]);
1.337 + ubnd = (ub == NULL ? +CPX_INFBOUND : ub[j]);
1.338 + if (lbnd <= -CPX_INFBOUND && ubnd >= +CPX_INFBOUND)
1.339 + type = GLP_FR;
1.340 + else if (ubnd >= +CPX_INFBOUND)
1.341 + type = GLP_LO;
1.342 + else if (lbnd <= -CPX_INFBOUND)
1.343 + type = GLP_UP;
1.344 + else if (lbnd != ubnd)
1.345 + type = GLP_DB;
1.346 + else
1.347 + type = GLP_FX;
1.348 + glp_set_col_bnds(lp->prob, n+j+1, type, lbnd, ubnd);
1.349 + if (obj != NULL)
1.350 + glp_set_obj_coef(lp->prob, n+j+1, obj[j]);
1.351 + beg = cmatbeg[j];
1.352 + end = (j < ccnt-1 ? cmatbeg[j+1] : nzcnt);
1.353 + for (k = beg; k < end; k++)
1.354 + lp->iwork[k-beg] = cmatind[k]+1;
1.355 + glp_set_mat_col(lp->prob, n+j+1, end-beg, lp->iwork-1,
1.356 + cmatval+beg-1);
1.357 + for (k = beg; k < end; k++)
1.358 + lp->iwork[k-beg] = 0;
1.359 + }
1.360 +done: return errcode;
1.361 +}
1.362 +
1.363 +int CPXaddrows(CPXENV *env, CPXLP *lp, int ccnt, int rcnt, int nzcnt,
1.364 + const double rhs[], const char sense[], const int rmatbeg[],
1.365 + const int rmatind[], const double rmatval[], char *colname[],
1.366 + char *rowname[])
1.367 +{ int i, j, k, m, n, beg, end, type, errcode;
1.368 + double temp;
1.369 + errcode = checklp(env, lp);
1.370 + if (errcode) goto done;
1.371 + if (ccnt < 0 || rcnt < 0 || nzcnt < 0)
1.372 + { errcode = error(env, CPXERR_BAD_ARGUMENT);
1.373 + goto done;
1.374 + }
1.375 + if (rcnt > 0)
1.376 + { if (rmatbeg == NULL || rmatind == NULL || rmatval == NULL)
1.377 + { errcode = error(env, CPXERR_NULL_POINTER);
1.378 + goto done;
1.379 + }
1.380 + }
1.381 + m = glp_get_num_rows(lp->prob);
1.382 + n = glp_get_num_cols(lp->prob);
1.383 + enlargeiwork(lp, n+ccnt);
1.384 + for (i = 0; i < rcnt; i++)
1.385 + { if (sense != NULL)
1.386 + { if (!(sense[i] == 'L' || sense[i] == 'E' ||
1.387 + sense[i] == 'G' || sense[i] == 'R'))
1.388 + { errcode = error(env, CPXERR_BAD_SENSE, i);
1.389 + goto done;
1.390 + }
1.391 + }
1.392 + beg = rmatbeg[i];
1.393 + if (i > 0 && !(rmatbeg[i-1] <= beg))
1.394 + { errcode = error(env, CPXERR_ARRAY_NOT_ASCENDING, i);
1.395 + goto done;
1.396 + }
1.397 + if (!(0 <= beg && beg <= nzcnt))
1.398 + { errcode = error(env, CPXERR_INDEX_RANGE);
1.399 + goto done;
1.400 + }
1.401 + end = (i < rcnt-1 ? rmatbeg[i+1] : nzcnt);
1.402 + for (k = beg; k < end; k++)
1.403 + { if (!(0 <= rmatind[k] && rmatind[k] < n+ccnt))
1.404 + { errcode = error(env, CPXERR_COL_INDEX_RANGE, k);
1.405 + goto done;
1.406 + }
1.407 + }
1.408 + errcode = 0;
1.409 + for (k = beg; k < end; k++)
1.410 + { if (lp->iwork[rmatind[k]])
1.411 + { errcode = error(env, CPXERR_DUP_ENTRY);
1.412 + break;
1.413 + }
1.414 + lp->iwork[rmatind[k]] = 1;
1.415 + }
1.416 + for (k = beg; k < end; k++)
1.417 + lp->iwork[rmatind[k]] = 0;
1.418 + if (errcode) goto done;
1.419 + if (rowname != NULL)
1.420 + { if (rowname[i] == NULL)
1.421 + { errcode = error(env, CPXERR_NULL_NAME, i);
1.422 + goto done;
1.423 + }
1.424 + }
1.425 + }
1.426 + for (j = 0; j < ccnt; j++)
1.427 + { if (colname != NULL)
1.428 + { if (colname[j] == NULL)
1.429 + { errcode = error(env, CPXERR_NULL_NAME, j);
1.430 + goto done;
1.431 + }
1.432 + }
1.433 + }
1.434 + errcode = 0;
1.435 + invalidate(lp);
1.436 + if (rcnt > 0)
1.437 + glp_add_rows(lp->prob, rcnt);
1.438 + if (ccnt > 0)
1.439 + glp_add_cols(lp->prob, ccnt);
1.440 + enlargerflag(lp);
1.441 + for (i = 0; i < rcnt; i++)
1.442 + { if (rowname != NULL)
1.443 + glp_set_row_name(lp->prob, m+i+1, rowname[i]);
1.444 + temp = (rhs == NULL ? 0.0 : rhs[i]);
1.445 + if (sense == NULL || sense[i] == 'E')
1.446 + { lp->rflag[m+i] = RF_NOT_RANGED;
1.447 + type = GLP_FX;
1.448 + }
1.449 + else if (sense[i] == 'L')
1.450 + { lp->rflag[m+i] = RF_NOT_RANGED;
1.451 + type = GLP_UP;
1.452 + }
1.453 + else if (sense[i] == 'G')
1.454 + { lp->rflag[m+i] = RF_NOT_RANGED;
1.455 + type = GLP_LO;
1.456 + }
1.457 + else if (sense[i] == 'R')
1.458 + { lp->rflag[m+i] = RF_RANGED_POS;
1.459 + type = GLP_FX;
1.460 + }
1.461 + else
1.462 + xassert(sense != sense);
1.463 + glp_set_row_bnds(lp->prob, m+i+1, type, temp, temp);
1.464 + beg = rmatbeg[i];
1.465 + end = (i < rcnt-1 ? rmatbeg[i+1] : nzcnt);
1.466 + for (k = beg; k < end; k++)
1.467 + lp->iwork[k-beg] = rmatind[k]+1;
1.468 + glp_set_mat_row(lp->prob, m+i+1, end-beg, lp->iwork-1,
1.469 + rmatval+beg-1);
1.470 + for (k = beg; k < end; k++)
1.471 + lp->iwork[k-beg] = 0;
1.472 + }
1.473 + for (j = 0; j < ccnt; j++)
1.474 + { if (colname != NULL)
1.475 + glp_set_col_name(lp->prob, n+j+1, colname[j]);
1.476 + glp_set_col_bnds(lp->prob, n+j+1, GLP_LO, 0.0, 0.0);
1.477 + }
1.478 +done: return errcode;
1.479 +}
1.480 +
1.481 +int CPXbaropt(CPXENV *env, CPXLP *lp)
1.482 +{ xassert(env == env);
1.483 + xassert(lp == lp);
1.484 + xprintf("CPXbaropt: not implemented yet\n");
1.485 + exit(EXIT_FAILURE);
1.486 + return -1;
1.487 +}
1.488 +
1.489 +int CPXbinvrow(CPXENV *env, CPXLP *lp, int i, double y[])
1.490 +{ xassert(env == env);
1.491 + xassert(lp == lp);
1.492 + xassert(i == i);
1.493 + xassert(y == y);
1.494 + xprintf("CPXbinvrow: not implemented yet\n");
1.495 + exit(EXIT_FAILURE);
1.496 + return -1;
1.497 +}
1.498 +
1.499 +int CPXchgbds(CPXENV *env, CPXLP *lp, int cnt, const int indices[],
1.500 + const char lu[], const double bd[])
1.501 +{ int j, n, type, errcode;
1.502 + double lbnd, ubnd;
1.503 + errcode = checklp(env, lp);
1.504 + if (errcode) goto done;
1.505 + if (cnt < 0)
1.506 + { errcode = error(env, CPXERR_BAD_ARGUMENT);
1.507 + goto done;
1.508 + }
1.509 + if (cnt > 0)
1.510 + { if (indices == NULL || lu == NULL || bd == NULL)
1.511 + { errcode = error(env, CPXERR_NULL_POINTER);
1.512 + goto done;
1.513 + }
1.514 + }
1.515 + n = glp_get_num_cols(lp->prob);
1.516 + for (j = 0; j < cnt; j++)
1.517 + { if (!(0 <= indices[j] && indices[j] < n))
1.518 + { errcode = error(env, CPXERR_COL_INDEX_RANGE, j);
1.519 + goto done;
1.520 + }
1.521 + if (!(lu[j] == 'L' || lu[j] == 'U' || lu[j] == 'B'))
1.522 + { errcode = error(env, CPXERR_BAD_LUB, j);
1.523 + goto done;
1.524 + }
1.525 + }
1.526 + errcode = 0;
1.527 + invalidate(lp);
1.528 + for (j = 0; j < cnt; j++)
1.529 + { type = glp_get_col_type(lp->prob, indices[j]+1);
1.530 + lbnd = glp_get_col_lb(lp->prob, indices[j]+1);
1.531 + ubnd = glp_get_col_ub(lp->prob, indices[j]+1);
1.532 + if (type == GLP_FR || type == GLP_UP)
1.533 + lbnd = -CPX_INFBOUND;
1.534 + if (type == GLP_FR || type == GLP_LO)
1.535 + ubnd = +CPX_INFBOUND;
1.536 + if (lu[j] == 'L')
1.537 + lbnd = bd[j];
1.538 + else if (lu[j] == 'U')
1.539 + ubnd = bd[j];
1.540 + else if (lu[j] == 'B')
1.541 + lbnd = ubnd = bd[j];
1.542 + else
1.543 + xassert(lu != lu);
1.544 + if (lbnd <= -CPX_INFBOUND && ubnd >= +CPX_INFBOUND)
1.545 + type = GLP_FR;
1.546 + else if (ubnd >= +CPX_INFBOUND)
1.547 + type = GLP_LO;
1.548 + else if (lbnd <= -CPX_INFBOUND)
1.549 + type = GLP_UP;
1.550 + else if (lbnd != ubnd)
1.551 + type = GLP_DB;
1.552 + else
1.553 + type = GLP_FX;
1.554 + glp_set_col_bnds(lp->prob, indices[j]+1, type, lbnd, ubnd);
1.555 + }
1.556 +done: return errcode;
1.557 +}
1.558 +
1.559 +int CPXchgcoeflist(CPXENV *env, CPXLP *lp, int numcoefs,
1.560 + const int rowlist[], const int collist[], const double vallist[])
1.561 +{ int i, j, k, m, n, rcnt, ccnt, len, ptr, errcode;
1.562 + int *head, *next, *ind;
1.563 + double *val;
1.564 + errcode = checklp(env, lp);
1.565 + if (errcode) goto done;
1.566 + if (numcoefs < 0)
1.567 + { errcode = error(env, CPXERR_BAD_ARGUMENT);
1.568 + goto done;
1.569 + }
1.570 + if (numcoefs == 0)
1.571 + { errcode = 0;
1.572 + goto done;
1.573 + }
1.574 + if (rowlist == NULL || collist == NULL || vallist == NULL)
1.575 + { errcode = error(env, CPXERR_NULL_POINTER);
1.576 + goto done;
1.577 + }
1.578 + /* check triplets and determine the number of rows and columns
1.579 + to be changed */
1.580 + m = glp_get_num_rows(lp->prob);
1.581 + n = glp_get_num_cols(lp->prob);
1.582 + enlargeiwork(lp, m);
1.583 + enlargeiwork(lp, n);
1.584 + rcnt = ccnt = 0;
1.585 + for (k = 0; k < numcoefs; k++)
1.586 + { i = rowlist[k];
1.587 + if (!(0 <= i && i < m))
1.588 + { errcode = error(env, CPXERR_ROW_INDEX_RANGE, i);
1.589 + goto done;
1.590 + }
1.591 + if (!(lp->iwork[i] & 0x01))
1.592 + rcnt++, lp->iwork[i] |= 0x01;
1.593 + j = collist[k];
1.594 + if (!(0 <= j && j < n))
1.595 + { errcode = error(env, CPXERR_COL_INDEX_RANGE, j);
1.596 + goto done;
1.597 + }
1.598 + if (!(lp->iwork[j] & 0x02))
1.599 + ccnt++, lp->iwork[j] |= 0x02;
1.600 + }
1.601 + memset(lp->iwork, 0, m * sizeof(int));
1.602 + memset(lp->iwork, 0, n * sizeof(int));
1.603 + errcode = 0;
1.604 + invalidate(lp);
1.605 + if (rcnt <= ccnt)
1.606 + { /* change the matrix by rows */
1.607 + /* build the linked list of triplets:
1.608 + head[i] is a pointer to first triplet for row i
1.609 + next[k] is a pointer to next triplet for the same row */
1.610 + head = xcalloc(m, sizeof(int));
1.611 + for (i = 0; i < m; i++)
1.612 + head[i] = -1;
1.613 + next = xcalloc(numcoefs, sizeof(int));
1.614 + for (k = 0; k < numcoefs; k++)
1.615 + { i = rowlist[k];
1.616 + next[k] = head[i];
1.617 + head[i] = k;
1.618 + }
1.619 + /* check duplicate columns */
1.620 + for (i = 0; i < m; i++)
1.621 + { for (k = head[i]; k >= 0; k = next[k])
1.622 + { j = collist[k];
1.623 + if (lp->iwork[j])
1.624 + { xfree(head);
1.625 + xfree(next);
1.626 + errcode = error(env, CPXERR_DUP_ENTRY);
1.627 + goto done;
1.628 + }
1.629 + lp->iwork[j] = 1;
1.630 + }
1.631 + for (k = head[i]; k >= 0; k = next[k])
1.632 + lp->iwork[collist[k]] = 0;
1.633 + }
1.634 + /* perform operation */
1.635 + ind = xcalloc(1+n, sizeof(int));
1.636 + val = xcalloc(1+n, sizeof(double));
1.637 + for (i = 0; i < m; i++)
1.638 + { if (head[i] < 0) continue;
1.639 + len = glp_get_mat_row(lp->prob, i+1, ind, val);
1.640 + for (ptr = 1; ptr <= len; ptr++)
1.641 + { j = ind[ptr]-1;
1.642 + xassert(lp->iwork[j] == 0);
1.643 + lp->iwork[j] = ptr;
1.644 + }
1.645 + for (k = head[i]; k >= 0; k = next[k])
1.646 + { j = collist[k];
1.647 + if (lp->iwork[j] == 0)
1.648 + lp->iwork[j] = ++len;
1.649 + ptr = lp->iwork[j];
1.650 + ind[ptr] = j+1, val[ptr] = vallist[k];
1.651 + }
1.652 + glp_set_mat_row(lp->prob, i+1, len, ind, val);
1.653 + for (ptr = 1; ptr <= len; ptr++)
1.654 + lp->iwork[ind[ptr]-1] = 0;
1.655 + }
1.656 + }
1.657 + else
1.658 + { /* change the matrix by columns */
1.659 + /* build the linked lists of triplets:
1.660 + head[j] is a pointer to first triplet for column j
1.661 + next[k] is a pointer to next triplet for the same column */
1.662 + head = xcalloc(n, sizeof(int));
1.663 + for (j = 0; j < n; j++)
1.664 + head[j] = -1;
1.665 + next = xcalloc(numcoefs, sizeof(int));
1.666 + for (k = 0; k < numcoefs; k++)
1.667 + { j = collist[k];
1.668 + next[k] = head[j];
1.669 + head[j] = k;
1.670 + }
1.671 + /* check duplicate rows */
1.672 + for (j = 0; j < n; j++)
1.673 + { for (k = head[j]; k >= 0; k = next[k])
1.674 + { i = rowlist[k];
1.675 + if (lp->iwork[i])
1.676 + { xfree(head);
1.677 + xfree(next);
1.678 + errcode = error(env, CPXERR_DUP_ENTRY);
1.679 + goto done;
1.680 + }
1.681 + lp->iwork[i] = 1;
1.682 + }
1.683 + for (k = head[j]; k >= 0; k = next[k])
1.684 + lp->iwork[rowlist[k]] = 0;
1.685 + }
1.686 + /* perform operation */
1.687 + ind = xcalloc(1+m, sizeof(int));
1.688 + val = xcalloc(1+m, sizeof(double));
1.689 + for (j = 0; j < n; j++)
1.690 + { if (head[j] < 0) continue;
1.691 + len = glp_get_mat_col(lp->prob, j+1, ind, val);
1.692 + for (ptr = 1; ptr <= len; ptr++)
1.693 + { i = ind[ptr]-1;
1.694 + xassert(lp->iwork[i] == 0);
1.695 + lp->iwork[i] = ptr;
1.696 + }
1.697 + for (k = head[j]; k >= 0; k = next[k])
1.698 + { i = rowlist[k];
1.699 + if (lp->iwork[i] == 0)
1.700 + lp->iwork[i] = ++len;
1.701 + ptr = lp->iwork[i];
1.702 + ind[ptr] = i+1, val[ptr] = vallist[k];
1.703 + }
1.704 + glp_set_mat_col(lp->prob, j+1, len, ind, val);
1.705 + for (ptr = 1; ptr <= len; ptr++)
1.706 + lp->iwork[ind[ptr]-1] = 0;
1.707 + }
1.708 + }
1.709 + xfree(head);
1.710 + xfree(next);
1.711 + xfree(ind);
1.712 + xfree(val);
1.713 +done: return errcode;
1.714 +}
1.715 +
1.716 +void CPXchgobjsen(CPXENV *env, CPXLP *lp, int maxormin)
1.717 +{ int errcode;
1.718 + errcode = checklp(env, lp);
1.719 + if (errcode) goto done;
1.720 + if (!(maxormin == CPX_MIN || maxormin == CPX_MAX))
1.721 + { errcode = error(env, CPXERR_BAD_ARGUMENT);
1.722 + goto done;
1.723 + }
1.724 + errcode = 0;
1.725 + invalidate(lp);
1.726 + if (maxormin == CPX_MIN)
1.727 + glp_set_obj_dir(lp->prob, GLP_MIN);
1.728 + else
1.729 + glp_set_obj_dir(lp->prob, GLP_MAX);
1.730 +done: xassert(errcode == errcode);
1.731 + return;
1.732 +}
1.733 +
1.734 +int CPXchgsense(CPXENV *env, CPXLP *lp, int cnt, const int indices[],
1.735 + const char sense[])
1.736 +{ int i, m, type, errcode;
1.737 + double rhs;
1.738 + errcode = checklp(env, lp);
1.739 + if (errcode) goto done;
1.740 + if (cnt < 0)
1.741 + { errcode = error(env, CPXERR_BAD_ARGUMENT);
1.742 + goto done;
1.743 + }
1.744 + if (cnt > 0 && (indices == NULL || sense == NULL))
1.745 + { errcode = error(env, CPXERR_NULL_POINTER);
1.746 + goto done;
1.747 + }
1.748 + m = glp_get_num_rows(lp->prob);
1.749 + for (i = 0; i < cnt; i++)
1.750 + { if (!(0 <= indices[i] && indices[i] < m))
1.751 + { errcode = error(env, CPXERR_ROW_INDEX_RANGE, i);
1.752 + goto done;
1.753 + }
1.754 + if (!(sense[i] == 'L' || sense[i] == 'E' || sense[i] == 'G' ||
1.755 + sense[i] == 'R'))
1.756 + { errcode = error(env, CPXERR_BAD_SENSE, i);
1.757 + goto done;
1.758 + }
1.759 + }
1.760 + errcode = 0;
1.761 + invalidate(lp);
1.762 + for (i = 0; i < cnt; i++)
1.763 + { type = glp_get_row_type(lp->prob, indices[i]+1);
1.764 + if (lp->rflag[indices[i]] == RF_NOT_RANGED)
1.765 + { if (type == GLP_LO || type == GLP_FX)
1.766 + rhs = glp_get_row_lb(lp->prob, indices[i]+1);
1.767 + else if (type == GLP_UP)
1.768 + rhs = glp_get_row_ub(lp->prob, indices[i]+1);
1.769 + else
1.770 + xassert(type != type);
1.771 + }
1.772 + else if (lp->rflag[indices[i]] == RF_RANGED_POS)
1.773 + { xassert(type == GLP_DB || type == GLP_FX);
1.774 + rhs = glp_get_row_lb(lp->prob, indices[i]+1);
1.775 + }
1.776 + else if (lp->rflag[indices[i]] == RF_RANGED_NEG)
1.777 + { xassert(type == GLP_DB);
1.778 + rhs = glp_get_row_ub(lp->prob, indices[i]+1);
1.779 + }
1.780 + else
1.781 + xassert(lp != lp);
1.782 + if (sense[i] == 'L')
1.783 + { lp->rflag[indices[i]] = RF_NOT_RANGED;
1.784 + type = GLP_UP;
1.785 + }
1.786 + else if (sense[i] == 'E')
1.787 + { lp->rflag[indices[i]] = RF_NOT_RANGED;
1.788 + type = GLP_FX;
1.789 + }
1.790 + else if (sense[i] == 'G')
1.791 + { lp->rflag[indices[i]] = RF_NOT_RANGED;
1.792 + type = GLP_LO;
1.793 + }
1.794 + else if (sense[i] == 'R')
1.795 + { lp->rflag[indices[i]] = RF_RANGED_POS;
1.796 + type = GLP_FX;
1.797 + }
1.798 + else
1.799 + xassert(sense != sense);
1.800 + glp_set_row_bnds(lp->prob, indices[i]+1, type, rhs, rhs);
1.801 + }
1.802 +done: return errcode;
1.803 +}
1.804 +
1.805 +int CPXcloseCPLEX(CPXENV **_env)
1.806 +{ CPXENV *env;
1.807 + CPXLP *lp;
1.808 + int errcode;
1.809 + if (_env == NULL)
1.810 + { errcode = CPXERR_NULL_POINTER;
1.811 + goto done;
1.812 + }
1.813 + env = *_env;
1.814 + errcode = checkenv(env);
1.815 + if (errcode) goto done;
1.816 + while (env->list != NULL)
1.817 + { lp = env->list;
1.818 + errcode = CPXfreeprob(env, &lp);
1.819 + xassert(!errcode);
1.820 + }
1.821 + xfree(env->intparam);
1.822 + xfree(env->dblparam);
1.823 + xfree(env);
1.824 + *_env = NULL;
1.825 + errcode = 0;
1.826 +done: return errcode;
1.827 +}
1.828 +
1.829 +int CPXcopybase(CPXENV *env, CPXLP *lp, const int cstat[],
1.830 + const int rstat[])
1.831 +{ int i, j, m, n, stat, errcode;
1.832 + errcode = checklp(env, lp);
1.833 + if (errcode) goto done;
1.834 + m = glp_get_num_rows(lp->prob);
1.835 + n = glp_get_num_cols(lp->prob);
1.836 + if (m > 0 && rstat == NULL || n > 0 && cstat == NULL)
1.837 + { errcode = error(env, CPXERR_NULL_POINTER);
1.838 + goto done;
1.839 + }
1.840 + for (i = 0; i < m; i++)
1.841 + { if (!(rstat[i] == CPX_AT_LOWER || rstat[i] == CPX_BASIC ||
1.842 + rstat[i] == CPX_AT_UPPER))
1.843 + { errcode = error(env, CPXERR_BAD_STATUS, i);
1.844 + goto done;
1.845 + }
1.846 + }
1.847 + for (j = 0; j < n; j++)
1.848 + { if (!(cstat[j] == CPX_AT_LOWER || cstat[j] == CPX_BASIC ||
1.849 + cstat[j] == CPX_AT_UPPER || cstat[j] == CPX_FREE_SUPER))
1.850 + { errcode = error(env, CPXERR_BAD_STATUS, j);
1.851 + goto done;
1.852 + }
1.853 + }
1.854 + errcode = 0;
1.855 + invalidate(lp);
1.856 + for (i = 0; i < m; i++)
1.857 + { if (rstat[i] == CPX_AT_LOWER)
1.858 + stat = GLP_NL;
1.859 + else if (rstat[i] == CPX_BASIC)
1.860 + stat = GLP_BS;
1.861 + else if (rstat[i] == CPX_AT_UPPER)
1.862 + stat = GLP_NU;
1.863 + else
1.864 + xassert(rstat != rstat);
1.865 + glp_set_row_stat(lp->prob, i+1, stat);
1.866 + }
1.867 + for (j = 0; j < n; j++)
1.868 + { if (cstat[j] == CPX_AT_LOWER)
1.869 + stat = GLP_NL;
1.870 + else if (cstat[j] == CPX_BASIC)
1.871 + stat = GLP_BS;
1.872 + else if (cstat[j] == CPX_AT_UPPER)
1.873 + stat = GLP_NU;
1.874 + else if (cstat[j] == CPX_FREE_SUPER)
1.875 + stat = GLP_NF;
1.876 + else
1.877 + xassert(cstat != cstat);
1.878 + glp_set_col_stat(lp->prob, j+1, stat);
1.879 + }
1.880 +done: return errcode;
1.881 +}
1.882 +
1.883 +int CPXcopybasednorms(CPXENV *env, CPXLP *lp, const int cstat[],
1.884 + const int rstat[], const double dnorm[])
1.885 +{ int errcode;
1.886 + errcode = CPXcopybase(env, lp, cstat, rstat);
1.887 + xassert(dnorm == dnorm);
1.888 + return errcode;
1.889 +}
1.890 +
1.891 +int CPXcopylp(CPXENV *env, CPXLP *lp, int numcols, int numrows,
1.892 + int objsen, const double obj[], const double rhs[],
1.893 + const char sense[], const int matbeg[], const int matcnt[],
1.894 + const int matind[], const double matval[], const double lb[],
1.895 + const double ub[], const double rngval[])
1.896 +{ int errcode;
1.897 + errcode = CPXcopylpwnames(env, lp, numcols, numrows, objsen, obj,
1.898 + rhs, sense, matbeg, matcnt, matind, matval, lb, ub, rngval,
1.899 + NULL, NULL);
1.900 + return errcode;
1.901 +}
1.902 +
1.903 +int CPXcopylpwnames(CPXENV *env, CPXLP *lp, int numcols, int numrows,
1.904 + int objsen, const double obj[], const double rhs[],
1.905 + const char sense[], const int matbeg[], const int matcnt[],
1.906 + const int matind[], const double matval[], const double lb[],
1.907 + const double ub[], const double rngval[], char *colname[],
1.908 + char *rowname[])
1.909 +{ int i, j, k, beg, end, type, errcode;
1.910 + double lbnd, ubnd;
1.911 + char name[255+1];
1.912 + errcode = checklp(env, lp);
1.913 + if (errcode) goto done;
1.914 + if (numcols < 0 || numrows < 0)
1.915 + { errcode = error(env, CPXERR_BAD_ARGUMENT);
1.916 + goto done;
1.917 + }
1.918 + if (!(objsen == CPX_MIN || objsen == CPX_MAX))
1.919 + { errcode = error(env, CPXERR_BAD_ARGUMENT);
1.920 + goto done;
1.921 + }
1.922 + if (numcols > 0)
1.923 + { if (matbeg == NULL || matcnt == NULL || matind == NULL ||
1.924 + matval == NULL)
1.925 + { errcode = error(env, CPXERR_NULL_POINTER);
1.926 + goto done;
1.927 + }
1.928 + }
1.929 + for (i = 0; i < numrows; i++)
1.930 + { if (sense != NULL)
1.931 + { if (!(sense[i] == 'L' || sense[i] == 'E' ||
1.932 + sense[i] == 'G' || sense[i] == 'R'))
1.933 + { errcode = error(env, CPXERR_BAD_SENSE, i);
1.934 + goto done;
1.935 + }
1.936 + }
1.937 + if (rowname != NULL)
1.938 + { if (rowname[i] == NULL)
1.939 + { errcode = error(env, CPXERR_NULL_NAME, i);
1.940 + goto done;
1.941 + }
1.942 + }
1.943 + }
1.944 + enlargeiwork(lp, numrows);
1.945 + for (j = 0; j < numcols; j++)
1.946 + { beg = matbeg[j];
1.947 + if (j > 0 && !(matbeg[j-1] <= beg))
1.948 + { errcode = error(env, CPXERR_ARRAY_NOT_ASCENDING, j);
1.949 + goto done;
1.950 + }
1.951 + if (beg < 0)
1.952 + { errcode = error(env, CPXERR_INDEX_RANGE);
1.953 + goto done;
1.954 + }
1.955 + end = beg + matcnt[j];
1.956 + if (!(beg <= end) || j < numcols-1 && !(end <= matbeg[j+1]))
1.957 + { errcode = error(env, CPXERR_COUNT_RANGE, j);
1.958 + goto done;
1.959 + }
1.960 + for (k = beg; k < end; k++)
1.961 + { if (!(0 <= matind[k] && matind[k] < numrows))
1.962 + { errcode = error(env, CPXERR_ROW_INDEX_RANGE, k);
1.963 + goto done;
1.964 + }
1.965 + }
1.966 + errcode = 0;
1.967 + for (k = beg; k < end; k++)
1.968 + { if (lp->iwork[matind[k]])
1.969 + { errcode = error(env, CPXERR_DUP_ENTRY);
1.970 + break;
1.971 + }
1.972 + lp->iwork[matind[k]] = 1;
1.973 + }
1.974 + for (k = beg; k < end; k++)
1.975 + lp->iwork[matind[k]] = 0;
1.976 + if (errcode) goto done;
1.977 + if (colname != NULL)
1.978 + { if (colname[j] != NULL)
1.979 + { errcode = error(env, CPXERR_NULL_NAME, j);
1.980 + goto done;
1.981 + }
1.982 + }
1.983 + }
1.984 + errcode = 0;
1.985 + invalidate(lp);
1.986 + if (glp_get_prob_name(lp->prob) == NULL)
1.987 + name[0] = '\0';
1.988 + else
1.989 + strcpy(name, glp_get_prob_name(lp->prob));
1.990 + glp_erase_prob(lp->prob);
1.991 + glp_set_prob_name(lp->prob, name);
1.992 + if (objsen == CPX_MIN)
1.993 + glp_set_obj_dir(lp->prob, GLP_MIN);
1.994 + else if (objsen == CPX_MAX)
1.995 + glp_set_obj_dir(lp->prob, GLP_MAX);
1.996 + else
1.997 + xassert(objsen != objsen);
1.998 + if (numrows > 0)
1.999 + glp_add_rows(lp->prob, numrows);
1.1000 + enlargerflag(lp);
1.1001 + for (i = 0; i < numrows; i++)
1.1002 + { if (rowname != NULL)
1.1003 + glp_set_row_name(lp->prob, i+1, rowname[i]);
1.1004 + lbnd = ubnd = (rhs == NULL ? 0.0 : rhs[i]);
1.1005 + if (sense == NULL || sense[i] == 'E')
1.1006 + { lp->rflag[i] = RF_NOT_RANGED;
1.1007 + type = GLP_FX;
1.1008 + }
1.1009 + else if (sense[i] == 'L')
1.1010 + { lp->rflag[i] = RF_NOT_RANGED;
1.1011 + type = GLP_UP;
1.1012 + }
1.1013 + else if (sense[i] == 'G')
1.1014 + { lp->rflag[i] = RF_NOT_RANGED;
1.1015 + type = GLP_LO;
1.1016 + }
1.1017 + else if (sense[i] == 'R')
1.1018 + { if (rngval == NULL || rngval[i] == 0.0)
1.1019 + { lp->rflag[i] = RF_RANGED_POS;
1.1020 + type = GLP_FX;
1.1021 + }
1.1022 + else if (rngval[i] > 0.0)
1.1023 + { lp->rflag[i] = RF_RANGED_POS;
1.1024 + type = GLP_DB;
1.1025 + ubnd += rngval[i];
1.1026 + }
1.1027 + else /* rngval[i] < 0.0 */
1.1028 + { lp->rflag[i] = RF_RANGED_NEG;
1.1029 + type = GLP_DB;
1.1030 + lbnd += rngval[i];
1.1031 + }
1.1032 + }
1.1033 + else
1.1034 + xassert(sense != sense);
1.1035 + glp_set_row_bnds(lp->prob, i+1, type, lbnd, ubnd);
1.1036 + }
1.1037 + if (numcols > 0)
1.1038 + glp_add_cols(lp->prob, numcols);
1.1039 + for (j = 0; j < numcols; j++)
1.1040 + { if (colname != NULL)
1.1041 + glp_set_col_name(lp->prob, j+1, colname[j]);
1.1042 + lbnd = (lb == NULL ? 0.0 : lb[j]);
1.1043 + ubnd = (ub == NULL ? +CPX_INFBOUND : ub[j]);
1.1044 + if (lbnd <= -CPX_INFBOUND && ubnd >= +CPX_INFBOUND)
1.1045 + type = GLP_FR;
1.1046 + else if (ubnd >= +CPX_INFBOUND)
1.1047 + type = GLP_LO;
1.1048 + else if (lbnd <= -CPX_INFBOUND)
1.1049 + type = GLP_UP;
1.1050 + else if (lbnd != ubnd)
1.1051 + type = GLP_DB;
1.1052 + else
1.1053 + type = GLP_FX;
1.1054 + glp_set_col_bnds(lp->prob, j+1, type, lbnd, ubnd);
1.1055 + if (obj != NULL)
1.1056 + glp_set_obj_coef(lp->prob, j+1, obj[j]);
1.1057 + beg = matbeg[j];
1.1058 + end = beg + matcnt[j];
1.1059 + for (k = beg; k < end; k++)
1.1060 + lp->iwork[k-beg] = matind[k]+1;
1.1061 + glp_set_mat_col(lp->prob, j+1, end-beg, lp->iwork-1,
1.1062 + matval+beg-1);
1.1063 + for (k = beg; k < end; k++)
1.1064 + lp->iwork[k-beg] = 0;
1.1065 + }
1.1066 +done: return errcode;
1.1067 +}
1.1068 +
1.1069 +CPXLP *CPXcreateprob(CPXENV *env, int *status, const char *probname)
1.1070 +{ CPXLP *lp = NULL;
1.1071 + int errcode;
1.1072 + errcode = checkenv(env);
1.1073 + if (errcode) goto done;
1.1074 + lp = xmalloc(sizeof(struct CPXLP));
1.1075 + lp->env = env;
1.1076 + lp->prob = glp_create_prob();
1.1077 + glp_set_prob_name(lp->prob, probname);
1.1078 + lp->rflen = 100;
1.1079 + lp->rflag = xcalloc(lp->rflen, sizeof(char));
1.1080 + lp->iwlen = 100;
1.1081 + lp->iwork = xcalloc(lp->iwlen, sizeof(int));
1.1082 + memset(lp->iwork, 0, lp->iwlen * sizeof(int));
1.1083 + lp->link = env->list;
1.1084 + env->list = lp;
1.1085 + invalidate(lp);
1.1086 +done: if (status != NULL) *status = errcode;
1.1087 + return lp;
1.1088 +}
1.1089 +
1.1090 +int CPXdelcols(CPXENV *env, CPXLP *lp, int begin, int end)
1.1091 +{ int j, n, errcode;
1.1092 + errcode = checklp(env, lp);
1.1093 + if (errcode) goto done;
1.1094 + n = glp_get_num_cols(lp->prob);
1.1095 + if (!(0 <= begin && begin <= end && end < n))
1.1096 + { errcode = error(env, CPXERR_INDEX_RANGE);
1.1097 + goto done;
1.1098 + }
1.1099 + errcode = 0;
1.1100 + invalidate(lp);
1.1101 + enlargeiwork(lp, end-begin+1);
1.1102 + for (j = begin; j <= end; j++)
1.1103 + lp->iwork[j-begin] = j+1;
1.1104 + glp_del_cols(lp->prob, end-begin+1, lp->iwork-1);
1.1105 + for (j = begin; j <= end; j++)
1.1106 + lp->iwork[j-begin] = 0;
1.1107 +done: return errcode;
1.1108 +}
1.1109 +
1.1110 +int CPXdelrows(CPXENV *env, CPXLP *lp, int begin, int end)
1.1111 +{ int i, m, errcode;
1.1112 + errcode = checklp(env, lp);
1.1113 + if (errcode) goto done;
1.1114 + m = glp_get_num_rows(lp->prob);
1.1115 + if (!(0 <= begin && begin <= end && end < m))
1.1116 + { errcode = error(env, CPXERR_INDEX_RANGE);
1.1117 + goto done;
1.1118 + }
1.1119 + errcode = 0;
1.1120 + invalidate(lp);
1.1121 + enlargeiwork(lp, end-begin+1);
1.1122 + for (i = begin; i <= end; i++)
1.1123 + lp->iwork[i-begin] = i+1;
1.1124 + glp_del_rows(lp->prob, end-begin+1, lp->iwork-1);
1.1125 + for (i = begin; i <= end; i++)
1.1126 + lp->iwork[i-begin] = 0;
1.1127 + for (i = end+1; i < m; i++)
1.1128 + lp->rflag[i-(end-begin+1)] = lp->rflag[i];
1.1129 +done: return errcode;
1.1130 +}
1.1131 +
1.1132 +int CPXdelsetcols(CPXENV *env, CPXLP *lp, int delstat[])
1.1133 +{ xassert(env == env);
1.1134 + xassert(lp == lp);
1.1135 + xassert(delstat == delstat);
1.1136 + xprintf("CPXdelsetcols: not implemented yet\n");
1.1137 + exit(EXIT_FAILURE);
1.1138 + return -1;
1.1139 +}
1.1140 +
1.1141 +int CPXdelsetrows(CPXENV *env, CPXLP *lp, int delstat[])
1.1142 +{ int i, m, cnt, ind, errcode;
1.1143 + errcode = checklp(env, lp);
1.1144 + if (errcode) goto done;
1.1145 + m = glp_get_num_rows(lp->prob);
1.1146 + if (m > 0 && delstat == NULL)
1.1147 + { errcode = error(env, CPXERR_NULL_POINTER);
1.1148 + goto done;
1.1149 + }
1.1150 + errcode = 0;
1.1151 + invalidate(lp);
1.1152 + enlargeiwork(lp, m);
1.1153 + cnt = ind = 0;
1.1154 + for (i = 0; i < m; i++)
1.1155 + { if (delstat[i] == 1)
1.1156 + { delstat[i] = -1;
1.1157 + lp->iwork[cnt++] = i+1;
1.1158 + }
1.1159 + else
1.1160 + { delstat[i] = ind;
1.1161 + lp->rflag[ind++] = lp->rflag[i];
1.1162 + }
1.1163 + }
1.1164 + if (cnt > 0)
1.1165 + glp_del_rows(lp->prob, cnt, lp->iwork-1);
1.1166 + for (i = 0; i < cnt; i++)
1.1167 + lp->iwork[i] = 0;
1.1168 +done: return errcode;
1.1169 +}
1.1170 +
1.1171 +int CPXdualopt(CPXENV *env, CPXLP *lp);
1.1172 +
1.1173 +int CPXfreeprob(CPXENV *env, CPXLP **_lp)
1.1174 +{ CPXLP *lp;
1.1175 + int errcode;
1.1176 + errcode = checkenv(env);
1.1177 + if (errcode) goto done;
1.1178 + if (_lp == NULL)
1.1179 + { errcode = error(env, CPXERR_NULL_POINTER);
1.1180 + goto done;
1.1181 + }
1.1182 + lp = *_lp;
1.1183 + errcode = checklp(env, lp);
1.1184 + if (errcode) goto done;
1.1185 + errcode = 0;
1.1186 + env = lp->env;
1.1187 + if (env->list == lp)
1.1188 + env->list = lp->link;
1.1189 + else
1.1190 + { CPXLP *pp;
1.1191 + for (pp = env->list; pp != NULL; pp = pp->link)
1.1192 + if (pp->link == lp) break;
1.1193 + xassert(pp != NULL);
1.1194 + pp->link = lp->link;
1.1195 + }
1.1196 + glp_delete_prob(lp->prob);
1.1197 + xfree(lp->rflag);
1.1198 + xfree(lp->iwork);
1.1199 + xfree(lp);
1.1200 + *_lp = NULL;
1.1201 +done: return errcode;
1.1202 +}
1.1203 +
1.1204 +int CPXgetbase(CPXENV *env, CPXLP *lp, int cstat[], int rstat[])
1.1205 +{ int i, j, m, n, stat, errcode;
1.1206 + errcode = checklp(env, lp);
1.1207 + if (errcode) goto done;
1.1208 + if (!lp->stat)
1.1209 + { errcode = error(env, CPXERR_NO_SOLN);
1.1210 + goto done;
1.1211 + }
1.1212 + if (lp->meth == CPX_ALG_PRIMAL || lp->meth == CPX_ALG_DUAL)
1.1213 + ;
1.1214 + else
1.1215 + { errcode = error(env, CPXERR_NO_BASIC_SOLN);
1.1216 + goto done;
1.1217 + }
1.1218 + errcode = 0;
1.1219 + if (rstat != NULL)
1.1220 + { m = glp_get_num_rows(lp->prob);
1.1221 + for (i = 0; i < m; i++)
1.1222 + { stat = glp_get_row_stat(lp->prob, i+1);
1.1223 + if (stat == GLP_BS)
1.1224 + rstat[i] = CPX_BASIC;
1.1225 + else if (lp->rflag[i] == RF_NOT_RANGED || stat != GLP_NU)
1.1226 + rstat[i] = CPX_AT_LOWER;
1.1227 + else
1.1228 + rstat[i] = CPX_AT_UPPER;
1.1229 + }
1.1230 + }
1.1231 + if (cstat != NULL)
1.1232 + { n = glp_get_num_cols(lp->prob);
1.1233 + for (j = 0; j < n; j++)
1.1234 + { stat = glp_get_col_stat(lp->prob, j+1);
1.1235 + if (stat == GLP_BS)
1.1236 + cstat[j] = CPX_BASIC;
1.1237 + else if (stat == GLP_NU)
1.1238 + cstat[j] = CPX_AT_UPPER;
1.1239 + else if (stat == GLP_NF)
1.1240 + cstat[j] = CPX_FREE_SUPER;
1.1241 + else
1.1242 + cstat[j] = CPX_AT_LOWER;
1.1243 + }
1.1244 + }
1.1245 +done: return errcode;
1.1246 +}
1.1247 +
1.1248 +int CPXgetbasednorms(CPXENV *env, CPXLP *lp, int cstat[], int rstat[],
1.1249 + double dnorm[])
1.1250 +{ int i, m, errcode;
1.1251 + errcode = CPXgetbase(env, lp, cstat, rstat);
1.1252 + if (errcode) goto done;
1.1253 + if (dnorm != NULL)
1.1254 + { m = glp_get_num_rows(lp->prob);
1.1255 + for (i = 0; i < m; i++) dnorm[i] = 1.0;
1.1256 + }
1.1257 +done: return errcode;
1.1258 +}
1.1259 +
1.1260 +int CPXgetbhead(CPXENV *env, CPXLP *lp, int head[], double x[])
1.1261 +{ xassert(env == env);
1.1262 + xassert(lp == lp);
1.1263 + xassert(head == head);
1.1264 + xassert(x == x);
1.1265 + xprintf("CPXgetbhead: not implemented yet\n");
1.1266 + exit(EXIT_FAILURE);
1.1267 + return -1;
1.1268 +}
1.1269 +
1.1270 +int CPXgetdblparam(CPXENV *env, int whichparam, double *value)
1.1271 +{ int k, errcode;
1.1272 + errcode = checkenv(env);
1.1273 + if (errcode) goto done;
1.1274 + k = finddblparam(whichparam);
1.1275 + if (k < 0)
1.1276 + { errcode = error(env, CPXERR_BAD_PARAM_NUM);
1.1277 + goto done;
1.1278 + }
1.1279 + errcode = 0;
1.1280 + if (value != NULL)
1.1281 + *value = env->dblparam[k];
1.1282 +done: return errcode;
1.1283 +}
1.1284 +
1.1285 +int CPXgetdj(CPXENV *env, CPXLP *lp, double dj[], int begin, int end)
1.1286 +{ int j, n, errcode;
1.1287 + errcode = checklp(env, lp);
1.1288 + if (errcode) goto done;
1.1289 + n = glp_get_num_cols(lp->prob);
1.1290 + if (!(0 <= begin && begin <= end && end < n))
1.1291 + { errcode = error(env, CPXERR_INDEX_RANGE);
1.1292 + goto done;
1.1293 + }
1.1294 + if (!lp->stat)
1.1295 + { errcode = error(env, CPXERR_NO_SOLN);
1.1296 + goto done;
1.1297 + }
1.1298 + errcode = 0;
1.1299 + if (lp->meth == CPX_ALG_PRIMAL || lp->meth == CPX_ALG_DUAL)
1.1300 + { if (dj != NULL)
1.1301 + { for (j = begin; j <= end; j++)
1.1302 + dj[j-begin] = glp_get_col_dual(lp->prob, j+1);
1.1303 + }
1.1304 + }
1.1305 + else
1.1306 + xassert(lp != lp);
1.1307 +done: return errcode;
1.1308 +}
1.1309 +
1.1310 +char *CPXgeterrorstring(CPXENV *env, int errcode, char *buffer)
1.1311 +{ const char *string;
1.1312 + xassert(env == env);
1.1313 + string = finderrstring(errcode);
1.1314 + if (string == NULL)
1.1315 + buffer = NULL;
1.1316 + else
1.1317 + sprintf(buffer, "CPLEX Error %5d: %s.\n", errcode, string);
1.1318 + return buffer;
1.1319 +}
1.1320 +
1.1321 +int CPXgetijdiv(CPXENV *env, CPXLP *lp, int *idiv, int *jdiv)
1.1322 +{ xassert(env == env);
1.1323 + xassert(lp == lp);
1.1324 + xassert(idiv == idiv);
1.1325 + xassert(jdiv == jdiv);
1.1326 + xprintf("CPXgetijdiv: not implemented yet\n");
1.1327 + exit(EXIT_FAILURE);
1.1328 + return -1;
1.1329 +}
1.1330 +
1.1331 +int CPXgetintparam(CPXENV *env, int whichparam, int *value)
1.1332 +{ int k, errcode;
1.1333 + errcode = checkenv(env);
1.1334 + if (errcode) goto done;
1.1335 + k = findintparam(whichparam);
1.1336 + if (k < 0)
1.1337 + { errcode = error(env, CPXERR_BAD_PARAM_NUM);
1.1338 + goto done;
1.1339 + }
1.1340 + errcode = 0;
1.1341 + if (value != NULL)
1.1342 + *value = env->intparam[k];
1.1343 +done: return errcode;
1.1344 +}
1.1345 +
1.1346 +int CPXgetlb(CPXENV *env, CPXLP *lp, double lb[], int begin, int end)
1.1347 +{ xassert(env == env);
1.1348 + xassert(lp == lp);
1.1349 + xassert(lb == lb);
1.1350 + xassert(begin == begin);
1.1351 + xassert(end == end);
1.1352 + xprintf("CPXgetlb: not implemented yet\n");
1.1353 + exit(EXIT_FAILURE);
1.1354 + return -1;
1.1355 +}
1.1356 +
1.1357 +int CPXgetmethod(CPXENV *env, CPXLP *lp)
1.1358 +{ int method;
1.1359 + if (checklp(env, lp))
1.1360 + method = CPX_ALG_NONE;
1.1361 + else
1.1362 + method = lp->meth;
1.1363 + return method;
1.1364 +}
1.1365 +
1.1366 +int CPXgetnumcols(CPXENV *env, CPXLP *lp)
1.1367 +{ int numcols;
1.1368 + if (checklp(env, lp))
1.1369 + numcols = 0;
1.1370 + else
1.1371 + numcols = glp_get_num_cols(lp->prob);
1.1372 + return numcols;
1.1373 +}
1.1374 +
1.1375 +int CPXgetnumnz(CPXENV *env, CPXLP *lp)
1.1376 +{ int numnz;
1.1377 + if (checklp(env, lp))
1.1378 + numnz = 0;
1.1379 + else
1.1380 + numnz = glp_get_num_nz(lp->prob);
1.1381 + return numnz;
1.1382 +}
1.1383 +
1.1384 +int CPXgetnumrows(CPXENV *env, CPXLP *lp)
1.1385 +{ int numrows;
1.1386 + if (checklp(env, lp))
1.1387 + numrows = 0;
1.1388 + else
1.1389 + numrows = glp_get_num_rows(lp->prob);
1.1390 + return numrows;
1.1391 +}
1.1392 +
1.1393 +int CPXgetobjval(CPXENV *env, CPXLP *lp, double *objval)
1.1394 +{ int errcode;
1.1395 + errcode = checklp(env, lp);
1.1396 + if (errcode) goto done;
1.1397 + if (!lp->stat)
1.1398 + { errcode = error(env, CPXERR_NO_SOLN);
1.1399 + goto done;
1.1400 + }
1.1401 + errcode = 0;
1.1402 + if (lp->meth == CPX_ALG_PRIMAL || lp->meth == CPX_ALG_DUAL)
1.1403 + { if (objval != NULL)
1.1404 + *objval = glp_get_obj_val(lp->prob);
1.1405 + }
1.1406 + else
1.1407 + xassert(lp != lp);
1.1408 +done: return errcode;
1.1409 +}
1.1410 +
1.1411 +int CPXgetpi(CPXENV *env, CPXLP *lp, double pi[], int begin, int end)
1.1412 +{ int i, m, errcode;
1.1413 + errcode = checklp(env, lp);
1.1414 + if (errcode) goto done;
1.1415 + m = glp_get_num_rows(lp->prob);
1.1416 + if (!(0 <= begin && begin <= end && end < m))
1.1417 + { errcode = error(env, CPXERR_INDEX_RANGE);
1.1418 + goto done;
1.1419 + }
1.1420 + if (!lp->stat)
1.1421 + { errcode = error(env, CPXERR_NO_SOLN);
1.1422 + goto done;
1.1423 + }
1.1424 + errcode = 0;
1.1425 + if (lp->meth == CPX_ALG_PRIMAL || lp->meth == CPX_ALG_DUAL)
1.1426 + { if (pi != NULL)
1.1427 + { for (i = begin; i <= end; i++)
1.1428 + pi[i-begin] = glp_get_row_dual(lp->prob, i+1);
1.1429 + }
1.1430 + }
1.1431 + else
1.1432 + xassert(lp != lp);
1.1433 +done: return errcode;
1.1434 +}
1.1435 +
1.1436 +int CPXgetsense(CPXENV *env, CPXLP *lp, char sense[], int begin,
1.1437 + int end)
1.1438 +{ xassert(env == env);
1.1439 + xassert(lp == lp);
1.1440 + xassert(sense == sense);
1.1441 + xassert(begin == begin);
1.1442 + xassert(end == end);
1.1443 + xprintf("CPXgetsense: not implemented yet\n");
1.1444 + exit(EXIT_FAILURE);
1.1445 + return -1;
1.1446 +}
1.1447 +
1.1448 +int CPXgetslack(CPXENV *env, CPXLP *lp, double slack[], int begin,
1.1449 + int end)
1.1450 +{ int i, m, type, errcode;
1.1451 + double temp;
1.1452 + errcode = checklp(env, lp);
1.1453 + if (errcode) goto done;
1.1454 + m = glp_get_num_rows(lp->prob);
1.1455 + if (!(0 <= begin && begin <= end && end < m))
1.1456 + { errcode = error(env, CPXERR_INDEX_RANGE);
1.1457 + goto done;
1.1458 + }
1.1459 + if (!lp->stat)
1.1460 + { errcode = error(env, CPXERR_NO_SOLN);
1.1461 + goto done;
1.1462 + }
1.1463 + errcode = 0;
1.1464 + if (lp->meth == CPX_ALG_PRIMAL || lp->meth == CPX_ALG_DUAL)
1.1465 + { if (slack != NULL)
1.1466 + { for (i = begin; i <= end; i++)
1.1467 + { type = glp_get_row_type(lp->prob, i+1);
1.1468 + temp = glp_get_row_prim(lp->prob, i+1);
1.1469 + if (lp->rflag[i] == RF_NOT_RANGED)
1.1470 + { if (type == GLP_LO || type == GLP_FX)
1.1471 + slack[i-begin] =
1.1472 + glp_get_row_lb(lp->prob, i+1) - temp;
1.1473 + else if (type == GLP_UP)
1.1474 + slack[i-begin] =
1.1475 + glp_get_row_ub(lp->prob, i+1) - temp;
1.1476 + else
1.1477 + xassert(type != type);
1.1478 + }
1.1479 + else if (lp->rflag[i] == RF_RANGED_POS)
1.1480 + { xassert(type == GLP_DB || type == GLP_FX);
1.1481 + slack[i-begin] =
1.1482 + temp - glp_get_row_lb(lp->prob, i+1);
1.1483 + }
1.1484 + else if (lp->rflag[i] == RF_RANGED_NEG)
1.1485 + { xassert(type == GLP_DB);
1.1486 + slack[i-begin] =
1.1487 + temp - glp_get_row_ub(lp->prob, i+1);
1.1488 + }
1.1489 + else
1.1490 + xassert(lp != lp);
1.1491 + }
1.1492 + }
1.1493 + }
1.1494 + else
1.1495 + xassert(lp != lp);
1.1496 +done: return errcode;
1.1497 +}
1.1498 +
1.1499 +int CPXgetstat(CPXENV *env, CPXLP *lp)
1.1500 +{ int stat;
1.1501 + if (checklp(env, lp))
1.1502 + stat = 0;
1.1503 + else
1.1504 + stat = lp->stat;
1.1505 + return stat;
1.1506 +}
1.1507 +
1.1508 +int CPXgetub(CPXENV *env, CPXLP *lp, double ub[], int begin, int end)
1.1509 +{ xassert(env == env);
1.1510 + xassert(lp == lp);
1.1511 + xassert(ub == ub);
1.1512 + xassert(begin == begin);
1.1513 + xassert(end == end);
1.1514 + xprintf("CPXgetub: not implemented yet\n");
1.1515 + exit(EXIT_FAILURE);
1.1516 + return -1;
1.1517 +}
1.1518 +
1.1519 +int CPXgetweight(CPXENV *env, CPXLP *lp, int rcnt, const int rmatbeg[],
1.1520 + const int rmatind[], const double rmatval[], double weight[],
1.1521 + int dpriind)
1.1522 +{ xassert(env == env);
1.1523 + xassert(lp == lp);
1.1524 + xassert(rcnt == rcnt);
1.1525 + xassert(rmatbeg == rmatbeg);
1.1526 + xassert(rmatind == rmatind);
1.1527 + xassert(rmatval == rmatval);
1.1528 + xassert(weight == weight);
1.1529 + xassert(dpriind == dpriind);
1.1530 + xprintf("CPXgetweight: not implemented yet\n");
1.1531 + exit(EXIT_FAILURE);
1.1532 + return -1;
1.1533 +}
1.1534 +
1.1535 +int CPXgetx(CPXENV *env, CPXLP *lp, double x[], int begin, int end)
1.1536 +{ int j, n, errcode;
1.1537 + errcode = checklp(env, lp);
1.1538 + if (errcode) goto done;
1.1539 + n = glp_get_num_cols(lp->prob);
1.1540 + if (!(0 <= begin && begin <= end && end < n))
1.1541 + { errcode = error(env, CPXERR_INDEX_RANGE);
1.1542 + goto done;
1.1543 + }
1.1544 + if (!lp->stat)
1.1545 + { errcode = error(env, CPXERR_NO_SOLN);
1.1546 + goto done;
1.1547 + }
1.1548 + errcode = 0;
1.1549 + if (lp->meth == CPX_ALG_PRIMAL || lp->meth == CPX_ALG_DUAL)
1.1550 + { if (x != NULL)
1.1551 + { for (j = begin; j <= end; j++)
1.1552 + x[j-begin] = glp_get_col_prim(lp->prob, j+1);
1.1553 + }
1.1554 + }
1.1555 + else
1.1556 + xassert(lp != lp);
1.1557 +done: return errcode;
1.1558 +}
1.1559 +
1.1560 +int CPXinfodblparam(CPXENV *env, int whichparam, double *defvalue,
1.1561 + double *minvalue, double *maxvalue)
1.1562 +{ int k, errcode;
1.1563 + errcode = checkenv(env);
1.1564 + if (errcode) goto done;
1.1565 + k = finddblparam(whichparam);
1.1566 + if (k < 0)
1.1567 + { errcode = error(env, CPXERR_BAD_PARAM_NUM);
1.1568 + goto done;
1.1569 + }
1.1570 + errcode = 0;
1.1571 + if (defvalue != NULL)
1.1572 + *defvalue = dblparam[k].defv;
1.1573 + if (minvalue != NULL)
1.1574 + *minvalue = dblparam[k].minv;
1.1575 + if (maxvalue != NULL)
1.1576 + *maxvalue = dblparam[k].maxv;
1.1577 +done: return errcode;
1.1578 +}
1.1579 +
1.1580 +int CPXinfointparam(CPXENV *env, int whichparam, int *defvalue,
1.1581 + int *minvalue, int *maxvalue)
1.1582 +{ int k, errcode;
1.1583 + errcode = checkenv(env);
1.1584 + if (errcode) goto done;
1.1585 + k = findintparam(whichparam);
1.1586 + if (k < 0)
1.1587 + { errcode = error(env, CPXERR_BAD_PARAM_NUM);
1.1588 + goto done;
1.1589 + }
1.1590 + errcode = 0;
1.1591 + if (defvalue != NULL)
1.1592 + *defvalue = intparam[k].defv;
1.1593 + if (minvalue != NULL)
1.1594 + *minvalue = intparam[k].minv;
1.1595 + if (maxvalue != NULL)
1.1596 + *maxvalue = intparam[k].maxv;
1.1597 +done: return errcode;
1.1598 +}
1.1599 +
1.1600 +int CPXmdleave(const CPXENV *env, CPXLP *lp, const int goodlist[],
1.1601 + int goodlen, double downratio[], double upratio[])
1.1602 +{ int k;
1.1603 + xassert(env == env);
1.1604 + xassert(lp == lp);
1.1605 + xassert(goodlist == goodlist);
1.1606 + xassert(goodlen >= 0);
1.1607 + xassert(downratio != NULL);
1.1608 + xassert(upratio != NULL);
1.1609 + /* not implemented yet */
1.1610 + for (k = 0; k < goodlen; k++)
1.1611 + downratio[k] = upratio[k] = 0.0;
1.1612 + return 0;
1.1613 +}
1.1614 +
1.1615 +int CPXnewcols(CPXENV *env, CPXLP *lp, int ccnt, const double obj[],
1.1616 + const double lb[], const double ub[], const char ctype[],
1.1617 + char *colname[])
1.1618 +{ int j, n, kind, type, errcode;
1.1619 + double lbnd, ubnd;
1.1620 + errcode = checklp(env, lp);
1.1621 + if (errcode) goto done;
1.1622 + if (ccnt < 0)
1.1623 + { errcode = error(env, CPXERR_BAD_ARGUMENT);
1.1624 + goto done;
1.1625 + }
1.1626 + for (j = 0; j < ccnt; j++)
1.1627 + { if (ctype != NULL)
1.1628 + { if (!(ctype[j] == 'C' || ctype[j] == 'B' ||
1.1629 + ctype[j] == 'I'))
1.1630 + { errcode = error(env, CPXERR_BAD_CTYPE, j);
1.1631 + goto done;
1.1632 + }
1.1633 + }
1.1634 + if (colname != NULL)
1.1635 + { if (colname[j] == NULL)
1.1636 + { errcode = error(env, CPXERR_NULL_NAME, j);
1.1637 + goto done;
1.1638 + }
1.1639 + }
1.1640 + }
1.1641 + errcode = 0;
1.1642 + invalidate(lp);
1.1643 + n = glp_get_num_cols(lp->prob);
1.1644 + if (ccnt > 0)
1.1645 + glp_add_cols(lp->prob, ccnt);
1.1646 + for (j = 0; j < ccnt; j++)
1.1647 + { if (colname != NULL)
1.1648 + glp_set_col_name(lp->prob, n+j+1, colname[j]);
1.1649 + if (obj != NULL)
1.1650 + glp_set_obj_coef(lp->prob, n+j+1, obj[j]);
1.1651 + lbnd = (lb == NULL ? 0.0 : lb[j]);
1.1652 + ubnd = (ub == NULL ? 0.0 : ub[j]);
1.1653 + if (lbnd <= -CPX_INFBOUND && ubnd >= +CPX_INFBOUND)
1.1654 + type = GLP_FR;
1.1655 + else if (ubnd >= +CPX_INFBOUND)
1.1656 + type = GLP_LO;
1.1657 + else if (lbnd <= -CPX_INFBOUND)
1.1658 + type = GLP_UP;
1.1659 + else if (lbnd != ubnd)
1.1660 + type = GLP_DB;
1.1661 + else
1.1662 + type = GLP_FX;
1.1663 + glp_set_col_bnds(lp->prob, n+j+1, type, lbnd, ubnd);
1.1664 + if (ctype != NULL)
1.1665 + { if (ctype[j] == 'C')
1.1666 + kind = GLP_CV;
1.1667 + else if (ctype[j] == 'B')
1.1668 + kind = GLP_BV;
1.1669 + else if (ctype[j] == 'I')
1.1670 + kind = GLP_IV;
1.1671 + else
1.1672 + xassert(ctype != ctype);
1.1673 + glp_set_col_kind(lp->prob, n+j+1, kind);
1.1674 + }
1.1675 + }
1.1676 +done: return errcode;
1.1677 +}
1.1678 +
1.1679 +int CPXnewrows(CPXENV *env, CPXLP *lp, int rcnt, const double rhs[],
1.1680 + const char sense[], const double rngval[], char *rowname[])
1.1681 +{ int i, m, type, errcode;
1.1682 + double lbnd, ubnd;
1.1683 + errcode = checklp(env, lp);
1.1684 + if (errcode) goto done;
1.1685 + if (rcnt < 0)
1.1686 + { errcode = error(env, CPXERR_BAD_ARGUMENT);
1.1687 + goto done;
1.1688 + }
1.1689 + for (i = 0; i < rcnt; i++)
1.1690 + { if (sense != NULL)
1.1691 + { if (!(sense[i] == 'L' || sense[i] == 'E' ||
1.1692 + sense[i] == 'G' || sense[i] == 'R'))
1.1693 + { errcode = error(env, CPXERR_BAD_SENSE, i);
1.1694 + goto done;
1.1695 + }
1.1696 + }
1.1697 + if (rowname != NULL)
1.1698 + { if (rowname[i] == NULL)
1.1699 + { errcode = error(env, CPXERR_NULL_NAME, i);
1.1700 + goto done;
1.1701 + }
1.1702 + }
1.1703 + }
1.1704 + errcode = 0;
1.1705 + invalidate(lp);
1.1706 + m = glp_get_num_rows(lp->prob);
1.1707 + if (rcnt > 0)
1.1708 + glp_add_rows(lp->prob, rcnt);
1.1709 + enlargerflag(lp);
1.1710 + for (i = 0; i < rcnt; i++)
1.1711 + { if (rowname != NULL)
1.1712 + glp_set_row_name(lp->prob, m+i+1, rowname[i]);
1.1713 + lbnd = ubnd = (rhs == NULL ? 0.0 : rhs[i]);
1.1714 + if (sense == NULL || sense[i] == 'E')
1.1715 + { lp->rflag[m+i] = RF_NOT_RANGED;
1.1716 + type = GLP_FX;
1.1717 + }
1.1718 + else if (sense[i] == 'L')
1.1719 + { lp->rflag[m+i] = RF_NOT_RANGED;
1.1720 + type = GLP_UP;
1.1721 + }
1.1722 + else if (sense[i] == 'G')
1.1723 + { lp->rflag[m+i] = RF_NOT_RANGED;
1.1724 + type = GLP_LO;
1.1725 + }
1.1726 + else if (sense[i] == 'R')
1.1727 + { if (rngval == NULL || rngval[i] == 0.0)
1.1728 + { lp->rflag[m+i] = RF_RANGED_POS;
1.1729 + type = GLP_FX;
1.1730 + }
1.1731 + else if (rngval[i] > 0.0)
1.1732 + { lp->rflag[m+i] = RF_RANGED_POS;
1.1733 + type = GLP_DB;
1.1734 + ubnd += rngval[i];
1.1735 + }
1.1736 + else /* rngval[i] < 0.0 */
1.1737 + { lp->rflag[m+i] = RF_RANGED_NEG;
1.1738 + type = GLP_DB;
1.1739 + lbnd += rngval[i];
1.1740 + }
1.1741 + }
1.1742 + else
1.1743 + xassert(sense != sense);
1.1744 + glp_set_row_bnds(lp->prob, m+i+1, type, lbnd, ubnd);
1.1745 + }
1.1746 +done: return errcode;
1.1747 +}
1.1748 +
1.1749 +CPXENV *CPXopenCPLEX(int *status)
1.1750 +{ CPXENV *env;
1.1751 + int k, card;
1.1752 + env = xmalloc(sizeof(CPXENV));
1.1753 + env->list = NULL;
1.1754 + card = sizeof(intparam) / sizeof(struct intparam);
1.1755 + env->intparam = xcalloc(card, sizeof(int));
1.1756 + for (k = 0; k < card; k++)
1.1757 + env->intparam[k] = intparam[k].defv;
1.1758 + card = sizeof(dblparam) / sizeof(struct dblparam);
1.1759 + env->dblparam = xcalloc(card, sizeof(double));
1.1760 + for (k = 0; k < card; k++)
1.1761 + env->dblparam[k] = dblparam[k].defv;
1.1762 + if (status != NULL) *status = 0;
1.1763 + return env;
1.1764 +}
1.1765 +
1.1766 +int CPXpivotin(CPXENV *env, CPXLP *lp, const int rlist[], int rlen)
1.1767 +{ int i, m, errcode;
1.1768 + errcode = checklp(env, lp);
1.1769 + if (errcode) goto done;
1.1770 + if (rlen < 0)
1.1771 + { errcode = error(env, CPXERR_BAD_ARGUMENT);
1.1772 + goto done;
1.1773 + }
1.1774 + if (rlen > 0 && rlist == NULL)
1.1775 + { errcode = error(env, CPXERR_NULL_POINTER);
1.1776 + goto done;
1.1777 + }
1.1778 + m = glp_get_num_rows(lp->prob);
1.1779 + for (i = 0; i < rlen; i++)
1.1780 + { if (!(0 <= rlist[i] && rlist[i] < m))
1.1781 + { errcode = error(env, CPXERR_ROW_INDEX_RANGE, i);
1.1782 + goto done;
1.1783 + }
1.1784 + }
1.1785 + errcode = 0;
1.1786 + for (i = 0; i < rlen; i++)
1.1787 + { if (glp_get_row_type(lp->prob, rlist[i]+1) != GLP_FX)
1.1788 + { if (glp_get_row_stat(lp->prob, rlist[i]+1) != GLP_BS)
1.1789 + { /* not implemented yet */
1.1790 + break;
1.1791 + }
1.1792 + }
1.1793 + }
1.1794 +done: return errcode;
1.1795 +}
1.1796 +
1.1797 +int CPXpivotout(CPXENV *env, CPXLP *lp, const int clist[], int clen)
1.1798 +{ int j, n, errcode;
1.1799 + errcode = checklp(env, lp);
1.1800 + if (errcode) goto done;
1.1801 + if (clen < 0)
1.1802 + { errcode = error(env, CPXERR_BAD_ARGUMENT);
1.1803 + goto done;
1.1804 + }
1.1805 + if (clen > 0 && clist == NULL)
1.1806 + { errcode = error(env, CPXERR_NULL_POINTER);
1.1807 + goto done;
1.1808 + }
1.1809 + n = glp_get_num_cols(lp->prob);
1.1810 + for (j = 0; j < clen; j++)
1.1811 + { if (!(0 <= clist[j] && clist[j] < n))
1.1812 + { errcode = error(env, CPXERR_COL_INDEX_RANGE, j);
1.1813 + goto done;
1.1814 + }
1.1815 + if (glp_get_col_type(lp->prob, clist[j]+1) != GLP_FX)
1.1816 + { errcode = error(env, CPXERR_NOT_FIXED);
1.1817 + goto done;
1.1818 + }
1.1819 + }
1.1820 + errcode = 0;
1.1821 + for (j = 0; j < clen; j++)
1.1822 + { if (glp_get_col_stat(lp->prob, clist[j]+1) == GLP_BS)
1.1823 + { /* not implemented yet */
1.1824 + break;
1.1825 + }
1.1826 + }
1.1827 +done: return errcode;
1.1828 +}
1.1829 +
1.1830 +int CPXprimopt(CPXENV *env, CPXLP *lp);
1.1831 +
1.1832 +int CPXsavwrite(CPXENV *env, CPXLP *lp, const char *filename)
1.1833 +{ xassert(env == env);
1.1834 + xassert(lp == lp);
1.1835 + xassert(filename == filename);
1.1836 + xprintf("CPXsavwrite: not implemented yet\n");
1.1837 + exit(EXIT_FAILURE);
1.1838 + return -1;
1.1839 +}
1.1840 +
1.1841 +int CPXsetdblparam(CPXENV *env, int whichparam, double newvalue)
1.1842 +{ int k, errcode;
1.1843 + errcode = checkenv(env);
1.1844 + if (errcode) goto done;
1.1845 + k = finddblparam(whichparam);
1.1846 + if (k < 0)
1.1847 + { errcode = error(env, CPXERR_BAD_PARAM_NUM);
1.1848 + goto done;
1.1849 + }
1.1850 + if (newvalue < dblparam[k].minv)
1.1851 + { errcode = error(env, CPXERR_PARAM_TOO_SMALL);
1.1852 + goto done;
1.1853 + }
1.1854 + if (newvalue > dblparam[k].maxv)
1.1855 + { errcode = error(env, CPXERR_PARAM_TOO_BIG);
1.1856 + goto done;
1.1857 + }
1.1858 + errcode = 0;
1.1859 + env->dblparam[k] = newvalue;
1.1860 +done: return errcode;
1.1861 +}
1.1862 +
1.1863 +int CPXsetintparam(CPXENV *env, int whichparam, int newvalue)
1.1864 +{ int k, errcode;
1.1865 + errcode = checkenv(env);
1.1866 + if (errcode) goto done;
1.1867 + k = findintparam(whichparam);
1.1868 + if (k < 0)
1.1869 + { errcode = error(env, CPXERR_BAD_PARAM_NUM);
1.1870 + goto done;
1.1871 + }
1.1872 + if (newvalue < intparam[k].minv)
1.1873 + { errcode = error(env, CPXERR_PARAM_TOO_SMALL);
1.1874 + goto done;
1.1875 + }
1.1876 + if (newvalue > intparam[k].maxv)
1.1877 + { errcode = error(env, CPXERR_PARAM_TOO_BIG);
1.1878 + goto done;
1.1879 + }
1.1880 + errcode = 0;
1.1881 + env->intparam[k] = newvalue;
1.1882 +done: return errcode;
1.1883 +}
1.1884 +
1.1885 +int CPXsolninfo(CPXENV *env, CPXLP *lp, int *solnmethod, int *solntype,
1.1886 + int *pfeasind, int *dfeasind)
1.1887 +{ int type, pfeas, dfeas, errcode;
1.1888 + errcode = checklp(env, lp);
1.1889 + if (errcode) goto done;
1.1890 + errcode = 0;
1.1891 + if (!lp->stat)
1.1892 + type = CPX_NO_SOLN, pfeas = dfeas = 0;
1.1893 + else if (lp->meth == CPX_ALG_PRIMAL || lp->meth == CPX_ALG_DUAL)
1.1894 + { type = CPX_BASIC_SOLN;
1.1895 + pfeas = (glp_get_prim_stat(lp->prob) == GLP_FEAS);
1.1896 + dfeas = (glp_get_dual_stat(lp->prob) == GLP_FEAS);
1.1897 + }
1.1898 + else
1.1899 + xassert(lp != lp);
1.1900 + if (solnmethod != NULL)
1.1901 + *solnmethod = lp->meth;
1.1902 + if (solntype != NULL)
1.1903 + *solntype = type;
1.1904 + if (pfeasind != NULL)
1.1905 + *pfeasind = pfeas;
1.1906 + if (dfeasind != NULL)
1.1907 + *dfeasind = dfeas;
1.1908 +done: return errcode;
1.1909 +}
1.1910 +
1.1911 +int CPXsolution(CPXENV *env, CPXLP *lp, int *lpstat, double *objval,
1.1912 + double x[], double pi[], double slack[], double dj[])
1.1913 +{ int m, n, errcode;
1.1914 + errcode = checklp(env, lp);
1.1915 + if (errcode) goto done;
1.1916 + if (!lp->stat)
1.1917 + { errcode = error(env, CPXERR_NO_SOLN);
1.1918 + goto done;
1.1919 + }
1.1920 + errcode = 0;
1.1921 + m = glp_get_num_rows(lp->prob);
1.1922 + n = glp_get_num_cols(lp->prob);
1.1923 + if (lp->meth == CPX_ALG_PRIMAL || lp->meth == CPX_ALG_DUAL)
1.1924 + { if (lpstat != NULL)
1.1925 + *lpstat = CPXgetstat(env, lp);
1.1926 + if (objval != NULL)
1.1927 + xassert(CPXgetobjval(env, lp, objval) == 0);
1.1928 + if (x != NULL)
1.1929 + xassert(CPXgetx(env, lp, x, 0, n-1) == 0);
1.1930 + if (pi != NULL)
1.1931 + xassert(CPXgetpi(env, lp, pi, 0, m-1) == 0);
1.1932 + if (slack != NULL)
1.1933 + xassert(CPXgetslack(env, lp, slack, 0, m-1) == 0);
1.1934 + if (dj != NULL)
1.1935 + xassert(CPXgetdj(env, lp, dj, 0, n-1) == 0);
1.1936 + }
1.1937 + else
1.1938 + xassert(lp != lp);
1.1939 +done: return errcode;
1.1940 +}
1.1941 +
1.1942 +int CPXstrongbranch(CPXENV *env, CPXLP *lp, const int goodlist[],
1.1943 + int goodlen, double downpen[], double uppen[], int itlim)
1.1944 +{ int k;
1.1945 + xassert(env == env);
1.1946 + xassert(lp == lp);
1.1947 + xassert(goodlist == goodlist);
1.1948 + xassert(goodlen >= 0);
1.1949 + xassert(downpen != NULL);
1.1950 + xassert(uppen != NULL);
1.1951 + xassert(itlim == itlim);
1.1952 + /* not implemented yet */
1.1953 + for (k = 0; k < goodlen; k++)
1.1954 + downpen[k] = uppen[k] = 0.0;
1.1955 + return 0;
1.1956 +}
1.1957 +
1.1958 +static int xstrcasecmp(const char *s1, const char *s2)
1.1959 +{ int c1, c2;
1.1960 + for (;;)
1.1961 + { c1 = toupper((unsigned char)*s1++);
1.1962 + c2 = toupper((unsigned char)*s2++);
1.1963 + if (c1 == '\0' || c1 != c2) break;
1.1964 + }
1.1965 + return c1 - c2;
1.1966 +}
1.1967 +
1.1968 +static void getfiletype(const char *filename, char type[3+1])
1.1969 +{ /* determine filetype from filename */
1.1970 + int beg, end;
1.1971 + beg = end = strlen(filename);
1.1972 + while (beg > 0 && filename[beg-1] != '.' && end - beg < 3)
1.1973 + beg--;
1.1974 + if (beg > 0 && filename[beg-1] == '.' &&
1.1975 + xstrcasecmp(&filename[beg], "gz") == 0)
1.1976 + { end = --beg;
1.1977 + while (beg > 0 && filename[beg-1] != '.' && end - beg < 3)
1.1978 + beg--;
1.1979 + }
1.1980 + if (beg > 0 && filename[beg-1] == '.')
1.1981 + { memcpy(type, &filename[beg], end - beg);
1.1982 + type[end - beg] = '\0';
1.1983 + }
1.1984 + else
1.1985 + type[0] = '\0';
1.1986 + return;
1.1987 +}
1.1988 +
1.1989 +int CPXwriteprob(CPXENV *env, CPXLP *lp, const char *filename,
1.1990 + const char *filetype)
1.1991 +{ glp_prob *copy;
1.1992 + int errcode;
1.1993 + char type[3+1];
1.1994 + errcode = checklp(env, lp);
1.1995 + if (errcode) goto done;
1.1996 + if (filename == NULL)
1.1997 + { errcode = error(env, CPXERR_NO_FILENAME);
1.1998 + goto done;
1.1999 + }
1.2000 + if (filetype == NULL)
1.2001 + getfiletype(filename, type), filetype = type;
1.2002 + if (xstrcasecmp(filetype, "MPS") == 0)
1.2003 + { glp_term_out(GLP_OFF);
1.2004 + errcode = glp_write_mps(lp->prob, GLP_MPS_FILE, NULL, filename)
1.2005 + ;
1.2006 + glp_term_out(GLP_ON);
1.2007 + }
1.2008 + else if (xstrcasecmp(filetype, "LP") == 0)
1.2009 + { glp_term_out(GLP_OFF);
1.2010 + errcode = glp_write_lp(lp->prob, NULL, filename);
1.2011 + glp_term_out(GLP_ON);
1.2012 + }
1.2013 + else if (xstrcasecmp(filetype, "RMP") == 0 ||
1.2014 + xstrcasecmp(filetype, "REW") == 0)
1.2015 + { copy = glp_create_prob();
1.2016 + glp_copy_prob(copy, lp->prob, GLP_OFF);
1.2017 + glp_term_out(GLP_OFF);
1.2018 + errcode = glp_write_mps(copy, GLP_MPS_DECK, NULL, filename);
1.2019 + glp_term_out(GLP_ON);
1.2020 + glp_delete_prob(copy);
1.2021 + }
1.2022 + else if (xstrcasecmp(filetype, "RLP") == 0)
1.2023 + { copy = glp_create_prob();
1.2024 + glp_copy_prob(copy, lp->prob, GLP_OFF);
1.2025 + glp_term_out(GLP_OFF);
1.2026 + errcode = glp_write_lp(copy, NULL, filename);
1.2027 + glp_term_out(GLP_ON);
1.2028 + glp_delete_prob(copy);
1.2029 + }
1.2030 + else
1.2031 + { errcode = error(env, CPXERR_BAD_FILETYPE);
1.2032 + goto done;
1.2033 + }
1.2034 + if (errcode)
1.2035 + errcode = error(env, CPXERR_FAIL_OPEN_WRITE, filename);
1.2036 +done: return errcode;
1.2037 +}
1.2038 +
1.2039 +/**********************************************************************/
1.2040 +
1.2041 +static int solvelp(CPXENV *env, CPXLP *lp, int meth)
1.2042 +{ glp_smcp parm;
1.2043 + int errcode;
1.2044 + errcode = checklp(env, lp);
1.2045 + if (errcode) goto done;
1.2046 + errcode = 0;
1.2047 + invalidate(lp);
1.2048 + glp_init_smcp(&parm);
1.2049 + switch (meth)
1.2050 + { case CPX_ALG_PRIMAL:
1.2051 + parm.meth = GLP_PRIMAL;
1.2052 + break;
1.2053 + case CPX_ALG_DUAL:
1.2054 + parm.meth = GLP_DUAL;
1.2055 + break;
1.2056 + default:
1.2057 + xassert(meth != meth);
1.2058 + }
1.2059 + switch (getintparam(env, CPX_PARAM_SIMDISPLAY))
1.2060 + { case 0:
1.2061 + parm.msg_lev = GLP_MSG_OFF;
1.2062 + break;
1.2063 + case 1:
1.2064 + parm.msg_lev = GLP_MSG_ALL;
1.2065 + break;
1.2066 + case 2:
1.2067 + parm.msg_lev = GLP_MSG_ALL;
1.2068 + parm.out_frq = 1;
1.2069 + break;
1.2070 + default:
1.2071 + xassert(env != env);
1.2072 + }
1.2073 + xassert(getdblparam == getdblparam);
1.2074 + switch (getintparam(env, CPX_PARAM_ADVIND))
1.2075 + { case 0:
1.2076 + glp_term_out(GLP_OFF);
1.2077 + glp_adv_basis(lp->prob, 0);
1.2078 + glp_term_out(GLP_ON);
1.2079 + break;
1.2080 + case 1:
1.2081 + case 2:
1.2082 + break;
1.2083 + default:
1.2084 + xassert(env != env);
1.2085 + }
1.2086 + if (!glp_bf_exists(lp->prob))
1.2087 + { if (glp_factorize(lp->prob) != 0)
1.2088 + { glp_term_out(GLP_OFF);
1.2089 + glp_adv_basis(lp->prob, 0);
1.2090 + glp_term_out(GLP_ON);
1.2091 + if (glp_factorize(lp->prob) != 0)
1.2092 + glp_std_basis(lp->prob);
1.2093 + }
1.2094 + }
1.2095 + xassert(glp_simplex(lp->prob, &parm) == 0);
1.2096 + switch (glp_get_status(lp->prob))
1.2097 + { case GLP_OPT:
1.2098 + lp->stat = CPX_STAT_OPTIMAL;
1.2099 + lp->meth = meth;
1.2100 + break;
1.2101 + case GLP_NOFEAS:
1.2102 + lp->stat = CPX_STAT_INFEASIBLE;
1.2103 + lp->meth = meth;
1.2104 + break;
1.2105 + case GLP_UNBND:
1.2106 + lp->stat = CPX_STAT_UNBOUNDED;
1.2107 + lp->meth = meth;
1.2108 + break;
1.2109 + default:
1.2110 + xassert(lp != lp);
1.2111 + }
1.2112 +done: return errcode;
1.2113 +}
1.2114 +
1.2115 +int CPXprimopt(CPXENV *env, CPXLP *lp)
1.2116 +{ int errcode;
1.2117 + errcode = solvelp(env, lp, CPX_ALG_PRIMAL);
1.2118 + return errcode;
1.2119 +}
1.2120 +
1.2121 +int CPXdualopt(CPXENV *env, CPXLP *lp)
1.2122 +{ int errcode;
1.2123 + errcode = solvelp(env, lp, CPX_ALG_DUAL);
1.2124 + return errcode;
1.2125 +}
1.2126 +
1.2127 +int CPXlpopt(CPXENV *env, CPXLP *lp)
1.2128 +{ int errcode;
1.2129 + errcode = solvelp(env, lp, CPX_ALG_PRIMAL);
1.2130 + return errcode;
1.2131 +}
1.2132 +
1.2133 +/* eof */