examples/cplex/cplex.c
author Alpar Juttner <alpar@cs.elte.hu>
Mon, 06 Dec 2010 13:09:21 +0100
changeset 1 c445c931472f
permissions -rw-r--r--
Import glpk-4.45

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