summaryrefslogtreecommitdiff
path: root/glpk-5.0/examples/cplex
diff options
context:
space:
mode:
authorPasha <pasha@member.fsf.org>2023-01-27 00:54:07 +0000
committerPasha <pasha@member.fsf.org>2023-01-27 00:54:07 +0000
commitef800d4ffafdbde7d7a172ad73bd984b1695c138 (patch)
tree920cc189130f1e98f252283fce94851443641a6d /glpk-5.0/examples/cplex
parentec4ae3c2b5cb0e83fb667f14f832ea94f68ef075 (diff)
downloadoneapi-master.tar.gz
oneapi-master.tar.bz2
simplex-glpk with modified glpk for fpgaHEADmaster
Diffstat (limited to 'glpk-5.0/examples/cplex')
-rw-r--r--glpk-5.0/examples/cplex/README44
-rw-r--r--glpk-5.0/examples/cplex/concorde.txt121
-rw-r--r--glpk-5.0/examples/cplex/cplex.c2127
-rw-r--r--glpk-5.0/examples/cplex/cplex.h298
4 files changed, 2590 insertions, 0 deletions
diff --git a/glpk-5.0/examples/cplex/README b/glpk-5.0/examples/cplex/README
new file mode 100644
index 0000000..38bb8b4
--- /dev/null
+++ b/glpk-5.0/examples/cplex/README
@@ -0,0 +1,44 @@
+The program module in this subdirectory is a crude implementation of
+CPLEX-like interface to GLPK API. It consists of two files: cplex.c and
+cplex.h.
+
+NOTE that this module is NOT a clean room implementation of the CPLEX
+callable library. It only implements a CPLEX-like interface to the GLPK
+API routines, and its main purpose is to provide possibility to build
+and run applications which normally use the CPLEX callable library.
+
+This module approximately corresponds to CPLEX 9.0.
+
+Currently this module can be used as a linear programming solver for
+Concorde, the state-of-the-art computer code for solving the symmetric
+traveling salesman problem (TSP) developed by David Applegate, Robert
+Bixby, Vasek Chvatal, and William Cook. For details about Concorde see
+its web page at http://www.tsp.gatech.edu/concorde.html.
+
+To build Concorde along with GLPK you need to do the following:
+
+1. Configure, build, and install GLPK.
+
+2. Download the Concorde tarball co031219.tgz (version Dec 19, 2003),
+ unpack and unarchive it.
+
+3. Copy files cplex.h and cplex.c to subdirectory concorde/LP/.
+
+4. Create file named lpglpk.c in subdirectory concorde/LP/. This file
+ must contain the following two lines:
+
+ #include "cplex.c"
+ #include "lpcplex8.c"
+
+5. Configure Concorde in usual way (./configure) and then build it with
+ the following command:
+
+ make CPPFLAGS=-I. LPSOLVER_INTERFACE=lpglpk.c LPSOLVER_LIB=-lglpk
+
+ The Concorde executable can be found in subdirectory concorde/TSP/.
+
+Please note that currently this GLPK interface module does not support
+some important features (namely, CPXgetijdiv, CPXmdleave, CPXpivotin,
+CPXpivotout, and CPXstrongbranch), so large (more than 1000 nodes) TSP
+instances cannot be solved in a reasonable time, and some instances may
+cause abnormal termination of Concorde (if CPXgetijdiv is called).
diff --git a/glpk-5.0/examples/cplex/concorde.txt b/glpk-5.0/examples/cplex/concorde.txt
new file mode 100644
index 0000000..c6f7aec
--- /dev/null
+++ b/glpk-5.0/examples/cplex/concorde.txt
@@ -0,0 +1,121 @@
+Solver: Concorde-03.12.19 (options used: -s 99)
+ http://www.tsp.gatech.edu/concorde.html
+LP Solver: GLPK 4.34 (CPLEX-like interface module examples/cplex)
+Computer: Intel Pentium 4 CPU 3GHz, 2GB of RAM
+Platform: Cygwin 1.5.24 (Windows XP 5.1 Build 2600 Service Pack 4)
+Compiler: GCC 3.4.4 (options used: -O2)
+Test set: http://www.iwr.uni-heidelberg.de/groups/comopt/software/
+ TSPLIB95/
+
+Problem Solution B&B Time, s
+--------- -------- --- -------
+a280 2579 1 3.09
+ali535 202339 1 21.88
+att48 10628 1 0.20
+att532 27686 7 74.31
+bayg29 1610 1 0.08
+bays29 2020 1 0.08
+berlin52 7542 1 0.11
+bier127 118282 1 0.62
+brazil58 25395 1 0.23
+brd14051
+brg180 1950 1 0.34
+burma14 3323 1 0.06
+ch130 6110 1 0.92
+ch150 6528 1 1.69
+d1291
+d15112
+d1655
+d18512
+d198 15780 3 4.92
+d2103
+d493 35002 5 123.89
+d657 48913 11 148.17
+dantzig42 699 1 0.08
+dsj1000 18660188 13 251.00
+eil101 (failed due to CPXgetijdiv)
+eil51 426 1 0.17
+eil76 538 1 0.11
+fl1400
+fl1577
+fl3795
+fl417 11861 1 47.20
+fnl4461
+fri26 937 1 0.05
+gil262 2378 3 10.39
+gr120 6942 1 0.66
+gr137 69853 1 2.09
+gr17 2085 1 0.03
+gr202 40160 1 3.97
+gr21 2707 1 0.03
+gr229 134602 7 19.45
+gr24 1272 1 0.03
+gr431 171414 9 40.67
+gr48 5046 1 0.22
+gr666 294358 3 40.23
+gr96 55209 1 1.22
+hk48 11461 1 0.08
+kroA100 21282 1 0.41
+kroA150 26524 1 2.09
+kroA200 29368 1 2.44
+kroB100 22141 1 1.20
+kroB150 26130 1 1.66
+kroB200 29437 1 1.41
+kroC100 20749 1 0.42
+kroD100 21294 1 0.50
+kroE100 22068 1 0.94
+lin105 14379 1 0.23
+lin318 42029 1 4.28
+nrw1379
+p654 34643 1 17.08
+pa561 2763 15 370.70
+pcb1173 56892 11 370.30
+pcb3038
+pcb442 59778 13 35.86
+pla33810
+pla7397
+pla85900
+pr1002 259045 1 23.08
+pr107 44303 1 0.38
+pr124 59030 1 1.23
+pr136 96772 1 2.19
+pr144 58537 1 0.89
+pr152 73682 1 2.73
+pr226 80369 1 2.72
+pr2392
+pr264 49135 1 1.61
+pr299 48191 3 14.52
+pr439 107217 15 117.75
+pr76 108159 1 0.95
+rat195 2323 5 12.91
+rat575 6773 19 202.52
+rat783 8806 1 37.92
+rat99 1211 1 0.50
+rd100 7910 1 0.28
+rd400 15281 11 74.41
+rl11849
+rl1304
+rl1323
+rl1889
+rl5915
+rl5934
+si1032 92650 1 82.09
+si175 21407 3 8.97
+si535 48450 1 71.28
+st70 675 1 0.20
+swiss42 1273 1 0.06
+ts225 126643 1 21.25
+tsp225 3916 1 10.14
+u1060 224094 13 507.44
+u1432
+u159 42080 1 0.41
+u1817
+u2152
+u2319
+u574 36905 1 32.84
+u724 41910 19 238.42
+ulysses16 6859 1 0.19
+ulysses22 7013 1 0.47
+usa13509
+vm1084 239297 9 543.38
+vm1748
diff --git a/glpk-5.0/examples/cplex/cplex.c b/glpk-5.0/examples/cplex/cplex.c
new file mode 100644
index 0000000..ffc2c99
--- /dev/null
+++ b/glpk-5.0/examples/cplex/cplex.c
@@ -0,0 +1,2127 @@
+/* cplex.c (CPLEX-like interface to GLPK API) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+* Copyright (C) 2001-2013 Free Software Foundation, Inc.
+* Written by Andrew Makhorin <mao@gnu.org>.
+*
+* GLPK is free software: you can redistribute it and/or modify it
+* under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* GLPK is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+* License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with GLPK. If not, see <http://www.gnu.org/licenses/>.
+***********************************************************************/
+
+#include <ctype.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <glpk.h>
+#include "cplex.h"
+
+struct CPXENV
+{ /* environment block */
+ CPXLP *list;
+ /* linked list of problem objects */
+ int *intparam; /* int intparam[]; */
+ /* integer control parameters */
+ double *dblparam; /* double dblparam[]; */
+ /* floating-point control parameters */
+};
+
+struct CPXLP
+{ /* problem object */
+ CPXENV *env;
+ /* pointer to environment block */
+ glp_prob *prob;
+ /* pointer to underlying GLPK problem object */
+ int rflen;
+ /* length of the array rflag */
+ char *rflag; /* char rflag[rflen]; */
+ /* rflag[i], i = 0,...,nrows-1, is a flag of i-th row: */
+#define RF_NOT_RANGED 0 /* not ranged */
+#define RF_RANGED_POS 1 /* ranged, RHS = lower bound */
+#define RF_RANGED_NEG 2 /* ranged, RHS = upper bound */
+ int stat;
+ /* solution status reported by CPXgetstat; zero means no solution
+ exists */
+ int meth;
+ /* method indicator reported by CPXgetmethod */
+ int iwlen;
+ /* length of the working array */
+ int *iwork; /* int iwork[iwlen] */
+ /* working array initialized by binary zeros */
+ CPXLP *link;
+ /* pointer to another problem object */
+};
+
+struct intparam
+{ int which;
+ int defv;
+ int minv;
+ int maxv;
+};
+
+struct dblparam
+{ int which;
+ double defv;
+ double minv;
+ double maxv;
+};
+
+struct errstring
+{ int code;
+ const char *string;
+};
+
+#define BIGINT 2100000000
+#define BIGDBL 1e75
+
+static const struct intparam intparam[] =
+{ {CPX_PARAM_ADVIND, 0, 0, 2},
+ {CPX_PARAM_AGGIND, -1, -1, BIGINT},
+ {CPX_PARAM_DATACHECK, CPX_OFF, CPX_OFF, CPX_ON},
+ {CPX_PARAM_DPRIIND, CPX_DPRIIND_AUTO, CPX_DPRIIND_AUTO,
+ CPX_DPRIIND_DEVEX},
+ {CPX_PARAM_FASTMIP, CPX_OFF, CPX_OFF, CPX_ON}, /* ??? */
+ {CPX_PARAM_ITLIM, BIGINT, 0, BIGINT},
+ {CPX_PARAM_PERIND, CPX_OFF, CPX_OFF, CPX_ON},
+ {CPX_PARAM_PPRIIND, CPX_PPRIIND_AUTO, CPX_PPRIIND_PARTIAL,
+ CPX_PPRIIND_FULL},
+ {CPX_PARAM_PREIND, CPX_ON, CPX_OFF, CPX_ON},
+ {CPX_PARAM_REINV, 0, 0, 10000},
+ {CPX_PARAM_SCRIND, CPX_OFF, CPX_OFF, CPX_ON},
+ {CPX_PARAM_SIMDISPLAY, 1, 0, 2},
+};
+
+static const struct dblparam dblparam[] =
+{ {CPX_PARAM_EPOPT, 1e-6, 1e-9, 1e-1},
+ {CPX_PARAM_EPPER, 1e-6, 1e-8, BIGDBL},
+ {CPX_PARAM_EPRHS, 1e-6, 1e-9, 1e-1},
+ {CPX_PARAM_OBJLLIM, -BIGDBL, -BIGDBL, +BIGDBL},
+ {CPX_PARAM_OBJULIM, +BIGDBL, -BIGDBL, +BIGDBL},
+};
+
+static const struct errstring errstring[] =
+{ {CPXERR_ARRAY_NOT_ASCENDING, "Array entry %d not ascending"},
+ {CPXERR_BAD_ARGUMENT, "Invalid argument"},
+ {CPXERR_BAD_CTYPE, "Invalid ctype entry %d"},
+ {CPXERR_BAD_FILETYPE, "Invalid filetype"},
+ {CPXERR_BAD_LUB, "Invalid bound change indicator entry %d"},
+ {CPXERR_BAD_PARAM_NUM, "Invalid parameter number"},
+ {CPXERR_BAD_SENSE, "Invalid sense entry %d"},
+ {CPXERR_BAD_STATUS, "Invalid status entry %d for basis specificat"
+ "ion"},
+ {CPXERR_COL_INDEX_RANGE, "Column index %d out of range"},
+ {CPXERR_COUNT_RANGE, "Count entry %d negative or larger than allo"
+ "wed"},
+ {CPXERR_DUP_ENTRY, "Duplicate entry"},
+ {CPXERR_FAIL_OPEN_WRITE, "Could not open file '%s' for writing"},
+ {CPXERR_INDEX_RANGE, "Index is outside range of valid values"},
+ {CPXERR_NEGATIVE_SURPLUS, "Insufficient array length"},
+ {CPXERR_NO_BASIC_SOLN, "No basic solution exists"},
+ {CPXERR_NO_ENVIRONMENT, "No environment exists"},
+ {CPXERR_NO_FILENAME, "File name not specified"},
+ {CPXERR_NO_MEMORY, "Out of memory"},
+ {CPXERR_NO_PROBLEM, "No problem exists"},
+ {CPXERR_NO_SOLN, "No solution exists"},
+ {CPXERR_NOT_FIXED, "Only fixed variables are pivoted out"},
+ {CPXERR_NULL_NAME, "Null pointer %d in name array"},
+ {CPXERR_NULL_POINTER, "Null pointer for required data"},
+ {CPXERR_PARAM_TOO_BIG, "Parameter value too big"},
+ {CPXERR_PARAM_TOO_SMALL, "Parameter value too small"},
+ {CPXERR_ROW_INDEX_RANGE, "Row index %d out of range"},
+};
+
+/**********************************************************************/
+
+#define xassert glp_assert
+#define xprintf glp_printf
+#define xmalloc glp_malloc
+#define xcalloc glp_calloc
+#define xfree glp_free
+
+/**********************************************************************/
+
+static int findintparam(int whichparam)
+{ int k, card;
+ card = sizeof(intparam) / sizeof(struct intparam);
+ for (k = 0; k < card; k++)
+ if (intparam[k].which == whichparam) return k;
+ return -1;
+}
+
+static int getintparam(CPXENV *env, int whichparam)
+{ int k;
+ xassert(env != NULL);
+ k = findintparam(whichparam);
+ xassert(k >= 0);
+ return env->intparam[k];
+}
+
+static int finddblparam(int whichparam)
+{ int k, card;
+ card = sizeof(dblparam) / sizeof(struct dblparam);
+ for (k = 0; k < card; k++)
+ if (dblparam[k].which == whichparam) return k;
+ return -1;
+}
+
+static double getdblparam(CPXENV *env, int whichparam)
+{ int k;
+ xassert(env != NULL);
+ k = finddblparam(whichparam);
+ xassert(k >= 0);
+ return env->dblparam[k];
+}
+
+static const char *finderrstring(int errcode)
+{ int k, card;
+ card = sizeof(errstring) / sizeof(struct errstring);
+ for (k = 0; k < card; k++)
+ { if (errstring[k].code == errcode)
+ return errstring[k].string;
+ }
+ return NULL;
+}
+
+static int error(CPXENV *env, int errcode, ...)
+{ va_list arg;
+ char buffer[510];
+ xassert(env != NULL);
+ if (getintparam(env, CPX_PARAM_SCRIND) == CPX_ON)
+ { xassert(CPXgeterrorstring(env, errcode, buffer) == buffer);
+ va_start(arg, errcode);
+ vprintf(buffer, arg);
+ va_end(arg);
+ }
+ return errcode;
+}
+
+static int checkenv(CPXENV *env)
+{ int errcode;
+ if (env == NULL)
+ errcode = CPXERR_NO_ENVIRONMENT;
+ else
+ errcode = 0;
+ return errcode;
+}
+
+static checklp(CPXENV *env, CPXLP *lp)
+{ int errcode;
+ errcode = checkenv(env);
+ if (errcode) goto done;
+ if (lp == NULL)
+ errcode = error(env, CPXERR_NO_PROBLEM);
+done: return errcode;
+}
+
+static void invalidate(CPXLP *lp)
+{ lp->stat = 0;
+ lp->meth = CPX_ALG_NONE;
+ return;
+}
+
+static void enlargerflag(CPXLP *lp)
+{ int m;
+ xassert(lp != NULL);
+ m = glp_get_num_rows(lp->prob);
+ if (lp->rflen < m)
+ { int rflen = lp->rflen;
+ char *rflag = lp->rflag;
+ while (lp->rflen < m)
+ { lp->rflen += lp->rflen;
+ xassert(lp->rflen > 0);
+ }
+ lp->rflag = xcalloc(lp->rflen, sizeof(char));
+ memcpy(lp->rflag, rflag, rflen);
+ xfree(rflag);
+ }
+ return;
+}
+
+static void enlargeiwork(CPXLP *lp, int len)
+{ xassert(len >= 0);
+ if (lp->iwlen < len)
+ { xfree(lp->iwork);
+ while (lp->iwlen < len)
+ { lp->iwlen += lp->iwlen;
+ xassert(lp->iwlen > 0);
+ }
+ lp->iwork = xcalloc(lp->iwlen, sizeof(int));
+ memset(lp->iwork, 0, lp->iwlen * sizeof(int));
+ }
+ return;
+}
+
+/**********************************************************************/
+
+int CPXaddcols(CPXENV *env, CPXLP *lp, int ccnt, int nzcnt,
+ const double obj[], const int cmatbeg[], const int cmatind[],
+ const double cmatval[], const double lb[], const double ub[],
+ char *colname[])
+{ int j, k, m, n, beg, end, type, errcode;
+ double lbnd, ubnd;
+ errcode = checklp(env, lp);
+ if (errcode) goto done;
+ if (ccnt < 0 || nzcnt < 0)
+ { errcode = error(env, CPXERR_BAD_ARGUMENT);
+ goto done;
+ }
+ if (ccnt > 0)
+ { if (cmatbeg == NULL || cmatind == NULL || cmatval == NULL)
+ { errcode = error(env, CPXERR_NULL_POINTER);
+ goto done;
+ }
+ }
+ m = glp_get_num_rows(lp->prob);
+ n = glp_get_num_cols(lp->prob);
+ enlargeiwork(lp, m);
+ for (j = 0; j < ccnt; j++)
+ { beg = cmatbeg[j];
+ if (j > 0 && !(cmatbeg[j-1] <= beg))
+ { errcode = error(env, CPXERR_ARRAY_NOT_ASCENDING, j);
+ goto done;
+ }
+ if (!(0 <= beg && beg <= nzcnt))
+ { errcode = error(env, CPXERR_INDEX_RANGE);
+ goto done;
+ }
+ end = (j < ccnt-1 ? cmatbeg[j+1] : nzcnt);
+ for (k = beg; k < end; k++)
+ { if (!(0 <= cmatind[k] && cmatind[k] < m))
+ { errcode = error(env, CPXERR_ROW_INDEX_RANGE, k);
+ goto done;
+ }
+ }
+ errcode = 0;
+ for (k = beg; k < end; k++)
+ { if (lp->iwork[cmatind[k]])
+ { errcode = error(env, CPXERR_DUP_ENTRY);
+ break;
+ }
+ lp->iwork[cmatind[k]] = 1;
+ }
+ for (k = beg; k < end; k++)
+ lp->iwork[cmatind[k]] = 0;
+ if (errcode) goto done;
+ if (colname != NULL)
+ { if (colname[j] == NULL)
+ { errcode = error(env, CPXERR_NULL_NAME, j);
+ goto done;
+ }
+ }
+ }
+ errcode = 0;
+ invalidate(lp);
+ if (ccnt > 0)
+ glp_add_cols(lp->prob, ccnt);
+ for (j = 0; j < ccnt; j++)
+ { if (colname != NULL)
+ glp_set_col_name(lp->prob, n+j+1, colname[j]);
+ lbnd = (lb == NULL ? 0.0 : lb[j]);
+ ubnd = (ub == NULL ? +CPX_INFBOUND : ub[j]);
+ if (lbnd <= -CPX_INFBOUND && ubnd >= +CPX_INFBOUND)
+ type = GLP_FR;
+ else if (ubnd >= +CPX_INFBOUND)
+ type = GLP_LO;
+ else if (lbnd <= -CPX_INFBOUND)
+ type = GLP_UP;
+ else if (lbnd != ubnd)
+ type = GLP_DB;
+ else
+ type = GLP_FX;
+ glp_set_col_bnds(lp->prob, n+j+1, type, lbnd, ubnd);
+ if (obj != NULL)
+ glp_set_obj_coef(lp->prob, n+j+1, obj[j]);
+ beg = cmatbeg[j];
+ end = (j < ccnt-1 ? cmatbeg[j+1] : nzcnt);
+ for (k = beg; k < end; k++)
+ lp->iwork[k-beg] = cmatind[k]+1;
+ glp_set_mat_col(lp->prob, n+j+1, end-beg, lp->iwork-1,
+ cmatval+beg-1);
+ for (k = beg; k < end; k++)
+ lp->iwork[k-beg] = 0;
+ }
+done: return errcode;
+}
+
+int CPXaddrows(CPXENV *env, CPXLP *lp, int ccnt, int rcnt, int nzcnt,
+ const double rhs[], const char sense[], const int rmatbeg[],
+ const int rmatind[], const double rmatval[], char *colname[],
+ char *rowname[])
+{ int i, j, k, m, n, beg, end, type, errcode;
+ double temp;
+ errcode = checklp(env, lp);
+ if (errcode) goto done;
+ if (ccnt < 0 || rcnt < 0 || nzcnt < 0)
+ { errcode = error(env, CPXERR_BAD_ARGUMENT);
+ goto done;
+ }
+ if (rcnt > 0)
+ { if (rmatbeg == NULL || rmatind == NULL || rmatval == NULL)
+ { errcode = error(env, CPXERR_NULL_POINTER);
+ goto done;
+ }
+ }
+ m = glp_get_num_rows(lp->prob);
+ n = glp_get_num_cols(lp->prob);
+ enlargeiwork(lp, n+ccnt);
+ for (i = 0; i < rcnt; i++)
+ { if (sense != NULL)
+ { if (!(sense[i] == 'L' || sense[i] == 'E' ||
+ sense[i] == 'G' || sense[i] == 'R'))
+ { errcode = error(env, CPXERR_BAD_SENSE, i);
+ goto done;
+ }
+ }
+ beg = rmatbeg[i];
+ if (i > 0 && !(rmatbeg[i-1] <= beg))
+ { errcode = error(env, CPXERR_ARRAY_NOT_ASCENDING, i);
+ goto done;
+ }
+ if (!(0 <= beg && beg <= nzcnt))
+ { errcode = error(env, CPXERR_INDEX_RANGE);
+ goto done;
+ }
+ end = (i < rcnt-1 ? rmatbeg[i+1] : nzcnt);
+ for (k = beg; k < end; k++)
+ { if (!(0 <= rmatind[k] && rmatind[k] < n+ccnt))
+ { errcode = error(env, CPXERR_COL_INDEX_RANGE, k);
+ goto done;
+ }
+ }
+ errcode = 0;
+ for (k = beg; k < end; k++)
+ { if (lp->iwork[rmatind[k]])
+ { errcode = error(env, CPXERR_DUP_ENTRY);
+ break;
+ }
+ lp->iwork[rmatind[k]] = 1;
+ }
+ for (k = beg; k < end; k++)
+ lp->iwork[rmatind[k]] = 0;
+ if (errcode) goto done;
+ if (rowname != NULL)
+ { if (rowname[i] == NULL)
+ { errcode = error(env, CPXERR_NULL_NAME, i);
+ goto done;
+ }
+ }
+ }
+ for (j = 0; j < ccnt; j++)
+ { if (colname != NULL)
+ { if (colname[j] == NULL)
+ { errcode = error(env, CPXERR_NULL_NAME, j);
+ goto done;
+ }
+ }
+ }
+ errcode = 0;
+ invalidate(lp);
+ if (rcnt > 0)
+ glp_add_rows(lp->prob, rcnt);
+ if (ccnt > 0)
+ glp_add_cols(lp->prob, ccnt);
+ enlargerflag(lp);
+ for (i = 0; i < rcnt; i++)
+ { if (rowname != NULL)
+ glp_set_row_name(lp->prob, m+i+1, rowname[i]);
+ temp = (rhs == NULL ? 0.0 : rhs[i]);
+ if (sense == NULL || sense[i] == 'E')
+ { lp->rflag[m+i] = RF_NOT_RANGED;
+ type = GLP_FX;
+ }
+ else if (sense[i] == 'L')
+ { lp->rflag[m+i] = RF_NOT_RANGED;
+ type = GLP_UP;
+ }
+ else if (sense[i] == 'G')
+ { lp->rflag[m+i] = RF_NOT_RANGED;
+ type = GLP_LO;
+ }
+ else if (sense[i] == 'R')
+ { lp->rflag[m+i] = RF_RANGED_POS;
+ type = GLP_FX;
+ }
+ else
+ xassert(sense != sense);
+ glp_set_row_bnds(lp->prob, m+i+1, type, temp, temp);
+ beg = rmatbeg[i];
+ end = (i < rcnt-1 ? rmatbeg[i+1] : nzcnt);
+ for (k = beg; k < end; k++)
+ lp->iwork[k-beg] = rmatind[k]+1;
+ glp_set_mat_row(lp->prob, m+i+1, end-beg, lp->iwork-1,
+ rmatval+beg-1);
+ for (k = beg; k < end; k++)
+ lp->iwork[k-beg] = 0;
+ }
+ for (j = 0; j < ccnt; j++)
+ { if (colname != NULL)
+ glp_set_col_name(lp->prob, n+j+1, colname[j]);
+ glp_set_col_bnds(lp->prob, n+j+1, GLP_LO, 0.0, 0.0);
+ }
+done: return errcode;
+}
+
+int CPXbaropt(CPXENV *env, CPXLP *lp)
+{ xassert(env == env);
+ xassert(lp == lp);
+ xprintf("CPXbaropt: not implemented yet\n");
+ exit(EXIT_FAILURE);
+ return -1;
+}
+
+int CPXbinvrow(CPXENV *env, CPXLP *lp, int i, double y[])
+{ xassert(env == env);
+ xassert(lp == lp);
+ xassert(i == i);
+ xassert(y == y);
+ xprintf("CPXbinvrow: not implemented yet\n");
+ exit(EXIT_FAILURE);
+ return -1;
+}
+
+int CPXchgbds(CPXENV *env, CPXLP *lp, int cnt, const int indices[],
+ const char lu[], const double bd[])
+{ int j, n, type, errcode;
+ double lbnd, ubnd;
+ errcode = checklp(env, lp);
+ if (errcode) goto done;
+ if (cnt < 0)
+ { errcode = error(env, CPXERR_BAD_ARGUMENT);
+ goto done;
+ }
+ if (cnt > 0)
+ { if (indices == NULL || lu == NULL || bd == NULL)
+ { errcode = error(env, CPXERR_NULL_POINTER);
+ goto done;
+ }
+ }
+ n = glp_get_num_cols(lp->prob);
+ for (j = 0; j < cnt; j++)
+ { if (!(0 <= indices[j] && indices[j] < n))
+ { errcode = error(env, CPXERR_COL_INDEX_RANGE, j);
+ goto done;
+ }
+ if (!(lu[j] == 'L' || lu[j] == 'U' || lu[j] == 'B'))
+ { errcode = error(env, CPXERR_BAD_LUB, j);
+ goto done;
+ }
+ }
+ errcode = 0;
+ invalidate(lp);
+ for (j = 0; j < cnt; j++)
+ { type = glp_get_col_type(lp->prob, indices[j]+1);
+ lbnd = glp_get_col_lb(lp->prob, indices[j]+1);
+ ubnd = glp_get_col_ub(lp->prob, indices[j]+1);
+ if (type == GLP_FR || type == GLP_UP)
+ lbnd = -CPX_INFBOUND;
+ if (type == GLP_FR || type == GLP_LO)
+ ubnd = +CPX_INFBOUND;
+ if (lu[j] == 'L')
+ lbnd = bd[j];
+ else if (lu[j] == 'U')
+ ubnd = bd[j];
+ else if (lu[j] == 'B')
+ lbnd = ubnd = bd[j];
+ else
+ xassert(lu != lu);
+ if (lbnd <= -CPX_INFBOUND && ubnd >= +CPX_INFBOUND)
+ type = GLP_FR;
+ else if (ubnd >= +CPX_INFBOUND)
+ type = GLP_LO;
+ else if (lbnd <= -CPX_INFBOUND)
+ type = GLP_UP;
+ else if (lbnd != ubnd)
+ type = GLP_DB;
+ else
+ type = GLP_FX;
+ glp_set_col_bnds(lp->prob, indices[j]+1, type, lbnd, ubnd);
+ }
+done: return errcode;
+}
+
+int CPXchgcoeflist(CPXENV *env, CPXLP *lp, int numcoefs,
+ const int rowlist[], const int collist[], const double vallist[])
+{ int i, j, k, m, n, rcnt, ccnt, len, ptr, errcode;
+ int *head, *next, *ind;
+ double *val;
+ errcode = checklp(env, lp);
+ if (errcode) goto done;
+ if (numcoefs < 0)
+ { errcode = error(env, CPXERR_BAD_ARGUMENT);
+ goto done;
+ }
+ if (numcoefs == 0)
+ { errcode = 0;
+ goto done;
+ }
+ if (rowlist == NULL || collist == NULL || vallist == NULL)
+ { errcode = error(env, CPXERR_NULL_POINTER);
+ goto done;
+ }
+ /* check triplets and determine the number of rows and columns
+ to be changed */
+ m = glp_get_num_rows(lp->prob);
+ n = glp_get_num_cols(lp->prob);
+ enlargeiwork(lp, m);
+ enlargeiwork(lp, n);
+ rcnt = ccnt = 0;
+ for (k = 0; k < numcoefs; k++)
+ { i = rowlist[k];
+ if (!(0 <= i && i < m))
+ { errcode = error(env, CPXERR_ROW_INDEX_RANGE, i);
+ goto done;
+ }
+ if (!(lp->iwork[i] & 0x01))
+ rcnt++, lp->iwork[i] |= 0x01;
+ j = collist[k];
+ if (!(0 <= j && j < n))
+ { errcode = error(env, CPXERR_COL_INDEX_RANGE, j);
+ goto done;
+ }
+ if (!(lp->iwork[j] & 0x02))
+ ccnt++, lp->iwork[j] |= 0x02;
+ }
+ memset(lp->iwork, 0, m * sizeof(int));
+ memset(lp->iwork, 0, n * sizeof(int));
+ errcode = 0;
+ invalidate(lp);
+ if (rcnt <= ccnt)
+ { /* change the matrix by rows */
+ /* build the linked list of triplets:
+ head[i] is a pointer to first triplet for row i
+ next[k] is a pointer to next triplet for the same row */
+ head = xcalloc(m, sizeof(int));
+ for (i = 0; i < m; i++)
+ head[i] = -1;
+ next = xcalloc(numcoefs, sizeof(int));
+ for (k = 0; k < numcoefs; k++)
+ { i = rowlist[k];
+ next[k] = head[i];
+ head[i] = k;
+ }
+ /* check duplicate columns */
+ for (i = 0; i < m; i++)
+ { for (k = head[i]; k >= 0; k = next[k])
+ { j = collist[k];
+ if (lp->iwork[j])
+ { xfree(head);
+ xfree(next);
+ errcode = error(env, CPXERR_DUP_ENTRY);
+ goto done;
+ }
+ lp->iwork[j] = 1;
+ }
+ for (k = head[i]; k >= 0; k = next[k])
+ lp->iwork[collist[k]] = 0;
+ }
+ /* perform operation */
+ ind = xcalloc(1+n, sizeof(int));
+ val = xcalloc(1+n, sizeof(double));
+ for (i = 0; i < m; i++)
+ { if (head[i] < 0) continue;
+ len = glp_get_mat_row(lp->prob, i+1, ind, val);
+ for (ptr = 1; ptr <= len; ptr++)
+ { j = ind[ptr]-1;
+ xassert(lp->iwork[j] == 0);
+ lp->iwork[j] = ptr;
+ }
+ for (k = head[i]; k >= 0; k = next[k])
+ { j = collist[k];
+ if (lp->iwork[j] == 0)
+ lp->iwork[j] = ++len;
+ ptr = lp->iwork[j];
+ ind[ptr] = j+1, val[ptr] = vallist[k];
+ }
+ glp_set_mat_row(lp->prob, i+1, len, ind, val);
+ for (ptr = 1; ptr <= len; ptr++)
+ lp->iwork[ind[ptr]-1] = 0;
+ }
+ }
+ else
+ { /* change the matrix by columns */
+ /* build the linked lists of triplets:
+ head[j] is a pointer to first triplet for column j
+ next[k] is a pointer to next triplet for the same column */
+ head = xcalloc(n, sizeof(int));
+ for (j = 0; j < n; j++)
+ head[j] = -1;
+ next = xcalloc(numcoefs, sizeof(int));
+ for (k = 0; k < numcoefs; k++)
+ { j = collist[k];
+ next[k] = head[j];
+ head[j] = k;
+ }
+ /* check duplicate rows */
+ for (j = 0; j < n; j++)
+ { for (k = head[j]; k >= 0; k = next[k])
+ { i = rowlist[k];
+ if (lp->iwork[i])
+ { xfree(head);
+ xfree(next);
+ errcode = error(env, CPXERR_DUP_ENTRY);
+ goto done;
+ }
+ lp->iwork[i] = 1;
+ }
+ for (k = head[j]; k >= 0; k = next[k])
+ lp->iwork[rowlist[k]] = 0;
+ }
+ /* perform operation */
+ ind = xcalloc(1+m, sizeof(int));
+ val = xcalloc(1+m, sizeof(double));
+ for (j = 0; j < n; j++)
+ { if (head[j] < 0) continue;
+ len = glp_get_mat_col(lp->prob, j+1, ind, val);
+ for (ptr = 1; ptr <= len; ptr++)
+ { i = ind[ptr]-1;
+ xassert(lp->iwork[i] == 0);
+ lp->iwork[i] = ptr;
+ }
+ for (k = head[j]; k >= 0; k = next[k])
+ { i = rowlist[k];
+ if (lp->iwork[i] == 0)
+ lp->iwork[i] = ++len;
+ ptr = lp->iwork[i];
+ ind[ptr] = i+1, val[ptr] = vallist[k];
+ }
+ glp_set_mat_col(lp->prob, j+1, len, ind, val);
+ for (ptr = 1; ptr <= len; ptr++)
+ lp->iwork[ind[ptr]-1] = 0;
+ }
+ }
+ xfree(head);
+ xfree(next);
+ xfree(ind);
+ xfree(val);
+done: return errcode;
+}
+
+void CPXchgobjsen(CPXENV *env, CPXLP *lp, int maxormin)
+{ int errcode;
+ errcode = checklp(env, lp);
+ if (errcode) goto done;
+ if (!(maxormin == CPX_MIN || maxormin == CPX_MAX))
+ { errcode = error(env, CPXERR_BAD_ARGUMENT);
+ goto done;
+ }
+ errcode = 0;
+ invalidate(lp);
+ if (maxormin == CPX_MIN)
+ glp_set_obj_dir(lp->prob, GLP_MIN);
+ else
+ glp_set_obj_dir(lp->prob, GLP_MAX);
+done: xassert(errcode == errcode);
+ return;
+}
+
+int CPXchgsense(CPXENV *env, CPXLP *lp, int cnt, const int indices[],
+ const char sense[])
+{ int i, m, type, errcode;
+ double rhs;
+ errcode = checklp(env, lp);
+ if (errcode) goto done;
+ if (cnt < 0)
+ { errcode = error(env, CPXERR_BAD_ARGUMENT);
+ goto done;
+ }
+ if (cnt > 0 && (indices == NULL || sense == NULL))
+ { errcode = error(env, CPXERR_NULL_POINTER);
+ goto done;
+ }
+ m = glp_get_num_rows(lp->prob);
+ for (i = 0; i < cnt; i++)
+ { if (!(0 <= indices[i] && indices[i] < m))
+ { errcode = error(env, CPXERR_ROW_INDEX_RANGE, i);
+ goto done;
+ }
+ if (!(sense[i] == 'L' || sense[i] == 'E' || sense[i] == 'G' ||
+ sense[i] == 'R'))
+ { errcode = error(env, CPXERR_BAD_SENSE, i);
+ goto done;
+ }
+ }
+ errcode = 0;
+ invalidate(lp);
+ for (i = 0; i < cnt; i++)
+ { type = glp_get_row_type(lp->prob, indices[i]+1);
+ if (lp->rflag[indices[i]] == RF_NOT_RANGED)
+ { if (type == GLP_LO || type == GLP_FX)
+ rhs = glp_get_row_lb(lp->prob, indices[i]+1);
+ else if (type == GLP_UP)
+ rhs = glp_get_row_ub(lp->prob, indices[i]+1);
+ else
+ xassert(type != type);
+ }
+ else if (lp->rflag[indices[i]] == RF_RANGED_POS)
+ { xassert(type == GLP_DB || type == GLP_FX);
+ rhs = glp_get_row_lb(lp->prob, indices[i]+1);
+ }
+ else if (lp->rflag[indices[i]] == RF_RANGED_NEG)
+ { xassert(type == GLP_DB);
+ rhs = glp_get_row_ub(lp->prob, indices[i]+1);
+ }
+ else
+ xassert(lp != lp);
+ if (sense[i] == 'L')
+ { lp->rflag[indices[i]] = RF_NOT_RANGED;
+ type = GLP_UP;
+ }
+ else if (sense[i] == 'E')
+ { lp->rflag[indices[i]] = RF_NOT_RANGED;
+ type = GLP_FX;
+ }
+ else if (sense[i] == 'G')
+ { lp->rflag[indices[i]] = RF_NOT_RANGED;
+ type = GLP_LO;
+ }
+ else if (sense[i] == 'R')
+ { lp->rflag[indices[i]] = RF_RANGED_POS;
+ type = GLP_FX;
+ }
+ else
+ xassert(sense != sense);
+ glp_set_row_bnds(lp->prob, indices[i]+1, type, rhs, rhs);
+ }
+done: return errcode;
+}
+
+int CPXcloseCPLEX(CPXENV **_env)
+{ CPXENV *env;
+ CPXLP *lp;
+ int errcode;
+ if (_env == NULL)
+ { errcode = CPXERR_NULL_POINTER;
+ goto done;
+ }
+ env = *_env;
+ errcode = checkenv(env);
+ if (errcode) goto done;
+ while (env->list != NULL)
+ { lp = env->list;
+ errcode = CPXfreeprob(env, &lp);
+ xassert(!errcode);
+ }
+ xfree(env->intparam);
+ xfree(env->dblparam);
+ xfree(env);
+ *_env = NULL;
+ errcode = 0;
+done: return errcode;
+}
+
+int CPXcopybase(CPXENV *env, CPXLP *lp, const int cstat[],
+ const int rstat[])
+{ int i, j, m, n, stat, errcode;
+ errcode = checklp(env, lp);
+ if (errcode) goto done;
+ m = glp_get_num_rows(lp->prob);
+ n = glp_get_num_cols(lp->prob);
+ if (m > 0 && rstat == NULL || n > 0 && cstat == NULL)
+ { errcode = error(env, CPXERR_NULL_POINTER);
+ goto done;
+ }
+ for (i = 0; i < m; i++)
+ { if (!(rstat[i] == CPX_AT_LOWER || rstat[i] == CPX_BASIC ||
+ rstat[i] == CPX_AT_UPPER))
+ { errcode = error(env, CPXERR_BAD_STATUS, i);
+ goto done;
+ }
+ }
+ for (j = 0; j < n; j++)
+ { if (!(cstat[j] == CPX_AT_LOWER || cstat[j] == CPX_BASIC ||
+ cstat[j] == CPX_AT_UPPER || cstat[j] == CPX_FREE_SUPER))
+ { errcode = error(env, CPXERR_BAD_STATUS, j);
+ goto done;
+ }
+ }
+ errcode = 0;
+ invalidate(lp);
+ for (i = 0; i < m; i++)
+ { if (rstat[i] == CPX_AT_LOWER)
+ stat = GLP_NL;
+ else if (rstat[i] == CPX_BASIC)
+ stat = GLP_BS;
+ else if (rstat[i] == CPX_AT_UPPER)
+ stat = GLP_NU;
+ else
+ xassert(rstat != rstat);
+ glp_set_row_stat(lp->prob, i+1, stat);
+ }
+ for (j = 0; j < n; j++)
+ { if (cstat[j] == CPX_AT_LOWER)
+ stat = GLP_NL;
+ else if (cstat[j] == CPX_BASIC)
+ stat = GLP_BS;
+ else if (cstat[j] == CPX_AT_UPPER)
+ stat = GLP_NU;
+ else if (cstat[j] == CPX_FREE_SUPER)
+ stat = GLP_NF;
+ else
+ xassert(cstat != cstat);
+ glp_set_col_stat(lp->prob, j+1, stat);
+ }
+done: return errcode;
+}
+
+int CPXcopybasednorms(CPXENV *env, CPXLP *lp, const int cstat[],
+ const int rstat[], const double dnorm[])
+{ int errcode;
+ errcode = CPXcopybase(env, lp, cstat, rstat);
+ xassert(dnorm == dnorm);
+ return errcode;
+}
+
+int CPXcopylp(CPXENV *env, CPXLP *lp, int numcols, int numrows,
+ int objsen, const double obj[], const double rhs[],
+ const char sense[], const int matbeg[], const int matcnt[],
+ const int matind[], const double matval[], const double lb[],
+ const double ub[], const double rngval[])
+{ int errcode;
+ errcode = CPXcopylpwnames(env, lp, numcols, numrows, objsen, obj,
+ rhs, sense, matbeg, matcnt, matind, matval, lb, ub, rngval,
+ NULL, NULL);
+ return errcode;
+}
+
+int CPXcopylpwnames(CPXENV *env, CPXLP *lp, int numcols, int numrows,
+ int objsen, const double obj[], const double rhs[],
+ const char sense[], const int matbeg[], const int matcnt[],
+ const int matind[], const double matval[], const double lb[],
+ const double ub[], const double rngval[], char *colname[],
+ char *rowname[])
+{ int i, j, k, beg, end, type, errcode;
+ double lbnd, ubnd;
+ char name[255+1];
+ errcode = checklp(env, lp);
+ if (errcode) goto done;
+ if (numcols < 0 || numrows < 0)
+ { errcode = error(env, CPXERR_BAD_ARGUMENT);
+ goto done;
+ }
+ if (!(objsen == CPX_MIN || objsen == CPX_MAX))
+ { errcode = error(env, CPXERR_BAD_ARGUMENT);
+ goto done;
+ }
+ if (numcols > 0)
+ { if (matbeg == NULL || matcnt == NULL || matind == NULL ||
+ matval == NULL)
+ { errcode = error(env, CPXERR_NULL_POINTER);
+ goto done;
+ }
+ }
+ for (i = 0; i < numrows; i++)
+ { if (sense != NULL)
+ { if (!(sense[i] == 'L' || sense[i] == 'E' ||
+ sense[i] == 'G' || sense[i] == 'R'))
+ { errcode = error(env, CPXERR_BAD_SENSE, i);
+ goto done;
+ }
+ }
+ if (rowname != NULL)
+ { if (rowname[i] == NULL)
+ { errcode = error(env, CPXERR_NULL_NAME, i);
+ goto done;
+ }
+ }
+ }
+ enlargeiwork(lp, numrows);
+ for (j = 0; j < numcols; j++)
+ { beg = matbeg[j];
+ if (j > 0 && !(matbeg[j-1] <= beg))
+ { errcode = error(env, CPXERR_ARRAY_NOT_ASCENDING, j);
+ goto done;
+ }
+ if (beg < 0)
+ { errcode = error(env, CPXERR_INDEX_RANGE);
+ goto done;
+ }
+ end = beg + matcnt[j];
+ if (!(beg <= end) || j < numcols-1 && !(end <= matbeg[j+1]))
+ { errcode = error(env, CPXERR_COUNT_RANGE, j);
+ goto done;
+ }
+ for (k = beg; k < end; k++)
+ { if (!(0 <= matind[k] && matind[k] < numrows))
+ { errcode = error(env, CPXERR_ROW_INDEX_RANGE, k);
+ goto done;
+ }
+ }
+ errcode = 0;
+ for (k = beg; k < end; k++)
+ { if (lp->iwork[matind[k]])
+ { errcode = error(env, CPXERR_DUP_ENTRY);
+ break;
+ }
+ lp->iwork[matind[k]] = 1;
+ }
+ for (k = beg; k < end; k++)
+ lp->iwork[matind[k]] = 0;
+ if (errcode) goto done;
+ if (colname != NULL)
+ { if (colname[j] != NULL)
+ { errcode = error(env, CPXERR_NULL_NAME, j);
+ goto done;
+ }
+ }
+ }
+ errcode = 0;
+ invalidate(lp);
+ if (glp_get_prob_name(lp->prob) == NULL)
+ name[0] = '\0';
+ else
+ strcpy(name, glp_get_prob_name(lp->prob));
+ glp_erase_prob(lp->prob);
+ glp_set_prob_name(lp->prob, name);
+ if (objsen == CPX_MIN)
+ glp_set_obj_dir(lp->prob, GLP_MIN);
+ else if (objsen == CPX_MAX)
+ glp_set_obj_dir(lp->prob, GLP_MAX);
+ else
+ xassert(objsen != objsen);
+ if (numrows > 0)
+ glp_add_rows(lp->prob, numrows);
+ enlargerflag(lp);
+ for (i = 0; i < numrows; i++)
+ { if (rowname != NULL)
+ glp_set_row_name(lp->prob, i+1, rowname[i]);
+ lbnd = ubnd = (rhs == NULL ? 0.0 : rhs[i]);
+ if (sense == NULL || sense[i] == 'E')
+ { lp->rflag[i] = RF_NOT_RANGED;
+ type = GLP_FX;
+ }
+ else if (sense[i] == 'L')
+ { lp->rflag[i] = RF_NOT_RANGED;
+ type = GLP_UP;
+ }
+ else if (sense[i] == 'G')
+ { lp->rflag[i] = RF_NOT_RANGED;
+ type = GLP_LO;
+ }
+ else if (sense[i] == 'R')
+ { if (rngval == NULL || rngval[i] == 0.0)
+ { lp->rflag[i] = RF_RANGED_POS;
+ type = GLP_FX;
+ }
+ else if (rngval[i] > 0.0)
+ { lp->rflag[i] = RF_RANGED_POS;
+ type = GLP_DB;
+ ubnd += rngval[i];
+ }
+ else /* rngval[i] < 0.0 */
+ { lp->rflag[i] = RF_RANGED_NEG;
+ type = GLP_DB;
+ lbnd += rngval[i];
+ }
+ }
+ else
+ xassert(sense != sense);
+ glp_set_row_bnds(lp->prob, i+1, type, lbnd, ubnd);
+ }
+ if (numcols > 0)
+ glp_add_cols(lp->prob, numcols);
+ for (j = 0; j < numcols; j++)
+ { if (colname != NULL)
+ glp_set_col_name(lp->prob, j+1, colname[j]);
+ lbnd = (lb == NULL ? 0.0 : lb[j]);
+ ubnd = (ub == NULL ? +CPX_INFBOUND : ub[j]);
+ if (lbnd <= -CPX_INFBOUND && ubnd >= +CPX_INFBOUND)
+ type = GLP_FR;
+ else if (ubnd >= +CPX_INFBOUND)
+ type = GLP_LO;
+ else if (lbnd <= -CPX_INFBOUND)
+ type = GLP_UP;
+ else if (lbnd != ubnd)
+ type = GLP_DB;
+ else
+ type = GLP_FX;
+ glp_set_col_bnds(lp->prob, j+1, type, lbnd, ubnd);
+ if (obj != NULL)
+ glp_set_obj_coef(lp->prob, j+1, obj[j]);
+ beg = matbeg[j];
+ end = beg + matcnt[j];
+ for (k = beg; k < end; k++)
+ lp->iwork[k-beg] = matind[k]+1;
+ glp_set_mat_col(lp->prob, j+1, end-beg, lp->iwork-1,
+ matval+beg-1);
+ for (k = beg; k < end; k++)
+ lp->iwork[k-beg] = 0;
+ }
+done: return errcode;
+}
+
+CPXLP *CPXcreateprob(CPXENV *env, int *status, const char *probname)
+{ CPXLP *lp = NULL;
+ int errcode;
+ errcode = checkenv(env);
+ if (errcode) goto done;
+ lp = xmalloc(sizeof(struct CPXLP));
+ lp->env = env;
+ lp->prob = glp_create_prob();
+ glp_set_prob_name(lp->prob, probname);
+ lp->rflen = 100;
+ lp->rflag = xcalloc(lp->rflen, sizeof(char));
+ lp->iwlen = 100;
+ lp->iwork = xcalloc(lp->iwlen, sizeof(int));
+ memset(lp->iwork, 0, lp->iwlen * sizeof(int));
+ lp->link = env->list;
+ env->list = lp;
+ invalidate(lp);
+done: if (status != NULL) *status = errcode;
+ return lp;
+}
+
+int CPXdelcols(CPXENV *env, CPXLP *lp, int begin, int end)
+{ int j, n, errcode;
+ errcode = checklp(env, lp);
+ if (errcode) goto done;
+ n = glp_get_num_cols(lp->prob);
+ if (!(0 <= begin && begin <= end && end < n))
+ { errcode = error(env, CPXERR_INDEX_RANGE);
+ goto done;
+ }
+ errcode = 0;
+ invalidate(lp);
+ enlargeiwork(lp, end-begin+1);
+ for (j = begin; j <= end; j++)
+ lp->iwork[j-begin] = j+1;
+ glp_del_cols(lp->prob, end-begin+1, lp->iwork-1);
+ for (j = begin; j <= end; j++)
+ lp->iwork[j-begin] = 0;
+done: return errcode;
+}
+
+int CPXdelrows(CPXENV *env, CPXLP *lp, int begin, int end)
+{ int i, m, errcode;
+ errcode = checklp(env, lp);
+ if (errcode) goto done;
+ m = glp_get_num_rows(lp->prob);
+ if (!(0 <= begin && begin <= end && end < m))
+ { errcode = error(env, CPXERR_INDEX_RANGE);
+ goto done;
+ }
+ errcode = 0;
+ invalidate(lp);
+ enlargeiwork(lp, end-begin+1);
+ for (i = begin; i <= end; i++)
+ lp->iwork[i-begin] = i+1;
+ glp_del_rows(lp->prob, end-begin+1, lp->iwork-1);
+ for (i = begin; i <= end; i++)
+ lp->iwork[i-begin] = 0;
+ for (i = end+1; i < m; i++)
+ lp->rflag[i-(end-begin+1)] = lp->rflag[i];
+done: return errcode;
+}
+
+int CPXdelsetcols(CPXENV *env, CPXLP *lp, int delstat[])
+{ xassert(env == env);
+ xassert(lp == lp);
+ xassert(delstat == delstat);
+ xprintf("CPXdelsetcols: not implemented yet\n");
+ exit(EXIT_FAILURE);
+ return -1;
+}
+
+int CPXdelsetrows(CPXENV *env, CPXLP *lp, int delstat[])
+{ int i, m, cnt, ind, errcode;
+ errcode = checklp(env, lp);
+ if (errcode) goto done;
+ m = glp_get_num_rows(lp->prob);
+ if (m > 0 && delstat == NULL)
+ { errcode = error(env, CPXERR_NULL_POINTER);
+ goto done;
+ }
+ errcode = 0;
+ invalidate(lp);
+ enlargeiwork(lp, m);
+ cnt = ind = 0;
+ for (i = 0; i < m; i++)
+ { if (delstat[i] == 1)
+ { delstat[i] = -1;
+ lp->iwork[cnt++] = i+1;
+ }
+ else
+ { delstat[i] = ind;
+ lp->rflag[ind++] = lp->rflag[i];
+ }
+ }
+ if (cnt > 0)
+ glp_del_rows(lp->prob, cnt, lp->iwork-1);
+ for (i = 0; i < cnt; i++)
+ lp->iwork[i] = 0;
+done: return errcode;
+}
+
+int CPXdualopt(CPXENV *env, CPXLP *lp);
+
+int CPXfreeprob(CPXENV *env, CPXLP **_lp)
+{ CPXLP *lp;
+ int errcode;
+ errcode = checkenv(env);
+ if (errcode) goto done;
+ if (_lp == NULL)
+ { errcode = error(env, CPXERR_NULL_POINTER);
+ goto done;
+ }
+ lp = *_lp;
+ errcode = checklp(env, lp);
+ if (errcode) goto done;
+ errcode = 0;
+ env = lp->env;
+ if (env->list == lp)
+ env->list = lp->link;
+ else
+ { CPXLP *pp;
+ for (pp = env->list; pp != NULL; pp = pp->link)
+ if (pp->link == lp) break;
+ xassert(pp != NULL);
+ pp->link = lp->link;
+ }
+ glp_delete_prob(lp->prob);
+ xfree(lp->rflag);
+ xfree(lp->iwork);
+ xfree(lp);
+ *_lp = NULL;
+done: return errcode;
+}
+
+int CPXgetbase(CPXENV *env, CPXLP *lp, int cstat[], int rstat[])
+{ int i, j, m, n, stat, errcode;
+ errcode = checklp(env, lp);
+ if (errcode) goto done;
+ if (!lp->stat)
+ { errcode = error(env, CPXERR_NO_SOLN);
+ goto done;
+ }
+ if (lp->meth == CPX_ALG_PRIMAL || lp->meth == CPX_ALG_DUAL)
+ ;
+ else
+ { errcode = error(env, CPXERR_NO_BASIC_SOLN);
+ goto done;
+ }
+ errcode = 0;
+ if (rstat != NULL)
+ { m = glp_get_num_rows(lp->prob);
+ for (i = 0; i < m; i++)
+ { stat = glp_get_row_stat(lp->prob, i+1);
+ if (stat == GLP_BS)
+ rstat[i] = CPX_BASIC;
+ else if (lp->rflag[i] == RF_NOT_RANGED || stat != GLP_NU)
+ rstat[i] = CPX_AT_LOWER;
+ else
+ rstat[i] = CPX_AT_UPPER;
+ }
+ }
+ if (cstat != NULL)
+ { n = glp_get_num_cols(lp->prob);
+ for (j = 0; j < n; j++)
+ { stat = glp_get_col_stat(lp->prob, j+1);
+ if (stat == GLP_BS)
+ cstat[j] = CPX_BASIC;
+ else if (stat == GLP_NU)
+ cstat[j] = CPX_AT_UPPER;
+ else if (stat == GLP_NF)
+ cstat[j] = CPX_FREE_SUPER;
+ else
+ cstat[j] = CPX_AT_LOWER;
+ }
+ }
+done: return errcode;
+}
+
+int CPXgetbasednorms(CPXENV *env, CPXLP *lp, int cstat[], int rstat[],
+ double dnorm[])
+{ int i, m, errcode;
+ errcode = CPXgetbase(env, lp, cstat, rstat);
+ if (errcode) goto done;
+ if (dnorm != NULL)
+ { m = glp_get_num_rows(lp->prob);
+ for (i = 0; i < m; i++) dnorm[i] = 1.0;
+ }
+done: return errcode;
+}
+
+int CPXgetbhead(CPXENV *env, CPXLP *lp, int head[], double x[])
+{ xassert(env == env);
+ xassert(lp == lp);
+ xassert(head == head);
+ xassert(x == x);
+ xprintf("CPXgetbhead: not implemented yet\n");
+ exit(EXIT_FAILURE);
+ return -1;
+}
+
+int CPXgetdblparam(CPXENV *env, int whichparam, double *value)
+{ int k, errcode;
+ errcode = checkenv(env);
+ if (errcode) goto done;
+ k = finddblparam(whichparam);
+ if (k < 0)
+ { errcode = error(env, CPXERR_BAD_PARAM_NUM);
+ goto done;
+ }
+ errcode = 0;
+ if (value != NULL)
+ *value = env->dblparam[k];
+done: return errcode;
+}
+
+int CPXgetdj(CPXENV *env, CPXLP *lp, double dj[], int begin, int end)
+{ int j, n, errcode;
+ errcode = checklp(env, lp);
+ if (errcode) goto done;
+ n = glp_get_num_cols(lp->prob);
+ if (!(0 <= begin && begin <= end && end < n))
+ { errcode = error(env, CPXERR_INDEX_RANGE);
+ goto done;
+ }
+ if (!lp->stat)
+ { errcode = error(env, CPXERR_NO_SOLN);
+ goto done;
+ }
+ errcode = 0;
+ if (lp->meth == CPX_ALG_PRIMAL || lp->meth == CPX_ALG_DUAL)
+ { if (dj != NULL)
+ { for (j = begin; j <= end; j++)
+ dj[j-begin] = glp_get_col_dual(lp->prob, j+1);
+ }
+ }
+ else
+ xassert(lp != lp);
+done: return errcode;
+}
+
+char *CPXgeterrorstring(CPXENV *env, int errcode, char *buffer)
+{ const char *string;
+ xassert(env == env);
+ string = finderrstring(errcode);
+ if (string == NULL)
+ buffer = NULL;
+ else
+ sprintf(buffer, "CPLEX Error %5d: %s.\n", errcode, string);
+ return buffer;
+}
+
+int CPXgetijdiv(CPXENV *env, CPXLP *lp, int *idiv, int *jdiv)
+{ xassert(env == env);
+ xassert(lp == lp);
+ xassert(idiv == idiv);
+ xassert(jdiv == jdiv);
+ xprintf("CPXgetijdiv: not implemented yet\n");
+ exit(EXIT_FAILURE);
+ return -1;
+}
+
+int CPXgetintparam(CPXENV *env, int whichparam, int *value)
+{ int k, errcode;
+ errcode = checkenv(env);
+ if (errcode) goto done;
+ k = findintparam(whichparam);
+ if (k < 0)
+ { errcode = error(env, CPXERR_BAD_PARAM_NUM);
+ goto done;
+ }
+ errcode = 0;
+ if (value != NULL)
+ *value = env->intparam[k];
+done: return errcode;
+}
+
+int CPXgetlb(CPXENV *env, CPXLP *lp, double lb[], int begin, int end)
+{ xassert(env == env);
+ xassert(lp == lp);
+ xassert(lb == lb);
+ xassert(begin == begin);
+ xassert(end == end);
+ xprintf("CPXgetlb: not implemented yet\n");
+ exit(EXIT_FAILURE);
+ return -1;
+}
+
+int CPXgetmethod(CPXENV *env, CPXLP *lp)
+{ int method;
+ if (checklp(env, lp))
+ method = CPX_ALG_NONE;
+ else
+ method = lp->meth;
+ return method;
+}
+
+int CPXgetnumcols(CPXENV *env, CPXLP *lp)
+{ int numcols;
+ if (checklp(env, lp))
+ numcols = 0;
+ else
+ numcols = glp_get_num_cols(lp->prob);
+ return numcols;
+}
+
+int CPXgetnumnz(CPXENV *env, CPXLP *lp)
+{ int numnz;
+ if (checklp(env, lp))
+ numnz = 0;
+ else
+ numnz = glp_get_num_nz(lp->prob);
+ return numnz;
+}
+
+int CPXgetnumrows(CPXENV *env, CPXLP *lp)
+{ int numrows;
+ if (checklp(env, lp))
+ numrows = 0;
+ else
+ numrows = glp_get_num_rows(lp->prob);
+ return numrows;
+}
+
+int CPXgetobjval(CPXENV *env, CPXLP *lp, double *objval)
+{ int errcode;
+ errcode = checklp(env, lp);
+ if (errcode) goto done;
+ if (!lp->stat)
+ { errcode = error(env, CPXERR_NO_SOLN);
+ goto done;
+ }
+ errcode = 0;
+ if (lp->meth == CPX_ALG_PRIMAL || lp->meth == CPX_ALG_DUAL)
+ { if (objval != NULL)
+ *objval = glp_get_obj_val(lp->prob);
+ }
+ else
+ xassert(lp != lp);
+done: return errcode;
+}
+
+int CPXgetpi(CPXENV *env, CPXLP *lp, double pi[], int begin, int end)
+{ int i, m, errcode;
+ errcode = checklp(env, lp);
+ if (errcode) goto done;
+ m = glp_get_num_rows(lp->prob);
+ if (!(0 <= begin && begin <= end && end < m))
+ { errcode = error(env, CPXERR_INDEX_RANGE);
+ goto done;
+ }
+ if (!lp->stat)
+ { errcode = error(env, CPXERR_NO_SOLN);
+ goto done;
+ }
+ errcode = 0;
+ if (lp->meth == CPX_ALG_PRIMAL || lp->meth == CPX_ALG_DUAL)
+ { if (pi != NULL)
+ { for (i = begin; i <= end; i++)
+ pi[i-begin] = glp_get_row_dual(lp->prob, i+1);
+ }
+ }
+ else
+ xassert(lp != lp);
+done: return errcode;
+}
+
+int CPXgetsense(CPXENV *env, CPXLP *lp, char sense[], int begin,
+ int end)
+{ xassert(env == env);
+ xassert(lp == lp);
+ xassert(sense == sense);
+ xassert(begin == begin);
+ xassert(end == end);
+ xprintf("CPXgetsense: not implemented yet\n");
+ exit(EXIT_FAILURE);
+ return -1;
+}
+
+int CPXgetslack(CPXENV *env, CPXLP *lp, double slack[], int begin,
+ int end)
+{ int i, m, type, errcode;
+ double temp;
+ errcode = checklp(env, lp);
+ if (errcode) goto done;
+ m = glp_get_num_rows(lp->prob);
+ if (!(0 <= begin && begin <= end && end < m))
+ { errcode = error(env, CPXERR_INDEX_RANGE);
+ goto done;
+ }
+ if (!lp->stat)
+ { errcode = error(env, CPXERR_NO_SOLN);
+ goto done;
+ }
+ errcode = 0;
+ if (lp->meth == CPX_ALG_PRIMAL || lp->meth == CPX_ALG_DUAL)
+ { if (slack != NULL)
+ { for (i = begin; i <= end; i++)
+ { type = glp_get_row_type(lp->prob, i+1);
+ temp = glp_get_row_prim(lp->prob, i+1);
+ if (lp->rflag[i] == RF_NOT_RANGED)
+ { if (type == GLP_LO || type == GLP_FX)
+ slack[i-begin] =
+ glp_get_row_lb(lp->prob, i+1) - temp;
+ else if (type == GLP_UP)
+ slack[i-begin] =
+ glp_get_row_ub(lp->prob, i+1) - temp;
+ else
+ xassert(type != type);
+ }
+ else if (lp->rflag[i] == RF_RANGED_POS)
+ { xassert(type == GLP_DB || type == GLP_FX);
+ slack[i-begin] =
+ temp - glp_get_row_lb(lp->prob, i+1);
+ }
+ else if (lp->rflag[i] == RF_RANGED_NEG)
+ { xassert(type == GLP_DB);
+ slack[i-begin] =
+ temp - glp_get_row_ub(lp->prob, i+1);
+ }
+ else
+ xassert(lp != lp);
+ }
+ }
+ }
+ else
+ xassert(lp != lp);
+done: return errcode;
+}
+
+int CPXgetstat(CPXENV *env, CPXLP *lp)
+{ int stat;
+ if (checklp(env, lp))
+ stat = 0;
+ else
+ stat = lp->stat;
+ return stat;
+}
+
+int CPXgetub(CPXENV *env, CPXLP *lp, double ub[], int begin, int end)
+{ xassert(env == env);
+ xassert(lp == lp);
+ xassert(ub == ub);
+ xassert(begin == begin);
+ xassert(end == end);
+ xprintf("CPXgetub: not implemented yet\n");
+ exit(EXIT_FAILURE);
+ return -1;
+}
+
+int CPXgetweight(CPXENV *env, CPXLP *lp, int rcnt, const int rmatbeg[],
+ const int rmatind[], const double rmatval[], double weight[],
+ int dpriind)
+{ xassert(env == env);
+ xassert(lp == lp);
+ xassert(rcnt == rcnt);
+ xassert(rmatbeg == rmatbeg);
+ xassert(rmatind == rmatind);
+ xassert(rmatval == rmatval);
+ xassert(weight == weight);
+ xassert(dpriind == dpriind);
+ xprintf("CPXgetweight: not implemented yet\n");
+ exit(EXIT_FAILURE);
+ return -1;
+}
+
+int CPXgetx(CPXENV *env, CPXLP *lp, double x[], int begin, int end)
+{ int j, n, errcode;
+ errcode = checklp(env, lp);
+ if (errcode) goto done;
+ n = glp_get_num_cols(lp->prob);
+ if (!(0 <= begin && begin <= end && end < n))
+ { errcode = error(env, CPXERR_INDEX_RANGE);
+ goto done;
+ }
+ if (!lp->stat)
+ { errcode = error(env, CPXERR_NO_SOLN);
+ goto done;
+ }
+ errcode = 0;
+ if (lp->meth == CPX_ALG_PRIMAL || lp->meth == CPX_ALG_DUAL)
+ { if (x != NULL)
+ { for (j = begin; j <= end; j++)
+ x[j-begin] = glp_get_col_prim(lp->prob, j+1);
+ }
+ }
+ else
+ xassert(lp != lp);
+done: return errcode;
+}
+
+int CPXinfodblparam(CPXENV *env, int whichparam, double *defvalue,
+ double *minvalue, double *maxvalue)
+{ int k, errcode;
+ errcode = checkenv(env);
+ if (errcode) goto done;
+ k = finddblparam(whichparam);
+ if (k < 0)
+ { errcode = error(env, CPXERR_BAD_PARAM_NUM);
+ goto done;
+ }
+ errcode = 0;
+ if (defvalue != NULL)
+ *defvalue = dblparam[k].defv;
+ if (minvalue != NULL)
+ *minvalue = dblparam[k].minv;
+ if (maxvalue != NULL)
+ *maxvalue = dblparam[k].maxv;
+done: return errcode;
+}
+
+int CPXinfointparam(CPXENV *env, int whichparam, int *defvalue,
+ int *minvalue, int *maxvalue)
+{ int k, errcode;
+ errcode = checkenv(env);
+ if (errcode) goto done;
+ k = findintparam(whichparam);
+ if (k < 0)
+ { errcode = error(env, CPXERR_BAD_PARAM_NUM);
+ goto done;
+ }
+ errcode = 0;
+ if (defvalue != NULL)
+ *defvalue = intparam[k].defv;
+ if (minvalue != NULL)
+ *minvalue = intparam[k].minv;
+ if (maxvalue != NULL)
+ *maxvalue = intparam[k].maxv;
+done: return errcode;
+}
+
+int CPXmdleave(const CPXENV *env, CPXLP *lp, const int goodlist[],
+ int goodlen, double downratio[], double upratio[])
+{ int k;
+ xassert(env == env);
+ xassert(lp == lp);
+ xassert(goodlist == goodlist);
+ xassert(goodlen >= 0);
+ xassert(downratio != NULL);
+ xassert(upratio != NULL);
+ /* not implemented yet */
+ for (k = 0; k < goodlen; k++)
+ downratio[k] = upratio[k] = 0.0;
+ return 0;
+}
+
+int CPXnewcols(CPXENV *env, CPXLP *lp, int ccnt, const double obj[],
+ const double lb[], const double ub[], const char ctype[],
+ char *colname[])
+{ int j, n, kind, type, errcode;
+ double lbnd, ubnd;
+ errcode = checklp(env, lp);
+ if (errcode) goto done;
+ if (ccnt < 0)
+ { errcode = error(env, CPXERR_BAD_ARGUMENT);
+ goto done;
+ }
+ for (j = 0; j < ccnt; j++)
+ { if (ctype != NULL)
+ { if (!(ctype[j] == 'C' || ctype[j] == 'B' ||
+ ctype[j] == 'I'))
+ { errcode = error(env, CPXERR_BAD_CTYPE, j);
+ goto done;
+ }
+ }
+ if (colname != NULL)
+ { if (colname[j] == NULL)
+ { errcode = error(env, CPXERR_NULL_NAME, j);
+ goto done;
+ }
+ }
+ }
+ errcode = 0;
+ invalidate(lp);
+ n = glp_get_num_cols(lp->prob);
+ if (ccnt > 0)
+ glp_add_cols(lp->prob, ccnt);
+ for (j = 0; j < ccnt; j++)
+ { if (colname != NULL)
+ glp_set_col_name(lp->prob, n+j+1, colname[j]);
+ if (obj != NULL)
+ glp_set_obj_coef(lp->prob, n+j+1, obj[j]);
+ lbnd = (lb == NULL ? 0.0 : lb[j]);
+ ubnd = (ub == NULL ? 0.0 : ub[j]);
+ if (lbnd <= -CPX_INFBOUND && ubnd >= +CPX_INFBOUND)
+ type = GLP_FR;
+ else if (ubnd >= +CPX_INFBOUND)
+ type = GLP_LO;
+ else if (lbnd <= -CPX_INFBOUND)
+ type = GLP_UP;
+ else if (lbnd != ubnd)
+ type = GLP_DB;
+ else
+ type = GLP_FX;
+ glp_set_col_bnds(lp->prob, n+j+1, type, lbnd, ubnd);
+ if (ctype != NULL)
+ { if (ctype[j] == 'C')
+ kind = GLP_CV;
+ else if (ctype[j] == 'B')
+ kind = GLP_BV;
+ else if (ctype[j] == 'I')
+ kind = GLP_IV;
+ else
+ xassert(ctype != ctype);
+ glp_set_col_kind(lp->prob, n+j+1, kind);
+ }
+ }
+done: return errcode;
+}
+
+int CPXnewrows(CPXENV *env, CPXLP *lp, int rcnt, const double rhs[],
+ const char sense[], const double rngval[], char *rowname[])
+{ int i, m, type, errcode;
+ double lbnd, ubnd;
+ errcode = checklp(env, lp);
+ if (errcode) goto done;
+ if (rcnt < 0)
+ { errcode = error(env, CPXERR_BAD_ARGUMENT);
+ goto done;
+ }
+ for (i = 0; i < rcnt; i++)
+ { if (sense != NULL)
+ { if (!(sense[i] == 'L' || sense[i] == 'E' ||
+ sense[i] == 'G' || sense[i] == 'R'))
+ { errcode = error(env, CPXERR_BAD_SENSE, i);
+ goto done;
+ }
+ }
+ if (rowname != NULL)
+ { if (rowname[i] == NULL)
+ { errcode = error(env, CPXERR_NULL_NAME, i);
+ goto done;
+ }
+ }
+ }
+ errcode = 0;
+ invalidate(lp);
+ m = glp_get_num_rows(lp->prob);
+ if (rcnt > 0)
+ glp_add_rows(lp->prob, rcnt);
+ enlargerflag(lp);
+ for (i = 0; i < rcnt; i++)
+ { if (rowname != NULL)
+ glp_set_row_name(lp->prob, m+i+1, rowname[i]);
+ lbnd = ubnd = (rhs == NULL ? 0.0 : rhs[i]);
+ if (sense == NULL || sense[i] == 'E')
+ { lp->rflag[m+i] = RF_NOT_RANGED;
+ type = GLP_FX;
+ }
+ else if (sense[i] == 'L')
+ { lp->rflag[m+i] = RF_NOT_RANGED;
+ type = GLP_UP;
+ }
+ else if (sense[i] == 'G')
+ { lp->rflag[m+i] = RF_NOT_RANGED;
+ type = GLP_LO;
+ }
+ else if (sense[i] == 'R')
+ { if (rngval == NULL || rngval[i] == 0.0)
+ { lp->rflag[m+i] = RF_RANGED_POS;
+ type = GLP_FX;
+ }
+ else if (rngval[i] > 0.0)
+ { lp->rflag[m+i] = RF_RANGED_POS;
+ type = GLP_DB;
+ ubnd += rngval[i];
+ }
+ else /* rngval[i] < 0.0 */
+ { lp->rflag[m+i] = RF_RANGED_NEG;
+ type = GLP_DB;
+ lbnd += rngval[i];
+ }
+ }
+ else
+ xassert(sense != sense);
+ glp_set_row_bnds(lp->prob, m+i+1, type, lbnd, ubnd);
+ }
+done: return errcode;
+}
+
+CPXENV *CPXopenCPLEX(int *status)
+{ CPXENV *env;
+ int k, card;
+ env = xmalloc(sizeof(CPXENV));
+ env->list = NULL;
+ card = sizeof(intparam) / sizeof(struct intparam);
+ env->intparam = xcalloc(card, sizeof(int));
+ for (k = 0; k < card; k++)
+ env->intparam[k] = intparam[k].defv;
+ card = sizeof(dblparam) / sizeof(struct dblparam);
+ env->dblparam = xcalloc(card, sizeof(double));
+ for (k = 0; k < card; k++)
+ env->dblparam[k] = dblparam[k].defv;
+ if (status != NULL) *status = 0;
+ return env;
+}
+
+int CPXpivotin(CPXENV *env, CPXLP *lp, const int rlist[], int rlen)
+{ int i, m, errcode;
+ errcode = checklp(env, lp);
+ if (errcode) goto done;
+ if (rlen < 0)
+ { errcode = error(env, CPXERR_BAD_ARGUMENT);
+ goto done;
+ }
+ if (rlen > 0 && rlist == NULL)
+ { errcode = error(env, CPXERR_NULL_POINTER);
+ goto done;
+ }
+ m = glp_get_num_rows(lp->prob);
+ for (i = 0; i < rlen; i++)
+ { if (!(0 <= rlist[i] && rlist[i] < m))
+ { errcode = error(env, CPXERR_ROW_INDEX_RANGE, i);
+ goto done;
+ }
+ }
+ errcode = 0;
+ for (i = 0; i < rlen; i++)
+ { if (glp_get_row_type(lp->prob, rlist[i]+1) != GLP_FX)
+ { if (glp_get_row_stat(lp->prob, rlist[i]+1) != GLP_BS)
+ { /* not implemented yet */
+ break;
+ }
+ }
+ }
+done: return errcode;
+}
+
+int CPXpivotout(CPXENV *env, CPXLP *lp, const int clist[], int clen)
+{ int j, n, errcode;
+ errcode = checklp(env, lp);
+ if (errcode) goto done;
+ if (clen < 0)
+ { errcode = error(env, CPXERR_BAD_ARGUMENT);
+ goto done;
+ }
+ if (clen > 0 && clist == NULL)
+ { errcode = error(env, CPXERR_NULL_POINTER);
+ goto done;
+ }
+ n = glp_get_num_cols(lp->prob);
+ for (j = 0; j < clen; j++)
+ { if (!(0 <= clist[j] && clist[j] < n))
+ { errcode = error(env, CPXERR_COL_INDEX_RANGE, j);
+ goto done;
+ }
+ if (glp_get_col_type(lp->prob, clist[j]+1) != GLP_FX)
+ { errcode = error(env, CPXERR_NOT_FIXED);
+ goto done;
+ }
+ }
+ errcode = 0;
+ for (j = 0; j < clen; j++)
+ { if (glp_get_col_stat(lp->prob, clist[j]+1) == GLP_BS)
+ { /* not implemented yet */
+ break;
+ }
+ }
+done: return errcode;
+}
+
+int CPXprimopt(CPXENV *env, CPXLP *lp);
+
+int CPXsavwrite(CPXENV *env, CPXLP *lp, const char *filename)
+{ xassert(env == env);
+ xassert(lp == lp);
+ xassert(filename == filename);
+ xprintf("CPXsavwrite: not implemented yet\n");
+ exit(EXIT_FAILURE);
+ return -1;
+}
+
+int CPXsetdblparam(CPXENV *env, int whichparam, double newvalue)
+{ int k, errcode;
+ errcode = checkenv(env);
+ if (errcode) goto done;
+ k = finddblparam(whichparam);
+ if (k < 0)
+ { errcode = error(env, CPXERR_BAD_PARAM_NUM);
+ goto done;
+ }
+ if (newvalue < dblparam[k].minv)
+ { errcode = error(env, CPXERR_PARAM_TOO_SMALL);
+ goto done;
+ }
+ if (newvalue > dblparam[k].maxv)
+ { errcode = error(env, CPXERR_PARAM_TOO_BIG);
+ goto done;
+ }
+ errcode = 0;
+ env->dblparam[k] = newvalue;
+done: return errcode;
+}
+
+int CPXsetintparam(CPXENV *env, int whichparam, int newvalue)
+{ int k, errcode;
+ errcode = checkenv(env);
+ if (errcode) goto done;
+ k = findintparam(whichparam);
+ if (k < 0)
+ { errcode = error(env, CPXERR_BAD_PARAM_NUM);
+ goto done;
+ }
+ if (newvalue < intparam[k].minv)
+ { errcode = error(env, CPXERR_PARAM_TOO_SMALL);
+ goto done;
+ }
+ if (newvalue > intparam[k].maxv)
+ { errcode = error(env, CPXERR_PARAM_TOO_BIG);
+ goto done;
+ }
+ errcode = 0;
+ env->intparam[k] = newvalue;
+done: return errcode;
+}
+
+int CPXsolninfo(CPXENV *env, CPXLP *lp, int *solnmethod, int *solntype,
+ int *pfeasind, int *dfeasind)
+{ int type, pfeas, dfeas, errcode;
+ errcode = checklp(env, lp);
+ if (errcode) goto done;
+ errcode = 0;
+ if (!lp->stat)
+ type = CPX_NO_SOLN, pfeas = dfeas = 0;
+ else if (lp->meth == CPX_ALG_PRIMAL || lp->meth == CPX_ALG_DUAL)
+ { type = CPX_BASIC_SOLN;
+ pfeas = (glp_get_prim_stat(lp->prob) == GLP_FEAS);
+ dfeas = (glp_get_dual_stat(lp->prob) == GLP_FEAS);
+ }
+ else
+ xassert(lp != lp);
+ if (solnmethod != NULL)
+ *solnmethod = lp->meth;
+ if (solntype != NULL)
+ *solntype = type;
+ if (pfeasind != NULL)
+ *pfeasind = pfeas;
+ if (dfeasind != NULL)
+ *dfeasind = dfeas;
+done: return errcode;
+}
+
+int CPXsolution(CPXENV *env, CPXLP *lp, int *lpstat, double *objval,
+ double x[], double pi[], double slack[], double dj[])
+{ int m, n, errcode;
+ errcode = checklp(env, lp);
+ if (errcode) goto done;
+ if (!lp->stat)
+ { errcode = error(env, CPXERR_NO_SOLN);
+ goto done;
+ }
+ errcode = 0;
+ m = glp_get_num_rows(lp->prob);
+ n = glp_get_num_cols(lp->prob);
+ if (lp->meth == CPX_ALG_PRIMAL || lp->meth == CPX_ALG_DUAL)
+ { if (lpstat != NULL)
+ *lpstat = CPXgetstat(env, lp);
+ if (objval != NULL)
+ xassert(CPXgetobjval(env, lp, objval) == 0);
+ if (x != NULL)
+ xassert(CPXgetx(env, lp, x, 0, n-1) == 0);
+ if (pi != NULL)
+ xassert(CPXgetpi(env, lp, pi, 0, m-1) == 0);
+ if (slack != NULL)
+ xassert(CPXgetslack(env, lp, slack, 0, m-1) == 0);
+ if (dj != NULL)
+ xassert(CPXgetdj(env, lp, dj, 0, n-1) == 0);
+ }
+ else
+ xassert(lp != lp);
+done: return errcode;
+}
+
+int CPXstrongbranch(CPXENV *env, CPXLP *lp, const int goodlist[],
+ int goodlen, double downpen[], double uppen[], int itlim)
+{ int k;
+ xassert(env == env);
+ xassert(lp == lp);
+ xassert(goodlist == goodlist);
+ xassert(goodlen >= 0);
+ xassert(downpen != NULL);
+ xassert(uppen != NULL);
+ xassert(itlim == itlim);
+ /* not implemented yet */
+ for (k = 0; k < goodlen; k++)
+ downpen[k] = uppen[k] = 0.0;
+ return 0;
+}
+
+static int xstrcasecmp(const char *s1, const char *s2)
+{ int c1, c2;
+ for (;;)
+ { c1 = toupper((unsigned char)*s1++);
+ c2 = toupper((unsigned char)*s2++);
+ if (c1 == '\0' || c1 != c2) break;
+ }
+ return c1 - c2;
+}
+
+static void getfiletype(const char *filename, char type[3+1])
+{ /* determine filetype from filename */
+ int beg, end;
+ beg = end = strlen(filename);
+ while (beg > 0 && filename[beg-1] != '.' && end - beg < 3)
+ beg--;
+ if (beg > 0 && filename[beg-1] == '.' &&
+ xstrcasecmp(&filename[beg], "gz") == 0)
+ { end = --beg;
+ while (beg > 0 && filename[beg-1] != '.' && end - beg < 3)
+ beg--;
+ }
+ if (beg > 0 && filename[beg-1] == '.')
+ { memcpy(type, &filename[beg], end - beg);
+ type[end - beg] = '\0';
+ }
+ else
+ type[0] = '\0';
+ return;
+}
+
+int CPXwriteprob(CPXENV *env, CPXLP *lp, const char *filename,
+ const char *filetype)
+{ glp_prob *copy;
+ int errcode;
+ char type[3+1];
+ errcode = checklp(env, lp);
+ if (errcode) goto done;
+ if (filename == NULL)
+ { errcode = error(env, CPXERR_NO_FILENAME);
+ goto done;
+ }
+ if (filetype == NULL)
+ getfiletype(filename, type), filetype = type;
+ if (xstrcasecmp(filetype, "MPS") == 0)
+ { glp_term_out(GLP_OFF);
+ errcode = glp_write_mps(lp->prob, GLP_MPS_FILE, NULL, filename)
+ ;
+ glp_term_out(GLP_ON);
+ }
+ else if (xstrcasecmp(filetype, "LP") == 0)
+ { glp_term_out(GLP_OFF);
+ errcode = glp_write_lp(lp->prob, NULL, filename);
+ glp_term_out(GLP_ON);
+ }
+ else if (xstrcasecmp(filetype, "RMP") == 0 ||
+ xstrcasecmp(filetype, "REW") == 0)
+ { copy = glp_create_prob();
+ glp_copy_prob(copy, lp->prob, GLP_OFF);
+ glp_term_out(GLP_OFF);
+ errcode = glp_write_mps(copy, GLP_MPS_DECK, NULL, filename);
+ glp_term_out(GLP_ON);
+ glp_delete_prob(copy);
+ }
+ else if (xstrcasecmp(filetype, "RLP") == 0)
+ { copy = glp_create_prob();
+ glp_copy_prob(copy, lp->prob, GLP_OFF);
+ glp_term_out(GLP_OFF);
+ errcode = glp_write_lp(copy, NULL, filename);
+ glp_term_out(GLP_ON);
+ glp_delete_prob(copy);
+ }
+ else
+ { errcode = error(env, CPXERR_BAD_FILETYPE);
+ goto done;
+ }
+ if (errcode)
+ errcode = error(env, CPXERR_FAIL_OPEN_WRITE, filename);
+done: return errcode;
+}
+
+/**********************************************************************/
+
+static int solvelp(CPXENV *env, CPXLP *lp, int meth)
+{ glp_smcp parm;
+ int errcode;
+ errcode = checklp(env, lp);
+ if (errcode) goto done;
+ errcode = 0;
+ invalidate(lp);
+ glp_init_smcp(&parm);
+ switch (meth)
+ { case CPX_ALG_PRIMAL:
+ parm.meth = GLP_PRIMAL;
+ break;
+ case CPX_ALG_DUAL:
+ parm.meth = GLP_DUAL;
+ break;
+ default:
+ xassert(meth != meth);
+ }
+ switch (getintparam(env, CPX_PARAM_SIMDISPLAY))
+ { case 0:
+ parm.msg_lev = GLP_MSG_OFF;
+ break;
+ case 1:
+ parm.msg_lev = GLP_MSG_ALL;
+ break;
+ case 2:
+ parm.msg_lev = GLP_MSG_ALL;
+ parm.out_frq = 1;
+ break;
+ default:
+ xassert(env != env);
+ }
+ xassert(getdblparam == getdblparam);
+ switch (getintparam(env, CPX_PARAM_ADVIND))
+ { case 0:
+ glp_term_out(GLP_OFF);
+ glp_adv_basis(lp->prob, 0);
+ glp_term_out(GLP_ON);
+ break;
+ case 1:
+ case 2:
+ break;
+ default:
+ xassert(env != env);
+ }
+ if (!glp_bf_exists(lp->prob))
+ { if (glp_factorize(lp->prob) != 0)
+ { glp_term_out(GLP_OFF);
+ glp_adv_basis(lp->prob, 0);
+ glp_term_out(GLP_ON);
+ if (glp_factorize(lp->prob) != 0)
+ glp_std_basis(lp->prob);
+ }
+ }
+ xassert(glp_simplex(lp->prob, &parm) == 0);
+ switch (glp_get_status(lp->prob))
+ { case GLP_OPT:
+ lp->stat = CPX_STAT_OPTIMAL;
+ lp->meth = meth;
+ break;
+ case GLP_NOFEAS:
+ lp->stat = CPX_STAT_INFEASIBLE;
+ lp->meth = meth;
+ break;
+ case GLP_UNBND:
+ lp->stat = CPX_STAT_UNBOUNDED;
+ lp->meth = meth;
+ break;
+ default:
+ xassert(lp != lp);
+ }
+done: return errcode;
+}
+
+int CPXprimopt(CPXENV *env, CPXLP *lp)
+{ int errcode;
+ errcode = solvelp(env, lp, CPX_ALG_PRIMAL);
+ return errcode;
+}
+
+int CPXdualopt(CPXENV *env, CPXLP *lp)
+{ int errcode;
+ errcode = solvelp(env, lp, CPX_ALG_DUAL);
+ return errcode;
+}
+
+int CPXlpopt(CPXENV *env, CPXLP *lp)
+{ int errcode;
+ errcode = solvelp(env, lp, CPX_ALG_PRIMAL);
+ return errcode;
+}
+
+/* eof */
diff --git a/glpk-5.0/examples/cplex/cplex.h b/glpk-5.0/examples/cplex/cplex.h
new file mode 100644
index 0000000..f9c64dc
--- /dev/null
+++ b/glpk-5.0/examples/cplex/cplex.h
@@ -0,0 +1,298 @@
+/* cplex.h (CPLEX-like interface to GLPK API) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+* Copyright (C) 2001-2013 Free Software Foundation, Inc.
+* Written by Andrew Makhorin <mao@gnu.org>.
+*
+* GLPK is free software: you can redistribute it and/or modify it
+* under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* GLPK is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+* License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with GLPK. If not, see <http://www.gnu.org/licenses/>.
+***********************************************************************/
+
+#ifndef _CPLEX_H
+#define _CPLEX_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct CPXENV CPXENV, *CPXENVptr;
+typedef struct CPXLP CPXLP, *CPXLPptr;
+
+#define CPX_VERSION 900
+
+#define CPX_OFF 0
+#define CPX_ON 1
+
+#define CPX_INFBOUND 1e20
+
+/* error codes: */
+#define CPXERR_NO_MEMORY 1001
+#define CPXERR_NO_ENVIRONMENT 1002
+#define CPXERR_BAD_ARGUMENT 1003
+#define CPXERR_NULL_POINTER 1004
+#define CPXERR_NO_PROBLEM 1009
+#define CPXERR_BAD_PARAM_NUM 1013
+#define CPXERR_PARAM_TOO_SMALL 1014
+#define CPXERR_PARAM_TOO_BIG 1015
+#define CPXERR_INDEX_RANGE 1200
+#define CPXERR_COL_INDEX_RANGE 1201
+#define CPXERR_ROW_INDEX_RANGE 1203
+#define CPXERR_NEGATIVE_SURPLUS 1207
+#define CPXERR_BAD_SENSE 1215
+#define CPXERR_NO_SOLN 1217
+#define CPXERR_NOT_FIXED 1221
+#define CPXERR_DUP_ENTRY 1222
+#define CPXERR_NULL_NAME 1224
+#define CPXERR_ARRAY_NOT_ASCENDING 1226
+#define CPXERR_COUNT_RANGE 1227
+#define CPXERR_BAD_LUB 1229
+#define CPXERR_BAD_STATUS 1253
+#define CPXERR_NO_BASIC_SOLN 1261
+#define CPXERR_NO_FILENAME 1421
+#define CPXERR_FAIL_OPEN_WRITE 1422
+#define CPXERR_BAD_FILETYPE 1424
+#define CPXERR_BAD_CTYPE 3021
+
+/* control parameters: */
+#define CPX_PARAM_ADVIND 1001
+#define CPX_PARAM_AGGIND 1003
+#define CPX_PARAM_DPRIIND 1009
+#define CPX_PARAM_EPOPT 1014
+#define CPX_PARAM_EPPER 1015
+#define CPX_PARAM_EPRHS 1016
+#define CPX_PARAM_FASTMIP 1017 /* ??? */
+#define CPX_PARAM_SIMDISPLAY 1019
+#define CPX_PARAM_ITLIM 1020
+#define CPX_PARAM_OBJLLIM 1025
+#define CPX_PARAM_OBJULIM 1026
+#define CPX_PARAM_PERIND 1027
+#define CPX_PARAM_PPRIIND 1029
+#define CPX_PARAM_PREIND 1030
+#define CPX_PARAM_REINV 1031
+#define CPX_PARAM_SCRIND 1035
+#define CPX_PARAM_DATACHECK 1056
+
+/* CPX_PARAM_DPRIIND: */
+#define CPX_DPRIIND_AUTO 0
+#define CPX_DPRIIND_FULL 1
+#define CPX_DPRIIND_STEEP 2
+#define CPX_DPRIIND_FULL_STEEP 3
+#define CPX_DPRIIND_STEEPQSTART 4
+#define CPX_DPRIIND_DEVEX 5
+
+/* CPX_PARAM_PPRIIND: */
+#define CPX_PPRIIND_PARTIAL (-1)
+#define CPX_PPRIIND_AUTO 0
+#define CPX_PPRIIND_DEVEX 1
+#define CPX_PPRIIND_STEEP 2
+#define CPX_PPRIIND_STEEPQSTART 3
+#define CPX_PPRIIND_FULL 4
+
+/* CPXgetprobtype: */
+#define CPXPROB_LP 0
+#define CPXPROB_MIP 1
+#define CPXPROB_RELAXED 2
+#define CPXPROB_FIXED 3
+#define CPXPROB_QP 5
+#define CPXPROB_ZEROEDQP 6
+
+/* CPXgetobjsen: */
+#define CPX_MIN 1
+#define CPX_MAX (-1)
+
+/* CPXgetbase: */
+#define CPX_AT_LOWER 0
+#define CPX_BASIC 1
+#define CPX_AT_UPPER 2
+#define CPX_FREE_SUPER 3
+
+/* CPXgetstat: */
+#define CPX_STAT_OPTIMAL 1
+#define CPX_STAT_UNBOUNDED 2
+#define CPX_STAT_INFEASIBLE 3
+#define CPX_STAT_INForUNBD 4
+#define CPX_STAT_OPTIMAL_INFEAS 5
+#define CPX_STAT_ABORT_IT_LIM 10
+#define CPX_STAT_ABORT_OBJ_LIM 12
+
+/* CPXgetmethod: */
+#define CPX_ALG_NONE 0
+#define CPX_ALG_PRIMAL 1
+#define CPX_ALG_DUAL 2
+#define CPX_ALG_BARRIER 4
+
+/* CPXsolninfo: */
+#define CPX_NO_SOLN 0
+#define CPX_BASIC_SOLN 1
+#define CPX_NONBASIC_SOLN 2
+#define CPX_PRIMAL_SOLN 3
+
+int CPXaddcols(CPXENV *env, CPXLP *lp, int ccnt, int nzcnt,
+ const double obj[], const int cmatbeg[], const int cmatind[],
+ const double cmatval[], const double lb[], const double ub[],
+ char *colname[]);
+
+int CPXaddrows(CPXENV *env, CPXLP *lp, int ccnt, int rcnt, int nzcnt,
+ const double rhs[], const char sense[], const int rmatbeg[],
+ const int rmatind[], const double rmatval[], char *colname[],
+ char *rowname[]);
+
+int CPXbaropt(CPXENV *env, CPXLP *lp);
+
+int CPXbinvrow(CPXENV *env, CPXLP *lp, int i, double y[]);
+
+int CPXchgbds(CPXENV *env, CPXLP *lp, int cnt, const int indices[],
+ const char lu[], const double bd[]);
+
+int CPXchgcoeflist(CPXENV *env, CPXLP *lp, int numcoefs,
+ const int rowlist[], const int collist[], const double vallist[]);
+
+void CPXchgobjsen(CPXENV *env, CPXLP *lp, int maxormin);
+
+int CPXchgsense(CPXENV *env, CPXLP *lp, int cnt, const int indices[],
+ const char sense[]);
+
+int CPXcloseCPLEX(CPXENV **env);
+
+int CPXcopybase(CPXENV *env, CPXLP *lp, const int cstat[],
+ const int rstat[]);
+
+int CPXcopybasednorms(CPXENV *env, CPXLP *lp, const int cstat[],
+ const int rstat[], const double dnorm[]);
+
+int CPXcopylp(CPXENV *env, CPXLP *lp, int numcols, int numrows,
+ int objsen, const double obj[], const double rhs[],
+ const char sense[], const int matbeg[], const int matcnt[],
+ const int matind[], const double matval[], const double lb[],
+ const double ub[], const double rngval[]);
+
+int CPXcopylpwnames(CPXENV *env, CPXLP *lp, int numcols, int numrows,
+ int objsen, const double obj[], const double rhs[],
+ const char sense[], const int matbeg[], const int matcnt[],
+ const int matind[], const double matval[], const double lb[],
+ const double ub[], const double rngval[], char *colname[],
+ char *rowname[]);
+
+CPXLP *CPXcreateprob(CPXENV *env, int *status, const char *probname);
+
+int CPXdelcols(CPXENV *env, CPXLP *lp, int begin, int end);
+
+int CPXdelrows(CPXENV *env, CPXLP *lp, int begin, int end);
+
+int CPXdelsetcols(CPXENV *env, CPXLP *lp, int delstat[]);
+
+int CPXdelsetrows(CPXENV *env, CPXLP *lp, int delstat[]);
+
+int CPXdualopt(CPXENV *env, CPXLP *lp);
+
+int CPXfreeprob(CPXENV *env, CPXLP **lp);
+
+int CPXgetbase(CPXENV *env, CPXLP *lp, int cstat[], int rstat[]);
+
+int CPXgetbasednorms(CPXENV *env, CPXLP *lp, int cstat[], int rstat[],
+ double dnorm[]);
+
+int CPXgetbhead(CPXENV *env, CPXLP *lp, int head[], double x[]);
+
+int CPXgetdblparam(CPXENV *env, int whichparam, double *value);
+
+int CPXgetdj(CPXENV *env, CPXLP *lp, double dj[], int begin, int end);
+
+char *CPXgeterrorstring(CPXENV *env, int errcode, char *buffer);
+
+int CPXgetijdiv(CPXENV *env, CPXLP *lp, int *idiv, int *jdiv);
+
+int CPXgetintparam(CPXENV *env, int whichparam, int *value);
+
+int CPXgetlb(CPXENV *env, CPXLP *lp, double lb[], int begin, int end);
+
+int CPXgetmethod(CPXENV *env, CPXLP *lp);
+
+int CPXgetnumcols(CPXENV *env, CPXLP *lp);
+
+int CPXgetnumnz(CPXENV *env, CPXLP *lp);
+
+int CPXgetnumrows(CPXENV *env, CPXLP *lp);
+
+int CPXgetobjval(CPXENV *env, CPXLP *lp, double *objval);
+
+int CPXgetpi(CPXENV *env, CPXLP *lp, double pi[], int begin, int end);
+
+int CPXgetsense(CPXENV *env, CPXLP *lp, char sense[], int begin,
+ int end);
+
+int CPXgetslack(CPXENV *env, CPXLP *lp, double slack[], int begin,
+ int end);
+
+int CPXgetstat(CPXENV *env, CPXLP *lp);
+
+int CPXgetub(CPXENV *env, CPXLP *lp, double ub[], int begin, int end);
+
+int CPXgetweight(CPXENV *env, CPXLP *lp, int rcnt, const int rmatbeg[],
+ const int rmatind[], const double rmatval[], double weight[],
+ int dpriind);
+
+int CPXgetx(CPXENV *env, CPXLP *lp, double x[], int begin, int end);
+
+int CPXinfodblparam(CPXENV *env, int whichparam, double *defvalue,
+ double *minvalue, double *maxvalue);
+
+int CPXinfointparam(CPXENV *env, int whichparam, int *defvalue,
+ int *minvalue, int *maxvalue);
+
+int CPXlpopt(CPXENV *env, CPXLP *lp);
+
+int CPXmdleave(const CPXENV *env, CPXLP *lp, const int goodlist[],
+ int goodlen, double downratio[], double upratio[]);
+
+int CPXnewcols(CPXENV *env, CPXLP *lp, int ccnt, const double obj[],
+ const double lb[], const double ub[], const char ctype[],
+ char *colname[]);
+
+int CPXnewrows(CPXENV *env, CPXLP *lp, int rcnt, const double rhs[],
+ const char sense[], const double rngval[], char *rowname[]);
+
+CPXENV *CPXopenCPLEX(int *status);
+
+int CPXpivotin(CPXENV *env, CPXLP *lp, const int rlist[], int rlen);
+
+int CPXpivotout(CPXENV *env, CPXLP *lp, const int clist[], int clen);
+
+int CPXprimopt(CPXENV *env, CPXLP *lp);
+
+int CPXsavwrite(CPXENV *env, CPXLP *lp, const char *filename);
+
+int CPXsetdblparam(CPXENV *env, int whichparam, double newvalue);
+
+int CPXsetintparam(CPXENV *env, int whichparam, int newvalue);
+
+int CPXsolninfo(CPXENV *env, CPXLP *lp, int *solnmethod, int *solntype,
+ int *pfeasind, int *dfeasind);
+
+int CPXsolution(CPXENV *env, CPXLP *lp, int *lpstat, double *objval,
+ double x[], double pi[], double slack[], double dj[]);
+
+int CPXstrongbranch(CPXENV *env, CPXLP *lp, const int goodlist[],
+ int goodlen, double downpen[], double uppen[], int itlim);
+
+int CPXwriteprob(CPXENV *env, CPXLP *lp, const char *filename,
+ const char *filetype);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+/* eof */