examples/cplex/cplex.c
changeset 1 c445c931472f
     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 */