aboutsummaryrefslogtreecommitdiffstats
path: root/test/monniaux/glpk-4.65/src/api
diff options
context:
space:
mode:
Diffstat (limited to 'test/monniaux/glpk-4.65/src/api')
-rw-r--r--test/monniaux/glpk-4.65/src/api/advbas.c155
-rw-r--r--test/monniaux/glpk-4.65/src/api/asnhall.c163
-rw-r--r--test/monniaux/glpk-4.65/src/api/asnlp.c104
-rw-r--r--test/monniaux/glpk-4.65/src/api/asnokalg.c154
-rw-r--r--test/monniaux/glpk-4.65/src/api/ckasn.c78
-rw-r--r--test/monniaux/glpk-4.65/src/api/ckcnf.c82
-rw-r--r--test/monniaux/glpk-4.65/src/api/cplex.c1283
-rw-r--r--test/monniaux/glpk-4.65/src/api/cpp.c185
-rw-r--r--test/monniaux/glpk-4.65/src/api/cpxbas.c269
-rw-r--r--test/monniaux/glpk-4.65/src/api/graph.c504
-rw-r--r--test/monniaux/glpk-4.65/src/api/gridgen.c769
-rw-r--r--test/monniaux/glpk-4.65/src/api/intfeas1.c267
-rw-r--r--test/monniaux/glpk-4.65/src/api/maxffalg.c130
-rw-r--r--test/monniaux/glpk-4.65/src/api/maxflp.c114
-rw-r--r--test/monniaux/glpk-4.65/src/api/mcflp.c114
-rw-r--r--test/monniaux/glpk-4.65/src/api/mcfokalg.c221
-rw-r--r--test/monniaux/glpk-4.65/src/api/mcfrelax.c251
-rw-r--r--test/monniaux/glpk-4.65/src/api/minisat1.c161
-rw-r--r--test/monniaux/glpk-4.65/src/api/mpl.c269
-rw-r--r--test/monniaux/glpk-4.65/src/api/mps.c1452
-rw-r--r--test/monniaux/glpk-4.65/src/api/netgen.c1020
-rw-r--r--test/monniaux/glpk-4.65/src/api/npp.c143
-rw-r--r--test/monniaux/glpk-4.65/src/api/pript.c186
-rw-r--r--test/monniaux/glpk-4.65/src/api/prmip.c155
-rw-r--r--test/monniaux/glpk-4.65/src/api/prob.h286
-rw-r--r--test/monniaux/glpk-4.65/src/api/prob1.c1588
-rw-r--r--test/monniaux/glpk-4.65/src/api/prob2.c491
-rw-r--r--test/monniaux/glpk-4.65/src/api/prob3.c166
-rw-r--r--test/monniaux/glpk-4.65/src/api/prob4.c156
-rw-r--r--test/monniaux/glpk-4.65/src/api/prob5.c168
-rw-r--r--test/monniaux/glpk-4.65/src/api/prrngs.c302
-rw-r--r--test/monniaux/glpk-4.65/src/api/prsol.c202
-rw-r--r--test/monniaux/glpk-4.65/src/api/rdasn.c164
-rw-r--r--test/monniaux/glpk-4.65/src/api/rdcc.c162
-rw-r--r--test/monniaux/glpk-4.65/src/api/rdcnf.c136
-rw-r--r--test/monniaux/glpk-4.65/src/api/rdipt.c185
-rw-r--r--test/monniaux/glpk-4.65/src/api/rdmaxf.c163
-rw-r--r--test/monniaux/glpk-4.65/src/api/rdmcf.c186
-rw-r--r--test/monniaux/glpk-4.65/src/api/rdmip.c172
-rw-r--r--test/monniaux/glpk-4.65/src/api/rdprob.c377
-rw-r--r--test/monniaux/glpk-4.65/src/api/rdsol.c225
-rw-r--r--test/monniaux/glpk-4.65/src/api/rmfgen.c368
-rw-r--r--test/monniaux/glpk-4.65/src/api/strong.c110
-rw-r--r--test/monniaux/glpk-4.65/src/api/topsort.c123
-rw-r--r--test/monniaux/glpk-4.65/src/api/wcliqex.c122
-rw-r--r--test/monniaux/glpk-4.65/src/api/weak.c150
-rw-r--r--test/monniaux/glpk-4.65/src/api/wrasn.c107
-rw-r--r--test/monniaux/glpk-4.65/src/api/wrcc.c102
-rw-r--r--test/monniaux/glpk-4.65/src/api/wrcnf.c87
-rw-r--r--test/monniaux/glpk-4.65/src/api/wript.c124
-rw-r--r--test/monniaux/glpk-4.65/src/api/wrmaxf.c104
-rw-r--r--test/monniaux/glpk-4.65/src/api/wrmcf.c122
-rw-r--r--test/monniaux/glpk-4.65/src/api/wrmip.c122
-rw-r--r--test/monniaux/glpk-4.65/src/api/wrprob.c166
-rw-r--r--test/monniaux/glpk-4.65/src/api/wrsol.c174
55 files changed, 15339 insertions, 0 deletions
diff --git a/test/monniaux/glpk-4.65/src/api/advbas.c b/test/monniaux/glpk-4.65/src/api/advbas.c
new file mode 100644
index 00000000..23067624
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/api/advbas.c
@@ -0,0 +1,155 @@
+/* advbas.c (construct advanced initial LP basis) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* Copyright (C) 2008-2016 Andrew Makhorin, Department for Applied
+* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights
+* reserved. E-mail: <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 "env.h"
+#include "prob.h"
+#include "triang.h"
+
+/***********************************************************************
+* NAME
+*
+* glp_adv_basis - construct advanced initial LP basis
+*
+* SYNOPSIS
+*
+* void glp_adv_basis(glp_prob *P, int flags);
+*
+* DESCRIPTION
+*
+* The routine glp_adv_basis constructs an advanced initial LP basis
+* for the specified problem object.
+*
+* The parameter flag is reserved for use in the future and should be
+* specified as zero.
+*
+* NOTE
+*
+* The routine glp_adv_basis should be called after the constraint
+* matrix has been scaled (if scaling is used). */
+
+static int mat(void *info, int k, int ind[], double val[])
+{ glp_prob *P = info;
+ int m = P->m;
+ int n = P->n;
+ GLPROW **row = P->row;
+ GLPCOL **col = P->col;
+ GLPAIJ *aij;
+ int i, j, len;
+ if (k > 0)
+ { /* retrieve scaled row of constraint matrix */
+ i = +k;
+ xassert(1 <= i && i <= m);
+ len = 0;
+ if (row[i]->type == GLP_FX)
+ { for (aij = row[i]->ptr; aij != NULL; aij = aij->r_next)
+ { j = aij->col->j;
+ if (col[j]->type != GLP_FX)
+ { len++;
+ ind[len] = j;
+ val[len] = aij->row->rii * aij->val * aij->col->sjj;
+ }
+ }
+ }
+ }
+ else
+ { /* retrieve scaled column of constraint matrix */
+ j = -k;
+ xassert(1 <= j && j <= n);
+ len = 0;
+ if (col[j]->type != GLP_FX)
+ { for (aij = col[j]->ptr; aij != NULL; aij = aij->c_next)
+ { i = aij->row->i;
+ if (row[i]->type == GLP_FX)
+ { len++;
+ ind[len] = i;
+ val[len] = aij->row->rii * aij->val * aij->col->sjj;
+ }
+ }
+ }
+ }
+ return len;
+}
+
+void glp_adv_basis(glp_prob *P, int flags)
+{ int i, j, k, m, n, min_mn, size, *rn, *cn;
+ char *flag;
+ if (flags != 0)
+ xerror("glp_adv_basis: flags = %d; invalid flags\n", flags);
+ m = P->m; /* number of rows */
+ n = P->n; /* number of columns */
+ if (m == 0 || n == 0)
+ { /* trivial case */
+ glp_std_basis(P);
+ goto done;
+ }
+ xprintf("Constructing initial basis...\n");
+ /* allocate working arrays */
+ min_mn = (m < n ? m : n);
+ rn = talloc(1+min_mn, int);
+ cn = talloc(1+min_mn, int);
+ flag = talloc(1+m, char);
+ /* make the basis empty */
+ for (i = 1; i <= m; i++)
+ { flag[i] = 0;
+ glp_set_row_stat(P, i, GLP_NS);
+ }
+ for (j = 1; j <= n; j++)
+ glp_set_col_stat(P, j, GLP_NS);
+ /* find maximal triangular part of the constraint matrix;
+ to prevent including non-fixed rows and fixed columns in the
+ triangular part, such rows and columns are temporarily made
+ empty by the routine mat */
+#if 1 /* FIXME: tolerance */
+ size = triang(m, n, mat, P, 0.001, rn, cn);
+#endif
+ xassert(0 <= size && size <= min_mn);
+ /* include in the basis non-fixed structural variables, whose
+ columns constitute the triangular part */
+ for (k = 1; k <= size; k++)
+ { i = rn[k];
+ xassert(1 <= i && i <= m);
+ flag[i] = 1;
+ j = cn[k];
+ xassert(1 <= j && j <= n);
+ glp_set_col_stat(P, j, GLP_BS);
+ }
+ /* include in the basis appropriate auxiliary variables, whose
+ unity columns preserve triangular form of the basis matrix */
+ for (i = 1; i <= m; i++)
+ { if (flag[i] == 0)
+ { glp_set_row_stat(P, i, GLP_BS);
+ if (P->row[i]->type != GLP_FX)
+ size++;
+ }
+ }
+ /* size of triangular part = (number of rows) - (number of basic
+ fixed auxiliary variables) */
+ xprintf("Size of triangular part is %d\n", size);
+ /* deallocate working arrays */
+ tfree(rn);
+ tfree(cn);
+ tfree(flag);
+done: return;
+}
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/api/asnhall.c b/test/monniaux/glpk-4.65/src/api/asnhall.c
new file mode 100644
index 00000000..d7112a10
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/api/asnhall.c
@@ -0,0 +1,163 @@
+/* asnhall.c (find bipartite matching of maximum cardinality) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* Copyright (C) 2009-2016 Andrew Makhorin, Department for Applied
+* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights
+* reserved. E-mail: <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 "env.h"
+#include "glpk.h"
+#include "mc21a.h"
+
+/***********************************************************************
+* NAME
+*
+* glp_asnprob_hall - find bipartite matching of maximum cardinality
+*
+* SYNOPSIS
+*
+* int glp_asnprob_hall(glp_graph *G, int v_set, int a_x);
+*
+* DESCRIPTION
+*
+* The routine glp_asnprob_hall finds a matching of maximal cardinality
+* in the specified bipartite graph G. It uses a version of the Fortran
+* routine MC21A developed by I.S.Duff [1], which implements Hall's
+* algorithm [2].
+*
+* RETURNS
+*
+* The routine glp_asnprob_hall returns the cardinality of the matching
+* found. However, if the specified graph is incorrect (as detected by
+* the routine glp_check_asnprob), the routine returns negative value.
+*
+* REFERENCES
+*
+* 1. I.S.Duff, Algorithm 575: Permutations for zero-free diagonal, ACM
+* Trans. on Math. Softw. 7 (1981), 387-390.
+*
+* 2. M.Hall, "An Algorithm for distinct representatives," Amer. Math.
+* Monthly 63 (1956), 716-717. */
+
+int glp_asnprob_hall(glp_graph *G, int v_set, int a_x)
+{ glp_vertex *v;
+ glp_arc *a;
+ int card, i, k, loc, n, n1, n2, xij;
+ int *num, *icn, *ip, *lenr, *iperm, *pr, *arp, *cv, *out;
+ if (v_set >= 0 && v_set > G->v_size - (int)sizeof(int))
+ xerror("glp_asnprob_hall: v_set = %d; invalid offset\n",
+ v_set);
+ if (a_x >= 0 && a_x > G->a_size - (int)sizeof(int))
+ xerror("glp_asnprob_hall: a_x = %d; invalid offset\n", a_x);
+ if (glp_check_asnprob(G, v_set))
+ return -1;
+ /* determine the number of vertices in sets R and S and renumber
+ vertices in S which correspond to columns of the matrix; skip
+ all isolated vertices */
+ num = xcalloc(1+G->nv, sizeof(int));
+ n1 = n2 = 0;
+ for (i = 1; i <= G->nv; i++)
+ { v = G->v[i];
+ if (v->in == NULL && v->out != NULL)
+ n1++, num[i] = 0; /* vertex in R */
+ else if (v->in != NULL && v->out == NULL)
+ n2++, num[i] = n2; /* vertex in S */
+ else
+ { xassert(v->in == NULL && v->out == NULL);
+ num[i] = -1; /* isolated vertex */
+ }
+ }
+ /* the matrix must be square, thus, if it has more columns than
+ rows, extra rows will be just empty, and vice versa */
+ n = (n1 >= n2 ? n1 : n2);
+ /* allocate working arrays */
+ icn = xcalloc(1+G->na, sizeof(int));
+ ip = xcalloc(1+n, sizeof(int));
+ lenr = xcalloc(1+n, sizeof(int));
+ iperm = xcalloc(1+n, sizeof(int));
+ pr = xcalloc(1+n, sizeof(int));
+ arp = xcalloc(1+n, sizeof(int));
+ cv = xcalloc(1+n, sizeof(int));
+ out = xcalloc(1+n, sizeof(int));
+ /* build the adjacency matrix of the bipartite graph in row-wise
+ format (rows are vertices in R, columns are vertices in S) */
+ k = 0, loc = 1;
+ for (i = 1; i <= G->nv; i++)
+ { if (num[i] != 0) continue;
+ /* vertex i in R */
+ ip[++k] = loc;
+ v = G->v[i];
+ for (a = v->out; a != NULL; a = a->t_next)
+ { xassert(num[a->head->i] != 0);
+ icn[loc++] = num[a->head->i];
+ }
+ lenr[k] = loc - ip[k];
+ }
+ xassert(loc-1 == G->na);
+ /* make all extra rows empty (all extra columns are empty due to
+ the row-wise format used) */
+ for (k++; k <= n; k++)
+ ip[k] = loc, lenr[k] = 0;
+ /* find a row permutation that maximizes the number of non-zeros
+ on the main diagonal */
+ card = mc21a(n, icn, ip, lenr, iperm, pr, arp, cv, out);
+#if 1 /* 18/II-2010 */
+ /* FIXED: if card = n, arp remains clobbered on exit */
+ for (i = 1; i <= n; i++)
+ arp[i] = 0;
+ for (i = 1; i <= card; i++)
+ { k = iperm[i];
+ xassert(1 <= k && k <= n);
+ xassert(arp[k] == 0);
+ arp[k] = i;
+ }
+#endif
+ /* store solution, if necessary */
+ if (a_x < 0) goto skip;
+ k = 0;
+ for (i = 1; i <= G->nv; i++)
+ { if (num[i] != 0) continue;
+ /* vertex i in R */
+ k++;
+ v = G->v[i];
+ for (a = v->out; a != NULL; a = a->t_next)
+ { /* arp[k] is the number of matched column or zero */
+ if (arp[k] == num[a->head->i])
+ { xassert(arp[k] != 0);
+ xij = 1;
+ }
+ else
+ xij = 0;
+ memcpy((char *)a->data + a_x, &xij, sizeof(int));
+ }
+ }
+skip: /* free working arrays */
+ xfree(num);
+ xfree(icn);
+ xfree(ip);
+ xfree(lenr);
+ xfree(iperm);
+ xfree(pr);
+ xfree(arp);
+ xfree(cv);
+ xfree(out);
+ return card;
+}
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/api/asnlp.c b/test/monniaux/glpk-4.65/src/api/asnlp.c
new file mode 100644
index 00000000..cfa925d0
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/api/asnlp.c
@@ -0,0 +1,104 @@
+/* asnlp.c (convert assignment problem to LP) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* Copyright (C) 2009-2016 Andrew Makhorin, Department for Applied
+* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights
+* reserved. E-mail: <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 "env.h"
+#include "glpk.h"
+
+/***********************************************************************
+* NAME
+*
+* glp_asnprob_lp - convert assignment problem to LP
+*
+* SYNOPSIS
+*
+* int glp_asnprob_lp(glp_prob *P, int form, glp_graph *G, int names,
+* int v_set, int a_cost);
+*
+* DESCRIPTION
+*
+* The routine glp_asnprob_lp builds an LP problem, which corresponds
+* to the assignment problem on the specified graph G.
+*
+* RETURNS
+*
+* If the LP problem has been successfully built, the routine returns
+* zero, otherwise, non-zero. */
+
+int glp_asnprob_lp(glp_prob *P, int form, glp_graph *G, int names,
+ int v_set, int a_cost)
+{ glp_vertex *v;
+ glp_arc *a;
+ int i, j, ret, ind[1+2];
+ double cost, val[1+2];
+ if (!(form == GLP_ASN_MIN || form == GLP_ASN_MAX ||
+ form == GLP_ASN_MMP))
+ xerror("glp_asnprob_lp: form = %d; invalid parameter\n",
+ form);
+ if (!(names == GLP_ON || names == GLP_OFF))
+ xerror("glp_asnprob_lp: names = %d; invalid parameter\n",
+ names);
+ if (v_set >= 0 && v_set > G->v_size - (int)sizeof(int))
+ xerror("glp_asnprob_lp: v_set = %d; invalid offset\n",
+ v_set);
+ if (a_cost >= 0 && a_cost > G->a_size - (int)sizeof(double))
+ xerror("glp_asnprob_lp: a_cost = %d; invalid offset\n",
+ a_cost);
+ ret = glp_check_asnprob(G, v_set);
+ if (ret != 0) goto done;
+ glp_erase_prob(P);
+ if (names) glp_set_prob_name(P, G->name);
+ glp_set_obj_dir(P, form == GLP_ASN_MIN ? GLP_MIN : GLP_MAX);
+ if (G->nv > 0) glp_add_rows(P, G->nv);
+ for (i = 1; i <= G->nv; i++)
+ { v = G->v[i];
+ if (names) glp_set_row_name(P, i, v->name);
+ glp_set_row_bnds(P, i, form == GLP_ASN_MMP ? GLP_UP : GLP_FX,
+ 1.0, 1.0);
+ }
+ if (G->na > 0) glp_add_cols(P, G->na);
+ for (i = 1, j = 0; i <= G->nv; i++)
+ { v = G->v[i];
+ for (a = v->out; a != NULL; a = a->t_next)
+ { j++;
+ if (names)
+ { char name[50+1];
+ sprintf(name, "x[%d,%d]", a->tail->i, a->head->i);
+ xassert(strlen(name) < sizeof(name));
+ glp_set_col_name(P, j, name);
+ }
+ ind[1] = a->tail->i, val[1] = +1.0;
+ ind[2] = a->head->i, val[2] = +1.0;
+ glp_set_mat_col(P, j, 2, ind, val);
+ glp_set_col_bnds(P, j, GLP_DB, 0.0, 1.0);
+ if (a_cost >= 0)
+ memcpy(&cost, (char *)a->data + a_cost, sizeof(double));
+ else
+ cost = 1.0;
+ glp_set_obj_coef(P, j, cost);
+ }
+ }
+ xassert(j == G->na);
+done: return ret;
+}
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/api/asnokalg.c b/test/monniaux/glpk-4.65/src/api/asnokalg.c
new file mode 100644
index 00000000..d55dbac7
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/api/asnokalg.c
@@ -0,0 +1,154 @@
+/* asnokalg.c (solve assignment problem with out-of-kilter alg.) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* Copyright (C) 2009-2016 Andrew Makhorin, Department for Applied
+* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights
+* reserved. E-mail: <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 "env.h"
+#include "glpk.h"
+#include "okalg.h"
+
+int glp_asnprob_okalg(int form, glp_graph *G, int v_set, int a_cost,
+ double *sol, int a_x)
+{ /* solve assignment problem with out-of-kilter algorithm */
+ glp_vertex *v;
+ glp_arc *a;
+ int nv, na, i, k, *tail, *head, *low, *cap, *cost, *x, *pi, ret;
+ double temp;
+ if (!(form == GLP_ASN_MIN || form == GLP_ASN_MAX ||
+ form == GLP_ASN_MMP))
+ xerror("glp_asnprob_okalg: form = %d; invalid parameter\n",
+ form);
+ if (v_set >= 0 && v_set > G->v_size - (int)sizeof(int))
+ xerror("glp_asnprob_okalg: v_set = %d; invalid offset\n",
+ v_set);
+ if (a_cost >= 0 && a_cost > G->a_size - (int)sizeof(double))
+ xerror("glp_asnprob_okalg: a_cost = %d; invalid offset\n",
+ a_cost);
+ if (a_x >= 0 && a_x > G->a_size - (int)sizeof(int))
+ xerror("glp_asnprob_okalg: a_x = %d; invalid offset\n", a_x);
+ if (glp_check_asnprob(G, v_set))
+ return GLP_EDATA;
+ /* nv is the total number of nodes in the resulting network */
+ nv = G->nv + 1;
+ /* na is the total number of arcs in the resulting network */
+ na = G->na + G->nv;
+ /* allocate working arrays */
+ tail = xcalloc(1+na, sizeof(int));
+ head = xcalloc(1+na, sizeof(int));
+ low = xcalloc(1+na, sizeof(int));
+ cap = xcalloc(1+na, sizeof(int));
+ cost = xcalloc(1+na, sizeof(int));
+ x = xcalloc(1+na, sizeof(int));
+ pi = xcalloc(1+nv, sizeof(int));
+ /* construct the resulting network */
+ k = 0;
+ /* (original arcs) */
+ for (i = 1; i <= G->nv; i++)
+ { v = G->v[i];
+ for (a = v->out; a != NULL; a = a->t_next)
+ { k++;
+ tail[k] = a->tail->i;
+ head[k] = a->head->i;
+ low[k] = 0;
+ cap[k] = 1;
+ if (a_cost >= 0)
+ memcpy(&temp, (char *)a->data + a_cost, sizeof(double));
+ else
+ temp = 1.0;
+ if (!(fabs(temp) <= (double)INT_MAX && temp == floor(temp)))
+ { ret = GLP_EDATA;
+ goto done;
+ }
+ cost[k] = (int)temp;
+ if (form != GLP_ASN_MIN) cost[k] = - cost[k];
+ }
+ }
+ /* (artificial arcs) */
+ for (i = 1; i <= G->nv; i++)
+ { v = G->v[i];
+ k++;
+ if (v->out == NULL)
+ tail[k] = i, head[k] = nv;
+ else if (v->in == NULL)
+ tail[k] = nv, head[k] = i;
+ else
+ xassert(v != v);
+ low[k] = (form == GLP_ASN_MMP ? 0 : 1);
+ cap[k] = 1;
+ cost[k] = 0;
+ }
+ xassert(k == na);
+ /* find minimal-cost circulation in the resulting network */
+ ret = okalg(nv, na, tail, head, low, cap, cost, x, pi);
+ switch (ret)
+ { case 0:
+ /* optimal circulation found */
+ ret = 0;
+ break;
+ case 1:
+ /* no feasible circulation exists */
+ ret = GLP_ENOPFS;
+ break;
+ case 2:
+ /* integer overflow occured */
+ ret = GLP_ERANGE;
+ goto done;
+ case 3:
+ /* optimality test failed (logic error) */
+ ret = GLP_EFAIL;
+ goto done;
+ default:
+ xassert(ret != ret);
+ }
+ /* store solution components */
+ /* (objective function = the total cost) */
+ if (sol != NULL)
+ { temp = 0.0;
+ for (k = 1; k <= na; k++)
+ temp += (double)cost[k] * (double)x[k];
+ if (form != GLP_ASN_MIN) temp = - temp;
+ *sol = temp;
+ }
+ /* (arc flows) */
+ if (a_x >= 0)
+ { k = 0;
+ for (i = 1; i <= G->nv; i++)
+ { v = G->v[i];
+ for (a = v->out; a != NULL; a = a->t_next)
+ { k++;
+ if (ret == 0)
+ xassert(x[k] == 0 || x[k] == 1);
+ memcpy((char *)a->data + a_x, &x[k], sizeof(int));
+ }
+ }
+ }
+done: /* free working arrays */
+ xfree(tail);
+ xfree(head);
+ xfree(low);
+ xfree(cap);
+ xfree(cost);
+ xfree(x);
+ xfree(pi);
+ return ret;
+}
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/api/ckasn.c b/test/monniaux/glpk-4.65/src/api/ckasn.c
new file mode 100644
index 00000000..56221a8a
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/api/ckasn.c
@@ -0,0 +1,78 @@
+/* ckasn.c (check correctness of assignment problem data) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* Copyright (C) 2009-2016 Andrew Makhorin, Department for Applied
+* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights
+* reserved. E-mail: <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 "env.h"
+#include "glpk.h"
+
+/***********************************************************************
+* NAME
+*
+* glp_check_asnprob - check correctness of assignment problem data
+*
+* SYNOPSIS
+*
+* int glp_check_asnprob(glp_graph *G, int v_set);
+*
+* RETURNS
+*
+* If the specified assignment problem data are correct, the routine
+* glp_check_asnprob returns zero, otherwise, non-zero. */
+
+int glp_check_asnprob(glp_graph *G, int v_set)
+{ glp_vertex *v;
+ int i, k, ret = 0;
+ if (v_set >= 0 && v_set > G->v_size - (int)sizeof(int))
+ xerror("glp_check_asnprob: v_set = %d; invalid offset\n",
+ v_set);
+ for (i = 1; i <= G->nv; i++)
+ { v = G->v[i];
+ if (v_set >= 0)
+ { memcpy(&k, (char *)v->data + v_set, sizeof(int));
+ if (k == 0)
+ { if (v->in != NULL)
+ { ret = 1;
+ break;
+ }
+ }
+ else if (k == 1)
+ { if (v->out != NULL)
+ { ret = 2;
+ break;
+ }
+ }
+ else
+ { ret = 3;
+ break;
+ }
+ }
+ else
+ { if (v->in != NULL && v->out != NULL)
+ { ret = 4;
+ break;
+ }
+ }
+ }
+ return ret;
+}
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/api/ckcnf.c b/test/monniaux/glpk-4.65/src/api/ckcnf.c
new file mode 100644
index 00000000..0ee47ed9
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/api/ckcnf.c
@@ -0,0 +1,82 @@
+/* ckcnf.c (check for CNF-SAT problem instance) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* Copyright (C) 2010-2016 Andrew Makhorin, Department for Applied
+* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights
+* reserved. E-mail: <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 "env.h"
+#include "prob.h"
+
+int glp_check_cnfsat(glp_prob *P)
+{ /* check for CNF-SAT problem instance */
+ int m = P->m;
+ int n = P->n;
+ GLPROW *row;
+ GLPCOL *col;
+ GLPAIJ *aij;
+ int i, j, neg;
+#if 0 /* 04/IV-2016 */
+ if (P == NULL || P->magic != GLP_PROB_MAGIC)
+ xerror("glp_check_cnfsat: P = %p; invalid problem object\n",
+ P);
+#endif
+ /* check columns */
+ for (j = 1; j <= n; j++)
+ { col = P->col[j];
+ /* the variable should be binary */
+ if (!(col->kind == GLP_IV && col->type == GLP_DB &&
+ col->lb == 0.0 && col->ub == 1.0))
+ return 1;
+ }
+ /* objective function should be zero */
+ if (P->c0 != 0.0)
+ return 2;
+ for (j = 1; j <= n; j++)
+ { col = P->col[j];
+ if (col->coef != 0.0)
+ return 3;
+ }
+ /* check rows */
+ for (i = 1; i <= m; i++)
+ { row = P->row[i];
+ /* the row should be of ">=" type */
+ if (row->type != GLP_LO)
+ return 4;
+ /* check constraint coefficients */
+ neg = 0;
+ for (aij = row->ptr; aij != NULL; aij = aij->r_next)
+ { /* the constraint coefficient should be +1 or -1 */
+ if (aij->val == +1.0)
+ ;
+ else if (aij->val == -1.0)
+ neg++;
+ else
+ return 5;
+ }
+ /* the right-hand side should be (1 - neg), where neg is the
+ number of negative constraint coefficients in the row */
+ if (row->lb != (double)(1 - neg))
+ return 6;
+ }
+ /* congratulations; this is CNF-SAT */
+ return 0;
+}
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/api/cplex.c b/test/monniaux/glpk-4.65/src/api/cplex.c
new file mode 100644
index 00000000..8403a646
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/api/cplex.c
@@ -0,0 +1,1283 @@
+/* cplex.c (CPLEX LP format routines) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* Copyright (C) 2009-2018 Andrew Makhorin, Department for Applied
+* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights
+* reserved. E-mail: <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 "env.h"
+#include "misc.h"
+#include "prob.h"
+
+#define xfprintf glp_format
+
+/***********************************************************************
+* NAME
+*
+* glp_init_cpxcp - initialize CPLEX LP format control parameters
+*
+* SYNOPSIS
+*
+* void glp_init_cpxcp(glp_cpxcp *parm):
+*
+* The routine glp_init_cpxcp initializes control parameters used by
+* the CPLEX LP input/output routines glp_read_lp and glp_write_lp with
+* default values.
+*
+* Default values of the control parameters are stored in the glp_cpxcp
+* structure, which the parameter parm points to. */
+
+void glp_init_cpxcp(glp_cpxcp *parm)
+{ xassert(parm != NULL);
+ return;
+}
+
+static void check_parm(const char *func, const glp_cpxcp *parm)
+{ /* check control parameters */
+ xassert(func != NULL);
+ xassert(parm != NULL);
+ return;
+}
+
+/***********************************************************************
+* NAME
+*
+* glp_read_lp - read problem data in CPLEX LP format
+*
+* SYNOPSIS
+*
+* int glp_read_lp(glp_prob *P, const glp_cpxcp *parm, const char
+* *fname);
+*
+* DESCRIPTION
+*
+* The routine glp_read_lp reads problem data in CPLEX LP format from
+* a text file.
+*
+* The parameter parm is a pointer to the structure glp_cpxcp, which
+* specifies control parameters used by the routine. If parm is NULL,
+* the routine uses default settings.
+*
+* The character string fname specifies a name of the text file to be
+* read.
+*
+* Note that before reading data the current content of the problem
+* object is completely erased with the routine glp_erase_prob.
+*
+* RETURNS
+*
+* If the operation was successful, the routine glp_read_lp returns
+* zero. Otherwise, it prints an error message and returns non-zero. */
+
+struct csa
+{ /* common storage area */
+ glp_prob *P;
+ /* LP/MIP problem object */
+ const glp_cpxcp *parm;
+ /* pointer to control parameters */
+ const char *fname;
+ /* name of input CPLEX LP file */
+ glp_file *fp;
+ /* stream assigned to input CPLEX LP file */
+ jmp_buf jump;
+ /* label for go to in case of error */
+ int count;
+ /* line count */
+ int c;
+ /* current character or EOF */
+ int token;
+ /* current token: */
+#define T_EOF 0x00 /* end of file */
+#define T_MINIMIZE 0x01 /* keyword 'minimize' */
+#define T_MAXIMIZE 0x02 /* keyword 'maximize' */
+#define T_SUBJECT_TO 0x03 /* keyword 'subject to' */
+#define T_BOUNDS 0x04 /* keyword 'bounds' */
+#define T_GENERAL 0x05 /* keyword 'general' */
+#define T_INTEGER 0x06 /* keyword 'integer' */
+#define T_BINARY 0x07 /* keyword 'binary' */
+#define T_END 0x08 /* keyword 'end' */
+#define T_NAME 0x09 /* symbolic name */
+#define T_NUMBER 0x0A /* numeric constant */
+#define T_PLUS 0x0B /* delimiter '+' */
+#define T_MINUS 0x0C /* delimiter '-' */
+#define T_COLON 0x0D /* delimiter ':' */
+#define T_LE 0x0E /* delimiter '<=' */
+#define T_GE 0x0F /* delimiter '>=' */
+#define T_EQ 0x10 /* delimiter '=' */
+ char image[255+1];
+ /* image of current token */
+ int imlen;
+ /* length of token image */
+ double value;
+ /* value of numeric constant */
+ int n_max;
+ /* length of the following five arrays (enlarged automatically,
+ if necessary) */
+ int *ind; /* int ind[1+n_max]; */
+ double *val; /* double val[1+n_max]; */
+ char *flag; /* char flag[1+n_max]; */
+ /* working arrays used to construct linear forms */
+ double *lb; /* double lb[1+n_max]; */
+ double *ub; /* double ub[1+n_max]; */
+ /* lower and upper bounds of variables (columns) */
+#if 1 /* 27/VII-2013 */
+ int lb_warn, ub_warn;
+ /* warning 'lower/upper bound redefined' already issued */
+#endif
+};
+
+#define CHAR_SET "!\"#$%&()/,.;?@_`'{}|~"
+/* characters that may appear in symbolic names */
+
+static void error(struct csa *csa, const char *fmt, ...)
+{ /* print error message and terminate processing */
+ va_list arg;
+ xprintf("%s:%d: ", csa->fname, csa->count);
+ va_start(arg, fmt);
+ xvprintf(fmt, arg);
+ va_end(arg);
+ longjmp(csa->jump, 1);
+ /* no return */
+}
+
+static void warning(struct csa *csa, const char *fmt, ...)
+{ /* print warning message and continue processing */
+ va_list arg;
+ xprintf("%s:%d: warning: ", csa->fname, csa->count);
+ va_start(arg, fmt);
+ xvprintf(fmt, arg);
+ va_end(arg);
+ return;
+}
+
+static void read_char(struct csa *csa)
+{ /* read next character from input file */
+ int c;
+ xassert(csa->c != EOF);
+ if (csa->c == '\n') csa->count++;
+ c = glp_getc(csa->fp);
+ if (c < 0)
+ { if (glp_ioerr(csa->fp))
+ error(csa, "read error - %s\n", get_err_msg());
+ else if (csa->c == '\n')
+ { csa->count--;
+ c = EOF;
+ }
+ else
+ { warning(csa, "missing final end of line\n");
+ c = '\n';
+ }
+ }
+ else if (c == '\n')
+ ;
+ else if (isspace(c))
+ c = ' ';
+ else if (iscntrl(c))
+ error(csa, "invalid control character 0x%02X\n", c);
+ csa->c = c;
+ return;
+}
+
+static void add_char(struct csa *csa)
+{ /* append current character to current token */
+ if (csa->imlen == sizeof(csa->image)-1)
+ error(csa, "token '%.15s...' too long\n", csa->image);
+ csa->image[csa->imlen++] = (char)csa->c;
+ csa->image[csa->imlen] = '\0';
+ read_char(csa);
+ return;
+}
+
+static int the_same(char *s1, char *s2)
+{ /* compare two character strings ignoring case sensitivity */
+ for (; *s1 != '\0'; s1++, s2++)
+ { if (tolower((unsigned char)*s1) != tolower((unsigned char)*s2))
+ return 0;
+ }
+ return 1;
+}
+
+static void scan_token(struct csa *csa)
+{ /* scan next token */
+ int flag;
+ csa->token = -1;
+ csa->image[0] = '\0';
+ csa->imlen = 0;
+ csa->value = 0.0;
+loop: flag = 0;
+ /* skip non-significant characters */
+ while (csa->c == ' ') read_char(csa);
+ /* recognize and scan current token */
+ if (csa->c == EOF)
+ csa->token = T_EOF;
+ else if (csa->c == '\n')
+ { read_char(csa);
+ /* if the next character is letter, it may begin a keyword */
+ if (isalpha(csa->c))
+ { flag = 1;
+ goto name;
+ }
+ goto loop;
+ }
+ else if (csa->c == '\\')
+ { /* comment; ignore everything until end-of-line */
+ while (csa->c != '\n') read_char(csa);
+ goto loop;
+ }
+ else if (isalpha(csa->c) || csa->c != '.' && strchr(CHAR_SET,
+ csa->c) != NULL)
+name: { /* symbolic name */
+ csa->token = T_NAME;
+ while (isalnum(csa->c) || strchr(CHAR_SET, csa->c) != NULL)
+ add_char(csa);
+ if (flag)
+ { /* check for keyword */
+ if (the_same(csa->image, "minimize"))
+ csa->token = T_MINIMIZE;
+ else if (the_same(csa->image, "minimum"))
+ csa->token = T_MINIMIZE;
+ else if (the_same(csa->image, "min"))
+ csa->token = T_MINIMIZE;
+ else if (the_same(csa->image, "maximize"))
+ csa->token = T_MAXIMIZE;
+ else if (the_same(csa->image, "maximum"))
+ csa->token = T_MAXIMIZE;
+ else if (the_same(csa->image, "max"))
+ csa->token = T_MAXIMIZE;
+ else if (the_same(csa->image, "subject"))
+ { if (csa->c == ' ')
+ { read_char(csa);
+ if (tolower(csa->c) == 't')
+ { csa->token = T_SUBJECT_TO;
+ csa->image[csa->imlen++] = ' ';
+ csa->image[csa->imlen] = '\0';
+ add_char(csa);
+ if (tolower(csa->c) != 'o')
+ error(csa, "keyword 'subject to' incomplete\n");
+ add_char(csa);
+ if (isalpha(csa->c))
+ error(csa, "keyword '%s%c...' not recognized\n",
+ csa->image, csa->c);
+ }
+ }
+ }
+ else if (the_same(csa->image, "such"))
+ { if (csa->c == ' ')
+ { read_char(csa);
+ if (tolower(csa->c) == 't')
+ { csa->token = T_SUBJECT_TO;
+ csa->image[csa->imlen++] = ' ';
+ csa->image[csa->imlen] = '\0';
+ add_char(csa);
+ if (tolower(csa->c) != 'h')
+err: error(csa, "keyword 'such that' incomplete\n");
+ add_char(csa);
+ if (tolower(csa->c) != 'a') goto err;
+ add_char(csa);
+ if (tolower(csa->c) != 't') goto err;
+ add_char(csa);
+ if (isalpha(csa->c))
+ error(csa, "keyword '%s%c...' not recognized\n",
+ csa->image, csa->c);
+ }
+ }
+ }
+ else if (the_same(csa->image, "st"))
+ csa->token = T_SUBJECT_TO;
+ else if (the_same(csa->image, "s.t."))
+ csa->token = T_SUBJECT_TO;
+ else if (the_same(csa->image, "st."))
+ csa->token = T_SUBJECT_TO;
+ else if (the_same(csa->image, "bounds"))
+ csa->token = T_BOUNDS;
+ else if (the_same(csa->image, "bound"))
+ csa->token = T_BOUNDS;
+ else if (the_same(csa->image, "general"))
+ csa->token = T_GENERAL;
+ else if (the_same(csa->image, "generals"))
+ csa->token = T_GENERAL;
+ else if (the_same(csa->image, "gen"))
+ csa->token = T_GENERAL;
+ else if (the_same(csa->image, "integer"))
+ csa->token = T_INTEGER;
+ else if (the_same(csa->image, "integers"))
+ csa->token = T_INTEGER;
+ else if (the_same(csa->image, "int"))
+ csa->token = T_INTEGER;
+ else if (the_same(csa->image, "binary"))
+ csa->token = T_BINARY;
+ else if (the_same(csa->image, "binaries"))
+ csa->token = T_BINARY;
+ else if (the_same(csa->image, "bin"))
+ csa->token = T_BINARY;
+ else if (the_same(csa->image, "end"))
+ csa->token = T_END;
+ }
+ }
+ else if (isdigit(csa->c) || csa->c == '.')
+ { /* numeric constant */
+ csa->token = T_NUMBER;
+ /* scan integer part */
+ while (isdigit(csa->c)) add_char(csa);
+ /* scan optional fractional part (it is mandatory, if there is
+ no integer part) */
+ if (csa->c == '.')
+ { add_char(csa);
+ if (csa->imlen == 1 && !isdigit(csa->c))
+ error(csa, "invalid use of decimal point\n");
+ while (isdigit(csa->c)) add_char(csa);
+ }
+ /* scan optional decimal exponent */
+ if (csa->c == 'e' || csa->c == 'E')
+ { add_char(csa);
+ if (csa->c == '+' || csa->c == '-') add_char(csa);
+ if (!isdigit(csa->c))
+ error(csa, "numeric constant '%s' incomplete\n",
+ csa->image);
+ while (isdigit(csa->c)) add_char(csa);
+ }
+ /* convert the numeric constant to floating-point */
+ if (str2num(csa->image, &csa->value))
+ error(csa, "numeric constant '%s' out of range\n",
+ csa->image);
+ }
+ else if (csa->c == '+')
+ csa->token = T_PLUS, add_char(csa);
+ else if (csa->c == '-')
+ csa->token = T_MINUS, add_char(csa);
+ else if (csa->c == ':')
+ csa->token = T_COLON, add_char(csa);
+ else if (csa->c == '<')
+ { csa->token = T_LE, add_char(csa);
+ if (csa->c == '=') add_char(csa);
+ }
+ else if (csa->c == '>')
+ { csa->token = T_GE, add_char(csa);
+ if (csa->c == '=') add_char(csa);
+ }
+ else if (csa->c == '=')
+ { csa->token = T_EQ, add_char(csa);
+ if (csa->c == '<')
+ csa->token = T_LE, add_char(csa);
+ else if (csa->c == '>')
+ csa->token = T_GE, add_char(csa);
+ }
+ else
+ error(csa, "character '%c' not recognized\n", csa->c);
+ /* skip non-significant characters */
+ while (csa->c == ' ') read_char(csa);
+ return;
+}
+
+static int find_col(struct csa *csa, char *name)
+{ /* find column by its symbolic name */
+ int j;
+ j = glp_find_col(csa->P, name);
+ if (j == 0)
+ { /* not found; create new column */
+ j = glp_add_cols(csa->P, 1);
+ glp_set_col_name(csa->P, j, name);
+ /* enlarge working arrays, if necessary */
+ if (csa->n_max < j)
+ { int n_max = csa->n_max;
+ int *ind = csa->ind;
+ double *val = csa->val;
+ char *flag = csa->flag;
+ double *lb = csa->lb;
+ double *ub = csa->ub;
+ csa->n_max += csa->n_max;
+ csa->ind = xcalloc(1+csa->n_max, sizeof(int));
+ memcpy(&csa->ind[1], &ind[1], n_max * sizeof(int));
+ xfree(ind);
+ csa->val = xcalloc(1+csa->n_max, sizeof(double));
+ memcpy(&csa->val[1], &val[1], n_max * sizeof(double));
+ xfree(val);
+ csa->flag = xcalloc(1+csa->n_max, sizeof(char));
+ memset(&csa->flag[1], 0, csa->n_max * sizeof(char));
+ memcpy(&csa->flag[1], &flag[1], n_max * sizeof(char));
+ xfree(flag);
+ csa->lb = xcalloc(1+csa->n_max, sizeof(double));
+ memcpy(&csa->lb[1], &lb[1], n_max * sizeof(double));
+ xfree(lb);
+ csa->ub = xcalloc(1+csa->n_max, sizeof(double));
+ memcpy(&csa->ub[1], &ub[1], n_max * sizeof(double));
+ xfree(ub);
+ }
+ csa->lb[j] = +DBL_MAX, csa->ub[j] = -DBL_MAX;
+ }
+ return j;
+}
+
+/***********************************************************************
+* parse_linear_form - parse linear form
+*
+* This routine parses the linear form using the following syntax:
+*
+* <variable> ::= <symbolic name>
+* <coefficient> ::= <numeric constant>
+* <term> ::= <variable> | <numeric constant> <variable>
+* <linear form> ::= <term> | + <term> | - <term> |
+* <linear form> + <term> | <linear form> - <term>
+*
+* The routine returns the number of terms in the linear form. */
+
+static int parse_linear_form(struct csa *csa)
+{ int j, k, len = 0, newlen;
+ double s, coef;
+loop: /* parse an optional sign */
+ if (csa->token == T_PLUS)
+ s = +1.0, scan_token(csa);
+ else if (csa->token == T_MINUS)
+ s = -1.0, scan_token(csa);
+ else
+ s = +1.0;
+ /* parse an optional coefficient */
+ if (csa->token == T_NUMBER)
+ coef = csa->value, scan_token(csa);
+ else
+ coef = 1.0;
+ /* parse a variable name */
+ if (csa->token != T_NAME)
+ error(csa, "missing variable name\n");
+ /* find the corresponding column */
+ j = find_col(csa, csa->image);
+ /* check if the variable is already used in the linear form */
+ if (csa->flag[j])
+ error(csa, "multiple use of variable '%s' not allowed\n",
+ csa->image);
+ /* add new term to the linear form */
+ len++, csa->ind[len] = j, csa->val[len] = s * coef;
+ /* and mark that the variable is used in the linear form */
+ csa->flag[j] = 1;
+ scan_token(csa);
+ /* if the next token is a sign, there is another term */
+ if (csa->token == T_PLUS || csa->token == T_MINUS) goto loop;
+ /* clear marks of the variables used in the linear form */
+ for (k = 1; k <= len; k++) csa->flag[csa->ind[k]] = 0;
+ /* remove zero coefficients */
+ newlen = 0;
+ for (k = 1; k <= len; k++)
+ { if (csa->val[k] != 0.0)
+ { newlen++;
+ csa->ind[newlen] = csa->ind[k];
+ csa->val[newlen] = csa->val[k];
+ }
+ }
+ return newlen;
+}
+
+/***********************************************************************
+* parse_objective - parse objective function
+*
+* This routine parses definition of the objective function using the
+* following syntax:
+*
+* <obj sense> ::= minimize | minimum | min | maximize | maximum | max
+* <obj name> ::= <empty> | <symbolic name> :
+* <obj function> ::= <obj sense> <obj name> <linear form> */
+
+static void parse_objective(struct csa *csa)
+{ /* parse objective sense */
+ int k, len;
+ /* parse the keyword 'minimize' or 'maximize' */
+ if (csa->token == T_MINIMIZE)
+ glp_set_obj_dir(csa->P, GLP_MIN);
+ else if (csa->token == T_MAXIMIZE)
+ glp_set_obj_dir(csa->P, GLP_MAX);
+ else
+ xassert(csa != csa);
+ scan_token(csa);
+ /* parse objective name */
+ if (csa->token == T_NAME && csa->c == ':')
+ { /* objective name is followed by a colon */
+ glp_set_obj_name(csa->P, csa->image);
+ scan_token(csa);
+ xassert(csa->token == T_COLON);
+ scan_token(csa);
+ }
+ else
+ { /* objective name is not specified; use default */
+ glp_set_obj_name(csa->P, "obj");
+ }
+ /* parse linear form */
+ len = parse_linear_form(csa);
+ for (k = 1; k <= len; k++)
+ glp_set_obj_coef(csa->P, csa->ind[k], csa->val[k]);
+ return;
+}
+
+/***********************************************************************
+* parse_constraints - parse constraints section
+*
+* This routine parses the constraints section using the following
+* syntax:
+*
+* <row name> ::= <empty> | <symbolic name> :
+* <row sense> ::= < | <= | =< | > | >= | => | =
+* <right-hand side> ::= <numeric constant> | + <numeric constant> |
+* - <numeric constant>
+* <constraint> ::= <row name> <linear form> <row sense>
+* <right-hand side>
+* <subject to> ::= subject to | such that | st | s.t. | st.
+* <constraints section> ::= <subject to> <constraint> |
+* <constraints section> <constraint> */
+
+static void parse_constraints(struct csa *csa)
+{ int i, len, type;
+ double s;
+ /* parse the keyword 'subject to' */
+ xassert(csa->token == T_SUBJECT_TO);
+ scan_token(csa);
+loop: /* create new row (constraint) */
+ i = glp_add_rows(csa->P, 1);
+ /* parse row name */
+ if (csa->token == T_NAME && csa->c == ':')
+ { /* row name is followed by a colon */
+ if (glp_find_row(csa->P, csa->image) != 0)
+ error(csa, "constraint '%s' multiply defined\n",
+ csa->image);
+ glp_set_row_name(csa->P, i, csa->image);
+ scan_token(csa);
+ xassert(csa->token == T_COLON);
+ scan_token(csa);
+ }
+ else
+ { /* row name is not specified; use default */
+ char name[50];
+ sprintf(name, "r.%d", csa->count);
+ glp_set_row_name(csa->P, i, name);
+ }
+ /* parse linear form */
+ len = parse_linear_form(csa);
+ glp_set_mat_row(csa->P, i, len, csa->ind, csa->val);
+ /* parse constraint sense */
+ if (csa->token == T_LE)
+ type = GLP_UP, scan_token(csa);
+ else if (csa->token == T_GE)
+ type = GLP_LO, scan_token(csa);
+ else if (csa->token == T_EQ)
+ type = GLP_FX, scan_token(csa);
+ else
+ error(csa, "missing constraint sense\n");
+ /* parse right-hand side */
+ if (csa->token == T_PLUS)
+ s = +1.0, scan_token(csa);
+ else if (csa->token == T_MINUS)
+ s = -1.0, scan_token(csa);
+ else
+ s = +1.0;
+ if (csa->token != T_NUMBER)
+ error(csa, "missing right-hand side\n");
+ glp_set_row_bnds(csa->P, i, type, s * csa->value, s * csa->value);
+ /* the rest of the current line must be empty */
+ if (!(csa->c == '\n' || csa->c == EOF))
+ error(csa, "invalid symbol(s) beyond right-hand side\n");
+ scan_token(csa);
+ /* if the next token is a sign, numeric constant, or a symbolic
+ name, here is another constraint */
+ if (csa->token == T_PLUS || csa->token == T_MINUS ||
+ csa->token == T_NUMBER || csa->token == T_NAME) goto loop;
+ return;
+}
+
+static void set_lower_bound(struct csa *csa, int j, double lb)
+{ /* set lower bound of j-th variable */
+ if (csa->lb[j] != +DBL_MAX && !csa->lb_warn)
+ { warning(csa, "lower bound of variable '%s' redefined\n",
+ glp_get_col_name(csa->P, j));
+ csa->lb_warn = 1;
+ }
+ csa->lb[j] = lb;
+ return;
+}
+
+static void set_upper_bound(struct csa *csa, int j, double ub)
+{ /* set upper bound of j-th variable */
+ if (csa->ub[j] != -DBL_MAX && !csa->ub_warn)
+ { warning(csa, "upper bound of variable '%s' redefined\n",
+ glp_get_col_name(csa->P, j));
+ csa->ub_warn = 1;
+ }
+ csa->ub[j] = ub;
+ return;
+}
+
+/***********************************************************************
+* parse_bounds - parse bounds section
+*
+* This routine parses the bounds section using the following syntax:
+*
+* <variable> ::= <symbolic name>
+* <infinity> ::= infinity | inf
+* <bound> ::= <numeric constant> | + <numeric constant> |
+* - <numeric constant> | + <infinity> | - <infinity>
+* <lt> ::= < | <= | =<
+* <gt> ::= > | >= | =>
+* <bound definition> ::= <bound> <lt> <variable> <lt> <bound> |
+* <bound> <lt> <variable> | <variable> <lt> <bound> |
+* <variable> <gt> <bound> | <variable> = <bound> | <variable> free
+* <bounds> ::= bounds | bound
+* <bounds section> ::= <bounds> |
+* <bounds section> <bound definition> */
+
+static void parse_bounds(struct csa *csa)
+{ int j, lb_flag;
+ double lb, s;
+ /* parse the keyword 'bounds' */
+ xassert(csa->token == T_BOUNDS);
+ scan_token(csa);
+loop: /* bound definition can start with a sign, numeric constant, or
+ a symbolic name */
+ if (!(csa->token == T_PLUS || csa->token == T_MINUS ||
+ csa->token == T_NUMBER || csa->token == T_NAME)) goto done;
+ /* parse bound definition */
+ if (csa->token == T_PLUS || csa->token == T_MINUS)
+ { /* parse signed lower bound */
+ lb_flag = 1;
+ s = (csa->token == T_PLUS ? +1.0 : -1.0);
+ scan_token(csa);
+ if (csa->token == T_NUMBER)
+ lb = s * csa->value, scan_token(csa);
+ else if (the_same(csa->image, "infinity") ||
+ the_same(csa->image, "inf"))
+ { if (s > 0.0)
+ error(csa, "invalid use of '+inf' as lower bound\n");
+ lb = -DBL_MAX, scan_token(csa);
+ }
+ else
+ error(csa, "missing lower bound\n");
+ }
+ else if (csa->token == T_NUMBER)
+ { /* parse unsigned lower bound */
+ lb_flag = 1;
+ lb = csa->value, scan_token(csa);
+ }
+ else
+ { /* lower bound is not specified */
+ lb_flag = 0;
+ }
+ /* parse the token that should follow the lower bound */
+ if (lb_flag)
+ { if (csa->token != T_LE)
+ error(csa, "missing '<', '<=', or '=<' after lower bound\n")
+ ;
+ scan_token(csa);
+ }
+ /* parse variable name */
+ if (csa->token != T_NAME)
+ error(csa, "missing variable name\n");
+ j = find_col(csa, csa->image);
+ /* set lower bound */
+ if (lb_flag) set_lower_bound(csa, j, lb);
+ scan_token(csa);
+ /* parse the context that follows the variable name */
+ if (csa->token == T_LE)
+ { /* parse upper bound */
+ scan_token(csa);
+ if (csa->token == T_PLUS || csa->token == T_MINUS)
+ { /* parse signed upper bound */
+ s = (csa->token == T_PLUS ? +1.0 : -1.0);
+ scan_token(csa);
+ if (csa->token == T_NUMBER)
+ { set_upper_bound(csa, j, s * csa->value);
+ scan_token(csa);
+ }
+ else if (the_same(csa->image, "infinity") ||
+ the_same(csa->image, "inf"))
+ { if (s < 0.0)
+ error(csa, "invalid use of '-inf' as upper bound\n");
+ set_upper_bound(csa, j, +DBL_MAX);
+ scan_token(csa);
+ }
+ else
+ error(csa, "missing upper bound\n");
+ }
+ else if (csa->token == T_NUMBER)
+ { /* parse unsigned upper bound */
+ set_upper_bound(csa, j, csa->value);
+ scan_token(csa);
+ }
+ else
+ error(csa, "missing upper bound\n");
+ }
+ else if (csa->token == T_GE)
+ { /* parse lower bound */
+ if (lb_flag)
+ { /* the context '... <= x >= ...' is invalid */
+ error(csa, "invalid bound definition\n");
+ }
+ scan_token(csa);
+ if (csa->token == T_PLUS || csa->token == T_MINUS)
+ { /* parse signed lower bound */
+ s = (csa->token == T_PLUS ? +1.0 : -1.0);
+ scan_token(csa);
+ if (csa->token == T_NUMBER)
+ { set_lower_bound(csa, j, s * csa->value);
+ scan_token(csa);
+ }
+ else if (the_same(csa->image, "infinity") ||
+ the_same(csa->image, "inf") == 0)
+ { if (s > 0.0)
+ error(csa, "invalid use of '+inf' as lower bound\n");
+ set_lower_bound(csa, j, -DBL_MAX);
+ scan_token(csa);
+ }
+ else
+ error(csa, "missing lower bound\n");
+ }
+ else if (csa->token == T_NUMBER)
+ { /* parse unsigned lower bound */
+ set_lower_bound(csa, j, csa->value);
+ scan_token(csa);
+ }
+ else
+ error(csa, "missing lower bound\n");
+ }
+ else if (csa->token == T_EQ)
+ { /* parse fixed value */
+ if (lb_flag)
+ { /* the context '... <= x = ...' is invalid */
+ error(csa, "invalid bound definition\n");
+ }
+ scan_token(csa);
+ if (csa->token == T_PLUS || csa->token == T_MINUS)
+ { /* parse signed fixed value */
+ s = (csa->token == T_PLUS ? +1.0 : -1.0);
+ scan_token(csa);
+ if (csa->token == T_NUMBER)
+ { set_lower_bound(csa, j, s * csa->value);
+ set_upper_bound(csa, j, s * csa->value);
+ scan_token(csa);
+ }
+ else
+ error(csa, "missing fixed value\n");
+ }
+ else if (csa->token == T_NUMBER)
+ { /* parse unsigned fixed value */
+ set_lower_bound(csa, j, csa->value);
+ set_upper_bound(csa, j, csa->value);
+ scan_token(csa);
+ }
+ else
+ error(csa, "missing fixed value\n");
+ }
+ else if (the_same(csa->image, "free"))
+ { /* parse the keyword 'free' */
+ if (lb_flag)
+ { /* the context '... <= x free ...' is invalid */
+ error(csa, "invalid bound definition\n");
+ }
+ set_lower_bound(csa, j, -DBL_MAX);
+ set_upper_bound(csa, j, +DBL_MAX);
+ scan_token(csa);
+ }
+ else if (!lb_flag)
+ { /* neither lower nor upper bounds are specified */
+ error(csa, "invalid bound definition\n");
+ }
+ goto loop;
+done: return;
+}
+
+/***********************************************************************
+* parse_integer - parse general, integer, or binary section
+*
+* <variable> ::= <symbolic name>
+* <general> ::= general | generals | gen
+* <integer> ::= integer | integers | int
+* <binary> ::= binary | binaries | bin
+* <section head> ::= <general> <integer> <binary>
+* <additional section> ::= <section head> |
+* <additional section> <variable> */
+
+static void parse_integer(struct csa *csa)
+{ int j, binary;
+ /* parse the keyword 'general', 'integer', or 'binary' */
+ if (csa->token == T_GENERAL)
+ binary = 0, scan_token(csa);
+ else if (csa->token == T_INTEGER)
+ binary = 0, scan_token(csa);
+ else if (csa->token == T_BINARY)
+ binary = 1, scan_token(csa);
+ else
+ xassert(csa != csa);
+ /* parse list of variables (may be empty) */
+ while (csa->token == T_NAME)
+ { /* find the corresponding column */
+ j = find_col(csa, csa->image);
+ /* change kind of the variable */
+ glp_set_col_kind(csa->P, j, GLP_IV);
+ /* set bounds for the binary variable */
+ if (binary)
+#if 0 /* 07/VIII-2013 */
+ { set_lower_bound(csa, j, 0.0);
+ set_upper_bound(csa, j, 1.0);
+ }
+#else
+ { set_lower_bound(csa, j,
+ csa->lb[j] == +DBL_MAX ? 0.0 : csa->lb[j]);
+ set_upper_bound(csa, j,
+ csa->ub[j] == -DBL_MAX ? 1.0 : csa->ub[j]);
+ }
+#endif
+ scan_token(csa);
+ }
+ return;
+}
+
+int glp_read_lp(glp_prob *P, const glp_cpxcp *parm, const char *fname)
+{ /* read problem data in CPLEX LP format */
+ glp_cpxcp _parm;
+ struct csa _csa, *csa = &_csa;
+ int ret;
+ xprintf("Reading problem data from '%s'...\n", fname);
+ if (parm == NULL)
+ glp_init_cpxcp(&_parm), parm = &_parm;
+ /* check control parameters */
+ check_parm("glp_read_lp", parm);
+ /* initialize common storage area */
+ csa->P = P;
+ csa->parm = parm;
+ csa->fname = fname;
+ csa->fp = NULL;
+ if (setjmp(csa->jump))
+ { ret = 1;
+ goto done;
+ }
+ csa->count = 0;
+ csa->c = '\n';
+ csa->token = T_EOF;
+ csa->image[0] = '\0';
+ csa->imlen = 0;
+ csa->value = 0.0;
+ csa->n_max = 100;
+ csa->ind = xcalloc(1+csa->n_max, sizeof(int));
+ csa->val = xcalloc(1+csa->n_max, sizeof(double));
+ csa->flag = xcalloc(1+csa->n_max, sizeof(char));
+ memset(&csa->flag[1], 0, csa->n_max * sizeof(char));
+ csa->lb = xcalloc(1+csa->n_max, sizeof(double));
+ csa->ub = xcalloc(1+csa->n_max, sizeof(double));
+#if 1 /* 27/VII-2013 */
+ csa->lb_warn = csa->ub_warn = 0;
+#endif
+ /* erase problem object */
+ glp_erase_prob(P);
+ glp_create_index(P);
+ /* open input CPLEX LP file */
+ csa->fp = glp_open(fname, "r");
+ if (csa->fp == NULL)
+ { xprintf("Unable to open '%s' - %s\n", fname, get_err_msg());
+ ret = 1;
+ goto done;
+ }
+ /* scan very first token */
+ scan_token(csa);
+ /* parse definition of the objective function */
+ if (!(csa->token == T_MINIMIZE || csa->token == T_MAXIMIZE))
+ error(csa, "'minimize' or 'maximize' keyword missing\n");
+ parse_objective(csa);
+ /* parse constraints section */
+ if (csa->token != T_SUBJECT_TO)
+ error(csa, "constraints section missing\n");
+ parse_constraints(csa);
+ /* parse optional bounds section */
+ if (csa->token == T_BOUNDS) parse_bounds(csa);
+ /* parse optional general, integer, and binary sections */
+ while (csa->token == T_GENERAL ||
+ csa->token == T_INTEGER ||
+ csa->token == T_BINARY) parse_integer(csa);
+ /* check for the keyword 'end' */
+ if (csa->token == T_END)
+ scan_token(csa);
+ else if (csa->token == T_EOF)
+ warning(csa, "keyword 'end' missing\n");
+ else
+ error(csa, "symbol '%s' in wrong position\n", csa->image);
+ /* nothing must follow the keyword 'end' (except comments) */
+ if (csa->token != T_EOF)
+ error(csa, "extra symbol(s) detected beyond 'end'\n");
+ /* set bounds of variables */
+ { int j, type;
+ double lb, ub;
+ for (j = 1; j <= P->n; j++)
+ { lb = csa->lb[j];
+ ub = csa->ub[j];
+ if (lb == +DBL_MAX) lb = 0.0; /* default lb */
+ if (ub == -DBL_MAX) ub = +DBL_MAX; /* default ub */
+ if (lb == -DBL_MAX && ub == +DBL_MAX)
+ type = GLP_FR;
+ else if (ub == +DBL_MAX)
+ type = GLP_LO;
+ else if (lb == -DBL_MAX)
+ type = GLP_UP;
+ else if (lb != ub)
+ type = GLP_DB;
+ else
+ type = GLP_FX;
+ glp_set_col_bnds(csa->P, j, type, lb, ub);
+ }
+ }
+ /* print some statistics */
+ xprintf("%d row%s, %d column%s, %d non-zero%s\n",
+ P->m, P->m == 1 ? "" : "s", P->n, P->n == 1 ? "" : "s",
+ P->nnz, P->nnz == 1 ? "" : "s");
+ if (glp_get_num_int(P) > 0)
+ { int ni = glp_get_num_int(P);
+ int nb = glp_get_num_bin(P);
+ if (ni == 1)
+ { if (nb == 0)
+ xprintf("One variable is integer\n");
+ else
+ xprintf("One variable is binary\n");
+ }
+ else
+ { xprintf("%d integer variables, ", ni);
+ if (nb == 0)
+ xprintf("none");
+ else if (nb == 1)
+ xprintf("one");
+ else if (nb == ni)
+ xprintf("all");
+ else
+ xprintf("%d", nb);
+ xprintf(" of which %s binary\n", nb == 1 ? "is" : "are");
+ }
+ }
+ xprintf("%d lines were read\n", csa->count);
+ /* problem data has been successfully read */
+ glp_delete_index(P);
+ glp_sort_matrix(P);
+ ret = 0;
+done: if (csa->fp != NULL) glp_close(csa->fp);
+ xfree(csa->ind);
+ xfree(csa->val);
+ xfree(csa->flag);
+ xfree(csa->lb);
+ xfree(csa->ub);
+ if (ret != 0) glp_erase_prob(P);
+ return ret;
+}
+
+/***********************************************************************
+* NAME
+*
+* glp_write_lp - write problem data in CPLEX LP format
+*
+* SYNOPSIS
+*
+* int glp_write_lp(glp_prob *P, const glp_cpxcp *parm, const char
+* *fname);
+*
+* DESCRIPTION
+*
+* The routine glp_write_lp writes problem data in CPLEX LP format to
+* a text file.
+*
+* The parameter parm is a pointer to the structure glp_cpxcp, which
+* specifies control parameters used by the routine. If parm is NULL,
+* the routine uses default settings.
+*
+* The character string fname specifies a name of the text file to be
+* written.
+*
+* RETURNS
+*
+* If the operation was successful, the routine glp_write_lp returns
+* zero. Otherwise, it prints an error message and returns non-zero. */
+
+#define csa csa1
+
+struct csa
+{ /* common storage area */
+ glp_prob *P;
+ /* pointer to problem object */
+ const glp_cpxcp *parm;
+ /* pointer to control parameters */
+};
+
+static int check_name(char *name)
+{ /* check if specified name is valid for CPLEX LP format */
+ if (*name == '.') return 1;
+ if (isdigit((unsigned char)*name)) return 1;
+ for (; *name; name++)
+ { if (!isalnum((unsigned char)*name) &&
+ strchr(CHAR_SET, (unsigned char)*name) == NULL) return 1;
+ }
+ return 0; /* name is ok */
+}
+
+static void adjust_name(char *name)
+{ /* attempt to adjust specified name to make it valid for CPLEX LP
+ format */
+ for (; *name; name++)
+ { if (*name == ' ')
+ *name = '_';
+ else if (*name == '-')
+ *name = '~';
+ else if (*name == '[')
+ *name = '(';
+ else if (*name == ']')
+ *name = ')';
+ }
+ return;
+}
+
+static char *row_name(struct csa *csa, int i, char rname[255+1])
+{ /* construct symbolic name of i-th row (constraint) */
+ const char *name;
+ if (i == 0)
+ name = glp_get_obj_name(csa->P);
+ else
+ name = glp_get_row_name(csa->P, i);
+ if (name == NULL) goto fake;
+ strcpy(rname, name);
+ adjust_name(rname);
+ if (check_name(rname)) goto fake;
+ return rname;
+fake: if (i == 0)
+ strcpy(rname, "obj");
+ else
+ sprintf(rname, "r_%d", i);
+ return rname;
+}
+
+static char *col_name(struct csa *csa, int j, char cname[255+1])
+{ /* construct symbolic name of j-th column (variable) */
+ const char *name;
+ name = glp_get_col_name(csa->P, j);
+ if (name == NULL) goto fake;
+ strcpy(cname, name);
+ adjust_name(cname);
+ if (check_name(cname)) goto fake;
+ return cname;
+#if 0 /* 18/I-2018 */
+fake: sprintf(cname, "x_%d", j);
+#else
+fake: /* construct fake name depending on column's attributes */
+ { GLPCOL *col = csa->P->col[j];
+ if (col->type == GLP_FX)
+ { /* fixed column */
+ sprintf(cname, "s_%d", j);
+ }
+ else if (col->kind == GLP_CV)
+ { /* continuous variable */
+ sprintf(cname, "x_%d", j);
+ }
+ else if (!(col->lb == 0 && col->ub == 1))
+ { /* general (non-binary) integer variable */
+ sprintf(cname, "y_%d", j);
+ }
+ else
+ { /* binary variable */
+ sprintf(cname, "z_%d", j);
+ }
+ }
+#endif
+ return cname;
+}
+
+int glp_write_lp(glp_prob *P, const glp_cpxcp *parm, const char *fname)
+{ /* write problem data in CPLEX LP format */
+ glp_cpxcp _parm;
+ struct csa _csa, *csa = &_csa;
+ glp_file *fp;
+ GLPROW *row;
+ GLPCOL *col;
+ GLPAIJ *aij;
+ int i, j, len, flag, count, ret;
+ char line[1000+1], term[500+1], name[255+1];
+ xprintf("Writing problem data to '%s'...\n", fname);
+ if (parm == NULL)
+ glp_init_cpxcp(&_parm), parm = &_parm;
+ /* check control parameters */
+ check_parm("glp_write_lp", parm);
+ /* initialize common storage area */
+ csa->P = P;
+ csa->parm = parm;
+ /* create output CPLEX LP file */
+ fp = glp_open(fname, "w"), count = 0;
+ if (fp == NULL)
+ { xprintf("Unable to create '%s' - %s\n", fname, get_err_msg());
+ ret = 1;
+ goto done;
+ }
+ /* write problem name */
+ xfprintf(fp, "\\* Problem: %s *\\\n",
+ P->name == NULL ? "Unknown" : P->name), count++;
+ xfprintf(fp, "\n"), count++;
+ /* the problem should contain at least one row and one column */
+ if (!(P->m > 0 && P->n > 0))
+ { xprintf("Warning: problem has no rows/columns\n");
+ xfprintf(fp, "\\* WARNING: PROBLEM HAS NO ROWS/COLUMNS *\\\n"),
+ count++;
+ xfprintf(fp, "\n"), count++;
+ goto skip;
+ }
+ /* write the objective function definition */
+ if (P->dir == GLP_MIN)
+ xfprintf(fp, "Minimize\n"), count++;
+ else if (P->dir == GLP_MAX)
+ xfprintf(fp, "Maximize\n"), count++;
+ else
+ xassert(P != P);
+ row_name(csa, 0, name);
+ sprintf(line, " %s:", name);
+ len = 0;
+ for (j = 1; j <= P->n; j++)
+ { col = P->col[j];
+ if (col->coef != 0.0 || col->ptr == NULL)
+ { len++;
+ col_name(csa, j, name);
+ if (col->coef == 0.0)
+ sprintf(term, " + 0 %s", name); /* empty column */
+ else if (col->coef == +1.0)
+ sprintf(term, " + %s", name);
+ else if (col->coef == -1.0)
+ sprintf(term, " - %s", name);
+ else if (col->coef > 0.0)
+ sprintf(term, " + %.*g %s", DBL_DIG, +col->coef, name);
+ else
+ sprintf(term, " - %.*g %s", DBL_DIG, -col->coef, name);
+ if (strlen(line) + strlen(term) > 72)
+ xfprintf(fp, "%s\n", line), line[0] = '\0', count++;
+ strcat(line, term);
+ }
+ }
+ if (len == 0)
+ { /* empty objective */
+ sprintf(term, " 0 %s", col_name(csa, 1, name));
+ strcat(line, term);
+ }
+ xfprintf(fp, "%s\n", line), count++;
+ if (P->c0 != 0.0)
+ xfprintf(fp, "\\* constant term = %.*g *\\\n", DBL_DIG, P->c0),
+ count++;
+ xfprintf(fp, "\n"), count++;
+ /* write the constraints section */
+ xfprintf(fp, "Subject To\n"), count++;
+ for (i = 1; i <= P->m; i++)
+ { row = P->row[i];
+ if (row->type == GLP_FR) continue; /* skip free row */
+ row_name(csa, i, name);
+ sprintf(line, " %s:", name);
+ /* linear form */
+ for (aij = row->ptr; aij != NULL; aij = aij->r_next)
+ { col_name(csa, aij->col->j, name);
+ if (aij->val == +1.0)
+ sprintf(term, " + %s", name);
+ else if (aij->val == -1.0)
+ sprintf(term, " - %s", name);
+ else if (aij->val > 0.0)
+ sprintf(term, " + %.*g %s", DBL_DIG, +aij->val, name);
+ else
+ sprintf(term, " - %.*g %s", DBL_DIG, -aij->val, name);
+ if (strlen(line) + strlen(term) > 72)
+ xfprintf(fp, "%s\n", line), line[0] = '\0', count++;
+ strcat(line, term);
+ }
+ if (row->type == GLP_DB)
+ { /* double-bounded (ranged) constraint */
+ sprintf(term, " - ~r_%d", i);
+ if (strlen(line) + strlen(term) > 72)
+ xfprintf(fp, "%s\n", line), line[0] = '\0', count++;
+ strcat(line, term);
+ }
+ else if (row->ptr == NULL)
+ { /* empty constraint */
+ sprintf(term, " 0 %s", col_name(csa, 1, name));
+ strcat(line, term);
+ }
+ /* right hand-side */
+ if (row->type == GLP_LO)
+ sprintf(term, " >= %.*g", DBL_DIG, row->lb);
+ else if (row->type == GLP_UP)
+ sprintf(term, " <= %.*g", DBL_DIG, row->ub);
+ else if (row->type == GLP_DB || row->type == GLP_FX)
+ sprintf(term, " = %.*g", DBL_DIG, row->lb);
+ else
+ xassert(row != row);
+ if (strlen(line) + strlen(term) > 72)
+ xfprintf(fp, "%s\n", line), line[0] = '\0', count++;
+ strcat(line, term);
+ xfprintf(fp, "%s\n", line), count++;
+ }
+ xfprintf(fp, "\n"), count++;
+ /* write the bounds section */
+ flag = 0;
+ for (i = 1; i <= P->m; i++)
+ { row = P->row[i];
+ if (row->type != GLP_DB) continue;
+ if (!flag)
+ xfprintf(fp, "Bounds\n"), flag = 1, count++;
+ xfprintf(fp, " 0 <= ~r_%d <= %.*g\n",
+ i, DBL_DIG, row->ub - row->lb), count++;
+ }
+ for (j = 1; j <= P->n; j++)
+ { col = P->col[j];
+ if (col->type == GLP_LO && col->lb == 0.0) continue;
+ if (!flag)
+ xfprintf(fp, "Bounds\n"), flag = 1, count++;
+ col_name(csa, j, name);
+ if (col->type == GLP_FR)
+ xfprintf(fp, " %s free\n", name), count++;
+ else if (col->type == GLP_LO)
+ xfprintf(fp, " %s >= %.*g\n",
+ name, DBL_DIG, col->lb), count++;
+ else if (col->type == GLP_UP)
+ xfprintf(fp, " -Inf <= %s <= %.*g\n",
+ name, DBL_DIG, col->ub), count++;
+ else if (col->type == GLP_DB)
+ xfprintf(fp, " %.*g <= %s <= %.*g\n",
+ DBL_DIG, col->lb, name, DBL_DIG, col->ub), count++;
+ else if (col->type == GLP_FX)
+ xfprintf(fp, " %s = %.*g\n",
+ name, DBL_DIG, col->lb), count++;
+ else
+ xassert(col != col);
+ }
+ if (flag) xfprintf(fp, "\n"), count++;
+ /* write the integer section */
+ flag = 0;
+ for (j = 1; j <= P->n; j++)
+ { col = P->col[j];
+ if (col->kind == GLP_CV) continue;
+ xassert(col->kind == GLP_IV);
+ if (!flag)
+ xfprintf(fp, "Generals\n"), flag = 1, count++;
+ xfprintf(fp, " %s\n", col_name(csa, j, name)), count++;
+ }
+ if (flag) xfprintf(fp, "\n"), count++;
+skip: /* write the end keyword */
+ xfprintf(fp, "End\n"), count++;
+#if 0 /* FIXME */
+ xfflush(fp);
+#endif
+ if (glp_ioerr(fp))
+ { xprintf("Write error on '%s' - %s\n", fname, get_err_msg());
+ ret = 1;
+ goto done;
+ }
+ /* problem data has been successfully written */
+ xprintf("%d lines were written\n", count);
+ ret = 0;
+done: if (fp != NULL) glp_close(fp);
+ return ret;
+}
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/api/cpp.c b/test/monniaux/glpk-4.65/src/api/cpp.c
new file mode 100644
index 00000000..ac3d63ef
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/api/cpp.c
@@ -0,0 +1,185 @@
+/* cpp.c (solve critical path problem) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* Copyright (C) 2010-2016 Andrew Makhorin, Department for Applied
+* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights
+* reserved. E-mail: <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 "env.h"
+#include "glpk.h"
+
+/***********************************************************************
+* NAME
+*
+* glp_cpp - solve critical path problem
+*
+* SYNOPSIS
+*
+* double glp_cpp(glp_graph *G, int v_t, int v_es, int v_ls);
+*
+* DESCRIPTION
+*
+* The routine glp_cpp solves the critical path problem represented in
+* the form of the project network.
+*
+* The parameter G is a pointer to the graph object, which specifies
+* the project network. This graph must be acyclic. Multiple arcs are
+* allowed being considered as single arcs.
+*
+* The parameter v_t specifies an offset of the field of type double
+* in the vertex data block, which contains time t[i] >= 0 needed to
+* perform corresponding job j. If v_t < 0, it is assumed that t[i] = 1
+* for all jobs.
+*
+* The parameter v_es specifies an offset of the field of type double
+* in the vertex data block, to which the routine stores earliest start
+* time for corresponding job. If v_es < 0, this time is not stored.
+*
+* The parameter v_ls specifies an offset of the field of type double
+* in the vertex data block, to which the routine stores latest start
+* time for corresponding job. If v_ls < 0, this time is not stored.
+*
+* RETURNS
+*
+* The routine glp_cpp returns the minimal project duration, that is,
+* minimal time needed to perform all jobs in the project. */
+
+static void sorting(glp_graph *G, int list[]);
+
+double glp_cpp(glp_graph *G, int v_t, int v_es, int v_ls)
+{ glp_vertex *v;
+ glp_arc *a;
+ int i, j, k, nv, *list;
+ double temp, total, *t, *es, *ls;
+ if (v_t >= 0 && v_t > G->v_size - (int)sizeof(double))
+ xerror("glp_cpp: v_t = %d; invalid offset\n", v_t);
+ if (v_es >= 0 && v_es > G->v_size - (int)sizeof(double))
+ xerror("glp_cpp: v_es = %d; invalid offset\n", v_es);
+ if (v_ls >= 0 && v_ls > G->v_size - (int)sizeof(double))
+ xerror("glp_cpp: v_ls = %d; invalid offset\n", v_ls);
+ nv = G->nv;
+ if (nv == 0)
+ { total = 0.0;
+ goto done;
+ }
+ /* allocate working arrays */
+ t = xcalloc(1+nv, sizeof(double));
+ es = xcalloc(1+nv, sizeof(double));
+ ls = xcalloc(1+nv, sizeof(double));
+ list = xcalloc(1+nv, sizeof(int));
+ /* retrieve job times */
+ for (i = 1; i <= nv; i++)
+ { v = G->v[i];
+ if (v_t >= 0)
+ { memcpy(&t[i], (char *)v->data + v_t, sizeof(double));
+ if (t[i] < 0.0)
+ xerror("glp_cpp: t[%d] = %g; invalid time\n", i, t[i]);
+ }
+ else
+ t[i] = 1.0;
+ }
+ /* perform topological sorting to determine the list of nodes
+ (jobs) such that if list[k] = i and list[kk] = j and there
+ exists arc (i->j), then k < kk */
+ sorting(G, list);
+ /* FORWARD PASS */
+ /* determine earliest start times */
+ for (k = 1; k <= nv; k++)
+ { j = list[k];
+ es[j] = 0.0;
+ for (a = G->v[j]->in; a != NULL; a = a->h_next)
+ { i = a->tail->i;
+ /* there exists arc (i->j) in the project network */
+ temp = es[i] + t[i];
+ if (es[j] < temp) es[j] = temp;
+ }
+ }
+ /* determine the minimal project duration */
+ total = 0.0;
+ for (i = 1; i <= nv; i++)
+ { temp = es[i] + t[i];
+ if (total < temp) total = temp;
+ }
+ /* BACKWARD PASS */
+ /* determine latest start times */
+ for (k = nv; k >= 1; k--)
+ { i = list[k];
+ ls[i] = total - t[i];
+ for (a = G->v[i]->out; a != NULL; a = a->t_next)
+ { j = a->head->i;
+ /* there exists arc (i->j) in the project network */
+ temp = ls[j] - t[i];
+ if (ls[i] > temp) ls[i] = temp;
+ }
+ /* avoid possible round-off errors */
+ if (ls[i] < es[i]) ls[i] = es[i];
+ }
+ /* store results, if necessary */
+ if (v_es >= 0)
+ { for (i = 1; i <= nv; i++)
+ { v = G->v[i];
+ memcpy((char *)v->data + v_es, &es[i], sizeof(double));
+ }
+ }
+ if (v_ls >= 0)
+ { for (i = 1; i <= nv; i++)
+ { v = G->v[i];
+ memcpy((char *)v->data + v_ls, &ls[i], sizeof(double));
+ }
+ }
+ /* free working arrays */
+ xfree(t);
+ xfree(es);
+ xfree(ls);
+ xfree(list);
+done: return total;
+}
+
+static void sorting(glp_graph *G, int list[])
+{ /* perform topological sorting to determine the list of nodes
+ (jobs) such that if list[k] = i and list[kk] = j and there
+ exists arc (i->j), then k < kk */
+ int i, k, nv, v_size, *num;
+ void **save;
+ nv = G->nv;
+ v_size = G->v_size;
+ save = xcalloc(1+nv, sizeof(void *));
+ num = xcalloc(1+nv, sizeof(int));
+ G->v_size = sizeof(int);
+ for (i = 1; i <= nv; i++)
+ { save[i] = G->v[i]->data;
+ G->v[i]->data = &num[i];
+ list[i] = 0;
+ }
+ if (glp_top_sort(G, 0) != 0)
+ xerror("glp_cpp: project network is not acyclic\n");
+ G->v_size = v_size;
+ for (i = 1; i <= nv; i++)
+ { G->v[i]->data = save[i];
+ k = num[i];
+ xassert(1 <= k && k <= nv);
+ xassert(list[k] == 0);
+ list[k] = i;
+ }
+ xfree(save);
+ xfree(num);
+ return;
+}
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/api/cpxbas.c b/test/monniaux/glpk-4.65/src/api/cpxbas.c
new file mode 100644
index 00000000..e1c656a7
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/api/cpxbas.c
@@ -0,0 +1,269 @@
+/* cpxbas.c (construct Bixby's initial LP basis) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* Copyright (C) 2008-2018 Andrew Makhorin, Department for Applied
+* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights
+* reserved. E-mail: <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 "env.h"
+#include "prob.h"
+
+struct var
+{ /* structural variable */
+ int j;
+ /* ordinal number */
+ double q;
+ /* penalty value */
+};
+
+static int CDECL fcmp(const void *ptr1, const void *ptr2)
+{ /* this routine is passed to the qsort() function */
+ struct var *col1 = (void *)ptr1, *col2 = (void *)ptr2;
+ if (col1->q < col2->q) return -1;
+ if (col1->q > col2->q) return +1;
+ return 0;
+}
+
+static int get_column(glp_prob *lp, int j, int ind[], double val[])
+{ /* Bixby's algorithm assumes that the constraint matrix is scaled
+ such that the maximum absolute value in every non-zero row and
+ column is 1 */
+ int k, len;
+ double big;
+ len = glp_get_mat_col(lp, j, ind, val);
+ big = 0.0;
+ for (k = 1; k <= len; k++)
+ if (big < fabs(val[k])) big = fabs(val[k]);
+ if (big == 0.0) big = 1.0;
+ for (k = 1; k <= len; k++) val[k] /= big;
+ return len;
+}
+
+static void cpx_basis(glp_prob *lp)
+{ /* main routine */
+ struct var *C, *C2, *C3, *C4;
+ int m, n, i, j, jk, k, l, ll, t, n2, n3, n4, type, len, *I, *r,
+ *ind;
+ double alpha, gamma, cmax, temp, *v, *val;
+ xprintf("Constructing initial basis...\n");
+ /* determine the number of rows and columns */
+ m = glp_get_num_rows(lp);
+ n = glp_get_num_cols(lp);
+ /* allocate working arrays */
+ C = xcalloc(1+n, sizeof(struct var));
+ I = xcalloc(1+m, sizeof(int));
+ r = xcalloc(1+m, sizeof(int));
+ v = xcalloc(1+m, sizeof(double));
+ ind = xcalloc(1+m, sizeof(int));
+ val = xcalloc(1+m, sizeof(double));
+ /* make all auxiliary variables non-basic */
+ for (i = 1; i <= m; i++)
+ { if (glp_get_row_type(lp, i) != GLP_DB)
+ glp_set_row_stat(lp, i, GLP_NS);
+ else if (fabs(glp_get_row_lb(lp, i)) <=
+ fabs(glp_get_row_ub(lp, i)))
+ glp_set_row_stat(lp, i, GLP_NL);
+ else
+ glp_set_row_stat(lp, i, GLP_NU);
+ }
+ /* make all structural variables non-basic */
+ for (j = 1; j <= n; j++)
+ { if (glp_get_col_type(lp, j) != GLP_DB)
+ glp_set_col_stat(lp, j, GLP_NS);
+ else if (fabs(glp_get_col_lb(lp, j)) <=
+ fabs(glp_get_col_ub(lp, j)))
+ glp_set_col_stat(lp, j, GLP_NL);
+ else
+ glp_set_col_stat(lp, j, GLP_NU);
+ }
+ /* C2 is a set of free structural variables */
+ n2 = 0, C2 = C + 0;
+ for (j = 1; j <= n; j++)
+ { type = glp_get_col_type(lp, j);
+ if (type == GLP_FR)
+ { n2++;
+ C2[n2].j = j;
+ C2[n2].q = 0.0;
+ }
+ }
+ /* C3 is a set of structural variables having excatly one (lower
+ or upper) bound */
+ n3 = 0, C3 = C2 + n2;
+ for (j = 1; j <= n; j++)
+ { type = glp_get_col_type(lp, j);
+ if (type == GLP_LO)
+ { n3++;
+ C3[n3].j = j;
+ C3[n3].q = + glp_get_col_lb(lp, j);
+ }
+ else if (type == GLP_UP)
+ { n3++;
+ C3[n3].j = j;
+ C3[n3].q = - glp_get_col_ub(lp, j);
+ }
+ }
+ /* C4 is a set of structural variables having both (lower and
+ upper) bounds */
+ n4 = 0, C4 = C3 + n3;
+ for (j = 1; j <= n; j++)
+ { type = glp_get_col_type(lp, j);
+ if (type == GLP_DB)
+ { n4++;
+ C4[n4].j = j;
+ C4[n4].q = glp_get_col_lb(lp, j) - glp_get_col_ub(lp, j);
+ }
+ }
+ /* compute gamma = max{|c[j]|: 1 <= j <= n} */
+ gamma = 0.0;
+ for (j = 1; j <= n; j++)
+ { temp = fabs(glp_get_obj_coef(lp, j));
+ if (gamma < temp) gamma = temp;
+ }
+ /* compute cmax */
+ cmax = (gamma == 0.0 ? 1.0 : 1000.0 * gamma);
+ /* compute final penalty for all structural variables within sets
+ C2, C3, and C4 */
+ switch (glp_get_obj_dir(lp))
+ { case GLP_MIN: temp = +1.0; break;
+ case GLP_MAX: temp = -1.0; break;
+ default: xassert(lp != lp);
+ }
+ for (k = 1; k <= n2+n3+n4; k++)
+ { j = C[k].j;
+ C[k].q += (temp * glp_get_obj_coef(lp, j)) / cmax;
+ }
+ /* sort structural variables within C2, C3, and C4 in ascending
+ order of penalty value */
+ qsort(C2+1, n2, sizeof(struct var), fcmp);
+ for (k = 1; k < n2; k++) xassert(C2[k].q <= C2[k+1].q);
+ qsort(C3+1, n3, sizeof(struct var), fcmp);
+ for (k = 1; k < n3; k++) xassert(C3[k].q <= C3[k+1].q);
+ qsort(C4+1, n4, sizeof(struct var), fcmp);
+ for (k = 1; k < n4; k++) xassert(C4[k].q <= C4[k+1].q);
+ /*** STEP 1 ***/
+ for (i = 1; i <= m; i++)
+ { type = glp_get_row_type(lp, i);
+ if (type != GLP_FX)
+ { /* row i is either free or inequality constraint */
+ glp_set_row_stat(lp, i, GLP_BS);
+ I[i] = 1;
+ r[i] = 1;
+ }
+ else
+ { /* row i is equality constraint */
+ I[i] = 0;
+ r[i] = 0;
+ }
+ v[i] = +DBL_MAX;
+ }
+ /*** STEP 2 ***/
+ for (k = 1; k <= n2+n3+n4; k++)
+ { jk = C[k].j;
+ len = get_column(lp, jk, ind, val);
+ /* let alpha = max{|A[l,jk]|: r[l] = 0} and let l' be such
+ that alpha = |A[l',jk]| */
+ alpha = 0.0, ll = 0;
+ for (t = 1; t <= len; t++)
+ { l = ind[t];
+ if (r[l] == 0 && alpha < fabs(val[t]))
+ alpha = fabs(val[t]), ll = l;
+ }
+ if (alpha >= 0.99)
+ { /* B := B union {jk} */
+ glp_set_col_stat(lp, jk, GLP_BS);
+ I[ll] = 1;
+ v[ll] = alpha;
+ /* r[l] := r[l] + 1 for all l such that |A[l,jk]| != 0 */
+ for (t = 1; t <= len; t++)
+ { l = ind[t];
+ if (val[t] != 0.0) r[l]++;
+ }
+ /* continue to the next k */
+ continue;
+ }
+ /* if |A[l,jk]| > 0.01 * v[l] for some l, continue to the
+ next k */
+ for (t = 1; t <= len; t++)
+ { l = ind[t];
+ if (fabs(val[t]) > 0.01 * v[l]) break;
+ }
+ if (t <= len) continue;
+ /* otherwise, let alpha = max{|A[l,jk]|: I[l] = 0} and let l'
+ be such that alpha = |A[l',jk]| */
+ alpha = 0.0, ll = 0;
+ for (t = 1; t <= len; t++)
+ { l = ind[t];
+ if (I[l] == 0 && alpha < fabs(val[t]))
+ alpha = fabs(val[t]), ll = l;
+ }
+ /* if alpha = 0, continue to the next k */
+ if (alpha == 0.0) continue;
+ /* B := B union {jk} */
+ glp_set_col_stat(lp, jk, GLP_BS);
+ I[ll] = 1;
+ v[ll] = alpha;
+ /* r[l] := r[l] + 1 for all l such that |A[l,jk]| != 0 */
+ for (t = 1; t <= len; t++)
+ { l = ind[t];
+ if (val[t] != 0.0) r[l]++;
+ }
+ }
+ /*** STEP 3 ***/
+ /* add an artificial variable (auxiliary variable for equality
+ constraint) to cover each remaining uncovered row */
+ for (i = 1; i <= m; i++)
+ if (I[i] == 0) glp_set_row_stat(lp, i, GLP_BS);
+ /* free working arrays */
+ xfree(C);
+ xfree(I);
+ xfree(r);
+ xfree(v);
+ xfree(ind);
+ xfree(val);
+ return;
+}
+
+/***********************************************************************
+* NAME
+*
+* glp_cpx_basis - construct Bixby's initial LP basis
+*
+* SYNOPSIS
+*
+* void glp_cpx_basis(glp_prob *lp);
+*
+* DESCRIPTION
+*
+* The routine glp_cpx_basis constructs an advanced initial basis for
+* the specified problem object.
+*
+* The routine is based on Bixby's algorithm described in the paper:
+*
+* Robert E. Bixby. Implementing the Simplex Method: The Initial Basis.
+* ORSA Journal on Computing, Vol. 4, No. 3, 1992, pp. 267-84. */
+
+void glp_cpx_basis(glp_prob *lp)
+{ if (lp->m == 0 || lp->n == 0)
+ glp_std_basis(lp);
+ else
+ cpx_basis(lp);
+ return;
+}
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/api/graph.c b/test/monniaux/glpk-4.65/src/api/graph.c
new file mode 100644
index 00000000..82994c84
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/api/graph.c
@@ -0,0 +1,504 @@
+/* graph.c (basic graph routines) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* Copyright (C) 2009-2016 Andrew Makhorin, Department for Applied
+* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights
+* reserved. E-mail: <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 "avl.h"
+#include "dmp.h"
+#include "env.h"
+#include "glpk.h"
+
+/* CAUTION: DO NOT CHANGE THE LIMITS BELOW */
+
+#define NV_MAX 100000000 /* = 100*10^6 */
+/* maximal number of vertices in the graph */
+
+#define NA_MAX 500000000 /* = 500*10^6 */
+/* maximal number of arcs in the graph */
+
+/***********************************************************************
+* NAME
+*
+* glp_create_graph - create graph
+*
+* SYNOPSIS
+*
+* glp_graph *glp_create_graph(int v_size, int a_size);
+*
+* DESCRIPTION
+*
+* The routine creates a new graph, which initially is empty, i.e. has
+* no vertices and arcs.
+*
+* The parameter v_size specifies the size of data associated with each
+* vertex of the graph (0 to 256 bytes).
+*
+* The parameter a_size specifies the size of data associated with each
+* arc of the graph (0 to 256 bytes).
+*
+* RETURNS
+*
+* The routine returns a pointer to the graph created. */
+
+static void create_graph(glp_graph *G, int v_size, int a_size)
+{ G->pool = dmp_create_pool();
+ G->name = NULL;
+ G->nv_max = 50;
+ G->nv = G->na = 0;
+ G->v = xcalloc(1+G->nv_max, sizeof(glp_vertex *));
+ G->index = NULL;
+ G->v_size = v_size;
+ G->a_size = a_size;
+ return;
+}
+
+glp_graph *glp_create_graph(int v_size, int a_size)
+{ glp_graph *G;
+ if (!(0 <= v_size && v_size <= 256))
+ xerror("glp_create_graph: v_size = %d; invalid size of vertex "
+ "data\n", v_size);
+ if (!(0 <= a_size && a_size <= 256))
+ xerror("glp_create_graph: a_size = %d; invalid size of arc dat"
+ "a\n", a_size);
+ G = xmalloc(sizeof(glp_graph));
+ create_graph(G, v_size, a_size);
+ return G;
+}
+
+/***********************************************************************
+* NAME
+*
+* glp_set_graph_name - assign (change) graph name
+*
+* SYNOPSIS
+*
+* void glp_set_graph_name(glp_graph *G, const char *name);
+*
+* DESCRIPTION
+*
+* The routine glp_set_graph_name assigns a symbolic name specified by
+* the character string name (1 to 255 chars) to the graph.
+*
+* If the parameter name is NULL or an empty string, the routine erases
+* the existing symbolic name of the graph. */
+
+void glp_set_graph_name(glp_graph *G, const char *name)
+{ if (G->name != NULL)
+ { dmp_free_atom(G->pool, G->name, strlen(G->name)+1);
+ G->name = NULL;
+ }
+ if (!(name == NULL || name[0] == '\0'))
+ { int j;
+ for (j = 0; name[j] != '\0'; j++)
+ { if (j == 256)
+ xerror("glp_set_graph_name: graph name too long\n");
+ if (iscntrl((unsigned char)name[j]))
+ xerror("glp_set_graph_name: graph name contains invalid "
+ "character(s)\n");
+ }
+ G->name = dmp_get_atom(G->pool, strlen(name)+1);
+ strcpy(G->name, name);
+ }
+ return;
+}
+
+/***********************************************************************
+* NAME
+*
+* glp_add_vertices - add new vertices to graph
+*
+* SYNOPSIS
+*
+* int glp_add_vertices(glp_graph *G, int nadd);
+*
+* DESCRIPTION
+*
+* The routine glp_add_vertices adds nadd vertices to the specified
+* graph. New vertices are always added to the end of the vertex list,
+* so ordinal numbers of existing vertices remain unchanged.
+*
+* Being added each new vertex is isolated (has no incident arcs).
+*
+* RETURNS
+*
+* The routine glp_add_vertices returns an ordinal number of the first
+* new vertex added to the graph. */
+
+int glp_add_vertices(glp_graph *G, int nadd)
+{ int i, nv_new;
+ if (nadd < 1)
+ xerror("glp_add_vertices: nadd = %d; invalid number of vertice"
+ "s\n", nadd);
+ if (nadd > NV_MAX - G->nv)
+ xerror("glp_add_vertices: nadd = %d; too many vertices\n",
+ nadd);
+ /* determine new number of vertices */
+ nv_new = G->nv + nadd;
+ /* increase the room, if necessary */
+ if (G->nv_max < nv_new)
+ { glp_vertex **save = G->v;
+ while (G->nv_max < nv_new)
+ { G->nv_max += G->nv_max;
+ xassert(G->nv_max > 0);
+ }
+ G->v = xcalloc(1+G->nv_max, sizeof(glp_vertex *));
+ memcpy(&G->v[1], &save[1], G->nv * sizeof(glp_vertex *));
+ xfree(save);
+ }
+ /* add new vertices to the end of the vertex list */
+ for (i = G->nv+1; i <= nv_new; i++)
+ { glp_vertex *v;
+ G->v[i] = v = dmp_get_atom(G->pool, sizeof(glp_vertex));
+ v->i = i;
+ v->name = NULL;
+ v->entry = NULL;
+ if (G->v_size == 0)
+ v->data = NULL;
+ else
+ { v->data = dmp_get_atom(G->pool, G->v_size);
+ memset(v->data, 0, G->v_size);
+ }
+ v->temp = NULL;
+ v->in = v->out = NULL;
+ }
+ /* set new number of vertices */
+ G->nv = nv_new;
+ /* return the ordinal number of the first vertex added */
+ return nv_new - nadd + 1;
+}
+
+/**********************************************************************/
+
+void glp_set_vertex_name(glp_graph *G, int i, const char *name)
+{ /* assign (change) vertex name */
+ glp_vertex *v;
+ if (!(1 <= i && i <= G->nv))
+ xerror("glp_set_vertex_name: i = %d; vertex number out of rang"
+ "e\n", i);
+ v = G->v[i];
+ if (v->name != NULL)
+ { if (v->entry != NULL)
+ { xassert(G->index != NULL);
+ avl_delete_node(G->index, v->entry);
+ v->entry = NULL;
+ }
+ dmp_free_atom(G->pool, v->name, strlen(v->name)+1);
+ v->name = NULL;
+ }
+ if (!(name == NULL || name[0] == '\0'))
+ { int k;
+ for (k = 0; name[k] != '\0'; k++)
+ { if (k == 256)
+ xerror("glp_set_vertex_name: i = %d; vertex name too lon"
+ "g\n", i);
+ if (iscntrl((unsigned char)name[k]))
+ xerror("glp_set_vertex_name: i = %d; vertex name contain"
+ "s invalid character(s)\n", i);
+ }
+ v->name = dmp_get_atom(G->pool, strlen(name)+1);
+ strcpy(v->name, name);
+ if (G->index != NULL)
+ { xassert(v->entry == NULL);
+ v->entry = avl_insert_node(G->index, v->name);
+ avl_set_node_link(v->entry, v);
+ }
+ }
+ return;
+}
+
+/***********************************************************************
+* NAME
+*
+* glp_add_arc - add new arc to graph
+*
+* SYNOPSIS
+*
+* glp_arc *glp_add_arc(glp_graph *G, int i, int j);
+*
+* DESCRIPTION
+*
+* The routine glp_add_arc adds a new arc to the specified graph.
+*
+* The parameters i and j specify the ordinal numbers of, resp., tail
+* and head vertices of the arc. Note that self-loops and multiple arcs
+* are allowed.
+*
+* RETURNS
+*
+* The routine glp_add_arc returns a pointer to the arc added. */
+
+glp_arc *glp_add_arc(glp_graph *G, int i, int j)
+{ glp_arc *a;
+ if (!(1 <= i && i <= G->nv))
+ xerror("glp_add_arc: i = %d; tail vertex number out of range\n"
+ , i);
+ if (!(1 <= j && j <= G->nv))
+ xerror("glp_add_arc: j = %d; head vertex number out of range\n"
+ , j);
+ if (G->na == NA_MAX)
+ xerror("glp_add_arc: too many arcs\n");
+ a = dmp_get_atom(G->pool, sizeof(glp_arc));
+ a->tail = G->v[i];
+ a->head = G->v[j];
+ if (G->a_size == 0)
+ a->data = NULL;
+ else
+ { a->data = dmp_get_atom(G->pool, G->a_size);
+ memset(a->data, 0, G->a_size);
+ }
+ a->temp = NULL;
+ a->t_prev = NULL;
+ a->t_next = G->v[i]->out;
+ if (a->t_next != NULL) a->t_next->t_prev = a;
+ a->h_prev = NULL;
+ a->h_next = G->v[j]->in;
+ if (a->h_next != NULL) a->h_next->h_prev = a;
+ G->v[i]->out = G->v[j]->in = a;
+ G->na++;
+ return a;
+}
+
+/***********************************************************************
+* NAME
+*
+* glp_del_vertices - delete vertices from graph
+*
+* SYNOPSIS
+*
+* void glp_del_vertices(glp_graph *G, int ndel, const int num[]);
+*
+* DESCRIPTION
+*
+* The routine glp_del_vertices deletes vertices along with all
+* incident arcs from the specified graph. Ordinal numbers of vertices
+* to be deleted should be placed in locations num[1], ..., num[ndel],
+* ndel > 0.
+*
+* Note that deleting vertices involves changing ordinal numbers of
+* other vertices remaining in the graph. New ordinal numbers of the
+* remaining vertices are assigned under the assumption that the
+* original order of vertices is not changed. */
+
+void glp_del_vertices(glp_graph *G, int ndel, const int num[])
+{ glp_vertex *v;
+ int i, k, nv_new;
+ /* scan the list of vertices to be deleted */
+ if (!(1 <= ndel && ndel <= G->nv))
+ xerror("glp_del_vertices: ndel = %d; invalid number of vertice"
+ "s\n", ndel);
+ for (k = 1; k <= ndel; k++)
+ { /* take the number of vertex to be deleted */
+ i = num[k];
+ /* obtain pointer to i-th vertex */
+ if (!(1 <= i && i <= G->nv))
+ xerror("glp_del_vertices: num[%d] = %d; vertex number out o"
+ "f range\n", k, i);
+ v = G->v[i];
+ /* check that the vertex is not marked yet */
+ if (v->i == 0)
+ xerror("glp_del_vertices: num[%d] = %d; duplicate vertex nu"
+ "mbers not allowed\n", k, i);
+ /* erase symbolic name assigned to the vertex */
+ glp_set_vertex_name(G, i, NULL);
+ xassert(v->name == NULL);
+ xassert(v->entry == NULL);
+ /* free vertex data, if allocated */
+ if (v->data != NULL)
+ dmp_free_atom(G->pool, v->data, G->v_size);
+ /* delete all incoming arcs */
+ while (v->in != NULL)
+ glp_del_arc(G, v->in);
+ /* delete all outgoing arcs */
+ while (v->out != NULL)
+ glp_del_arc(G, v->out);
+ /* mark the vertex to be deleted */
+ v->i = 0;
+ }
+ /* delete all marked vertices from the vertex list */
+ nv_new = 0;
+ for (i = 1; i <= G->nv; i++)
+ { /* obtain pointer to i-th vertex */
+ v = G->v[i];
+ /* check if the vertex is marked */
+ if (v->i == 0)
+ { /* it is marked, delete it */
+ dmp_free_atom(G->pool, v, sizeof(glp_vertex));
+ }
+ else
+ { /* it is not marked, keep it */
+ v->i = ++nv_new;
+ G->v[v->i] = v;
+ }
+ }
+ /* set new number of vertices in the graph */
+ G->nv = nv_new;
+ return;
+}
+
+/***********************************************************************
+* NAME
+*
+* glp_del_arc - delete arc from graph
+*
+* SYNOPSIS
+*
+* void glp_del_arc(glp_graph *G, glp_arc *a);
+*
+* DESCRIPTION
+*
+* The routine glp_del_arc deletes an arc from the specified graph.
+* The arc to be deleted must exist. */
+
+void glp_del_arc(glp_graph *G, glp_arc *a)
+{ /* some sanity checks */
+ xassert(G->na > 0);
+ xassert(1 <= a->tail->i && a->tail->i <= G->nv);
+ xassert(a->tail == G->v[a->tail->i]);
+ xassert(1 <= a->head->i && a->head->i <= G->nv);
+ xassert(a->head == G->v[a->head->i]);
+ /* remove the arc from the list of incoming arcs */
+ if (a->h_prev == NULL)
+ a->head->in = a->h_next;
+ else
+ a->h_prev->h_next = a->h_next;
+ if (a->h_next == NULL)
+ ;
+ else
+ a->h_next->h_prev = a->h_prev;
+ /* remove the arc from the list of outgoing arcs */
+ if (a->t_prev == NULL)
+ a->tail->out = a->t_next;
+ else
+ a->t_prev->t_next = a->t_next;
+ if (a->t_next == NULL)
+ ;
+ else
+ a->t_next->t_prev = a->t_prev;
+ /* free arc data, if allocated */
+ if (a->data != NULL)
+ dmp_free_atom(G->pool, a->data, G->a_size);
+ /* delete the arc from the graph */
+ dmp_free_atom(G->pool, a, sizeof(glp_arc));
+ G->na--;
+ return;
+}
+
+/***********************************************************************
+* NAME
+*
+* glp_erase_graph - erase graph content
+*
+* SYNOPSIS
+*
+* void glp_erase_graph(glp_graph *G, int v_size, int a_size);
+*
+* DESCRIPTION
+*
+* The routine glp_erase_graph erases the content of the specified
+* graph. The effect of this operation is the same as if the graph
+* would be deleted with the routine glp_delete_graph and then created
+* anew with the routine glp_create_graph, with exception that the
+* handle (pointer) to the graph remains valid. */
+
+static void delete_graph(glp_graph *G)
+{ dmp_delete_pool(G->pool);
+ xfree(G->v);
+ if (G->index != NULL) avl_delete_tree(G->index);
+ return;
+}
+
+void glp_erase_graph(glp_graph *G, int v_size, int a_size)
+{ if (!(0 <= v_size && v_size <= 256))
+ xerror("glp_erase_graph: v_size = %d; invalid size of vertex d"
+ "ata\n", v_size);
+ if (!(0 <= a_size && a_size <= 256))
+ xerror("glp_erase_graph: a_size = %d; invalid size of arc data"
+ "\n", a_size);
+ delete_graph(G);
+ create_graph(G, v_size, a_size);
+ return;
+}
+
+/***********************************************************************
+* NAME
+*
+* glp_delete_graph - delete graph
+*
+* SYNOPSIS
+*
+* void glp_delete_graph(glp_graph *G);
+*
+* DESCRIPTION
+*
+* The routine glp_delete_graph deletes the specified graph and frees
+* all the memory allocated to this program object. */
+
+void glp_delete_graph(glp_graph *G)
+{ delete_graph(G);
+ xfree(G);
+ return;
+}
+
+/**********************************************************************/
+
+void glp_create_v_index(glp_graph *G)
+{ /* create vertex name index */
+ glp_vertex *v;
+ int i;
+ if (G->index == NULL)
+ { G->index = avl_create_tree(avl_strcmp, NULL);
+ for (i = 1; i <= G->nv; i++)
+ { v = G->v[i];
+ xassert(v->entry == NULL);
+ if (v->name != NULL)
+ { v->entry = avl_insert_node(G->index, v->name);
+ avl_set_node_link(v->entry, v);
+ }
+ }
+ }
+ return;
+}
+
+int glp_find_vertex(glp_graph *G, const char *name)
+{ /* find vertex by its name */
+ AVLNODE *node;
+ int i = 0;
+ if (G->index == NULL)
+ xerror("glp_find_vertex: vertex name index does not exist\n");
+ if (!(name == NULL || name[0] == '\0' || strlen(name) > 255))
+ { node = avl_find_node(G->index, name);
+ if (node != NULL)
+ i = ((glp_vertex *)avl_get_node_link(node))->i;
+ }
+ return i;
+}
+
+void glp_delete_v_index(glp_graph *G)
+{ /* delete vertex name index */
+ int i;
+ if (G->index != NULL)
+ { avl_delete_tree(G->index), G->index = NULL;
+ for (i = 1; i <= G->nv; i++) G->v[i]->entry = NULL;
+ }
+ return;
+}
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/api/gridgen.c b/test/monniaux/glpk-4.65/src/api/gridgen.c
new file mode 100644
index 00000000..8cd3517f
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/api/gridgen.c
@@ -0,0 +1,769 @@
+/* gridgen.c (grid-like network problem generator) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* This code is a modified version of the program GRIDGEN, a grid-like
+* network problem generator developed by Yusin Lee and Jim Orlin.
+* The original code is publically available on the DIMACS ftp site at:
+* <ftp://dimacs.rutgers.edu/pub/netflow/generators/network/gridgen>.
+*
+* All changes concern only the program interface, so this modified
+* version produces exactly the same instances as the original version.
+*
+* Changes were made 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 "env.h"
+#include "glpk.h"
+
+/***********************************************************************
+* NAME
+*
+* glp_gridgen - grid-like network problem generator
+*
+* SYNOPSIS
+*
+* int glp_gridgen(glp_graph *G, int v_rhs, int a_cap, int a_cost,
+* const int parm[1+14]);
+*
+* DESCRIPTION
+*
+* The routine glp_gridgen is a grid-like network problem generator
+* developed by Yusin Lee and Jim Orlin.
+*
+* The parameter G specifies the graph object, to which the generated
+* problem data have to be stored. Note that on entry the graph object
+* is erased with the routine glp_erase_graph.
+*
+* The parameter v_rhs specifies an offset of the field of type double
+* in the vertex data block, to which the routine stores the supply or
+* demand value. If v_rhs < 0, the value is not stored.
+*
+* The parameter a_cap specifies an offset of the field of type double
+* in the arc data block, to which the routine stores the arc capacity.
+* If a_cap < 0, the capacity is not stored.
+*
+* The parameter a_cost specifies an offset of the field of type double
+* in the arc data block, to which the routine stores the per-unit cost
+* if the arc flow. If a_cost < 0, the cost is not stored.
+*
+* The array parm contains description of the network to be generated:
+*
+* parm[0] not used
+* parm[1] two-ways arcs indicator:
+* 1 - if links in both direction should be generated
+* 0 - otherwise
+* parm[2] random number seed (a positive integer)
+* parm[3] number of nodes (the number of nodes generated might be
+* slightly different to make the network a grid)
+* parm[4] grid width
+* parm[5] number of sources
+* parm[6] number of sinks
+* parm[7] average degree
+* parm[8] total flow
+* parm[9] distribution of arc costs:
+* 1 - uniform
+* 2 - exponential
+* parm[10] lower bound for arc cost (uniform)
+* 100 * lambda (exponential)
+* parm[11] upper bound for arc cost (uniform)
+* not used (exponential)
+* parm[12] distribution of arc capacities:
+* 1 - uniform
+* 2 - exponential
+* parm[13] lower bound for arc capacity (uniform)
+* 100 * lambda (exponential)
+* parm[14] upper bound for arc capacity (uniform)
+* not used (exponential)
+*
+* RETURNS
+*
+* If the instance was successfully generated, the routine glp_gridgen
+* returns zero; otherwise, if specified parameters are inconsistent,
+* the routine returns a non-zero error code.
+*
+* COMMENTS
+*
+* This network generator generates a grid-like network plus a super
+* node. In additional to the arcs connecting the nodes in the grid,
+* there is an arc from each supply node to the super node and from the
+* super node to each demand node to guarantee feasiblity. These arcs
+* have very high costs and very big capacities.
+*
+* The idea of this network generator is as follows: First, a grid of
+* n1 * n2 is generated. For example, 5 * 3. The nodes are numbered as
+* 1 to 15, and the supernode is numbered as n1*n2+1. Then arcs between
+* adjacent nodes are generated. For these arcs, the user is allowed to
+* specify either to generate two-way arcs or one-way arcs. If two-way
+* arcs are to be generated, two arcs, one in each direction, will be
+* generated between each adjacent node pairs. Otherwise, only one arc
+* will be generated. If this is the case, the arcs will be generated
+* in alterntive directions as shown below.
+*
+* 1 ---> 2 ---> 3 ---> 4 ---> 5
+* | ^ | ^ |
+* | | | | |
+* V | V | V
+* 6 <--- 7 <--- 8 <--- 9 <--- 10
+* | ^ | ^ |
+* | | | | |
+* V | V | V
+* 11 --->12 --->13 --->14 ---> 15
+*
+* Then the arcs between the super node and the source/sink nodes are
+* added as mentioned before. If the number of arcs still doesn't reach
+* the requirement, additional arcs will be added by uniformly picking
+* random node pairs. There is no checking to prevent multiple arcs
+* between any pair of nodes. However, there will be no self-arcs (arcs
+* that poins back to its tail node) in the network.
+*
+* The source and sink nodes are selected uniformly in the network, and
+* the imbalances of each source/sink node are also assigned by uniform
+* distribution. */
+
+struct stat_para
+{ /* structure for statistical distributions */
+ int distribution;
+ /* the distribution: */
+#define UNIFORM 1 /* uniform distribution */
+#define EXPONENTIAL 2 /* exponential distribution */
+ double parameter[5];
+ /* the parameters of the distribution */
+};
+
+struct arcs
+{ int from;
+ /* the FROM node of that arc */
+ int to;
+ /* the TO node of that arc */
+ int cost;
+ /* original cost of that arc */
+ int u;
+ /* capacity of the arc */
+};
+
+struct imbalance
+{ int node;
+ /* Node ID */
+ int supply;
+ /* Supply of that node */
+};
+
+struct csa
+{ /* common storage area */
+ glp_graph *G;
+ int v_rhs, a_cap, a_cost;
+ int seed;
+ /* random number seed */
+ int seed_original;
+ /* the original seed from input */
+ int two_way;
+ /* 0: generate arcs in both direction for the basic grid, except
+ for the arcs to/from the super node. 1: o/w */
+ int n_node;
+ /* total number of nodes in the network, numbered 1 to n_node,
+ including the super node, which is the last one */
+ int n_arc;
+ /* total number of arcs in the network, counting EVERY arc. */
+ int n_grid_arc;
+ /* number of arcs in the basic grid, including the arcs to/from
+ the super node */
+ int n_source, n_sink;
+ /* number of source and sink nodes */
+ int avg_degree;
+ /* average degree, arcs to and from the super node are counted */
+ int t_supply;
+ /* total supply in the network */
+ int n1, n2;
+ /* the two edges of the network grid. n1 >= n2 */
+ struct imbalance *source_list, *sink_list;
+ /* head of the array of source/sink nodes */
+ struct stat_para arc_costs;
+ /* the distribution of arc costs */
+ struct stat_para capacities;
+ /* distribution of the capacities of the arcs */
+ struct arcs *arc_list;
+ /* head of the arc list array. Arcs in this array are in the
+ order of grid_arcs, arcs to/from super node, and other arcs */
+};
+
+#define G (csa->G)
+#define v_rhs (csa->v_rhs)
+#define a_cap (csa->a_cap)
+#define a_cost (csa->a_cost)
+#define seed (csa->seed)
+#define seed_original (csa->seed_original)
+#define two_way (csa->two_way)
+#define n_node (csa->n_node)
+#define n_arc (csa->n_arc)
+#define n_grid_arc (csa->n_grid_arc)
+#define n_source (csa->n_source)
+#define n_sink (csa->n_sink)
+#define avg_degree (csa->avg_degree)
+#define t_supply (csa->t_supply)
+#define n1 (csa->n1)
+#define n2 (csa->n2)
+#define source_list (csa->source_list)
+#define sink_list (csa->sink_list)
+#define arc_costs (csa->arc_costs)
+#define capacities (csa->capacities)
+#define arc_list (csa->arc_list)
+
+static void assign_capacities(struct csa *csa);
+static void assign_costs(struct csa *csa);
+static void assign_imbalance(struct csa *csa);
+static int exponential(struct csa *csa, double lambda[1]);
+static struct arcs *gen_additional_arcs(struct csa *csa, struct arcs
+ *arc_ptr);
+static struct arcs *gen_basic_grid(struct csa *csa, struct arcs
+ *arc_ptr);
+static void gen_more_arcs(struct csa *csa, struct arcs *arc_ptr);
+static void generate(struct csa *csa);
+static void output(struct csa *csa);
+static double randy(struct csa *csa);
+static void select_source_sinks(struct csa *csa);
+static int uniform(struct csa *csa, double a[2]);
+
+int glp_gridgen(glp_graph *G_, int _v_rhs, int _a_cap, int _a_cost,
+ const int parm[1+14])
+{ struct csa _csa, *csa = &_csa;
+ int n, ret;
+ G = G_;
+ v_rhs = _v_rhs;
+ a_cap = _a_cap;
+ a_cost = _a_cost;
+ if (G != NULL)
+ { if (v_rhs >= 0 && v_rhs > G->v_size - (int)sizeof(double))
+ xerror("glp_gridgen: v_rhs = %d; invalid offset\n", v_rhs);
+ if (a_cap >= 0 && a_cap > G->a_size - (int)sizeof(double))
+ xerror("glp_gridgen: a_cap = %d; invalid offset\n", a_cap);
+ if (a_cost >= 0 && a_cost > G->a_size - (int)sizeof(double))
+ xerror("glp_gridgen: a_cost = %d; invalid offset\n", a_cost)
+ ;
+ }
+ /* Check the parameters for consistency. */
+ if (!(parm[1] == 0 || parm[1] == 1))
+ { ret = 1;
+ goto done;
+ }
+ if (parm[2] < 1)
+ { ret = 2;
+ goto done;
+ }
+ if (!(10 <= parm[3] && parm[3] <= 40000))
+ { ret = 3;
+ goto done;
+ }
+ if (!(1 <= parm[4] && parm[4] <= 40000))
+ { ret = 4;
+ goto done;
+ }
+ if (!(parm[5] >= 0 && parm[6] >= 0 && parm[5] + parm[6] <=
+ parm[3]))
+ { ret = 5;
+ goto done;
+ }
+ if (!(1 <= parm[7] && parm[7] <= parm[3]))
+ { ret = 6;
+ goto done;
+ }
+ if (parm[8] < 0)
+ { ret = 7;
+ goto done;
+ }
+ if (!(parm[9] == 1 || parm[9] == 2))
+ { ret = 8;
+ goto done;
+ }
+ if (parm[9] == 1 && parm[10] > parm[11] ||
+ parm[9] == 2 && parm[10] < 1)
+ { ret = 9;
+ goto done;
+ }
+ if (!(parm[12] == 1 || parm[12] == 2))
+ { ret = 10;
+ goto done;
+ }
+ if (parm[12] == 1 && !(0 <= parm[13] && parm[13] <= parm[14]) ||
+ parm[12] == 2 && parm[13] < 1)
+ { ret = 11;
+ goto done;
+ }
+ /* Initialize the graph object. */
+ if (G != NULL)
+ { glp_erase_graph(G, G->v_size, G->a_size);
+ glp_set_graph_name(G, "GRIDGEN");
+ }
+ /* Copy the generator parameters. */
+ two_way = parm[1];
+ seed_original = seed = parm[2];
+ n_node = parm[3];
+ n = parm[4];
+ n_source = parm[5];
+ n_sink = parm[6];
+ avg_degree = parm[7];
+ t_supply = parm[8];
+ arc_costs.distribution = parm[9];
+ if (parm[9] == 1)
+ { arc_costs.parameter[0] = parm[10];
+ arc_costs.parameter[1] = parm[11];
+ }
+ else
+ { arc_costs.parameter[0] = (double)parm[10] / 100.0;
+ arc_costs.parameter[1] = 0.0;
+ }
+ capacities.distribution = parm[12];
+ if (parm[12] == 1)
+ { capacities.parameter[0] = parm[13];
+ capacities.parameter[1] = parm[14];
+ }
+ else
+ { capacities.parameter[0] = (double)parm[13] / 100.0;
+ capacities.parameter[1] = 0.0;
+ }
+ /* Calculate the edge lengths of the grid according to the
+ input. */
+ if (n * n >= n_node)
+ { n1 = n;
+ n2 = (int)((double)n_node / (double)n + 0.5);
+ }
+ else
+ { n2 = n;
+ n1 = (int)((double)n_node / (double)n + 0.5);
+ }
+ /* Recalculate the total number of nodes and plus 1 for the super
+ node. */
+ n_node = n1 * n2 + 1;
+ n_arc = n_node * avg_degree;
+ n_grid_arc = (two_way + 1) * ((n1 - 1) * n2 + (n2 - 1) * n1) +
+ n_source + n_sink;
+ if (n_grid_arc > n_arc) n_arc = n_grid_arc;
+ arc_list = xcalloc(n_arc, sizeof(struct arcs));
+ source_list = xcalloc(n_source, sizeof(struct imbalance));
+ sink_list = xcalloc(n_sink, sizeof(struct imbalance));
+ /* Generate a random network. */
+ generate(csa);
+ /* Output the network. */
+ output(csa);
+ /* Free all allocated memory. */
+ xfree(arc_list);
+ xfree(source_list);
+ xfree(sink_list);
+ /* The instance has been successfully generated. */
+ ret = 0;
+done: return ret;
+}
+
+#undef random
+
+static void assign_capacities(struct csa *csa)
+{ /* Assign a capacity to each arc. */
+ struct arcs *arc_ptr = arc_list;
+ int (*random)(struct csa *csa, double *);
+ int i;
+ /* Determine the random number generator to use. */
+ switch (arc_costs.distribution)
+ { case UNIFORM:
+ random = uniform;
+ break;
+ case EXPONENTIAL:
+ random = exponential;
+ break;
+ default:
+ xassert(csa != csa);
+ }
+ /* Assign capacities to grid arcs. */
+ for (i = n_source + n_sink; i < n_grid_arc; i++, arc_ptr++)
+ arc_ptr->u = random(csa, capacities.parameter);
+ i = i - n_source - n_sink;
+ /* Assign capacities to arcs to/from supernode. */
+ for (; i < n_grid_arc; i++, arc_ptr++)
+ arc_ptr->u = t_supply;
+ /* Assign capacities to all other arcs. */
+ for (; i < n_arc; i++, arc_ptr++)
+ arc_ptr->u = random(csa, capacities.parameter);
+ return;
+}
+
+static void assign_costs(struct csa *csa)
+{ /* Assign a cost to each arc. */
+ struct arcs *arc_ptr = arc_list;
+ int (*random)(struct csa *csa, double *);
+ int i;
+ /* A high cost assigned to arcs to/from the supernode. */
+ int high_cost;
+ /* The maximum cost assigned to arcs in the base grid. */
+ int max_cost = 0;
+ /* Determine the random number generator to use. */
+ switch (arc_costs.distribution)
+ { case UNIFORM:
+ random = uniform;
+ break;
+ case EXPONENTIAL:
+ random = exponential;
+ break;
+ default:
+ xassert(csa != csa);
+ }
+ /* Assign costs to arcs in the base grid. */
+ for (i = n_source + n_sink; i < n_grid_arc; i++, arc_ptr++)
+ { arc_ptr->cost = random(csa, arc_costs.parameter);
+ if (max_cost < arc_ptr->cost) max_cost = arc_ptr->cost;
+ }
+ i = i - n_source - n_sink;
+ /* Assign costs to arcs to/from the super node. */
+ high_cost = max_cost * 2;
+ for (; i < n_grid_arc; i++, arc_ptr++)
+ arc_ptr->cost = high_cost;
+ /* Assign costs to all other arcs. */
+ for (; i < n_arc; i++, arc_ptr++)
+ arc_ptr->cost = random(csa, arc_costs.parameter);
+ return;
+}
+
+static void assign_imbalance(struct csa *csa)
+{ /* Assign an imbalance to each node. */
+ int total, i;
+ double avg;
+ struct imbalance *ptr;
+ /* assign the supply nodes */
+ avg = 2.0 * t_supply / n_source;
+ do
+ { for (i = 1, total = t_supply, ptr = source_list + 1;
+ i < n_source; i++, ptr++)
+ { ptr->supply = (int)(randy(csa) * avg + 0.5);
+ total -= ptr->supply;
+ }
+ source_list->supply = total;
+ }
+ /* redo all if the assignment "overshooted" */
+ while (total <= 0);
+ /* assign the demand nodes */
+ avg = -2.0 * t_supply / n_sink;
+ do
+ { for (i = 1, total = t_supply, ptr = sink_list + 1;
+ i < n_sink; i++, ptr++)
+ { ptr->supply = (int)(randy(csa) * avg - 0.5);
+ total += ptr->supply;
+ }
+ sink_list->supply = - total;
+ }
+ while (total <= 0);
+ return;
+}
+
+static int exponential(struct csa *csa, double lambda[1])
+{ /* Returns an "exponentially distributed" integer with parameter
+ lambda. */
+ return ((int)(- lambda[0] * log((double)randy(csa)) + 0.5));
+}
+
+static struct arcs *gen_additional_arcs(struct csa *csa, struct arcs
+ *arc_ptr)
+{ /* Generate an arc from each source to the supernode and from
+ supernode to each sink. */
+ int i;
+ for (i = 0; i < n_source; i++, arc_ptr++)
+ { arc_ptr->from = source_list[i].node;
+ arc_ptr->to = n_node;
+ }
+ for (i = 0; i < n_sink; i++, arc_ptr++)
+ { arc_ptr->to = sink_list[i].node;
+ arc_ptr->from = n_node;
+ }
+ return arc_ptr;
+}
+
+static struct arcs *gen_basic_grid(struct csa *csa, struct arcs
+ *arc_ptr)
+{ /* Generate the basic grid. */
+ int direction = 1, i, j, k;
+ if (two_way)
+ { /* Generate an arc in each direction. */
+ for (i = 1; i < n_node; i += n1)
+ { for (j = i, k = j + n1 - 1; j < k; j++)
+ { arc_ptr->from = j;
+ arc_ptr->to = j + 1;
+ arc_ptr++;
+ arc_ptr->from = j + 1;
+ arc_ptr->to = j;
+ arc_ptr++;
+ }
+ }
+ for (i = 1; i <= n1; i++)
+ { for (j = i + n1; j < n_node; j += n1)
+ { arc_ptr->from = j;
+ arc_ptr->to = j - n1;
+ arc_ptr++;
+ arc_ptr->from = j - n1;
+ arc_ptr->to = j;
+ arc_ptr++;
+ }
+ }
+ }
+ else
+ { /* Generate one arc in each direction. */
+ for (i = 1; i < n_node; i += n1)
+ { if (direction == 1)
+ j = i;
+ else
+ j = i + 1;
+ for (k = j + n1 - 1; j < k; j++)
+ { arc_ptr->from = j;
+ arc_ptr->to = j + direction;
+ arc_ptr++;
+ }
+ direction = - direction;
+ }
+ for (i = 1; i <= n1; i++)
+ { j = i + n1;
+ if (direction == 1)
+ { for (; j < n_node; j += n1)
+ { arc_ptr->from = j - n1;
+ arc_ptr->to = j;
+ arc_ptr++;
+ }
+ }
+ else
+ { for (; j < n_node; j += n1)
+ { arc_ptr->from = j - n1;
+ arc_ptr->to = j;
+ arc_ptr++;
+ }
+ }
+ direction = - direction;
+ }
+ }
+ return arc_ptr;
+}
+
+static void gen_more_arcs(struct csa *csa, struct arcs *arc_ptr)
+{ /* Generate random arcs to meet the specified density. */
+ int i;
+ double ab[2];
+ ab[0] = 0.9;
+ ab[1] = n_node - 0.99; /* upper limit is n_node-1 because the
+ supernode cannot be selected */
+ for (i = n_grid_arc; i < n_arc; i++, arc_ptr++)
+ { arc_ptr->from = uniform(csa, ab);
+ arc_ptr->to = uniform(csa, ab);
+ if (arc_ptr->from == arc_ptr->to)
+ { arc_ptr--;
+ i--;
+ }
+ }
+ return;
+}
+
+static void generate(struct csa *csa)
+{ /* Generate a random network. */
+ struct arcs *arc_ptr = arc_list;
+ arc_ptr = gen_basic_grid(csa, arc_ptr);
+ select_source_sinks(csa);
+ arc_ptr = gen_additional_arcs(csa, arc_ptr);
+ gen_more_arcs(csa, arc_ptr);
+ assign_costs(csa);
+ assign_capacities(csa);
+ assign_imbalance(csa);
+ return;
+}
+
+static void output(struct csa *csa)
+{ /* Output the network in DIMACS format. */
+ struct arcs *arc_ptr;
+ struct imbalance *imb_ptr;
+ int i;
+ if (G != NULL) goto skip;
+ /* Output "c", "p" records. */
+ xprintf("c generated by GRIDGEN\n");
+ xprintf("c seed %d\n", seed_original);
+ xprintf("c nodes %d\n", n_node);
+ xprintf("c grid size %d X %d\n", n1, n2);
+ xprintf("c sources %d sinks %d\n", n_source, n_sink);
+ xprintf("c avg. degree %d\n", avg_degree);
+ xprintf("c supply %d\n", t_supply);
+ switch (arc_costs.distribution)
+ { case UNIFORM:
+ xprintf("c arc costs: UNIFORM distr. min %d max %d\n",
+ (int)arc_costs.parameter[0],
+ (int)arc_costs.parameter[1]);
+ break;
+ case EXPONENTIAL:
+ xprintf("c arc costs: EXPONENTIAL distr. lambda %d\n",
+ (int)arc_costs.parameter[0]);
+ break;
+ default:
+ xassert(csa != csa);
+ }
+ switch (capacities.distribution)
+ { case UNIFORM:
+ xprintf("c arc caps : UNIFORM distr. min %d max %d\n",
+ (int)capacities.parameter[0],
+ (int)capacities.parameter[1]);
+ break;
+ case EXPONENTIAL:
+ xprintf("c arc caps : EXPONENTIAL distr. %d lambda %d\n",
+ (int)capacities.parameter[0]);
+ break;
+ default:
+ xassert(csa != csa);
+ }
+skip: if (G == NULL)
+ xprintf("p min %d %d\n", n_node, n_arc);
+ else
+ { glp_add_vertices(G, n_node);
+ if (v_rhs >= 0)
+ { double zero = 0.0;
+ for (i = 1; i <= n_node; i++)
+ { glp_vertex *v = G->v[i];
+ memcpy((char *)v->data + v_rhs, &zero, sizeof(double));
+ }
+ }
+ }
+ /* Output "n node supply". */
+ for (i = 0, imb_ptr = source_list; i < n_source; i++, imb_ptr++)
+ { if (G == NULL)
+ xprintf("n %d %d\n", imb_ptr->node, imb_ptr->supply);
+ else
+ { if (v_rhs >= 0)
+ { double temp = (double)imb_ptr->supply;
+ glp_vertex *v = G->v[imb_ptr->node];
+ memcpy((char *)v->data + v_rhs, &temp, sizeof(double));
+ }
+ }
+ }
+ for (i = 0, imb_ptr = sink_list; i < n_sink; i++, imb_ptr++)
+ { if (G == NULL)
+ xprintf("n %d %d\n", imb_ptr->node, imb_ptr->supply);
+ else
+ { if (v_rhs >= 0)
+ { double temp = (double)imb_ptr->supply;
+ glp_vertex *v = G->v[imb_ptr->node];
+ memcpy((char *)v->data + v_rhs, &temp, sizeof(double));
+ }
+ }
+ }
+ /* Output "a from to lowcap=0 hicap cost". */
+ for (i = 0, arc_ptr = arc_list; i < n_arc; i++, arc_ptr++)
+ { if (G == NULL)
+ xprintf("a %d %d 0 %d %d\n", arc_ptr->from, arc_ptr->to,
+ arc_ptr->u, arc_ptr->cost);
+ else
+ { glp_arc *a = glp_add_arc(G, arc_ptr->from, arc_ptr->to);
+ if (a_cap >= 0)
+ { double temp = (double)arc_ptr->u;
+ memcpy((char *)a->data + a_cap, &temp, sizeof(double));
+ }
+ if (a_cost >= 0)
+ { double temp = (double)arc_ptr->cost;
+ memcpy((char *)a->data + a_cost, &temp, sizeof(double));
+ }
+ }
+ }
+ return;
+}
+
+static double randy(struct csa *csa)
+{ /* Returns a random number between 0.0 and 1.0.
+ See Ward Cheney & David Kincaid, "Numerical Mathematics and
+ Computing," 2Ed, pp. 335. */
+ seed = 16807 * seed % 2147483647;
+ if (seed < 0) seed = - seed;
+ return seed * 4.6566128752459e-10;
+}
+
+static void select_source_sinks(struct csa *csa)
+{ /* Randomly select the source nodes and sink nodes. */
+ int i, *int_ptr;
+ int *temp_list; /* a temporary list of nodes */
+ struct imbalance *ptr;
+ double ab[2]; /* parameter for random number generator */
+ ab[0] = 0.9;
+ ab[1] = n_node - 0.99; /* upper limit is n_node-1 because the
+ supernode cannot be selected */
+ temp_list = xcalloc(n_node, sizeof(int));
+ for (i = 0, int_ptr = temp_list; i < n_node; i++, int_ptr++)
+ *int_ptr = 0;
+ /* Select the source nodes. */
+ for (i = 0, ptr = source_list; i < n_source; i++, ptr++)
+ { ptr->node = uniform(csa, ab);
+ if (temp_list[ptr->node] == 1) /* check for duplicates */
+ { ptr--;
+ i--;
+ }
+ else
+ temp_list[ptr->node] = 1;
+ }
+ /* Select the sink nodes. */
+ for (i = 0, ptr = sink_list; i < n_sink; i++, ptr++)
+ { ptr->node = uniform(csa, ab);
+ if (temp_list[ptr->node] == 1)
+ { ptr--;
+ i--;
+ }
+ else
+ temp_list[ptr->node] = 1;
+ }
+ xfree(temp_list);
+ return;
+}
+
+int uniform(struct csa *csa, double a[2])
+{ /* Generates an integer uniformly selected from [a[0],a[1]]. */
+ return (int)((a[1] - a[0]) * randy(csa) + a[0] + 0.5);
+}
+
+/**********************************************************************/
+
+#if 0
+int main(void)
+{ int parm[1+14];
+ double temp;
+ scanf("%d", &parm[1]);
+ scanf("%d", &parm[2]);
+ scanf("%d", &parm[3]);
+ scanf("%d", &parm[4]);
+ scanf("%d", &parm[5]);
+ scanf("%d", &parm[6]);
+ scanf("%d", &parm[7]);
+ scanf("%d", &parm[8]);
+ scanf("%d", &parm[9]);
+ if (parm[9] == 1)
+ { scanf("%d", &parm[10]);
+ scanf("%d", &parm[11]);
+ }
+ else
+ { scanf("%le", &temp);
+ parm[10] = (int)(100.0 * temp + .5);
+ parm[11] = 0;
+ }
+ scanf("%d", &parm[12]);
+ if (parm[12] == 1)
+ { scanf("%d", &parm[13]);
+ scanf("%d", &parm[14]);
+ }
+ else
+ { scanf("%le", &temp);
+ parm[13] = (int)(100.0 * temp + .5);
+ parm[14] = 0;
+ }
+ glp_gridgen(NULL, 0, 0, 0, parm);
+ return 0;
+}
+#endif
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/api/intfeas1.c b/test/monniaux/glpk-4.65/src/api/intfeas1.c
new file mode 100644
index 00000000..43064351
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/api/intfeas1.c
@@ -0,0 +1,267 @@
+/* intfeas1.c (solve integer feasibility problem) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* Copyright (C) 2011-2016 Andrew Makhorin, Department for Applied
+* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights
+* reserved. E-mail: <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 "env.h"
+#include "npp.h"
+
+int glp_intfeas1(glp_prob *P, int use_bound, int obj_bound)
+{ /* solve integer feasibility problem */
+ NPP *npp = NULL;
+ glp_prob *mip = NULL;
+ int *obj_ind = NULL;
+ double *obj_val = NULL;
+ int obj_row = 0;
+ int i, j, k, obj_len, temp, ret;
+#if 0 /* 04/IV-2016 */
+ /* check the problem object */
+ if (P == NULL || P->magic != GLP_PROB_MAGIC)
+ xerror("glp_intfeas1: P = %p; invalid problem object\n",
+ P);
+#endif
+ if (P->tree != NULL)
+ xerror("glp_intfeas1: operation not allowed\n");
+ /* integer solution is currently undefined */
+ P->mip_stat = GLP_UNDEF;
+ P->mip_obj = 0.0;
+ /* check columns (variables) */
+ for (j = 1; j <= P->n; j++)
+ { GLPCOL *col = P->col[j];
+#if 0 /* binarization is not yet implemented */
+ if (!(col->kind == GLP_IV || col->type == GLP_FX))
+ { xprintf("glp_intfeas1: column %d: non-integer non-fixed var"
+ "iable not allowed\n", j);
+#else
+ if (!((col->kind == GLP_IV && col->lb == 0.0 && col->ub == 1.0)
+ || col->type == GLP_FX))
+ { xprintf("glp_intfeas1: column %d: non-binary non-fixed vari"
+ "able not allowed\n", j);
+#endif
+ ret = GLP_EDATA;
+ goto done;
+ }
+ temp = (int)col->lb;
+ if ((double)temp != col->lb)
+ { if (col->type == GLP_FX)
+ xprintf("glp_intfeas1: column %d: fixed value %g is non-"
+ "integer or out of range\n", j, col->lb);
+ else
+ xprintf("glp_intfeas1: column %d: lower bound %g is non-"
+ "integer or out of range\n", j, col->lb);
+ ret = GLP_EDATA;
+ goto done;
+ }
+ temp = (int)col->ub;
+ if ((double)temp != col->ub)
+ { xprintf("glp_intfeas1: column %d: upper bound %g is non-int"
+ "eger or out of range\n", j, col->ub);
+ ret = GLP_EDATA;
+ goto done;
+ }
+ if (col->type == GLP_DB && col->lb > col->ub)
+ { xprintf("glp_intfeas1: column %d: lower bound %g is greater"
+ " than upper bound %g\n", j, col->lb, col->ub);
+ ret = GLP_EBOUND;
+ goto done;
+ }
+ }
+ /* check rows (constraints) */
+ for (i = 1; i <= P->m; i++)
+ { GLPROW *row = P->row[i];
+ GLPAIJ *aij;
+ for (aij = row->ptr; aij != NULL; aij = aij->r_next)
+ { temp = (int)aij->val;
+ if ((double)temp != aij->val)
+ { xprintf("glp_intfeas1: row = %d, column %d: constraint c"
+ "oefficient %g is non-integer or out of range\n",
+ i, aij->col->j, aij->val);
+ ret = GLP_EDATA;
+ goto done;
+ }
+ }
+ temp = (int)row->lb;
+ if ((double)temp != row->lb)
+ { if (row->type == GLP_FX)
+ xprintf("glp_intfeas1: row = %d: fixed value %g is non-i"
+ "nteger or out of range\n", i, row->lb);
+ else
+ xprintf("glp_intfeas1: row = %d: lower bound %g is non-i"
+ "nteger or out of range\n", i, row->lb);
+ ret = GLP_EDATA;
+ goto done;
+ }
+ temp = (int)row->ub;
+ if ((double)temp != row->ub)
+ { xprintf("glp_intfeas1: row = %d: upper bound %g is non-inte"
+ "ger or out of range\n", i, row->ub);
+ ret = GLP_EDATA;
+ goto done;
+ }
+ if (row->type == GLP_DB && row->lb > row->ub)
+ { xprintf("glp_intfeas1: row %d: lower bound %g is greater th"
+ "an upper bound %g\n", i, row->lb, row->ub);
+ ret = GLP_EBOUND;
+ goto done;
+ }
+ }
+ /* check the objective function */
+#if 1 /* 08/I-2017 by cmatraki & mao */
+ if (!use_bound)
+ { /* skip check if no obj. bound is specified */
+ goto skip;
+ }
+#endif
+ temp = (int)P->c0;
+ if ((double)temp != P->c0)
+ { xprintf("glp_intfeas1: objective constant term %g is non-integ"
+ "er or out of range\n", P->c0);
+ ret = GLP_EDATA;
+ goto done;
+ }
+ for (j = 1; j <= P->n; j++)
+ { temp = (int)P->col[j]->coef;
+ if ((double)temp != P->col[j]->coef)
+ { xprintf("glp_intfeas1: column %d: objective coefficient is "
+ "non-integer or out of range\n", j, P->col[j]->coef);
+ ret = GLP_EDATA;
+ goto done;
+ }
+ }
+#if 1 /* 08/I-2017 by cmatraki & mao */
+skip: ;
+#endif
+ /* save the objective function and set it to zero */
+ obj_ind = xcalloc(1+P->n, sizeof(int));
+ obj_val = xcalloc(1+P->n, sizeof(double));
+ obj_len = 0;
+ obj_ind[0] = 0;
+ obj_val[0] = P->c0;
+ P->c0 = 0.0;
+ for (j = 1; j <= P->n; j++)
+ { if (P->col[j]->coef != 0.0)
+ { obj_len++;
+ obj_ind[obj_len] = j;
+ obj_val[obj_len] = P->col[j]->coef;
+ P->col[j]->coef = 0.0;
+ }
+ }
+ /* add inequality to bound the objective function, if required */
+ if (!use_bound)
+ xprintf("Will search for ANY feasible solution\n");
+ else
+ { xprintf("Will search only for solution not worse than %d\n",
+ obj_bound);
+ obj_row = glp_add_rows(P, 1);
+ glp_set_mat_row(P, obj_row, obj_len, obj_ind, obj_val);
+ if (P->dir == GLP_MIN)
+ glp_set_row_bnds(P, obj_row,
+ GLP_UP, 0.0, (double)obj_bound - obj_val[0]);
+ else if (P->dir == GLP_MAX)
+ glp_set_row_bnds(P, obj_row,
+ GLP_LO, (double)obj_bound - obj_val[0], 0.0);
+ else
+ xassert(P != P);
+ }
+ /* create preprocessor workspace */
+ xprintf("Translating to CNF-SAT...\n");
+ xprintf("Original problem has %d row%s, %d column%s, and %d non-z"
+ "ero%s\n", P->m, P->m == 1 ? "" : "s", P->n, P->n == 1 ? "" :
+ "s", P->nnz, P->nnz == 1 ? "" : "s");
+ npp = npp_create_wksp();
+ /* load the original problem into the preprocessor workspace */
+ npp_load_prob(npp, P, GLP_OFF, GLP_MIP, GLP_OFF);
+ /* perform translation to SAT-CNF problem instance */
+ ret = npp_sat_encode_prob(npp);
+ if (ret == 0)
+ ;
+ else if (ret == GLP_ENOPFS)
+ xprintf("PROBLEM HAS NO INTEGER FEASIBLE SOLUTION\n");
+ else if (ret == GLP_ERANGE)
+ xprintf("glp_intfeas1: translation to SAT-CNF failed because o"
+ "f integer overflow\n");
+ else
+ xassert(ret != ret);
+ if (ret != 0)
+ goto done;
+ /* build SAT-CNF problem instance and try to solve it */
+ mip = glp_create_prob();
+ npp_build_prob(npp, mip);
+ ret = glp_minisat1(mip);
+ /* only integer feasible solution can be postprocessed */
+ if (!(mip->mip_stat == GLP_OPT || mip->mip_stat == GLP_FEAS))
+ { P->mip_stat = mip->mip_stat;
+ goto done;
+ }
+ /* postprocess the solution found */
+ npp_postprocess(npp, mip);
+ /* the transformed problem is no longer needed */
+ glp_delete_prob(mip), mip = NULL;
+ /* store solution to the original problem object */
+ npp_unload_sol(npp, P);
+ /* change the solution status to 'integer feasible' */
+ P->mip_stat = GLP_FEAS;
+ /* check integer feasibility */
+ for (i = 1; i <= P->m; i++)
+ { GLPROW *row;
+ GLPAIJ *aij;
+ double sum;
+ row = P->row[i];
+ sum = 0.0;
+ for (aij = row->ptr; aij != NULL; aij = aij->r_next)
+ sum += aij->val * aij->col->mipx;
+ xassert(sum == row->mipx);
+ if (row->type == GLP_LO || row->type == GLP_DB ||
+ row->type == GLP_FX)
+ xassert(sum >= row->lb);
+ if (row->type == GLP_UP || row->type == GLP_DB ||
+ row->type == GLP_FX)
+ xassert(sum <= row->ub);
+ }
+ /* compute value of the original objective function */
+ P->mip_obj = obj_val[0];
+ for (k = 1; k <= obj_len; k++)
+ P->mip_obj += obj_val[k] * P->col[obj_ind[k]]->mipx;
+ xprintf("Objective value = %17.9e\n", P->mip_obj);
+done: /* delete the transformed problem, if it exists */
+ if (mip != NULL)
+ glp_delete_prob(mip);
+ /* delete the preprocessor workspace, if it exists */
+ if (npp != NULL)
+ npp_delete_wksp(npp);
+ /* remove inequality used to bound the objective function */
+ if (obj_row > 0)
+ { int ind[1+1];
+ ind[1] = obj_row;
+ glp_del_rows(P, 1, ind);
+ }
+ /* restore the original objective function */
+ if (obj_ind != NULL)
+ { P->c0 = obj_val[0];
+ for (k = 1; k <= obj_len; k++)
+ P->col[obj_ind[k]]->coef = obj_val[k];
+ xfree(obj_ind);
+ xfree(obj_val);
+ }
+ return ret;
+}
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/api/maxffalg.c b/test/monniaux/glpk-4.65/src/api/maxffalg.c
new file mode 100644
index 00000000..0f3f9b04
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/api/maxffalg.c
@@ -0,0 +1,130 @@
+/* maxffalg.c (find maximal flow with Ford-Fulkerson algorithm) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* Copyright (C) 2009-2016 Andrew Makhorin, Department for Applied
+* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights
+* reserved. E-mail: <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 "env.h"
+#include "ffalg.h"
+#include "glpk.h"
+
+int glp_maxflow_ffalg(glp_graph *G, int s, int t, int a_cap,
+ double *sol, int a_x, int v_cut)
+{ /* find maximal flow with Ford-Fulkerson algorithm */
+ glp_vertex *v;
+ glp_arc *a;
+ int nv, na, i, k, flag, *tail, *head, *cap, *x, ret;
+ char *cut;
+ double temp;
+ if (!(1 <= s && s <= G->nv))
+ xerror("glp_maxflow_ffalg: s = %d; source node number out of r"
+ "ange\n", s);
+ if (!(1 <= t && t <= G->nv))
+ xerror("glp_maxflow_ffalg: t = %d: sink node number out of ran"
+ "ge\n", t);
+ if (s == t)
+ xerror("glp_maxflow_ffalg: s = t = %d; source and sink nodes m"
+ "ust be distinct\n", s);
+ if (a_cap >= 0 && a_cap > G->a_size - (int)sizeof(double))
+ xerror("glp_maxflow_ffalg: a_cap = %d; invalid offset\n",
+ a_cap);
+ if (v_cut >= 0 && v_cut > G->v_size - (int)sizeof(int))
+ xerror("glp_maxflow_ffalg: v_cut = %d; invalid offset\n",
+ v_cut);
+ /* allocate working arrays */
+ nv = G->nv;
+ na = G->na;
+ tail = xcalloc(1+na, sizeof(int));
+ head = xcalloc(1+na, sizeof(int));
+ cap = xcalloc(1+na, sizeof(int));
+ x = xcalloc(1+na, sizeof(int));
+ if (v_cut < 0)
+ cut = NULL;
+ else
+ cut = xcalloc(1+nv, sizeof(char));
+ /* copy the flow network */
+ k = 0;
+ for (i = 1; i <= G->nv; i++)
+ { v = G->v[i];
+ for (a = v->out; a != NULL; a = a->t_next)
+ { k++;
+ tail[k] = a->tail->i;
+ head[k] = a->head->i;
+ if (tail[k] == head[k])
+ { ret = GLP_EDATA;
+ goto done;
+ }
+ if (a_cap >= 0)
+ memcpy(&temp, (char *)a->data + a_cap, sizeof(double));
+ else
+ temp = 1.0;
+ if (!(0.0 <= temp && temp <= (double)INT_MAX &&
+ temp == floor(temp)))
+ { ret = GLP_EDATA;
+ goto done;
+ }
+ cap[k] = (int)temp;
+ }
+ }
+ xassert(k == na);
+ /* find maximal flow in the flow network */
+ ffalg(nv, na, tail, head, s, t, cap, x, cut);
+ ret = 0;
+ /* store solution components */
+ /* (objective function = total flow through the network) */
+ if (sol != NULL)
+ { temp = 0.0;
+ for (k = 1; k <= na; k++)
+ { if (tail[k] == s)
+ temp += (double)x[k];
+ else if (head[k] == s)
+ temp -= (double)x[k];
+ }
+ *sol = temp;
+ }
+ /* (arc flows) */
+ if (a_x >= 0)
+ { k = 0;
+ for (i = 1; i <= G->nv; i++)
+ { v = G->v[i];
+ for (a = v->out; a != NULL; a = a->t_next)
+ { temp = (double)x[++k];
+ memcpy((char *)a->data + a_x, &temp, sizeof(double));
+ }
+ }
+ }
+ /* (node flags) */
+ if (v_cut >= 0)
+ { for (i = 1; i <= G->nv; i++)
+ { v = G->v[i];
+ flag = cut[i];
+ memcpy((char *)v->data + v_cut, &flag, sizeof(int));
+ }
+ }
+done: /* free working arrays */
+ xfree(tail);
+ xfree(head);
+ xfree(cap);
+ xfree(x);
+ if (cut != NULL) xfree(cut);
+ return ret;
+}
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/api/maxflp.c b/test/monniaux/glpk-4.65/src/api/maxflp.c
new file mode 100644
index 00000000..1135b78c
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/api/maxflp.c
@@ -0,0 +1,114 @@
+/* maxflp.c (convert maximum flow problem to LP) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* Copyright (C) 2009-2016 Andrew Makhorin, Department for Applied
+* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights
+* reserved. E-mail: <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 "env.h"
+#include "glpk.h"
+
+/***********************************************************************
+* NAME
+*
+* glp_maxflow_lp - convert maximum flow problem to LP
+*
+* SYNOPSIS
+*
+* void glp_maxflow_lp(glp_prob *lp, glp_graph *G, int names, int s,
+* int t, int a_cap);
+*
+* DESCRIPTION
+*
+* The routine glp_maxflow_lp builds an LP problem, which corresponds
+* to the maximum flow problem on the specified network G. */
+
+void glp_maxflow_lp(glp_prob *lp, glp_graph *G, int names, int s,
+ int t, int a_cap)
+{ glp_vertex *v;
+ glp_arc *a;
+ int i, j, type, ind[1+2];
+ double cap, val[1+2];
+ if (!(names == GLP_ON || names == GLP_OFF))
+ xerror("glp_maxflow_lp: names = %d; invalid parameter\n",
+ names);
+ if (!(1 <= s && s <= G->nv))
+ xerror("glp_maxflow_lp: s = %d; source node number out of rang"
+ "e\n", s);
+ if (!(1 <= t && t <= G->nv))
+ xerror("glp_maxflow_lp: t = %d: sink node number out of range "
+ "\n", t);
+ if (s == t)
+ xerror("glp_maxflow_lp: s = t = %d; source and sink nodes must"
+ " be distinct\n", s);
+ if (a_cap >= 0 && a_cap > G->a_size - (int)sizeof(double))
+ xerror("glp_maxflow_lp: a_cap = %d; invalid offset\n", a_cap);
+ glp_erase_prob(lp);
+ if (names) glp_set_prob_name(lp, G->name);
+ glp_set_obj_dir(lp, GLP_MAX);
+ glp_add_rows(lp, G->nv);
+ for (i = 1; i <= G->nv; i++)
+ { v = G->v[i];
+ if (names) glp_set_row_name(lp, i, v->name);
+ if (i == s)
+ type = GLP_LO;
+ else if (i == t)
+ type = GLP_UP;
+ else
+ type = GLP_FX;
+ glp_set_row_bnds(lp, i, type, 0.0, 0.0);
+ }
+ if (G->na > 0) glp_add_cols(lp, G->na);
+ for (i = 1, j = 0; i <= G->nv; i++)
+ { v = G->v[i];
+ for (a = v->out; a != NULL; a = a->t_next)
+ { j++;
+ if (names)
+ { char name[50+1];
+ sprintf(name, "x[%d,%d]", a->tail->i, a->head->i);
+ xassert(strlen(name) < sizeof(name));
+ glp_set_col_name(lp, j, name);
+ }
+ if (a->tail->i != a->head->i)
+ { ind[1] = a->tail->i, val[1] = +1.0;
+ ind[2] = a->head->i, val[2] = -1.0;
+ glp_set_mat_col(lp, j, 2, ind, val);
+ }
+ if (a_cap >= 0)
+ memcpy(&cap, (char *)a->data + a_cap, sizeof(double));
+ else
+ cap = 1.0;
+ if (cap == DBL_MAX)
+ type = GLP_LO;
+ else if (cap != 0.0)
+ type = GLP_DB;
+ else
+ type = GLP_FX;
+ glp_set_col_bnds(lp, j, type, 0.0, cap);
+ if (a->tail->i == s)
+ glp_set_obj_coef(lp, j, +1.0);
+ else if (a->head->i == s)
+ glp_set_obj_coef(lp, j, -1.0);
+ }
+ }
+ xassert(j == G->na);
+ return;
+}
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/api/mcflp.c b/test/monniaux/glpk-4.65/src/api/mcflp.c
new file mode 100644
index 00000000..5cd24060
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/api/mcflp.c
@@ -0,0 +1,114 @@
+/* mcflp.c (convert minimum cost flow problem to LP) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* Copyright (C) 2009-2016 Andrew Makhorin, Department for Applied
+* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights
+* reserved. E-mail: <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 "env.h"
+#include "glpk.h"
+
+/***********************************************************************
+* NAME
+*
+* glp_mincost_lp - convert minimum cost flow problem to LP
+*
+* SYNOPSIS
+*
+* void glp_mincost_lp(glp_prob *lp, glp_graph *G, int names,
+* int v_rhs, int a_low, int a_cap, int a_cost);
+*
+* DESCRIPTION
+*
+* The routine glp_mincost_lp builds an LP problem, which corresponds
+* to the minimum cost flow problem on the specified network G. */
+
+void glp_mincost_lp(glp_prob *lp, glp_graph *G, int names, int v_rhs,
+ int a_low, int a_cap, int a_cost)
+{ glp_vertex *v;
+ glp_arc *a;
+ int i, j, type, ind[1+2];
+ double rhs, low, cap, cost, val[1+2];
+ if (!(names == GLP_ON || names == GLP_OFF))
+ xerror("glp_mincost_lp: names = %d; invalid parameter\n",
+ names);
+ if (v_rhs >= 0 && v_rhs > G->v_size - (int)sizeof(double))
+ xerror("glp_mincost_lp: v_rhs = %d; invalid offset\n", v_rhs);
+ if (a_low >= 0 && a_low > G->a_size - (int)sizeof(double))
+ xerror("glp_mincost_lp: a_low = %d; invalid offset\n", a_low);
+ if (a_cap >= 0 && a_cap > G->a_size - (int)sizeof(double))
+ xerror("glp_mincost_lp: a_cap = %d; invalid offset\n", a_cap);
+ if (a_cost >= 0 && a_cost > G->a_size - (int)sizeof(double))
+ xerror("glp_mincost_lp: a_cost = %d; invalid offset\n", a_cost)
+ ;
+ glp_erase_prob(lp);
+ if (names) glp_set_prob_name(lp, G->name);
+ if (G->nv > 0) glp_add_rows(lp, G->nv);
+ for (i = 1; i <= G->nv; i++)
+ { v = G->v[i];
+ if (names) glp_set_row_name(lp, i, v->name);
+ if (v_rhs >= 0)
+ memcpy(&rhs, (char *)v->data + v_rhs, sizeof(double));
+ else
+ rhs = 0.0;
+ glp_set_row_bnds(lp, i, GLP_FX, rhs, rhs);
+ }
+ if (G->na > 0) glp_add_cols(lp, G->na);
+ for (i = 1, j = 0; i <= G->nv; i++)
+ { v = G->v[i];
+ for (a = v->out; a != NULL; a = a->t_next)
+ { j++;
+ if (names)
+ { char name[50+1];
+ sprintf(name, "x[%d,%d]", a->tail->i, a->head->i);
+ xassert(strlen(name) < sizeof(name));
+ glp_set_col_name(lp, j, name);
+ }
+ if (a->tail->i != a->head->i)
+ { ind[1] = a->tail->i, val[1] = +1.0;
+ ind[2] = a->head->i, val[2] = -1.0;
+ glp_set_mat_col(lp, j, 2, ind, val);
+ }
+ if (a_low >= 0)
+ memcpy(&low, (char *)a->data + a_low, sizeof(double));
+ else
+ low = 0.0;
+ if (a_cap >= 0)
+ memcpy(&cap, (char *)a->data + a_cap, sizeof(double));
+ else
+ cap = 1.0;
+ if (cap == DBL_MAX)
+ type = GLP_LO;
+ else if (low != cap)
+ type = GLP_DB;
+ else
+ type = GLP_FX;
+ glp_set_col_bnds(lp, j, type, low, cap);
+ if (a_cost >= 0)
+ memcpy(&cost, (char *)a->data + a_cost, sizeof(double));
+ else
+ cost = 0.0;
+ glp_set_obj_coef(lp, j, cost);
+ }
+ }
+ xassert(j == G->na);
+ return;
+}
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/api/mcfokalg.c b/test/monniaux/glpk-4.65/src/api/mcfokalg.c
new file mode 100644
index 00000000..786dc71b
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/api/mcfokalg.c
@@ -0,0 +1,221 @@
+/* mcfokalg.c (find minimum-cost flow with out-of-kilter algorithm) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* Copyright (C) 2009-2016 Andrew Makhorin, Department for Applied
+* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights
+* reserved. E-mail: <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 "env.h"
+#include "glpk.h"
+#include "okalg.h"
+
+int glp_mincost_okalg(glp_graph *G, int v_rhs, int a_low, int a_cap,
+ int a_cost, double *sol, int a_x, int v_pi)
+{ /* find minimum-cost flow with out-of-kilter algorithm */
+ glp_vertex *v;
+ glp_arc *a;
+ int nv, na, i, k, s, t, *tail, *head, *low, *cap, *cost, *x, *pi,
+ ret;
+ double sum, temp;
+ if (v_rhs >= 0 && v_rhs > G->v_size - (int)sizeof(double))
+ xerror("glp_mincost_okalg: v_rhs = %d; invalid offset\n",
+ v_rhs);
+ if (a_low >= 0 && a_low > G->a_size - (int)sizeof(double))
+ xerror("glp_mincost_okalg: a_low = %d; invalid offset\n",
+ a_low);
+ if (a_cap >= 0 && a_cap > G->a_size - (int)sizeof(double))
+ xerror("glp_mincost_okalg: a_cap = %d; invalid offset\n",
+ a_cap);
+ if (a_cost >= 0 && a_cost > G->a_size - (int)sizeof(double))
+ xerror("glp_mincost_okalg: a_cost = %d; invalid offset\n",
+ a_cost);
+ if (a_x >= 0 && a_x > G->a_size - (int)sizeof(double))
+ xerror("glp_mincost_okalg: a_x = %d; invalid offset\n", a_x);
+ if (v_pi >= 0 && v_pi > G->v_size - (int)sizeof(double))
+ xerror("glp_mincost_okalg: v_pi = %d; invalid offset\n", v_pi);
+ /* s is artificial source node */
+ s = G->nv + 1;
+ /* t is artificial sink node */
+ t = s + 1;
+ /* nv is the total number of nodes in the resulting network */
+ nv = t;
+ /* na is the total number of arcs in the resulting network */
+ na = G->na + 1;
+ for (i = 1; i <= G->nv; i++)
+ { v = G->v[i];
+ if (v_rhs >= 0)
+ memcpy(&temp, (char *)v->data + v_rhs, sizeof(double));
+ else
+ temp = 0.0;
+ if (temp != 0.0) na++;
+ }
+ /* allocate working arrays */
+ tail = xcalloc(1+na, sizeof(int));
+ head = xcalloc(1+na, sizeof(int));
+ low = xcalloc(1+na, sizeof(int));
+ cap = xcalloc(1+na, sizeof(int));
+ cost = xcalloc(1+na, sizeof(int));
+ x = xcalloc(1+na, sizeof(int));
+ pi = xcalloc(1+nv, sizeof(int));
+ /* construct the resulting network */
+ k = 0;
+ /* (original arcs) */
+ for (i = 1; i <= G->nv; i++)
+ { v = G->v[i];
+ for (a = v->out; a != NULL; a = a->t_next)
+ { k++;
+ tail[k] = a->tail->i;
+ head[k] = a->head->i;
+ if (tail[k] == head[k])
+ { ret = GLP_EDATA;
+ goto done;
+ }
+ if (a_low >= 0)
+ memcpy(&temp, (char *)a->data + a_low, sizeof(double));
+ else
+ temp = 0.0;
+ if (!(0.0 <= temp && temp <= (double)INT_MAX &&
+ temp == floor(temp)))
+ { ret = GLP_EDATA;
+ goto done;
+ }
+ low[k] = (int)temp;
+ if (a_cap >= 0)
+ memcpy(&temp, (char *)a->data + a_cap, sizeof(double));
+ else
+ temp = 1.0;
+ if (!((double)low[k] <= temp && temp <= (double)INT_MAX &&
+ temp == floor(temp)))
+ { ret = GLP_EDATA;
+ goto done;
+ }
+ cap[k] = (int)temp;
+ if (a_cost >= 0)
+ memcpy(&temp, (char *)a->data + a_cost, sizeof(double));
+ else
+ temp = 0.0;
+ if (!(fabs(temp) <= (double)INT_MAX && temp == floor(temp)))
+ { ret = GLP_EDATA;
+ goto done;
+ }
+ cost[k] = (int)temp;
+ }
+ }
+ /* (artificial arcs) */
+ sum = 0.0;
+ for (i = 1; i <= G->nv; i++)
+ { v = G->v[i];
+ if (v_rhs >= 0)
+ memcpy(&temp, (char *)v->data + v_rhs, sizeof(double));
+ else
+ temp = 0.0;
+ if (!(fabs(temp) <= (double)INT_MAX && temp == floor(temp)))
+ { ret = GLP_EDATA;
+ goto done;
+ }
+ if (temp > 0.0)
+ { /* artificial arc from s to original source i */
+ k++;
+ tail[k] = s;
+ head[k] = i;
+ low[k] = cap[k] = (int)(+temp); /* supply */
+ cost[k] = 0;
+ sum += (double)temp;
+ }
+ else if (temp < 0.0)
+ { /* artificial arc from original sink i to t */
+ k++;
+ tail[k] = i;
+ head[k] = t;
+ low[k] = cap[k] = (int)(-temp); /* demand */
+ cost[k] = 0;
+ }
+ }
+ /* (feedback arc from t to s) */
+ k++;
+ xassert(k == na);
+ tail[k] = t;
+ head[k] = s;
+ if (sum > (double)INT_MAX)
+ { ret = GLP_EDATA;
+ goto done;
+ }
+ low[k] = cap[k] = (int)sum; /* total supply/demand */
+ cost[k] = 0;
+ /* find minimal-cost circulation in the resulting network */
+ ret = okalg(nv, na, tail, head, low, cap, cost, x, pi);
+ switch (ret)
+ { case 0:
+ /* optimal circulation found */
+ ret = 0;
+ break;
+ case 1:
+ /* no feasible circulation exists */
+ ret = GLP_ENOPFS;
+ break;
+ case 2:
+ /* integer overflow occured */
+ ret = GLP_ERANGE;
+ goto done;
+ case 3:
+ /* optimality test failed (logic error) */
+ ret = GLP_EFAIL;
+ goto done;
+ default:
+ xassert(ret != ret);
+ }
+ /* store solution components */
+ /* (objective function = the total cost) */
+ if (sol != NULL)
+ { temp = 0.0;
+ for (k = 1; k <= na; k++)
+ temp += (double)cost[k] * (double)x[k];
+ *sol = temp;
+ }
+ /* (arc flows) */
+ if (a_x >= 0)
+ { k = 0;
+ for (i = 1; i <= G->nv; i++)
+ { v = G->v[i];
+ for (a = v->out; a != NULL; a = a->t_next)
+ { temp = (double)x[++k];
+ memcpy((char *)a->data + a_x, &temp, sizeof(double));
+ }
+ }
+ }
+ /* (node potentials = Lagrange multipliers) */
+ if (v_pi >= 0)
+ { for (i = 1; i <= G->nv; i++)
+ { v = G->v[i];
+ temp = - (double)pi[i];
+ memcpy((char *)v->data + v_pi, &temp, sizeof(double));
+ }
+ }
+done: /* free working arrays */
+ xfree(tail);
+ xfree(head);
+ xfree(low);
+ xfree(cap);
+ xfree(cost);
+ xfree(x);
+ xfree(pi);
+ return ret;
+}
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/api/mcfrelax.c b/test/monniaux/glpk-4.65/src/api/mcfrelax.c
new file mode 100644
index 00000000..9b34949a
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/api/mcfrelax.c
@@ -0,0 +1,251 @@
+/* mcfrelax.c (find minimum-cost flow with RELAX-IV) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* Copyright (C) 2013-2016 Andrew Makhorin, Department for Applied
+* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights
+* reserved. E-mail: <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 "env.h"
+#include "glpk.h"
+#include "relax4.h"
+
+static int overflow(int u, int v)
+{ /* check for integer overflow on computing u + v */
+ if (u > 0 && v > 0 && u + v < 0) return 1;
+ if (u < 0 && v < 0 && u + v > 0) return 1;
+ return 0;
+}
+
+int glp_mincost_relax4(glp_graph *G, int v_rhs, int a_low, int a_cap,
+ int a_cost, int crash, double *sol, int a_x, int a_rc)
+{ /* find minimum-cost flow with Bertsekas-Tseng relaxation method
+ (RELAX-IV) */
+ glp_vertex *v;
+ glp_arc *a;
+ struct relax4_csa csa;
+ int i, k, large, n, na, ret;
+ double cap, cost, low, rc, rhs, sum, x;
+ if (v_rhs >= 0 && v_rhs > G->v_size - (int)sizeof(double))
+ xerror("glp_mincost_relax4: v_rhs = %d; invalid offset\n",
+ v_rhs);
+ if (a_low >= 0 && a_low > G->a_size - (int)sizeof(double))
+ xerror("glp_mincost_relax4: a_low = %d; invalid offset\n",
+ a_low);
+ if (a_cap >= 0 && a_cap > G->a_size - (int)sizeof(double))
+ xerror("glp_mincost_relax4: a_cap = %d; invalid offset\n",
+ a_cap);
+ if (a_cost >= 0 && a_cost > G->a_size - (int)sizeof(double))
+ xerror("glp_mincost_relax4: a_cost = %d; invalid offset\n",
+ a_cost);
+ if (a_x >= 0 && a_x > G->a_size - (int)sizeof(double))
+ xerror("glp_mincost_relax4: a_x = %d; invalid offset\n",
+ a_x);
+ if (a_rc >= 0 && a_rc > G->a_size - (int)sizeof(double))
+ xerror("glp_mincost_relax4: a_rc = %d; invalid offset\n",
+ a_rc);
+ csa.n = n = G->nv; /* number of nodes */
+ csa.na = na = G->na; /* number of arcs */
+ csa.large = large = INT_MAX / 4;
+ csa.repeat = 0;
+ csa.crash = crash;
+ /* allocate working arrays */
+ csa.startn = xcalloc(1+na, sizeof(int));
+ csa.endn = xcalloc(1+na, sizeof(int));
+ csa.fou = xcalloc(1+n, sizeof(int));
+ csa.nxtou = xcalloc(1+na, sizeof(int));
+ csa.fin = xcalloc(1+n, sizeof(int));
+ csa.nxtin = xcalloc(1+na, sizeof(int));
+ csa.rc = xcalloc(1+na, sizeof(int));
+ csa.u = xcalloc(1+na, sizeof(int));
+ csa.dfct = xcalloc(1+n, sizeof(int));
+ csa.x = xcalloc(1+na, sizeof(int));
+ csa.label = xcalloc(1+n, sizeof(int));
+ csa.prdcsr = xcalloc(1+n, sizeof(int));
+ csa.save = xcalloc(1+na, sizeof(int));
+ csa.tfstou = xcalloc(1+n, sizeof(int));
+ csa.tnxtou = xcalloc(1+na, sizeof(int));
+ csa.tfstin = xcalloc(1+n, sizeof(int));
+ csa.tnxtin = xcalloc(1+na, sizeof(int));
+ csa.nxtqueue = xcalloc(1+n, sizeof(int));
+ csa.scan = xcalloc(1+n, sizeof(char));
+ csa.mark = xcalloc(1+n, sizeof(char));
+ if (crash)
+ { csa.extend_arc = xcalloc(1+n, sizeof(int));
+ csa.sb_level = xcalloc(1+n, sizeof(int));
+ csa.sb_arc = xcalloc(1+n, sizeof(int));
+ }
+ else
+ { csa.extend_arc = NULL;
+ csa.sb_level = NULL;
+ csa.sb_arc = NULL;
+ }
+ /* scan nodes */
+ for (i = 1; i <= n; i++)
+ { v = G->v[i];
+ /* get supply at i-th node */
+ if (v_rhs >= 0)
+ memcpy(&rhs, (char *)v->data + v_rhs, sizeof(double));
+ else
+ rhs = 0.0;
+ if (!(fabs(rhs) <= (double)large && rhs == floor(rhs)))
+ { ret = GLP_EDATA;
+ goto done;
+ }
+ /* set demand at i-th node */
+ csa.dfct[i] = -(int)rhs;
+ }
+ /* scan arcs */
+ k = 0;
+ for (i = 1; i <= n; i++)
+ { v = G->v[i];
+ for (a = v->out; a != NULL; a = a->t_next)
+ { k++;
+ /* set endpoints of k-th arc */
+ if (a->tail->i == a->head->i)
+ { /* self-loops not allowed */
+ ret = GLP_EDATA;
+ goto done;
+ }
+ csa.startn[k] = a->tail->i;
+ csa.endn[k] = a->head->i;
+ /* set per-unit cost for k-th arc flow */
+ if (a_cost >= 0)
+ memcpy(&cost, (char *)a->data + a_cost, sizeof(double));
+ else
+ cost = 0.0;
+ if (!(fabs(cost) <= (double)large && cost == floor(cost)))
+ { ret = GLP_EDATA;
+ goto done;
+ }
+ csa.rc[k] = (int)cost;
+ /* get lower bound for k-th arc flow */
+ if (a_low >= 0)
+ memcpy(&low, (char *)a->data + a_low, sizeof(double));
+ else
+ low = 0.0;
+ if (!(0.0 <= low && low <= (double)large &&
+ low == floor(low)))
+ { ret = GLP_EDATA;
+ goto done;
+ }
+ /* get upper bound for k-th arc flow */
+ if (a_cap >= 0)
+ memcpy(&cap, (char *)a->data + a_cap, sizeof(double));
+ else
+ cap = 1.0;
+ if (!(low <= cap && cap <= (double)large &&
+ cap == floor(cap)))
+ { ret = GLP_EDATA;
+ goto done;
+ }
+ /* substitute x = x' + low, where 0 <= x' <= cap - low */
+ csa.u[k] = (int)(cap - low);
+ /* correct demands at endpoints of k-th arc */
+ if (overflow(csa.dfct[a->tail->i], +low))
+ { ret = GLP_ERANGE;
+ goto done;
+ }
+#if 0 /* 29/IX-2017 */
+ csa.dfct[a->tail->i] += low;
+#else
+ csa.dfct[a->tail->i] += (int)low;
+#endif
+ if (overflow(csa.dfct[a->head->i], -low))
+ { ret = GLP_ERANGE;
+ goto done;
+ }
+#if 0 /* 29/IX-2017 */
+ csa.dfct[a->head->i] -= low;
+#else
+ csa.dfct[a->head->i] -= (int)low;
+#endif
+ }
+ }
+ /* construct linked list for network topology */
+ relax4_inidat(&csa);
+ /* find minimum-cost flow */
+ ret = relax4(&csa);
+ if (ret != 0)
+ { /* problem is found to be infeasible */
+ xassert(1 <= ret && ret <= 8);
+ ret = GLP_ENOPFS;
+ goto done;
+ }
+ /* store solution */
+ sum = 0.0;
+ k = 0;
+ for (i = 1; i <= n; i++)
+ { v = G->v[i];
+ for (a = v->out; a != NULL; a = a->t_next)
+ { k++;
+ /* get lower bound for k-th arc flow */
+ if (a_low >= 0)
+ memcpy(&low, (char *)a->data + a_low, sizeof(double));
+ else
+ low = 0.0;
+ /* store original flow x = x' + low thru k-th arc */
+ x = (double)csa.x[k] + low;
+ if (a_x >= 0)
+ memcpy((char *)a->data + a_x, &x, sizeof(double));
+ /* store reduced cost for k-th arc flow */
+ rc = (double)csa.rc[k];
+ if (a_rc >= 0)
+ memcpy((char *)a->data + a_rc, &rc, sizeof(double));
+ /* get per-unit cost for k-th arc flow */
+ if (a_cost >= 0)
+ memcpy(&cost, (char *)a->data + a_cost, sizeof(double));
+ else
+ cost = 0.0;
+ /* compute the total cost */
+ sum += cost * x;
+ }
+ }
+ /* store the total cost */
+ if (sol != NULL)
+ *sol = sum;
+done: /* free working arrays */
+ xfree(csa.startn);
+ xfree(csa.endn);
+ xfree(csa.fou);
+ xfree(csa.nxtou);
+ xfree(csa.fin);
+ xfree(csa.nxtin);
+ xfree(csa.rc);
+ xfree(csa.u);
+ xfree(csa.dfct);
+ xfree(csa.x);
+ xfree(csa.label);
+ xfree(csa.prdcsr);
+ xfree(csa.save);
+ xfree(csa.tfstou);
+ xfree(csa.tnxtou);
+ xfree(csa.tfstin);
+ xfree(csa.tnxtin);
+ xfree(csa.nxtqueue);
+ xfree(csa.scan);
+ xfree(csa.mark);
+ if (crash)
+ { xfree(csa.extend_arc);
+ xfree(csa.sb_level);
+ xfree(csa.sb_arc);
+ }
+ return ret;
+}
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/api/minisat1.c b/test/monniaux/glpk-4.65/src/api/minisat1.c
new file mode 100644
index 00000000..a669c487
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/api/minisat1.c
@@ -0,0 +1,161 @@
+/* minisat1.c (driver to MiniSat solver) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* Copyright (C) 2011-2016 Andrew Makhorin, Department for Applied
+* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights
+* reserved. E-mail: <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 "env.h"
+#include "minisat.h"
+#include "prob.h"
+
+int glp_minisat1(glp_prob *P)
+{ /* solve CNF-SAT problem with MiniSat solver */
+ solver *s;
+ GLPAIJ *aij;
+ int i, j, len, ret, *ind;
+ double sum;
+#if 0 /* 04/IV-2016 */
+ /* check problem object */
+ if (P == NULL || P->magic != GLP_PROB_MAGIC)
+ xerror("glp_minisat1: P = %p; invalid problem object\n",
+ P);
+#endif
+ if (P->tree != NULL)
+ xerror("glp_minisat1: operation not allowed\n");
+ /* integer solution is currently undefined */
+ P->mip_stat = GLP_UNDEF;
+ P->mip_obj = 0.0;
+ /* check that problem object encodes CNF-SAT instance */
+ if (glp_check_cnfsat(P) != 0)
+ { xprintf("glp_minisat1: problem object does not encode CNF-SAT "
+ "instance\n");
+ ret = GLP_EDATA;
+ goto done;
+ }
+#if 0 /* 08/I-2017 by cmatraki */
+#if 1 /* 07/XI-2015 */
+ if (sizeof(void *) != sizeof(int))
+ { xprintf("glp_minisat1: sorry, MiniSat solver is not supported "
+ "on 64-bit platforms\n");
+ ret = GLP_EFAIL;
+ goto done;
+ }
+#endif
+#else
+ if (sizeof(void *) != sizeof(size_t))
+ { xprintf("glp_minisat1: sorry, MiniSat solver is not supported "
+ "on this platform\n");
+ ret = GLP_EFAIL;
+ goto done;
+ }
+#endif
+ /* solve CNF-SAT problem */
+ xprintf("Solving CNF-SAT problem...\n");
+ xprintf("Instance has %d variable%s, %d clause%s, and %d literal%"
+ "s\n", P->n, P->n == 1 ? "" : "s", P->m, P->m == 1 ? "" : "s",
+ P->nnz, P->nnz == 1 ? "" : "s");
+ /* if CNF-SAT has no clauses, it is satisfiable */
+ if (P->m == 0)
+ { P->mip_stat = GLP_OPT;
+ for (j = 1; j <= P->n; j++)
+ P->col[j]->mipx = 0.0;
+ goto fini;
+ }
+ /* if CNF-SAT has an empty clause, it is unsatisfiable */
+ for (i = 1; i <= P->m; i++)
+ { if (P->row[i]->ptr == NULL)
+ { P->mip_stat = GLP_NOFEAS;
+ goto fini;
+ }
+ }
+ /* prepare input data for the solver */
+ s = solver_new();
+ solver_setnvars(s, P->n);
+ ind = xcalloc(1+P->n, sizeof(int));
+ for (i = 1; i <= P->m; i++)
+ { len = 0;
+ for (aij = P->row[i]->ptr; aij != NULL; aij = aij->r_next)
+ { ind[++len] = toLit(aij->col->j-1);
+ if (aij->val < 0.0)
+ ind[len] = lit_neg(ind[len]);
+ }
+ xassert(len > 0);
+#if 0 /* 08/I-2017 by cmatraki */
+ xassert(solver_addclause(s, &ind[1], &ind[1+len]));
+#else
+ if (!solver_addclause(s, &ind[1], &ind[1+len]))
+ { /* found trivial conflict */
+ xfree(ind);
+ solver_delete(s);
+ P->mip_stat = GLP_NOFEAS;
+ goto fini;
+ }
+#endif
+ }
+ xfree(ind);
+ /* call the solver */
+ s->verbosity = 1;
+ if (solver_solve(s, 0, 0))
+ { /* instance is reported as satisfiable */
+ P->mip_stat = GLP_OPT;
+ /* copy solution to the problem object */
+ xassert(s->model.size == P->n);
+ for (j = 1; j <= P->n; j++)
+ { P->col[j]->mipx =
+ s->model.ptr[j-1] == l_True ? 1.0 : 0.0;
+ }
+ /* compute row values */
+ for (i = 1; i <= P->m; i++)
+ { sum = 0;
+ for (aij = P->row[i]->ptr; aij != NULL; aij = aij->r_next)
+ sum += aij->val * aij->col->mipx;
+ P->row[i]->mipx = sum;
+ }
+ /* check integer feasibility */
+ for (i = 1; i <= P->m; i++)
+ { if (P->row[i]->mipx < P->row[i]->lb)
+ { /* solution is wrong */
+ P->mip_stat = GLP_UNDEF;
+ break;
+ }
+ }
+ }
+ else
+ { /* instance is reported as unsatisfiable */
+ P->mip_stat = GLP_NOFEAS;
+ }
+ solver_delete(s);
+fini: /* report the instance status */
+ if (P->mip_stat == GLP_OPT)
+ { xprintf("SATISFIABLE\n");
+ ret = 0;
+ }
+ else if (P->mip_stat == GLP_NOFEAS)
+ { xprintf("UNSATISFIABLE\n");
+ ret = 0;
+ }
+ else
+ { xprintf("glp_minisat1: solver failed\n");
+ ret = GLP_EFAIL;
+ }
+done: return ret;
+}
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/api/mpl.c b/test/monniaux/glpk-4.65/src/api/mpl.c
new file mode 100644
index 00000000..cfa6f75b
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/api/mpl.c
@@ -0,0 +1,269 @@
+/* mpl.c (processing model in GNU MathProg language) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* Copyright (C) 2008-2016 Andrew Makhorin, Department for Applied
+* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights
+* reserved. E-mail: <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 "mpl.h"
+#include "prob.h"
+
+glp_tran *glp_mpl_alloc_wksp(void)
+{ /* allocate the MathProg translator workspace */
+ glp_tran *tran;
+ tran = mpl_initialize();
+ return tran;
+}
+
+void glp_mpl_init_rand(glp_tran *tran, int seed)
+{ /* initialize pseudo-random number generator */
+ if (tran->phase != 0)
+ xerror("glp_mpl_init_rand: invalid call sequence\n");
+ rng_init_rand(tran->rand, seed);
+ return;
+}
+
+int glp_mpl_read_model(glp_tran *tran, const char *fname, int skip)
+{ /* read and translate model section */
+ int ret;
+ if (tran->phase != 0)
+ xerror("glp_mpl_read_model: invalid call sequence\n");
+ ret = mpl_read_model(tran, (char *)fname, skip);
+ if (ret == 1 || ret == 2)
+ ret = 0;
+ else if (ret == 4)
+ ret = 1;
+ else
+ xassert(ret != ret);
+ return ret;
+}
+
+int glp_mpl_read_data(glp_tran *tran, const char *fname)
+{ /* read and translate data section */
+ int ret;
+ if (!(tran->phase == 1 || tran->phase == 2))
+ xerror("glp_mpl_read_data: invalid call sequence\n");
+ ret = mpl_read_data(tran, (char *)fname);
+ if (ret == 2)
+ ret = 0;
+ else if (ret == 4)
+ ret = 1;
+ else
+ xassert(ret != ret);
+ return ret;
+}
+
+int glp_mpl_generate(glp_tran *tran, const char *fname)
+{ /* generate the model */
+ int ret;
+ if (!(tran->phase == 1 || tran->phase == 2))
+ xerror("glp_mpl_generate: invalid call sequence\n");
+ ret = mpl_generate(tran, (char *)fname);
+ if (ret == 3)
+ ret = 0;
+ else if (ret == 4)
+ ret = 1;
+ return ret;
+}
+
+void glp_mpl_build_prob(glp_tran *tran, glp_prob *prob)
+{ /* build LP/MIP problem instance from the model */
+ int m, n, i, j, t, kind, type, len, *ind;
+ double lb, ub, *val;
+ if (tran->phase != 3)
+ xerror("glp_mpl_build_prob: invalid call sequence\n");
+ /* erase the problem object */
+ glp_erase_prob(prob);
+ /* set problem name */
+ glp_set_prob_name(prob, mpl_get_prob_name(tran));
+ /* build rows (constraints) */
+ m = mpl_get_num_rows(tran);
+ if (m > 0)
+ glp_add_rows(prob, m);
+ for (i = 1; i <= m; i++)
+ { /* set row name */
+ glp_set_row_name(prob, i, mpl_get_row_name(tran, i));
+ /* set row bounds */
+ type = mpl_get_row_bnds(tran, i, &lb, &ub);
+ switch (type)
+ { case MPL_FR: type = GLP_FR; break;
+ case MPL_LO: type = GLP_LO; break;
+ case MPL_UP: type = GLP_UP; break;
+ case MPL_DB: type = GLP_DB; break;
+ case MPL_FX: type = GLP_FX; break;
+ default: xassert(type != type);
+ }
+ if (type == GLP_DB && fabs(lb - ub) < 1e-9 * (1.0 + fabs(lb)))
+ { type = GLP_FX;
+ if (fabs(lb) <= fabs(ub)) ub = lb; else lb = ub;
+ }
+ glp_set_row_bnds(prob, i, type, lb, ub);
+ /* warn about non-zero constant term */
+ if (mpl_get_row_c0(tran, i) != 0.0)
+ xprintf("glp_mpl_build_prob: row %s; constant term %.12g ig"
+ "nored\n",
+ mpl_get_row_name(tran, i), mpl_get_row_c0(tran, i));
+ }
+ /* build columns (variables) */
+ n = mpl_get_num_cols(tran);
+ if (n > 0)
+ glp_add_cols(prob, n);
+ for (j = 1; j <= n; j++)
+ { /* set column name */
+ glp_set_col_name(prob, j, mpl_get_col_name(tran, j));
+ /* set column kind */
+ kind = mpl_get_col_kind(tran, j);
+ switch (kind)
+ { case MPL_NUM:
+ break;
+ case MPL_INT:
+ case MPL_BIN:
+ glp_set_col_kind(prob, j, GLP_IV);
+ break;
+ default:
+ xassert(kind != kind);
+ }
+ /* set column bounds */
+ type = mpl_get_col_bnds(tran, j, &lb, &ub);
+ switch (type)
+ { case MPL_FR: type = GLP_FR; break;
+ case MPL_LO: type = GLP_LO; break;
+ case MPL_UP: type = GLP_UP; break;
+ case MPL_DB: type = GLP_DB; break;
+ case MPL_FX: type = GLP_FX; break;
+ default: xassert(type != type);
+ }
+ if (kind == MPL_BIN)
+ { if (type == GLP_FR || type == GLP_UP || lb < 0.0) lb = 0.0;
+ if (type == GLP_FR || type == GLP_LO || ub > 1.0) ub = 1.0;
+ type = GLP_DB;
+ }
+ if (type == GLP_DB && fabs(lb - ub) < 1e-9 * (1.0 + fabs(lb)))
+ { type = GLP_FX;
+ if (fabs(lb) <= fabs(ub)) ub = lb; else lb = ub;
+ }
+ glp_set_col_bnds(prob, j, type, lb, ub);
+ }
+ /* load the constraint matrix */
+ ind = xcalloc(1+n, sizeof(int));
+ val = xcalloc(1+n, sizeof(double));
+ for (i = 1; i <= m; i++)
+ { len = mpl_get_mat_row(tran, i, ind, val);
+ glp_set_mat_row(prob, i, len, ind, val);
+ }
+ /* build objective function (the first objective is used) */
+ for (i = 1; i <= m; i++)
+ { kind = mpl_get_row_kind(tran, i);
+ if (kind == MPL_MIN || kind == MPL_MAX)
+ { /* set objective name */
+ glp_set_obj_name(prob, mpl_get_row_name(tran, i));
+ /* set optimization direction */
+ glp_set_obj_dir(prob, kind == MPL_MIN ? GLP_MIN : GLP_MAX);
+ /* set constant term */
+ glp_set_obj_coef(prob, 0, mpl_get_row_c0(tran, i));
+ /* set objective coefficients */
+ len = mpl_get_mat_row(tran, i, ind, val);
+ for (t = 1; t <= len; t++)
+ glp_set_obj_coef(prob, ind[t], val[t]);
+ break;
+ }
+ }
+ /* free working arrays */
+ xfree(ind);
+ xfree(val);
+ return;
+}
+
+int glp_mpl_postsolve(glp_tran *tran, glp_prob *prob, int sol)
+{ /* postsolve the model */
+ int i, j, m, n, stat, ret;
+ double prim, dual;
+ if (!(tran->phase == 3 && !tran->flag_p))
+ xerror("glp_mpl_postsolve: invalid call sequence\n");
+ if (!(sol == GLP_SOL || sol == GLP_IPT || sol == GLP_MIP))
+ xerror("glp_mpl_postsolve: sol = %d; invalid parameter\n",
+ sol);
+ m = mpl_get_num_rows(tran);
+ n = mpl_get_num_cols(tran);
+ if (!(m == glp_get_num_rows(prob) &&
+ n == glp_get_num_cols(prob)))
+ xerror("glp_mpl_postsolve: wrong problem object\n");
+ if (!mpl_has_solve_stmt(tran))
+ { ret = 0;
+ goto done;
+ }
+ for (i = 1; i <= m; i++)
+ { if (sol == GLP_SOL)
+ { stat = glp_get_row_stat(prob, i);
+ prim = glp_get_row_prim(prob, i);
+ dual = glp_get_row_dual(prob, i);
+ }
+ else if (sol == GLP_IPT)
+ { stat = 0;
+ prim = glp_ipt_row_prim(prob, i);
+ dual = glp_ipt_row_dual(prob, i);
+ }
+ else if (sol == GLP_MIP)
+ { stat = 0;
+ prim = glp_mip_row_val(prob, i);
+ dual = 0.0;
+ }
+ else
+ xassert(sol != sol);
+ if (fabs(prim) < 1e-9) prim = 0.0;
+ if (fabs(dual) < 1e-9) dual = 0.0;
+ mpl_put_row_soln(tran, i, stat, prim, dual);
+ }
+ for (j = 1; j <= n; j++)
+ { if (sol == GLP_SOL)
+ { stat = glp_get_col_stat(prob, j);
+ prim = glp_get_col_prim(prob, j);
+ dual = glp_get_col_dual(prob, j);
+ }
+ else if (sol == GLP_IPT)
+ { stat = 0;
+ prim = glp_ipt_col_prim(prob, j);
+ dual = glp_ipt_col_dual(prob, j);
+ }
+ else if (sol == GLP_MIP)
+ { stat = 0;
+ prim = glp_mip_col_val(prob, j);
+ dual = 0.0;
+ }
+ else
+ xassert(sol != sol);
+ if (fabs(prim) < 1e-9) prim = 0.0;
+ if (fabs(dual) < 1e-9) dual = 0.0;
+ mpl_put_col_soln(tran, j, stat, prim, dual);
+ }
+ ret = mpl_postsolve(tran);
+ if (ret == 3)
+ ret = 0;
+ else if (ret == 4)
+ ret = 1;
+done: return ret;
+}
+
+void glp_mpl_free_wksp(glp_tran *tran)
+{ /* free the MathProg translator workspace */
+ mpl_terminate(tran);
+ return;
+}
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/api/mps.c b/test/monniaux/glpk-4.65/src/api/mps.c
new file mode 100644
index 00000000..3bdc6db1
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/api/mps.c
@@ -0,0 +1,1452 @@
+/* mps.c (MPS format routines) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* Copyright (C) 2008-2016 Andrew Makhorin, Department for Applied
+* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights
+* reserved. E-mail: <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 "env.h"
+#include "misc.h"
+#include "prob.h"
+
+#define xfprintf glp_format
+
+/***********************************************************************
+* NAME
+*
+* glp_init_mpscp - initialize MPS format control parameters
+*
+* SYNOPSIS
+*
+* void glp_init_mpscp(glp_mpscp *parm);
+*
+* DESCRIPTION
+*
+* The routine glp_init_mpscp initializes control parameters, which are
+* used by the MPS input/output routines glp_read_mps and glp_write_mps,
+* with default values.
+*
+* Default values of the control parameters are stored in the glp_mpscp
+* structure, which the parameter parm points to. */
+
+void glp_init_mpscp(glp_mpscp *parm)
+{ parm->blank = '\0';
+ parm->obj_name = NULL;
+ parm->tol_mps = 1e-12;
+ return;
+}
+
+static void check_parm(const char *func, const glp_mpscp *parm)
+{ /* check control parameters */
+ if (!(0x00 <= parm->blank && parm->blank <= 0xFF) ||
+ !(parm->blank == '\0' || isprint(parm->blank)))
+ xerror("%s: blank = 0x%02X; invalid parameter\n",
+ func, parm->blank);
+ if (!(parm->obj_name == NULL || strlen(parm->obj_name) <= 255))
+ xerror("%s: obj_name = \"%.12s...\"; parameter too long\n",
+ func, parm->obj_name);
+ if (!(0.0 <= parm->tol_mps && parm->tol_mps < 1.0))
+ xerror("%s: tol_mps = %g; invalid parameter\n",
+ func, parm->tol_mps);
+ return;
+}
+
+/***********************************************************************
+* NAME
+*
+* glp_read_mps - read problem data in MPS format
+*
+* SYNOPSIS
+*
+* int glp_read_mps(glp_prob *P, int fmt, const glp_mpscp *parm,
+* const char *fname);
+*
+* DESCRIPTION
+*
+* The routine glp_read_mps reads problem data in MPS format from a
+* text file.
+*
+* The parameter fmt specifies the version of MPS format:
+*
+* GLP_MPS_DECK - fixed (ancient) MPS format;
+* GLP_MPS_FILE - free (modern) MPS format.
+*
+* The parameter parm is a pointer to the structure glp_mpscp, which
+* specifies control parameters used by the routine. If parm is NULL,
+* the routine uses default settings.
+*
+* The character string fname specifies a name of the text file to be
+* read.
+*
+* Note that before reading data the current content of the problem
+* object is completely erased with the routine glp_erase_prob.
+*
+* RETURNS
+*
+* If the operation was successful, the routine glp_read_mps returns
+* zero. Otherwise, it prints an error message and returns non-zero. */
+
+struct csa
+{ /* common storage area */
+ glp_prob *P;
+ /* pointer to problem object */
+ int deck;
+ /* MPS format (0 - free, 1 - fixed) */
+ const glp_mpscp *parm;
+ /* pointer to control parameters */
+ const char *fname;
+ /* name of input MPS file */
+ glp_file *fp;
+ /* stream assigned to input MPS file */
+ jmp_buf jump;
+ /* label for go to in case of error */
+ int recno;
+ /* current record (card) number */
+ int recpos;
+ /* current record (card) position */
+ int c;
+ /* current character */
+ int fldno;
+ /* current field number */
+ char field[255+1];
+ /* current field content */
+ int w80;
+ /* warning 'record must not be longer than 80 chars' issued */
+ int wef;
+ /* warning 'extra fields detected beyond field 6' issued */
+ int obj_row;
+ /* objective row number */
+ void *work1, *work2, *work3;
+ /* working arrays */
+};
+
+static void error(struct csa *csa, const char *fmt, ...)
+{ /* print error message and terminate processing */
+ va_list arg;
+ xprintf("%s:%d: ", csa->fname, csa->recno);
+ va_start(arg, fmt);
+ xvprintf(fmt, arg);
+ va_end(arg);
+ longjmp(csa->jump, 1);
+ /* no return */
+}
+
+static void warning(struct csa *csa, const char *fmt, ...)
+{ /* print warning message and continue processing */
+ va_list arg;
+ xprintf("%s:%d: warning: ", csa->fname, csa->recno);
+ va_start(arg, fmt);
+ xvprintf(fmt, arg);
+ va_end(arg);
+ return;
+}
+
+static void read_char(struct csa *csa)
+{ /* read next character */
+ int c;
+ if (csa->c == '\n')
+ csa->recno++, csa->recpos = 0;
+ csa->recpos++;
+read: c = glp_getc(csa->fp);
+ if (c < 0)
+ { if (glp_ioerr(csa->fp))
+ error(csa, "read error - %s\n", get_err_msg());
+ else if (csa->c == '\n')
+ error(csa, "unexpected end of file\n");
+ else
+ { warning(csa, "missing final end of line\n");
+ c = '\n';
+ }
+ }
+ else if (c == '\n')
+ ;
+ else if (csa->c == '\r')
+ { c = '\r';
+ goto badc;
+ }
+ else if (csa->deck && c == '\r')
+ { csa->c = '\r';
+ goto read;
+ }
+ else if (c == ' ')
+ ;
+ else if (isspace(c))
+ { if (csa->deck)
+badc: error(csa, "in fixed MPS format white-space character 0x%02"
+ "X is not allowed\n", c);
+ c = ' ';
+ }
+ else if (iscntrl(c))
+ error(csa, "invalid control character 0x%02X\n", c);
+ if (csa->deck && csa->recpos == 81 && c != '\n' && csa->w80 < 1)
+ { warning(csa, "in fixed MPS format record must not be longer th"
+ "an 80 characters\n");
+ csa->w80++;
+ }
+ csa->c = c;
+ return;
+}
+
+static int indicator(struct csa *csa, int name)
+{ /* skip comment records and read possible indicator record */
+ int ret;
+ /* reset current field number */
+ csa->fldno = 0;
+loop: /* read the very first character of the next record */
+ xassert(csa->c == '\n');
+ read_char(csa);
+ if (csa->c == ' ' || csa->c == '\n')
+ { /* data record */
+ ret = 0;
+ }
+ else if (csa->c == '*')
+ { /* comment record */
+ while (csa->c != '\n')
+ read_char(csa);
+ goto loop;
+ }
+ else
+ { /* indicator record */
+ int len = 0;
+ while (csa->c != ' ' && csa->c != '\n' && len < 12)
+ { csa->field[len++] = (char)csa->c;
+ read_char(csa);
+ }
+ csa->field[len] = '\0';
+ if (!(strcmp(csa->field, "NAME") == 0 ||
+ strcmp(csa->field, "ROWS") == 0 ||
+ strcmp(csa->field, "COLUMNS") == 0 ||
+ strcmp(csa->field, "RHS") == 0 ||
+ strcmp(csa->field, "RANGES") == 0 ||
+ strcmp(csa->field, "BOUNDS") == 0 ||
+ strcmp(csa->field, "ENDATA") == 0))
+ error(csa, "invalid indicator record\n");
+ if (!name)
+ { while (csa->c != '\n')
+ read_char(csa);
+ }
+ ret = 1;
+ }
+ return ret;
+}
+
+static void read_field(struct csa *csa)
+{ /* read next field of the current data record */
+ csa->fldno++;
+ if (csa->deck)
+ { /* fixed MPS format */
+ int beg, end, pos;
+ /* determine predefined field positions */
+ if (csa->fldno == 1)
+ beg = 2, end = 3;
+ else if (csa->fldno == 2)
+ beg = 5, end = 12;
+ else if (csa->fldno == 3)
+ beg = 15, end = 22;
+ else if (csa->fldno == 4)
+ beg = 25, end = 36;
+ else if (csa->fldno == 5)
+ beg = 40, end = 47;
+ else if (csa->fldno == 6)
+ beg = 50, end = 61;
+ else
+ xassert(csa != csa);
+ /* skip blanks preceding the current field */
+ if (csa->c != '\n')
+ { pos = csa->recpos;
+ while (csa->recpos < beg)
+ { if (csa->c == ' ')
+ ;
+ else if (csa->c == '\n')
+ break;
+ else
+ error(csa, "in fixed MPS format positions %d-%d must "
+ "be blank\n", pos, beg-1);
+ read_char(csa);
+ }
+ }
+ /* skip possible comment beginning in the field 3 or 5 */
+ if ((csa->fldno == 3 || csa->fldno == 5) && csa->c == '$')
+ { while (csa->c != '\n')
+ read_char(csa);
+ }
+ /* read the current field */
+ for (pos = beg; pos <= end; pos++)
+ { if (csa->c == '\n') break;
+ csa->field[pos-beg] = (char)csa->c;
+ read_char(csa);
+ }
+ csa->field[pos-beg] = '\0';
+ strtrim(csa->field);
+ /* skip blanks following the last field */
+ if (csa->fldno == 6 && csa->c != '\n')
+ { while (csa->recpos <= 72)
+ { if (csa->c == ' ')
+ ;
+ else if (csa->c == '\n')
+ break;
+ else
+ error(csa, "in fixed MPS format positions 62-72 must "
+ "be blank\n");
+ read_char(csa);
+ }
+ while (csa->c != '\n')
+ read_char(csa);
+ }
+ }
+ else
+ { /* free MPS format */
+ int len;
+ /* skip blanks preceding the current field */
+ while (csa->c == ' ')
+ read_char(csa);
+ /* skip possible comment */
+ if (csa->c == '$')
+ { while (csa->c != '\n')
+ read_char(csa);
+ }
+ /* read the current field */
+ len = 0;
+ while (!(csa->c == ' ' || csa->c == '\n'))
+ { if (len == 255)
+ error(csa, "length of field %d exceeds 255 characters\n",
+ csa->fldno++);
+ csa->field[len++] = (char)csa->c;
+ read_char(csa);
+ }
+ csa->field[len] = '\0';
+ /* skip anything following the last field (any extra fields
+ are considered to be comments) */
+ if (csa->fldno == 6)
+ { while (csa->c == ' ')
+ read_char(csa);
+ if (csa->c != '$' && csa->c != '\n' && csa->wef < 1)
+ { warning(csa, "some extra field(s) detected beyond field "
+ "6; field(s) ignored\n");
+ csa->wef++;
+ }
+ while (csa->c != '\n')
+ read_char(csa);
+ }
+ }
+ return;
+}
+
+static void patch_name(struct csa *csa, char *name)
+{ /* process embedded blanks in symbolic name */
+ int blank = csa->parm->blank;
+ if (blank == '\0')
+ { /* remove emedded blanks */
+ strspx(name);
+ }
+ else
+ { /* replace embedded blanks by specified character */
+ for (; *name != '\0'; name++)
+ if (*name == ' ') *name = (char)blank;
+ }
+ return;
+}
+
+static double read_number(struct csa *csa)
+{ /* read next field and convert it to floating-point number */
+ double x;
+ char *s;
+ /* read next field */
+ read_field(csa);
+ xassert(csa->fldno == 4 || csa->fldno == 6);
+ if (csa->field[0] == '\0')
+ error(csa, "missing numeric value in field %d\n", csa->fldno);
+ /* skip initial spaces of the field */
+ for (s = csa->field; *s == ' '; s++);
+ /* perform conversion */
+ if (str2num(s, &x) != 0)
+ error(csa, "cannot convert '%s' to floating-point number\n",
+ s);
+ return x;
+}
+
+static void skip_field(struct csa *csa)
+{ /* read and skip next field (assumed to be blank) */
+ read_field(csa);
+ if (csa->field[0] != '\0')
+ error(csa, "field %d must be blank\n", csa->fldno);
+ return;
+}
+
+static void read_name(struct csa *csa)
+{ /* read NAME indicator record */
+ if (!(indicator(csa, 1) && strcmp(csa->field, "NAME") == 0))
+ error(csa, "missing NAME indicator record\n");
+ /* this indicator record looks like a data record; simulate that
+ fields 1 and 2 were read */
+ csa->fldno = 2;
+ /* field 3: model name */
+ read_field(csa), patch_name(csa, csa->field);
+ if (csa->field[0] == '\0')
+ warning(csa, "missing model name in field 3\n");
+ else
+ glp_set_prob_name(csa->P, csa->field);
+ /* skip anything following field 3 */
+ while (csa->c != '\n')
+ read_char(csa);
+ return;
+}
+
+static void read_rows(struct csa *csa)
+{ /* read ROWS section */
+ int i, type;
+loop: if (indicator(csa, 0)) goto done;
+ /* field 1: row type */
+ read_field(csa), strspx(csa->field);
+ if (strcmp(csa->field, "N") == 0)
+ type = GLP_FR;
+ else if (strcmp(csa->field, "G") == 0)
+ type = GLP_LO;
+ else if (strcmp(csa->field, "L") == 0)
+ type = GLP_UP;
+ else if (strcmp(csa->field, "E") == 0)
+ type = GLP_FX;
+ else if (csa->field[0] == '\0')
+ error(csa, "missing row type in field 1\n");
+ else
+ error(csa, "invalid row type in field 1\n");
+ /* field 2: row name */
+ read_field(csa), patch_name(csa, csa->field);
+ if (csa->field[0] == '\0')
+ error(csa, "missing row name in field 2\n");
+ if (glp_find_row(csa->P, csa->field) != 0)
+ error(csa, "row '%s' multiply specified\n", csa->field);
+ i = glp_add_rows(csa->P, 1);
+ glp_set_row_name(csa->P, i, csa->field);
+ glp_set_row_bnds(csa->P, i, type, 0.0, 0.0);
+ /* fields 3, 4, 5, and 6 must be blank */
+ skip_field(csa);
+ skip_field(csa);
+ skip_field(csa);
+ skip_field(csa);
+ goto loop;
+done: return;
+}
+
+static void read_columns(struct csa *csa)
+{ /* read COLUMNS section */
+ int i, j, f, len, kind = GLP_CV, *ind;
+ double aij, *val;
+ char name[255+1], *flag;
+ /* allocate working arrays */
+ csa->work1 = ind = xcalloc(1+csa->P->m, sizeof(int));
+ csa->work2 = val = xcalloc(1+csa->P->m, sizeof(double));
+ csa->work3 = flag = xcalloc(1+csa->P->m, sizeof(char));
+ memset(&flag[1], 0, csa->P->m);
+ /* no current column exists */
+ j = 0, len = 0;
+loop: if (indicator(csa, 0)) goto done;
+ /* field 1 must be blank */
+ if (csa->deck)
+ { read_field(csa);
+ if (csa->field[0] != '\0')
+ error(csa, "field 1 must be blank\n");
+ }
+ else
+ csa->fldno++;
+ /* field 2: column or kind name */
+ read_field(csa), patch_name(csa, csa->field);
+ strcpy(name, csa->field);
+ /* field 3: row name or keyword 'MARKER' */
+ read_field(csa), patch_name(csa, csa->field);
+ if (strcmp(csa->field, "'MARKER'") == 0)
+ { /* process kind data record */
+ /* field 4 must be blank */
+ if (csa->deck)
+ { read_field(csa);
+ if (csa->field[0] != '\0')
+ error(csa, "field 4 must be blank\n");
+ }
+ else
+ csa->fldno++;
+ /* field 5: keyword 'INTORG' or 'INTEND' */
+ read_field(csa), patch_name(csa, csa->field);
+ if (strcmp(csa->field, "'INTORG'") == 0)
+ kind = GLP_IV;
+ else if (strcmp(csa->field, "'INTEND'") == 0)
+ kind = GLP_CV;
+ else if (csa->field[0] == '\0')
+ error(csa, "missing keyword in field 5\n");
+ else
+ error(csa, "invalid keyword in field 5\n");
+ /* field 6 must be blank */
+ skip_field(csa);
+ goto loop;
+ }
+ /* process column name specified in field 2 */
+ if (name[0] == '\0')
+ { /* the same column as in previous data record */
+ if (j == 0)
+ error(csa, "missing column name in field 2\n");
+ }
+ else if (j != 0 && strcmp(name, csa->P->col[j]->name) == 0)
+ { /* the same column as in previous data record */
+ xassert(j != 0);
+ }
+ else
+ { /* store the current column */
+ if (j != 0)
+ { glp_set_mat_col(csa->P, j, len, ind, val);
+ while (len > 0) flag[ind[len--]] = 0;
+ }
+ /* create new column */
+ if (glp_find_col(csa->P, name) != 0)
+ error(csa, "column '%s' multiply specified\n", name);
+ j = glp_add_cols(csa->P, 1);
+ glp_set_col_name(csa->P, j, name);
+ glp_set_col_kind(csa->P, j, kind);
+ if (kind == GLP_CV)
+ glp_set_col_bnds(csa->P, j, GLP_LO, 0.0, 0.0);
+ else if (kind == GLP_IV)
+ glp_set_col_bnds(csa->P, j, GLP_DB, 0.0, 1.0);
+ else
+ xassert(kind != kind);
+ }
+ /* process fields 3-4 and 5-6 */
+ for (f = 3; f <= 5; f += 2)
+ { /* field 3 or 5: row name */
+ if (f == 3)
+ { if (csa->field[0] == '\0')
+ error(csa, "missing row name in field 3\n");
+ }
+ else
+ { read_field(csa), patch_name(csa, csa->field);
+ if (csa->field[0] == '\0')
+ { /* if field 5 is blank, field 6 also must be blank */
+ skip_field(csa);
+ continue;
+ }
+ }
+ i = glp_find_row(csa->P, csa->field);
+ if (i == 0)
+ error(csa, "row '%s' not found\n", csa->field);
+ if (flag[i])
+ error(csa, "duplicate coefficient in row '%s'\n",
+ csa->field);
+ /* field 4 or 6: coefficient value */
+ aij = read_number(csa);
+ if (fabs(aij) < csa->parm->tol_mps) aij = 0.0;
+ len++, ind[len] = i, val[len] = aij, flag[i] = 1;
+ }
+ goto loop;
+done: /* store the last column */
+ if (j != 0)
+ glp_set_mat_col(csa->P, j, len, ind, val);
+ /* free working arrays */
+ xfree(ind);
+ xfree(val);
+ xfree(flag);
+ csa->work1 = csa->work2 = csa->work3 = NULL;
+ return;
+}
+
+static void read_rhs(struct csa *csa)
+{ /* read RHS section */
+ int i, f, v, type;
+ double rhs;
+ char name[255+1], *flag;
+ /* allocate working array */
+ csa->work3 = flag = xcalloc(1+csa->P->m, sizeof(char));
+ memset(&flag[1], 0, csa->P->m);
+ /* no current RHS vector exists */
+ v = 0;
+loop: if (indicator(csa, 0)) goto done;
+ /* field 1 must be blank */
+ if (csa->deck)
+ { read_field(csa);
+ if (csa->field[0] != '\0')
+ error(csa, "field 1 must be blank\n");
+ }
+ else
+ csa->fldno++;
+ /* field 2: RHS vector name */
+ read_field(csa), patch_name(csa, csa->field);
+ if (csa->field[0] == '\0')
+ { /* the same RHS vector as in previous data record */
+ if (v == 0)
+ { warning(csa, "missing RHS vector name in field 2\n");
+ goto blnk;
+ }
+ }
+ else if (v != 0 && strcmp(csa->field, name) == 0)
+ { /* the same RHS vector as in previous data record */
+ xassert(v != 0);
+ }
+ else
+blnk: { /* new RHS vector */
+ if (v != 0)
+ error(csa, "multiple RHS vectors not supported\n");
+ v++;
+ strcpy(name, csa->field);
+ }
+ /* process fields 3-4 and 5-6 */
+ for (f = 3; f <= 5; f += 2)
+ { /* field 3 or 5: row name */
+ read_field(csa), patch_name(csa, csa->field);
+ if (csa->field[0] == '\0')
+ { if (f == 3)
+ error(csa, "missing row name in field 3\n");
+ else
+ { /* if field 5 is blank, field 6 also must be blank */
+ skip_field(csa);
+ continue;
+ }
+ }
+ i = glp_find_row(csa->P, csa->field);
+ if (i == 0)
+ error(csa, "row '%s' not found\n", csa->field);
+ if (flag[i])
+ error(csa, "duplicate right-hand side for row '%s'\n",
+ csa->field);
+ /* field 4 or 6: right-hand side value */
+ rhs = read_number(csa);
+ if (fabs(rhs) < csa->parm->tol_mps) rhs = 0.0;
+ type = csa->P->row[i]->type;
+ if (type == GLP_FR)
+ { if (i == csa->obj_row)
+ glp_set_obj_coef(csa->P, 0, rhs);
+ else if (rhs != 0.0)
+ warning(csa, "non-zero right-hand side for free row '%s'"
+ " ignored\n", csa->P->row[i]->name);
+ }
+ else
+ glp_set_row_bnds(csa->P, i, type, rhs, rhs);
+ flag[i] = 1;
+ }
+ goto loop;
+done: /* free working array */
+ xfree(flag);
+ csa->work3 = NULL;
+ return;
+}
+
+static void read_ranges(struct csa *csa)
+{ /* read RANGES section */
+ int i, f, v, type;
+ double rhs, rng;
+ char name[255+1], *flag;
+ /* allocate working array */
+ csa->work3 = flag = xcalloc(1+csa->P->m, sizeof(char));
+ memset(&flag[1], 0, csa->P->m);
+ /* no current RANGES vector exists */
+ v = 0;
+loop: if (indicator(csa, 0)) goto done;
+ /* field 1 must be blank */
+ if (csa->deck)
+ { read_field(csa);
+ if (csa->field[0] != '\0')
+ error(csa, "field 1 must be blank\n");
+ }
+ else
+ csa->fldno++;
+ /* field 2: RANGES vector name */
+ read_field(csa), patch_name(csa, csa->field);
+ if (csa->field[0] == '\0')
+ { /* the same RANGES vector as in previous data record */
+ if (v == 0)
+ { warning(csa, "missing RANGES vector name in field 2\n");
+ goto blnk;
+ }
+ }
+ else if (v != 0 && strcmp(csa->field, name) == 0)
+ { /* the same RANGES vector as in previous data record */
+ xassert(v != 0);
+ }
+ else
+blnk: { /* new RANGES vector */
+ if (v != 0)
+ error(csa, "multiple RANGES vectors not supported\n");
+ v++;
+ strcpy(name, csa->field);
+ }
+ /* process fields 3-4 and 5-6 */
+ for (f = 3; f <= 5; f += 2)
+ { /* field 3 or 5: row name */
+ read_field(csa), patch_name(csa, csa->field);
+ if (csa->field[0] == '\0')
+ { if (f == 3)
+ error(csa, "missing row name in field 3\n");
+ else
+ { /* if field 5 is blank, field 6 also must be blank */
+ skip_field(csa);
+ continue;
+ }
+ }
+ i = glp_find_row(csa->P, csa->field);
+ if (i == 0)
+ error(csa, "row '%s' not found\n", csa->field);
+ if (flag[i])
+ error(csa, "duplicate range for row '%s'\n", csa->field);
+ /* field 4 or 6: range value */
+ rng = read_number(csa);
+ if (fabs(rng) < csa->parm->tol_mps) rng = 0.0;
+ type = csa->P->row[i]->type;
+ if (type == GLP_FR)
+ warning(csa, "range for free row '%s' ignored\n",
+ csa->P->row[i]->name);
+ else if (type == GLP_LO)
+ { rhs = csa->P->row[i]->lb;
+#if 0 /* 26/V-2017 by cmatraki */
+ glp_set_row_bnds(csa->P, i, rhs == 0.0 ? GLP_FX : GLP_DB,
+#else
+ glp_set_row_bnds(csa->P, i, rng == 0.0 ? GLP_FX : GLP_DB,
+#endif
+ rhs, rhs + fabs(rng));
+ }
+ else if (type == GLP_UP)
+ { rhs = csa->P->row[i]->ub;
+#if 0 /* 26/V-2017 by cmatraki */
+ glp_set_row_bnds(csa->P, i, rhs == 0.0 ? GLP_FX : GLP_DB,
+#else
+ glp_set_row_bnds(csa->P, i, rng == 0.0 ? GLP_FX : GLP_DB,
+#endif
+ rhs - fabs(rng), rhs);
+ }
+ else if (type == GLP_FX)
+ { rhs = csa->P->row[i]->lb;
+ if (rng > 0.0)
+ glp_set_row_bnds(csa->P, i, GLP_DB, rhs, rhs + rng);
+ else if (rng < 0.0)
+ glp_set_row_bnds(csa->P, i, GLP_DB, rhs + rng, rhs);
+ }
+ else
+ xassert(type != type);
+ flag[i] = 1;
+ }
+ goto loop;
+done: /* free working array */
+ xfree(flag);
+ csa->work3 = NULL;
+ return;
+}
+
+static void read_bounds(struct csa *csa)
+{ /* read BOUNDS section */
+ GLPCOL *col;
+ int j, v, mask, data;
+ double bnd, lb, ub;
+ char type[2+1], name[255+1], *flag;
+ /* allocate working array */
+ csa->work3 = flag = xcalloc(1+csa->P->n, sizeof(char));
+ memset(&flag[1], 0, csa->P->n);
+ /* no current BOUNDS vector exists */
+ v = 0;
+loop: if (indicator(csa, 0)) goto done;
+ /* field 1: bound type */
+ read_field(csa);
+ if (strcmp(csa->field, "LO") == 0)
+ mask = 0x01, data = 1;
+ else if (strcmp(csa->field, "UP") == 0)
+ mask = 0x10, data = 1;
+ else if (strcmp(csa->field, "FX") == 0)
+ mask = 0x11, data = 1;
+ else if (strcmp(csa->field, "FR") == 0)
+ mask = 0x11, data = 0;
+ else if (strcmp(csa->field, "MI") == 0)
+ mask = 0x01, data = 0;
+ else if (strcmp(csa->field, "PL") == 0)
+ mask = 0x10, data = 0;
+ else if (strcmp(csa->field, "LI") == 0)
+ mask = 0x01, data = 1;
+ else if (strcmp(csa->field, "UI") == 0)
+ mask = 0x10, data = 1;
+ else if (strcmp(csa->field, "BV") == 0)
+ mask = 0x11, data = 0;
+ else if (csa->field[0] == '\0')
+ error(csa, "missing bound type in field 1\n");
+ else
+ error(csa, "invalid bound type in field 1\n");
+ strcpy(type, csa->field);
+ /* field 2: BOUNDS vector name */
+ read_field(csa), patch_name(csa, csa->field);
+ if (csa->field[0] == '\0')
+ { /* the same BOUNDS vector as in previous data record */
+ if (v == 0)
+ { warning(csa, "missing BOUNDS vector name in field 2\n");
+ goto blnk;
+ }
+ }
+ else if (v != 0 && strcmp(csa->field, name) == 0)
+ { /* the same BOUNDS vector as in previous data record */
+ xassert(v != 0);
+ }
+ else
+blnk: { /* new BOUNDS vector */
+ if (v != 0)
+ error(csa, "multiple BOUNDS vectors not supported\n");
+ v++;
+ strcpy(name, csa->field);
+ }
+ /* field 3: column name */
+ read_field(csa), patch_name(csa, csa->field);
+ if (csa->field[0] == '\0')
+ error(csa, "missing column name in field 3\n");
+ j = glp_find_col(csa->P, csa->field);
+ if (j == 0)
+ error(csa, "column '%s' not found\n", csa->field);
+ if ((flag[j] & mask) == 0x01)
+ error(csa, "duplicate lower bound for column '%s'\n",
+ csa->field);
+ if ((flag[j] & mask) == 0x10)
+ error(csa, "duplicate upper bound for column '%s'\n",
+ csa->field);
+ xassert((flag[j] & mask) == 0x00);
+ /* field 4: bound value */
+ if (data)
+ { bnd = read_number(csa);
+ if (fabs(bnd) < csa->parm->tol_mps) bnd = 0.0;
+ }
+ else
+ read_field(csa), bnd = 0.0;
+ /* get current column bounds */
+ col = csa->P->col[j];
+ if (col->type == GLP_FR)
+ lb = -DBL_MAX, ub = +DBL_MAX;
+ else if (col->type == GLP_LO)
+ lb = col->lb, ub = +DBL_MAX;
+ else if (col->type == GLP_UP)
+ lb = -DBL_MAX, ub = col->ub;
+ else if (col->type == GLP_DB)
+ lb = col->lb, ub = col->ub;
+ else if (col->type == GLP_FX)
+ lb = ub = col->lb;
+ else
+ xassert(col != col);
+ /* change column bounds */
+ if (strcmp(type, "LO") == 0)
+ lb = bnd;
+ else if (strcmp(type, "UP") == 0)
+ ub = bnd;
+ else if (strcmp(type, "FX") == 0)
+ lb = ub = bnd;
+ else if (strcmp(type, "FR") == 0)
+ lb = -DBL_MAX, ub = +DBL_MAX;
+ else if (strcmp(type, "MI") == 0)
+ lb = -DBL_MAX;
+ else if (strcmp(type, "PL") == 0)
+ ub = +DBL_MAX;
+ else if (strcmp(type, "LI") == 0)
+ { glp_set_col_kind(csa->P, j, GLP_IV);
+ lb = ceil(bnd);
+#if 1 /* 16/VII-2013 */
+ /* if column upper bound has not been explicitly specified,
+ take it as +inf */
+ if (!(flag[j] & 0x10))
+ ub = +DBL_MAX;
+#endif
+ }
+ else if (strcmp(type, "UI") == 0)
+ { glp_set_col_kind(csa->P, j, GLP_IV);
+ ub = floor(bnd);
+ }
+ else if (strcmp(type, "BV") == 0)
+ { glp_set_col_kind(csa->P, j, GLP_IV);
+ lb = 0.0, ub = 1.0;
+ }
+ else
+ xassert(type != type);
+ /* set new column bounds */
+ if (lb == -DBL_MAX && ub == +DBL_MAX)
+ glp_set_col_bnds(csa->P, j, GLP_FR, lb, ub);
+ else if (ub == +DBL_MAX)
+ glp_set_col_bnds(csa->P, j, GLP_LO, lb, ub);
+ else if (lb == -DBL_MAX)
+ glp_set_col_bnds(csa->P, j, GLP_UP, lb, ub);
+ else if (lb != ub)
+ glp_set_col_bnds(csa->P, j, GLP_DB, lb, ub);
+ else
+ glp_set_col_bnds(csa->P, j, GLP_FX, lb, ub);
+ flag[j] |= (char)mask;
+ /* fields 5 and 6 must be blank */
+ skip_field(csa);
+ skip_field(csa);
+ goto loop;
+done: /* free working array */
+ xfree(flag);
+ csa->work3 = NULL;
+ return;
+}
+
+int glp_read_mps(glp_prob *P, int fmt, const glp_mpscp *parm,
+ const char *fname)
+{ /* read problem data in MPS format */
+ glp_mpscp _parm;
+ struct csa _csa, *csa = &_csa;
+ int ret;
+ xprintf("Reading problem data from '%s'...\n", fname);
+ if (!(fmt == GLP_MPS_DECK || fmt == GLP_MPS_FILE))
+ xerror("glp_read_mps: fmt = %d; invalid parameter\n", fmt);
+ if (parm == NULL)
+ glp_init_mpscp(&_parm), parm = &_parm;
+ /* check control parameters */
+ check_parm("glp_read_mps", parm);
+ /* initialize common storage area */
+ csa->P = P;
+ csa->deck = (fmt == GLP_MPS_DECK);
+ csa->parm = parm;
+ csa->fname = fname;
+ csa->fp = NULL;
+ if (setjmp(csa->jump))
+ { ret = 1;
+ goto done;
+ }
+ csa->recno = csa->recpos = 0;
+ csa->c = '\n';
+ csa->fldno = 0;
+ csa->field[0] = '\0';
+ csa->w80 = csa->wef = 0;
+ csa->obj_row = 0;
+ csa->work1 = csa->work2 = csa->work3 = NULL;
+ /* erase problem object */
+ glp_erase_prob(P);
+ glp_create_index(P);
+ /* open input MPS file */
+ csa->fp = glp_open(fname, "r");
+ if (csa->fp == NULL)
+ { xprintf("Unable to open '%s' - %s\n", fname, get_err_msg());
+ ret = 1;
+ goto done;
+ }
+ /* read NAME indicator record */
+ read_name(csa);
+ if (P->name != NULL)
+ xprintf("Problem: %s\n", P->name);
+ /* read ROWS section */
+ if (!(indicator(csa, 0) && strcmp(csa->field, "ROWS") == 0))
+ error(csa, "missing ROWS indicator record\n");
+ read_rows(csa);
+ /* determine objective row */
+ if (parm->obj_name == NULL || parm->obj_name[0] == '\0')
+ { /* use the first row of N type */
+ int i;
+ for (i = 1; i <= P->m; i++)
+ { if (P->row[i]->type == GLP_FR)
+ { csa->obj_row = i;
+ break;
+ }
+ }
+ if (csa->obj_row == 0)
+ warning(csa, "unable to determine objective row\n");
+ }
+ else
+ { /* use a row with specified name */
+ int i;
+ for (i = 1; i <= P->m; i++)
+ { xassert(P->row[i]->name != NULL);
+ if (strcmp(parm->obj_name, P->row[i]->name) == 0)
+ { csa->obj_row = i;
+ break;
+ }
+ }
+ if (csa->obj_row == 0)
+ error(csa, "objective row '%s' not found\n",
+ parm->obj_name);
+ }
+ if (csa->obj_row != 0)
+ { glp_set_obj_name(P, P->row[csa->obj_row]->name);
+ xprintf("Objective: %s\n", P->obj);
+ }
+ /* read COLUMNS section */
+ if (strcmp(csa->field, "COLUMNS") != 0)
+ error(csa, "missing COLUMNS indicator record\n");
+ read_columns(csa);
+ /* set objective coefficients */
+ if (csa->obj_row != 0)
+ { GLPAIJ *aij;
+ for (aij = P->row[csa->obj_row]->ptr; aij != NULL; aij =
+ aij->r_next) glp_set_obj_coef(P, aij->col->j, aij->val);
+ }
+ /* read optional RHS section */
+ if (strcmp(csa->field, "RHS") == 0)
+ read_rhs(csa);
+ /* read optional RANGES section */
+ if (strcmp(csa->field, "RANGES") == 0)
+ read_ranges(csa);
+ /* read optional BOUNDS section */
+ if (strcmp(csa->field, "BOUNDS") == 0)
+ read_bounds(csa);
+ /* read ENDATA indicator record */
+ if (strcmp(csa->field, "ENDATA") != 0)
+ error(csa, "invalid use of %s indicator record\n",
+ csa->field);
+ /* print some statistics */
+ xprintf("%d row%s, %d column%s, %d non-zero%s\n",
+ P->m, P->m == 1 ? "" : "s", P->n, P->n == 1 ? "" : "s",
+ P->nnz, P->nnz == 1 ? "" : "s");
+ if (glp_get_num_int(P) > 0)
+ { int ni = glp_get_num_int(P);
+ int nb = glp_get_num_bin(P);
+ if (ni == 1)
+ { if (nb == 0)
+ xprintf("One variable is integer\n");
+ else
+ xprintf("One variable is binary\n");
+ }
+ else
+ { xprintf("%d integer variables, ", ni);
+ if (nb == 0)
+ xprintf("none");
+ else if (nb == 1)
+ xprintf("one");
+ else if (nb == ni)
+ xprintf("all");
+ else
+ xprintf("%d", nb);
+ xprintf(" of which %s binary\n", nb == 1 ? "is" : "are");
+ }
+ }
+ xprintf("%d records were read\n", csa->recno);
+#if 1 /* 31/III-2016 */
+ /* free (unbounded) row(s) in MPS file are intended to specify
+ * objective function(s), so all such rows can be removed */
+#if 1 /* 08/VIII-2013 */
+ /* remove free rows */
+ { int i, nrs, *num;
+ num = talloc(1+P->m, int);
+ nrs = 0;
+ for (i = 1; i <= P->m; i++)
+ { if (P->row[i]->type == GLP_FR)
+ num[++nrs] = i;
+ }
+ if (nrs > 0)
+ { glp_del_rows(P, nrs, num);
+ if (nrs == 1)
+ xprintf("One free row was removed\n");
+ else
+ xprintf("%d free rows were removed\n", nrs);
+ }
+ tfree(num);
+ }
+#endif
+#else
+ /* if objective function row is free, remove it */
+ if (csa->obj_row != 0 && P->row[csa->obj_row]->type == GLP_FR)
+ { int num[1+1];
+ num[1] = csa->obj_row;
+ glp_del_rows(P, 1, num);
+ xprintf("Free objective row was removed\n");
+ }
+#endif
+ /* problem data has been successfully read */
+ glp_delete_index(P);
+ glp_sort_matrix(P);
+ ret = 0;
+done: if (csa->fp != NULL) glp_close(csa->fp);
+ if (csa->work1 != NULL) xfree(csa->work1);
+ if (csa->work2 != NULL) xfree(csa->work2);
+ if (csa->work3 != NULL) xfree(csa->work3);
+ if (ret != 0) glp_erase_prob(P);
+ return ret;
+}
+
+/***********************************************************************
+* NAME
+*
+* glp_write_mps - write problem data in MPS format
+*
+* SYNOPSIS
+*
+* int glp_write_mps(glp_prob *P, int fmt, const glp_mpscp *parm,
+* const char *fname);
+*
+* DESCRIPTION
+*
+* The routine glp_write_mps writes problem data in MPS format to a
+* text file.
+*
+* The parameter fmt specifies the version of MPS format:
+*
+* GLP_MPS_DECK - fixed (ancient) MPS format;
+* GLP_MPS_FILE - free (modern) MPS format.
+*
+* The parameter parm is a pointer to the structure glp_mpscp, which
+* specifies control parameters used by the routine. If parm is NULL,
+* the routine uses default settings.
+*
+* The character string fname specifies a name of the text file to be
+* written.
+*
+* RETURNS
+*
+* If the operation was successful, the routine glp_read_mps returns
+* zero. Otherwise, it prints an error message and returns non-zero. */
+
+#define csa csa1
+
+struct csa
+{ /* common storage area */
+ glp_prob *P;
+ /* pointer to problem object */
+ int deck;
+ /* MPS format (0 - free, 1 - fixed) */
+ const glp_mpscp *parm;
+ /* pointer to control parameters */
+ char field[255+1];
+ /* field buffer */
+};
+
+static char *mps_name(struct csa *csa)
+{ /* make problem name */
+ char *f;
+ if (csa->P->name == NULL)
+ csa->field[0] = '\0';
+ else if (csa->deck)
+ { strncpy(csa->field, csa->P->name, 8);
+ csa->field[8] = '\0';
+ }
+ else
+ strcpy(csa->field, csa->P->name);
+ for (f = csa->field; *f != '\0'; f++)
+ if (*f == ' ') *f = '_';
+ return csa->field;
+}
+
+static char *row_name(struct csa *csa, int i)
+{ /* make i-th row name */
+ char *f;
+ xassert(0 <= i && i <= csa->P->m);
+ if (i == 0 || csa->P->row[i]->name == NULL ||
+ csa->deck && strlen(csa->P->row[i]->name) > 8)
+ sprintf(csa->field, "R%07d", i);
+ else
+ { strcpy(csa->field, csa->P->row[i]->name);
+ for (f = csa->field; *f != '\0'; f++)
+ if (*f == ' ') *f = '_';
+ }
+ return csa->field;
+}
+
+static char *col_name(struct csa *csa, int j)
+{ /* make j-th column name */
+ char *f;
+ xassert(1 <= j && j <= csa->P->n);
+ if (csa->P->col[j]->name == NULL ||
+ csa->deck && strlen(csa->P->col[j]->name) > 8)
+ sprintf(csa->field, "C%07d", j);
+ else
+ { strcpy(csa->field, csa->P->col[j]->name);
+ for (f = csa->field; *f != '\0'; f++)
+ if (*f == ' ') *f = '_';
+ }
+ return csa->field;
+}
+
+static char *mps_numb(struct csa *csa, double val)
+{ /* format floating-point number */
+ int dig;
+ char *exp;
+ for (dig = 12; dig >= 6; dig--)
+ { if (val != 0.0 && fabs(val) < 0.002)
+ sprintf(csa->field, "%.*E", dig-1, val);
+ else
+ sprintf(csa->field, "%.*G", dig, val);
+ exp = strchr(csa->field, 'E');
+ if (exp != NULL)
+ sprintf(exp+1, "%d", atoi(exp+1));
+ if (strlen(csa->field) <= 12) break;
+ }
+ xassert(strlen(csa->field) <= 12);
+ return csa->field;
+}
+
+int glp_write_mps(glp_prob *P, int fmt, const glp_mpscp *parm,
+ const char *fname)
+{ /* write problem data in MPS format */
+ glp_mpscp _parm;
+ struct csa _csa, *csa = &_csa;
+ glp_file *fp;
+ int out_obj, one_col = 0, empty = 0;
+ int i, j, recno, marker, count, gap, ret;
+ xprintf("Writing problem data to '%s'...\n", fname);
+ if (!(fmt == GLP_MPS_DECK || fmt == GLP_MPS_FILE))
+ xerror("glp_write_mps: fmt = %d; invalid parameter\n", fmt);
+ if (parm == NULL)
+ glp_init_mpscp(&_parm), parm = &_parm;
+ /* check control parameters */
+ check_parm("glp_write_mps", parm);
+ /* initialize common storage area */
+ csa->P = P;
+ csa->deck = (fmt == GLP_MPS_DECK);
+ csa->parm = parm;
+ /* create output MPS file */
+ fp = glp_open(fname, "w"), recno = 0;
+ if (fp == NULL)
+ { xprintf("Unable to create '%s' - %s\n", fname, get_err_msg());
+ ret = 1;
+ goto done;
+ }
+ /* write comment records */
+ xfprintf(fp, "* %-*s%s\n", P->name == NULL ? 1 : 12, "Problem:",
+ P->name == NULL ? "" : P->name), recno++;
+ xfprintf(fp, "* %-12s%s\n", "Class:", glp_get_num_int(P) == 0 ?
+ "LP" : "MIP"), recno++;
+ xfprintf(fp, "* %-12s%d\n", "Rows:", P->m), recno++;
+ if (glp_get_num_int(P) == 0)
+ xfprintf(fp, "* %-12s%d\n", "Columns:", P->n), recno++;
+ else
+ xfprintf(fp, "* %-12s%d (%d integer, %d binary)\n",
+ "Columns:", P->n, glp_get_num_int(P), glp_get_num_bin(P)),
+ recno++;
+ xfprintf(fp, "* %-12s%d\n", "Non-zeros:", P->nnz), recno++;
+ xfprintf(fp, "* %-12s%s\n", "Format:", csa->deck ? "Fixed MPS" :
+ "Free MPS"), recno++;
+ xfprintf(fp, "*\n", recno++);
+ /* write NAME indicator record */
+ xfprintf(fp, "NAME%*s%s\n",
+ P->name == NULL ? 0 : csa->deck ? 10 : 1, "", mps_name(csa)),
+ recno++;
+#if 1
+ /* determine whether to write the objective row */
+ out_obj = 1;
+ for (i = 1; i <= P->m; i++)
+ { if (P->row[i]->type == GLP_FR)
+ { out_obj = 0;
+ break;
+ }
+ }
+#endif
+ /* write ROWS section */
+ xfprintf(fp, "ROWS\n"), recno++;
+ for (i = (out_obj ? 0 : 1); i <= P->m; i++)
+ { int type;
+ type = (i == 0 ? GLP_FR : P->row[i]->type);
+ if (type == GLP_FR)
+ type = 'N';
+ else if (type == GLP_LO)
+ type = 'G';
+ else if (type == GLP_UP)
+ type = 'L';
+ else if (type == GLP_DB || type == GLP_FX)
+ type = 'E';
+ else
+ xassert(type != type);
+ xfprintf(fp, " %c%*s%s\n", type, csa->deck ? 2 : 1, "",
+ row_name(csa, i)), recno++;
+ }
+ /* write COLUMNS section */
+ xfprintf(fp, "COLUMNS\n"), recno++;
+ marker = 0;
+ for (j = 1; j <= P->n; j++)
+ { GLPAIJ cj, *aij;
+ int kind;
+ kind = P->col[j]->kind;
+ if (kind == GLP_CV)
+ { if (marker % 2 == 1)
+ { /* close current integer block */
+ marker++;
+ xfprintf(fp, "%*sM%07d%*s'MARKER'%*s'INTEND'\n",
+ csa->deck ? 4 : 1, "", marker, csa->deck ? 2 : 1, "",
+ csa->deck ? 17 : 1, ""), recno++;
+ }
+ }
+ else if (kind == GLP_IV)
+ { if (marker % 2 == 0)
+ { /* open new integer block */
+ marker++;
+ xfprintf(fp, "%*sM%07d%*s'MARKER'%*s'INTORG'\n",
+ csa->deck ? 4 : 1, "", marker, csa->deck ? 2 : 1, "",
+ csa->deck ? 17 : 1, ""), recno++;
+ }
+ }
+ else
+ xassert(kind != kind);
+ if (out_obj && P->col[j]->coef != 0.0)
+ { /* make fake objective coefficient */
+ aij = &cj;
+ aij->row = NULL;
+ aij->val = P->col[j]->coef;
+ aij->c_next = P->col[j]->ptr;
+ }
+ else
+ aij = P->col[j]->ptr;
+#if 1 /* FIXME */
+ if (aij == NULL)
+ { /* empty column */
+ empty++;
+ xfprintf(fp, "%*s%-*s", csa->deck ? 4 : 1, "",
+ csa->deck ? 8 : 1, col_name(csa, j));
+ /* we need a row */
+ xassert(P->m > 0);
+ xfprintf(fp, "%*s%-*s",
+ csa->deck ? 2 : 1, "", csa->deck ? 8 : 1,
+ row_name(csa, 1));
+ xfprintf(fp, "%*s0%*s$ empty column\n",
+ csa->deck ? 13 : 1, "", csa->deck ? 3 : 1, ""), recno++;
+ }
+#endif
+ count = 0;
+ for (aij = aij; aij != NULL; aij = aij->c_next)
+ { if (one_col || count % 2 == 0)
+ xfprintf(fp, "%*s%-*s", csa->deck ? 4 : 1, "",
+ csa->deck ? 8 : 1, col_name(csa, j));
+ gap = (one_col || count % 2 == 0 ? 2 : 3);
+ xfprintf(fp, "%*s%-*s",
+ csa->deck ? gap : 1, "", csa->deck ? 8 : 1,
+ row_name(csa, aij->row == NULL ? 0 : aij->row->i));
+ xfprintf(fp, "%*s%*s",
+ csa->deck ? 2 : 1, "", csa->deck ? 12 : 1,
+ mps_numb(csa, aij->val)), count++;
+ if (one_col || count % 2 == 0)
+ xfprintf(fp, "\n"), recno++;
+ }
+ if (!(one_col || count % 2 == 0))
+ xfprintf(fp, "\n"), recno++;
+ }
+ if (marker % 2 == 1)
+ { /* close last integer block */
+ marker++;
+ xfprintf(fp, "%*sM%07d%*s'MARKER'%*s'INTEND'\n",
+ csa->deck ? 4 : 1, "", marker, csa->deck ? 2 : 1, "",
+ csa->deck ? 17 : 1, ""), recno++;
+ }
+#if 1
+ if (empty > 0)
+ xprintf("Warning: problem has %d empty column(s)\n", empty);
+#endif
+ /* write RHS section */
+ xfprintf(fp, "RHS\n"), recno++;
+ count = 0;
+ for (i = (out_obj ? 0 : 1); i <= P->m; i++)
+ { int type;
+ double rhs;
+ if (i == 0)
+ rhs = P->c0;
+ else
+ { type = P->row[i]->type;
+ if (type == GLP_FR)
+ rhs = 0.0;
+ else if (type == GLP_LO)
+ rhs = P->row[i]->lb;
+ else if (type == GLP_UP)
+ rhs = P->row[i]->ub;
+ else if (type == GLP_DB || type == GLP_FX)
+ rhs = P->row[i]->lb;
+ else
+ xassert(type != type);
+ }
+ if (rhs != 0.0)
+ { if (one_col || count % 2 == 0)
+ xfprintf(fp, "%*s%-*s", csa->deck ? 4 : 1, "",
+ csa->deck ? 8 : 1, "RHS1");
+ gap = (one_col || count % 2 == 0 ? 2 : 3);
+ xfprintf(fp, "%*s%-*s",
+ csa->deck ? gap : 1, "", csa->deck ? 8 : 1,
+ row_name(csa, i));
+ xfprintf(fp, "%*s%*s",
+ csa->deck ? 2 : 1, "", csa->deck ? 12 : 1,
+ mps_numb(csa, rhs)), count++;
+ if (one_col || count % 2 == 0)
+ xfprintf(fp, "\n"), recno++;
+ }
+ }
+ if (!(one_col || count % 2 == 0))
+ xfprintf(fp, "\n"), recno++;
+ /* write RANGES section */
+ for (i = P->m; i >= 1; i--)
+ if (P->row[i]->type == GLP_DB) break;
+ if (i == 0) goto bnds;
+ xfprintf(fp, "RANGES\n"), recno++;
+ count = 0;
+ for (i = 1; i <= P->m; i++)
+ { if (P->row[i]->type == GLP_DB)
+ { if (one_col || count % 2 == 0)
+ xfprintf(fp, "%*s%-*s", csa->deck ? 4 : 1, "",
+ csa->deck ? 8 : 1, "RNG1");
+ gap = (one_col || count % 2 == 0 ? 2 : 3);
+ xfprintf(fp, "%*s%-*s",
+ csa->deck ? gap : 1, "", csa->deck ? 8 : 1,
+ row_name(csa, i));
+ xfprintf(fp, "%*s%*s",
+ csa->deck ? 2 : 1, "", csa->deck ? 12 : 1,
+ mps_numb(csa, P->row[i]->ub - P->row[i]->lb)), count++;
+ if (one_col || count % 2 == 0)
+ xfprintf(fp, "\n"), recno++;
+ }
+ }
+ if (!(one_col || count % 2 == 0))
+ xfprintf(fp, "\n"), recno++;
+bnds: /* write BOUNDS section */
+ for (j = P->n; j >= 1; j--)
+ if (!(P->col[j]->kind == GLP_CV &&
+ P->col[j]->type == GLP_LO && P->col[j]->lb == 0.0))
+ break;
+ if (j == 0) goto endt;
+ xfprintf(fp, "BOUNDS\n"), recno++;
+ for (j = 1; j <= P->n; j++)
+ { int type, data[2];
+ double bnd[2];
+ char *spec[2];
+ spec[0] = spec[1] = NULL;
+ type = P->col[j]->type;
+ if (type == GLP_FR)
+ spec[0] = "FR", data[0] = 0;
+ else if (type == GLP_LO)
+ { if (P->col[j]->lb != 0.0)
+ spec[0] = "LO", data[0] = 1, bnd[0] = P->col[j]->lb;
+ if (P->col[j]->kind == GLP_IV)
+ spec[1] = "PL", data[1] = 0;
+ }
+ else if (type == GLP_UP)
+ { spec[0] = "MI", data[0] = 0;
+ spec[1] = "UP", data[1] = 1, bnd[1] = P->col[j]->ub;
+ }
+ else if (type == GLP_DB)
+ { if (P->col[j]->lb != 0.0)
+ spec[0] = "LO", data[0] = 1, bnd[0] = P->col[j]->lb;
+ spec[1] = "UP", data[1] = 1, bnd[1] = P->col[j]->ub;
+ }
+ else if (type == GLP_FX)
+ spec[0] = "FX", data[0] = 1, bnd[0] = P->col[j]->lb;
+ else
+ xassert(type != type);
+ for (i = 0; i <= 1; i++)
+ { if (spec[i] != NULL)
+ { xfprintf(fp, " %s %-*s%*s%-*s", spec[i],
+ csa->deck ? 8 : 1, "BND1", csa->deck ? 2 : 1, "",
+ csa->deck ? 8 : 1, col_name(csa, j));
+ if (data[i])
+ xfprintf(fp, "%*s%*s", csa->deck ? 2 : 1, "",
+ csa->deck ? 12 : 1, mps_numb(csa, bnd[i]));
+ xfprintf(fp, "\n"), recno++;
+ }
+ }
+ }
+endt: /* write ENDATA indicator record */
+ xfprintf(fp, "ENDATA\n"), recno++;
+#if 0 /* FIXME */
+ xfflush(fp);
+#endif
+ if (glp_ioerr(fp))
+ { xprintf("Write error on '%s' - %s\n", fname, get_err_msg());
+ ret = 1;
+ goto done;
+ }
+ /* problem data has been successfully written */
+ xprintf("%d records were written\n", recno);
+ ret = 0;
+done: if (fp != NULL) glp_close(fp);
+ return ret;
+}
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/api/netgen.c b/test/monniaux/glpk-4.65/src/api/netgen.c
new file mode 100644
index 00000000..519fd609
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/api/netgen.c
@@ -0,0 +1,1020 @@
+/* netgen.c (Klingman's network problem generator) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* This code is the result of translation of the Fortran program NETGEN
+* developed by Dr. Darwin Klingman, which is publically available from
+* NETLIB at <http://www.netlib.org/lp/generators>.
+*
+* The translation was made 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 "env.h"
+#include "glpk.h"
+
+/***********************************************************************
+* NAME
+*
+* glp_netgen - Klingman's network problem generator
+*
+* SYNOPSIS
+*
+* int glp_netgen(glp_graph *G, int v_rhs, int a_cap, int a_cost,
+* const int parm[1+15]);
+*
+* DESCRIPTION
+*
+* The routine glp_netgen is a network problem generator developed by
+* Dr. Darwin Klingman. It can create capacitated and uncapacitated
+* minimum cost flow (or transshipment), transportation, and assignment
+* problems.
+*
+* The parameter G specifies the graph object, to which the generated
+* problem data have to be stored. Note that on entry the graph object
+* is erased with the routine glp_erase_graph.
+*
+* The parameter v_rhs specifies an offset of the field of type double
+* in the vertex data block, to which the routine stores the supply or
+* demand value. If v_rhs < 0, the value is not stored.
+*
+* The parameter a_cap specifies an offset of the field of type double
+* in the arc data block, to which the routine stores the arc capacity.
+* If a_cap < 0, the capacity is not stored.
+*
+* The parameter a_cost specifies an offset of the field of type double
+* in the arc data block, to which the routine stores the per-unit cost
+* if the arc flow. If a_cost < 0, the cost is not stored.
+*
+* The array parm contains description of the network to be generated:
+*
+* parm[0] not used
+* parm[1] (iseed) 8-digit positive random number seed
+* parm[2] (nprob) 8-digit problem id number
+* parm[3] (nodes) total number of nodes
+* parm[4] (nsorc) total number of source nodes (including
+* transshipment nodes)
+* parm[5] (nsink) total number of sink nodes (including
+* transshipment nodes)
+* parm[6] (iarcs) number of arcs
+* parm[7] (mincst) minimum cost for arcs
+* parm[8] (maxcst) maximum cost for arcs
+* parm[9] (itsup) total supply
+* parm[10] (ntsorc) number of transshipment source nodes
+* parm[11] (ntsink) number of transshipment sink nodes
+* parm[12] (iphic) percentage of skeleton arcs to be given
+* the maximum cost
+* parm[13] (ipcap) percentage of arcs to be capacitated
+* parm[14] (mincap) minimum upper bound for capacitated arcs
+* parm[15] (maxcap) maximum upper bound for capacitated arcs
+*
+* The routine generates a transportation problem if:
+*
+* nsorc + nsink = nodes, ntsorc = 0, and ntsink = 0.
+*
+* The routine generates an assignment problem if the requirements for
+* a transportation problem are met and:
+*
+* nsorc = nsink and itsup = nsorc.
+*
+* RETURNS
+*
+* If the instance was successfully generated, the routine glp_netgen
+* returns zero; otherwise, if specified parameters are inconsistent,
+* the routine returns a non-zero error code.
+*
+* REFERENCES
+*
+* D.Klingman, A.Napier, and J.Stutz. NETGEN: A program for generating
+* large scale capacitated assignment, transportation, and minimum cost
+* flow networks. Management Science 20 (1974), 814-20. */
+
+struct csa
+{ /* common storage area */
+ glp_graph *G;
+ int v_rhs, a_cap, a_cost;
+ int nodes, iarcs, mincst, maxcst, itsup, nsorc, nsink, nonsor,
+ nfsink, narcs, nsort, nftsor, ipcap, mincap, maxcap, ktl,
+ nodlft, *ipred, *ihead, *itail, *iflag, *isup, *lsinks, mult,
+ modul, i15, i16, jran;
+};
+
+#define G (csa->G)
+#define v_rhs (csa->v_rhs)
+#define a_cap (csa->a_cap)
+#define a_cost (csa->a_cost)
+#define nodes (csa->nodes)
+#define iarcs (csa->iarcs)
+#define mincst (csa->mincst)
+#define maxcst (csa->maxcst)
+#define itsup (csa->itsup)
+#define nsorc (csa->nsorc)
+#define nsink (csa->nsink)
+#define nonsor (csa->nonsor)
+#define nfsink (csa->nfsink)
+#define narcs (csa->narcs)
+#define nsort (csa->nsort)
+#define nftsor (csa->nftsor)
+#define ipcap (csa->ipcap)
+#define mincap (csa->mincap)
+#define maxcap (csa->maxcap)
+#define ktl (csa->ktl)
+#define nodlft (csa->nodlft)
+#if 0
+/* spent a day to find out this bug */
+#define ist (csa->ist)
+#else
+#define ist (ipred[0])
+#endif
+#define ipred (csa->ipred)
+#define ihead (csa->ihead)
+#define itail (csa->itail)
+#define iflag (csa->iflag)
+#define isup (csa->isup)
+#define lsinks (csa->lsinks)
+#define mult (csa->mult)
+#define modul (csa->modul)
+#define i15 (csa->i15)
+#define i16 (csa->i16)
+#define jran (csa->jran)
+
+static void cresup(struct csa *csa);
+static void chain(struct csa *csa, int lpick, int lsorc);
+static void chnarc(struct csa *csa, int lsorc);
+static void sort(struct csa *csa);
+static void pickj(struct csa *csa, int it);
+static void assign(struct csa *csa);
+static void setran(struct csa *csa, int iseed);
+static int iran(struct csa *csa, int ilow, int ihigh);
+
+int glp_netgen(glp_graph *G_, int _v_rhs, int _a_cap, int _a_cost,
+ const int parm[1+15])
+{ struct csa _csa, *csa = &_csa;
+ int iseed, nprob, ntsorc, ntsink, iphic, i, nskel, nltr, ltsink,
+ ntrans, npsink, nftr, npsorc, ntravl, ntrrem, lsorc, lpick,
+ nsksr, nsrchn, j, item, l, ks, k, ksp, li, n, ii, it, ih, icap,
+ jcap, icost, jcost, ret;
+ G = G_;
+ v_rhs = _v_rhs;
+ a_cap = _a_cap;
+ a_cost = _a_cost;
+ if (G != NULL)
+ { if (v_rhs >= 0 && v_rhs > G->v_size - (int)sizeof(double))
+ xerror("glp_netgen: v_rhs = %d; invalid offset\n", v_rhs);
+ if (a_cap >= 0 && a_cap > G->a_size - (int)sizeof(double))
+ xerror("glp_netgen: a_cap = %d; invalid offset\n", a_cap);
+ if (a_cost >= 0 && a_cost > G->a_size - (int)sizeof(double))
+ xerror("glp_netgen: a_cost = %d; invalid offset\n", a_cost);
+ }
+ /* Input the user's random number seed and fix it if
+ non-positive. */
+ iseed = parm[1];
+ nprob = parm[2];
+ if (iseed <= 0) iseed = 13502460;
+ setran(csa, iseed);
+ /* Input the user's problem characteristics. */
+ nodes = parm[3];
+ nsorc = parm[4];
+ nsink = parm[5];
+ iarcs = parm[6];
+ mincst = parm[7];
+ maxcst = parm[8];
+ itsup = parm[9];
+ ntsorc = parm[10];
+ ntsink = parm[11];
+ iphic = parm[12];
+ ipcap = parm[13];
+ mincap = parm[14];
+ maxcap = parm[15];
+ /* Check the size of the problem. */
+ if (!(10 <= nodes && nodes <= 100000))
+ { ret = 1;
+ goto done;
+ }
+ /* Check user supplied parameters for consistency. */
+ if (!(nsorc >= 0 && nsink >= 0 && nsorc + nsink <= nodes))
+ { ret = 2;
+ goto done;
+ }
+ if (iarcs < 0)
+ { ret = 3;
+ goto done;
+ }
+ if (mincst > maxcst)
+ { ret = 4;
+ goto done;
+ }
+ if (itsup < 0)
+ { ret = 5;
+ goto done;
+ }
+ if (!(0 <= ntsorc && ntsorc <= nsorc))
+ { ret = 6;
+ goto done;
+ }
+ if (!(0 <= ntsink && ntsink <= nsink))
+ { ret = 7;
+ goto done;
+ }
+ if (!(0 <= iphic && iphic <= 100))
+ { ret = 8;
+ goto done;
+ }
+ if (!(0 <= ipcap && ipcap <= 100))
+ { ret = 9;
+ goto done;
+ }
+ if (mincap > maxcap)
+ { ret = 10;
+ goto done;
+ }
+ /* Initailize the graph object. */
+ if (G != NULL)
+ { glp_erase_graph(G, G->v_size, G->a_size);
+ glp_add_vertices(G, nodes);
+ if (v_rhs >= 0)
+ { double zero = 0.0;
+ for (i = 1; i <= nodes; i++)
+ { glp_vertex *v = G->v[i];
+ memcpy((char *)v->data + v_rhs, &zero, sizeof(double));
+ }
+ }
+ }
+ /* Allocate working arrays. */
+ ipred = xcalloc(1+nodes, sizeof(int));
+ ihead = xcalloc(1+nodes, sizeof(int));
+ itail = xcalloc(1+nodes, sizeof(int));
+ iflag = xcalloc(1+nodes, sizeof(int));
+ isup = xcalloc(1+nodes, sizeof(int));
+ lsinks = xcalloc(1+nodes, sizeof(int));
+ /* Print the problem documentation records. */
+ if (G == NULL)
+ { xprintf("BEGIN\n");
+ xprintf("NETGEN PROBLEM%8d%10s%10d NODES AND%10d ARCS\n",
+ nprob, "", nodes, iarcs);
+ xprintf("USER:%11d%11d%11d%11d%11d%11d\nDATA:%11d%11d%11d%11d%"
+ "11d%11d\n", iseed, nsorc, nsink, mincst,
+ maxcst, itsup, ntsorc, ntsink, iphic, ipcap,
+ mincap, maxcap);
+ }
+ else
+ glp_set_graph_name(G, "NETGEN");
+ /* Set various constants used in the program. */
+ narcs = 0;
+ nskel = 0;
+ nltr = nodes - nsink;
+ ltsink = nltr + ntsink;
+ ntrans = nltr - nsorc;
+ nfsink = nltr + 1;
+ nonsor = nodes - nsorc + ntsorc;
+ npsink = nsink - ntsink;
+ nodlft = nodes - nsink + ntsink;
+ nftr = nsorc + 1;
+ nftsor = nsorc - ntsorc + 1;
+ npsorc = nsorc - ntsorc;
+ /* Randomly distribute the supply among the source nodes. */
+ if (npsorc + npsink == nodes && npsorc == npsink &&
+ itsup == nsorc)
+ { assign(csa);
+ nskel = nsorc;
+ goto L390;
+ }
+ cresup(csa);
+ /* Print the supply records. */
+ if (G == NULL)
+ { xprintf("SUPPLY\n");
+ for (i = 1; i <= nsorc; i++)
+ xprintf("%6s%6d%18s%10d\n", "", i, "", isup[i]);
+ xprintf("ARCS\n");
+ }
+ else
+ { if (v_rhs >= 0)
+ { for (i = 1; i <= nsorc; i++)
+ { double temp = (double)isup[i];
+ glp_vertex *v = G->v[i];
+ memcpy((char *)v->data + v_rhs, &temp, sizeof(double));
+ }
+ }
+ }
+ /* Make the sources point to themselves in ipred array. */
+ for (i = 1; i <= nsorc; i++)
+ ipred[i] = i;
+ if (ntrans == 0) goto L170;
+ /* Chain the transshipment nodes together in the ipred array. */
+ ist = nftr;
+ ipred[nltr] = 0;
+ for (i = nftr; i < nltr; i++)
+ ipred[i] = i+1;
+ /* Form even length chains for 60 percent of the transshipments.*/
+ ntravl = 6 * ntrans / 10;
+ ntrrem = ntrans - ntravl;
+L140: lsorc = 1;
+ while (ntravl != 0)
+ { lpick = iran(csa, 1, ntravl + ntrrem);
+ ntravl--;
+ chain(csa, lpick, lsorc);
+ if (lsorc == nsorc) goto L140;
+ lsorc++;
+ }
+ /* Add the remaining transshipments to the chains. */
+ while (ntrrem != 0)
+ {
+ lpick = iran(csa, 1, ntrrem);
+ ntrrem--;
+ lsorc = iran(csa, 1, nsorc);
+ chain(csa, lpick, lsorc);
+ }
+L170: /* Set all demands equal to zero. */
+ for (i = nfsink; i <= nodes; i++)
+ ipred[i] = 0;
+ /* The following loop takes one chain at a time (through the use
+ of logic contained in the loop and calls to other routines) and
+ creates the remaining network arcs. */
+ for (lsorc = 1; lsorc <= nsorc; lsorc++)
+ { chnarc(csa, lsorc);
+ for (i = nfsink; i <= nodes; i++)
+ iflag[i] = 0;
+ /* Choose the number of sinks to be hooked up to the current
+ chain. */
+ if (ntrans != 0)
+ nsksr = (nsort * 2 * nsink) / ntrans;
+ else
+ nsksr = nsink / nsorc + 1;
+ if (nsksr < 2) nsksr = 2;
+ if (nsksr > nsink) nsksr = nsink;
+ nsrchn = nsort;
+ /* Randomly pick nsksr sinks and put their names in lsinks. */
+ ktl = nsink;
+ for (j = 1; j <= nsksr; j++)
+ { item = iran(csa, 1, ktl);
+ ktl--;
+ for (l = nfsink; l <= nodes; l++)
+ { if (iflag[l] != 1)
+ { item--;
+ if (item == 0) goto L230;
+ }
+ }
+ break;
+L230: lsinks[j] = l;
+ iflag[l] = 1;
+ }
+ /* If last source chain, add all sinks with zero demand to
+ lsinks list. */
+ if (lsorc == nsorc)
+ { for (j = nfsink; j <= nodes; j++)
+ { if (ipred[j] == 0 && iflag[j] != 1)
+ { nsksr++;
+ lsinks[nsksr] = j;
+ iflag[j] = 1;
+ }
+ }
+ }
+ /* Create demands for group of sinks in lsinks. */
+ ks = isup[lsorc] / nsksr;
+ k = ipred[lsorc];
+ for (i = 1; i <= nsksr; i++)
+ { nsort++;
+ ksp = iran(csa, 1, ks);
+ j = iran(csa, 1, nsksr);
+ itail[nsort] = k;
+ li = lsinks[i];
+ ihead[nsort] = li;
+ ipred[li] += ksp;
+ li = lsinks[j];
+ ipred[li] += ks - ksp;
+ n = iran(csa, 1, nsrchn);
+ k = lsorc;
+ for (ii = 1; ii <= n; ii++)
+ k = ipred[k];
+ }
+ li = lsinks[1];
+ ipred[li] += isup[lsorc] - ks * nsksr;
+ nskel += nsort;
+ /* Sort the arcs in the chain from source lsorc using itail as
+ sort key. */
+ sort(csa);
+ /* Print this part of skeleton and create the arcs for these
+ nodes. */
+ i = 1;
+ itail[nsort+1] = 0;
+L300: for (j = nftsor; j <= nodes; j++)
+ iflag[j] = 0;
+ ktl = nonsor - 1;
+ it = itail[i];
+ iflag[it] = 1;
+L320: ih = ihead[i];
+ iflag[ih] = 1;
+ narcs++;
+ ktl--;
+ /* Determine if this skeleton arc should be capacitated. */
+ icap = itsup;
+ jcap = iran(csa, 1, 100);
+ if (jcap <= ipcap)
+ { icap = isup[lsorc];
+ if (mincap > icap) icap = mincap;
+ }
+ /* Determine if this skeleton arc should have the maximum
+ cost. */
+ icost = maxcst;
+ jcost = iran(csa, 1, 100);
+ if (jcost > iphic)
+ icost = iran(csa, mincst, maxcst);
+ if (G == NULL)
+ xprintf("%6s%6d%6d%2s%10d%10d\n", "", it, ih, "", icost,
+ icap);
+ else
+ { glp_arc *a = glp_add_arc(G, it, ih);
+ if (a_cap >= 0)
+ { double temp = (double)icap;
+ memcpy((char *)a->data + a_cap, &temp, sizeof(double));
+ }
+ if (a_cost >= 0)
+ { double temp = (double)icost;
+ memcpy((char *)a->data + a_cost, &temp, sizeof(double));
+ }
+ }
+ i++;
+ if (itail[i] == it) goto L320;
+ pickj(csa, it);
+ if (i <= nsort) goto L300;
+ }
+ /* Create arcs from the transshipment sinks. */
+ if (ntsink != 0)
+ { for (i = nfsink; i <= ltsink; i++)
+ { for (j = nftsor; j <= nodes; j++)
+ iflag[j] = 0;
+ ktl = nonsor - 1;
+ iflag[i] = 1;
+ pickj(csa, i);
+ }
+ }
+L390: /* Print the demand records and end record. */
+ if (G == NULL)
+ { xprintf("DEMAND\n");
+ for (i = nfsink; i <= nodes; i++)
+ xprintf("%6s%6d%18s%10d\n", "", i, "", ipred[i]);
+ xprintf("END\n");
+ }
+ else
+ { if (v_rhs >= 0)
+ { for (i = nfsink; i <= nodes; i++)
+ { double temp = - (double)ipred[i];
+ glp_vertex *v = G->v[i];
+ memcpy((char *)v->data + v_rhs, &temp, sizeof(double));
+ }
+ }
+ }
+ /* Free working arrays. */
+ xfree(ipred);
+ xfree(ihead);
+ xfree(itail);
+ xfree(iflag);
+ xfree(isup);
+ xfree(lsinks);
+ /* The instance has been successfully generated. */
+ ret = 0;
+done: return ret;
+}
+
+/***********************************************************************
+* The routine cresup randomly distributes the total supply among the
+* source nodes. */
+
+static void cresup(struct csa *csa)
+{ int i, j, ks, ksp;
+ xassert(itsup > nsorc);
+ ks = itsup / nsorc;
+ for (i = 1; i <= nsorc; i++)
+ isup[i] = 0;
+ for (i = 1; i <= nsorc; i++)
+ { ksp = iran(csa, 1, ks);
+ j = iran(csa, 1, nsorc);
+ isup[i] += ksp;
+ isup[j] += ks - ksp;
+ }
+ j = iran(csa, 1, nsorc);
+ isup[j] += itsup - ks * nsorc;
+ return;
+}
+
+/***********************************************************************
+* The routine chain adds node lpick to the end of the chain with source
+* node lsorc. */
+
+static void chain(struct csa *csa, int lpick, int lsorc)
+{ int i, j, k, l, m;
+ k = 0;
+ m = ist;
+ for (i = 1; i <= lpick; i++)
+ { l = k;
+ k = m;
+ m = ipred[k];
+ }
+ ipred[l] = m;
+ j = ipred[lsorc];
+ ipred[k] = j;
+ ipred[lsorc] = k;
+ return;
+}
+
+/***********************************************************************
+* The routine chnarc puts the arcs in the chain from source lsorc into
+* the ihead and itail arrays for sorting. */
+
+static void chnarc(struct csa *csa, int lsorc)
+{ int ito, ifrom;
+ nsort = 0;
+ ito = ipred[lsorc];
+L10: if (ito == lsorc) return;
+ nsort++;
+ ifrom = ipred[ito];
+ ihead[nsort] = ito;
+ itail[nsort] = ifrom;
+ ito = ifrom;
+ goto L10;
+}
+
+/***********************************************************************
+* The routine sort sorts the nsort arcs in the ihead and itail arrays.
+* ihead is used as the sort key (i.e. forward star sort order). */
+
+static void sort(struct csa *csa)
+{ int i, j, k, l, m, n, it;
+ n = nsort;
+ m = n;
+L10: m /= 2;
+ if (m == 0) return;
+ k = n - m;
+ j = 1;
+L20: i = j;
+L30: l = i + m;
+ if (itail[i] <= itail[l]) goto L40;
+ it = itail[i];
+ itail[i] = itail[l];
+ itail[l] = it;
+ it = ihead[i];
+ ihead[i] = ihead[l];
+ ihead[l] = it;
+ i -= m;
+ if (i >= 1) goto L30;
+L40: j++;
+ if (j <= k) goto L20;
+ goto L10;
+}
+
+/***********************************************************************
+* The routine pickj creates a random number of arcs out of node 'it'.
+* Various parameters are dynamically adjusted in an attempt to ensure
+* that the generated network has the correct number of arcs. */
+
+static void pickj(struct csa *csa, int it)
+{ int j, k, l, nn, nupbnd, icap, jcap, icost;
+ if ((nodlft - 1) * 2 > iarcs - narcs - 1)
+ { nodlft--;
+ return;
+ }
+ if ((iarcs - narcs + nonsor - ktl - 1) / nodlft - nonsor + 1 >= 0)
+ k = nonsor;
+ else
+ { nupbnd = (iarcs - narcs - nodlft) / nodlft * 2;
+L40: k = iran(csa, 1, nupbnd);
+ if (nodlft == 1) k = iarcs - narcs;
+ if ((nodlft - 1) * (nonsor - 1) < iarcs - narcs - k) goto L40;
+ }
+ nodlft--;
+ for (j = 1; j <= k; j++)
+ { nn = iran(csa, 1, ktl);
+ ktl--;
+ for (l = nftsor; l <= nodes; l++)
+ { if (iflag[l] != 1)
+ { nn--;
+ if (nn == 0) goto L70;
+ }
+ }
+ return;
+L70: iflag[l] = 1;
+ icap = itsup;
+ jcap = iran(csa, 1, 100);
+ if (jcap <= ipcap)
+ icap = iran(csa, mincap, maxcap);
+ icost = iran(csa, mincst, maxcst);
+ if (G == NULL)
+ xprintf("%6s%6d%6d%2s%10d%10d\n", "", it, l, "", icost,
+ icap);
+ else
+ { glp_arc *a = glp_add_arc(G, it, l);
+ if (a_cap >= 0)
+ { double temp = (double)icap;
+ memcpy((char *)a->data + a_cap, &temp, sizeof(double));
+ }
+ if (a_cost >= 0)
+ { double temp = (double)icost;
+ memcpy((char *)a->data + a_cost, &temp, sizeof(double));
+ }
+ }
+ narcs++;
+ }
+ return;
+}
+
+/***********************************************************************
+* The routine assign generate assignment problems. It defines the unit
+* supplies, builds a skeleton, then calls pickj to create the arcs. */
+
+static void assign(struct csa *csa)
+{ int i, it, nn, l, ll, icost;
+ if (G == NULL)
+ xprintf("SUPPLY\n");
+ for (i = 1; i <= nsorc; i++)
+ { isup[i] = 1;
+ iflag[i] = 0;
+ if (G == NULL)
+ xprintf("%6s%6d%18s%10d\n", "", i, "", isup[i]);
+ else
+ { if (v_rhs >= 0)
+ { double temp = (double)isup[i];
+ glp_vertex *v = G->v[i];
+ memcpy((char *)v->data + v_rhs, &temp, sizeof(double));
+ }
+ }
+ }
+ if (G == NULL)
+ xprintf("ARCS\n");
+ for (i = nfsink; i <= nodes; i++)
+ ipred[i] = 1;
+ for (it = 1; it <= nsorc; it++)
+ { for (i = nfsink; i <= nodes; i++)
+ iflag[i] = 0;
+ ktl = nsink - 1;
+ nn = iran(csa, 1, nsink - it + 1);
+ for (l = 1; l <= nsorc; l++)
+ { if (iflag[l] != 1)
+ { nn--;
+ if (nn == 0) break;
+ }
+ }
+ narcs++;
+ ll = nsorc + l;
+ icost = iran(csa, mincst, maxcst);
+ if (G == NULL)
+ xprintf("%6s%6d%6d%2s%10d%10d\n", "", it, ll, "", icost,
+ isup[1]);
+ else
+ { glp_arc *a = glp_add_arc(G, it, ll);
+ if (a_cap >= 0)
+ { double temp = (double)isup[1];
+ memcpy((char *)a->data + a_cap, &temp, sizeof(double));
+ }
+ if (a_cost >= 0)
+ { double temp = (double)icost;
+ memcpy((char *)a->data + a_cost, &temp, sizeof(double));
+ }
+ }
+ iflag[l] = 1;
+ iflag[ll] = 1;
+ pickj(csa, it);
+ }
+ return;
+}
+
+/***********************************************************************
+* Portable congruential (uniform) random number generator:
+*
+* next_value = ((7**5) * previous_value) modulo ((2**31)-1)
+*
+* This generator consists of three routines:
+*
+* (1) setran - initializes constants and seed
+* (2) iran - generates an integer random number
+* (3) rran - generates a real random number
+*
+* The generator requires a machine with at least 32 bits of precision.
+* The seed (iseed) must be in the range [1,(2**31)-1]. */
+
+static void setran(struct csa *csa, int iseed)
+{ xassert(iseed >= 1);
+ mult = 16807;
+ modul = 2147483647;
+ i15 = 1 << 15;
+ i16 = 1 << 16;
+ jran = iseed;
+ return;
+}
+
+/***********************************************************************
+* The routine iran generates an integer random number between ilow and
+* ihigh. If ilow > ihigh then iran returns ihigh. */
+
+static int iran(struct csa *csa, int ilow, int ihigh)
+{ int ixhi, ixlo, ixalo, leftlo, ixahi, ifulhi, irtlo, iover,
+ irthi, j;
+ ixhi = jran / i16;
+ ixlo = jran - ixhi * i16;
+ ixalo = ixlo * mult;
+ leftlo = ixalo / i16;
+ ixahi = ixhi * mult;
+ ifulhi = ixahi + leftlo;
+ irtlo = ixalo - leftlo * i16;
+ iover = ifulhi / i15;
+ irthi = ifulhi - iover * i15;
+ jran = ((irtlo - modul) + irthi * i16) + iover;
+ if (jran < 0) jran += modul;
+ j = ihigh - ilow + 1;
+ if (j > 0)
+ return jran % j + ilow;
+ else
+ return ihigh;
+}
+
+/***********************************************************************
+* NAME
+*
+* glp_netgen_prob - Klingman's standard network problem instance
+*
+* SYNOPSIS
+*
+* void glp_netgen_prob(int nprob, int parm[1+15]);
+*
+* DESCRIPTION
+*
+* The routine glp_netgen_prob provides the set of parameters for
+* Klingman's network problem generator (see the routine glp_netgen),
+* which describe a standard network problem instance.
+*
+* The parameter nprob (101 <= nprob <= 150) specifies the problem
+* instance number.
+*
+* The array parm contains description of the network, provided by the
+* routine. (For detailed description of these parameters see comments
+* to the routine glp_netgen.)
+*
+* PROBLEM CHARACTERISTICS
+*
+* The table below shows characteristics of Klingman's standard network
+* problem instances.
+*
+* Problem Nodes Arcs Optimum
+* ------- ----- ----- ----------
+* 101 5000 25336 6191726
+* 102 5000 25387 72337144
+* 103 5000 25355 218947553
+* 104 5000 25344 -19100371
+* 105 5000 25332 31192578
+* 106 5000 12870 4314276
+* 107 5000 37832 7393769
+* 108 5000 50309 8405738
+* 109 5000 75299 9190300
+* 110 5000 12825 8975048
+* 111 5000 37828 4747532
+* 112 5000 50325 4012671
+* 113 5000 75318 2979725
+* 114 5000 26514 5821181
+* 115 5000 25962 6353310
+* 116 5000 25304 5915426
+* 117 5000 12816 4420560
+* 118 5000 37797 7045842
+* 119 5000 50301 7724179
+* 120 5000 75330 8455200
+* 121 5000 25000 66366360
+* 122 5000 25000 30997529
+* 123 5000 25000 23388777
+* 124 5000 25000 17803443
+* 125 5000 25000 14119622
+* 126 5000 12500 18802218
+* 127 5000 37500 27674647
+* 128 5000 50000 30906194
+* 129 5000 75000 40905209
+* 130 5000 12500 38939608
+* 131 5000 37500 16752978
+* 132 5000 50000 13302951
+* 133 5000 75000 9830268
+* 134 1000 25000 3804874
+* 135 2500 25000 11729616
+* 136 7500 25000 33318101
+* 137 10000 25000 46426030
+* 138 5000 25000 60710879
+* 139 5000 25000 32729682
+* 140 5000 25000 27183831
+* 141 5000 25000 19963286
+* 142 5000 25000 20243457
+* 143 5000 25000 18586777
+* 144 5000 25000 2504591
+* 145 5000 25000 215956138
+* 146 5000 25000 2253113811
+* 147 5000 25000 -427908373
+* 148 5000 25000 -92965318
+* 149 5000 25000 86051224
+* 150 5000 25000 619314919 */
+
+static const int data[50][1+15] =
+{ { 0, 13502460, 101, 5000, 2500, 2500, 25000,
+ 1, 100, 250000, 0, 0, 0, 100, 1, 1000
+ },
+ { 0, 4281922, 102, 5000, 2500, 2500, 25000,
+ 1, 100, 2500000, 0, 0, 0, 100, 1, 1000
+ },
+ { 0, 44820113, 103, 5000, 2500, 2500, 25000,
+ 1, 100, 6250000, 0, 0, 0, 100, 1, 1000
+ },
+ { 0, 13450451, 104, 5000, 2500, 2500, 25000,
+ -100, -1, 250000, 0, 0, 0, 100, 1, 1000
+ },
+ { 0, 14719436, 105, 5000, 2500, 2500, 25000,
+ 101, 200, 250000, 0, 0, 0, 100, 1, 1000
+ },
+ { 0, 17365786, 106, 5000, 2500, 2500, 12500,
+ 1, 100, 125000, 0, 0, 0, 100, 1, 1000
+ },
+ { 0, 19540113, 107, 5000, 2500, 2500, 37500,
+ 1, 100, 375000, 0, 0, 0, 100, 1, 1000
+ },
+ { 0, 19560313, 108, 5000, 2500, 2500, 50000,
+ 1, 100, 500000, 0, 0, 0, 100, 1, 1000
+ },
+ { 0, 2403509, 109, 5000, 2500, 2500, 75000,
+ 1, 100, 750000, 0, 0, 0, 100, 1, 1000
+ },
+ { 0, 92480414, 110, 5000, 2500, 2500, 12500,
+ 1, 100, 250000, 0, 0, 0, 100, 1, 1000
+ },
+ { 0, 4230140, 111, 5000, 2500, 2500, 37500,
+ 1, 100, 250000, 0, 0, 0, 100, 1, 1000
+ },
+ { 0, 10032490, 112, 5000, 2500, 2500, 50000,
+ 1, 100, 250000, 0, 0, 0, 100, 1, 1000
+ },
+ { 0, 17307474, 113, 5000, 2500, 2500, 75000,
+ 1, 100, 250000, 0, 0, 0, 100, 1, 1000
+ },
+ { 0, 4925114, 114, 5000, 500, 4500, 25000,
+ 1, 100, 250000, 0, 0, 0, 100, 1, 1000
+ },
+ { 0, 19842704, 115, 5000, 1500, 3500, 25000,
+ 1, 100, 250000, 0, 0, 0, 100, 1, 1000
+ },
+ { 0, 88392060, 116, 5000, 2500, 2500, 25000,
+ 1, 100, 250000, 0, 0, 0, 0, 1, 1000
+ },
+ { 0, 12904407, 117, 5000, 2500, 2500, 12500,
+ 1, 100, 125000, 0, 0, 0, 0, 1, 1000
+ },
+ { 0, 11811811, 118, 5000, 2500, 2500, 37500,
+ 1, 100, 375000, 0, 0, 0, 0, 1, 1000
+ },
+ { 0, 90023593, 119, 5000, 2500, 2500, 50000,
+ 1, 100, 500000, 0, 0, 0, 0, 1, 1000
+ },
+ { 0, 93028922, 120, 5000, 2500, 2500, 75000,
+ 1, 100, 750000, 0, 0, 0, 0, 1, 1000
+ },
+ { 0, 72707401, 121, 5000, 50, 50, 25000,
+ 1, 100, 250000, 50, 50, 0, 100, 1, 1000
+ },
+ { 0, 93040771, 122, 5000, 250, 250, 25000,
+ 1, 100, 250000, 250, 250, 0, 100, 1, 1000
+ },
+ { 0, 70220611, 123, 5000, 500, 500, 25000,
+ 1, 100, 250000, 500, 500, 0, 100, 1, 1000
+ },
+ { 0, 52774811, 124, 5000, 1000, 1000, 25000,
+ 1, 100, 250000, 1000, 1000, 0, 100, 1, 1000
+ },
+ { 0, 22492311, 125, 5000, 1500, 1500, 25000,
+ 1, 100, 250000, 1500, 1500, 0, 100, 1, 1000
+ },
+ { 0, 35269337, 126, 5000, 500, 500, 12500,
+ 1, 100, 125000, 500, 500, 0, 100, 1, 1000
+ },
+ { 0, 30140502, 127, 5000, 500, 500, 37500,
+ 1, 100, 375000, 500, 500, 0, 100, 1, 1000
+ },
+ { 0, 49205455, 128, 5000, 500, 500, 50000,
+ 1, 100, 500000, 500, 500, 0, 100, 1, 1000
+ },
+ { 0, 42958341, 129, 5000, 500, 500, 75000,
+ 1, 100, 750000, 500, 500, 0, 100, 1, 1000
+ },
+ { 0, 25440925, 130, 5000, 500, 500, 12500,
+ 1, 100, 250000, 500, 500, 0, 100, 1, 1000
+ },
+ { 0, 75294924, 131, 5000, 500, 500, 37500,
+ 1, 100, 250000, 500, 500, 0, 100, 1, 1000
+ },
+ { 0, 4463965, 132, 5000, 500, 500, 50000,
+ 1, 100, 250000, 500, 500, 0, 100, 1, 1000
+ },
+ { 0, 13390427, 133, 5000, 500, 500, 75000,
+ 1, 100, 250000, 500, 500, 0, 100, 1, 1000
+ },
+ { 0, 95250971, 134, 1000, 500, 500, 25000,
+ 1, 100, 250000, 500, 500, 0, 100, 1, 1000
+ },
+ { 0, 54830522, 135, 2500, 500, 500, 25000,
+ 1, 100, 250000, 500, 500, 0, 100, 1, 1000
+ },
+ { 0, 520593, 136, 7500, 500, 500, 25000,
+ 1, 100, 250000, 500, 500, 0, 100, 1, 1000
+ },
+ { 0, 52900925, 137, 10000, 500, 500, 25000,
+ 1, 100, 250000, 500, 500, 0, 100, 1, 1000
+ },
+ { 0, 22603395, 138, 5000, 500, 500, 25000,
+ 1, 100, 250000, 500, 500, 0, 100, 1, 50
+ },
+ { 0, 55253099, 139, 5000, 500, 500, 25000,
+ 1, 100, 250000, 500, 500, 0, 100, 1, 250
+ },
+ { 0, 75357001, 140, 5000, 500, 500, 25000,
+ 1, 100, 250000, 500, 500, 0, 100, 1, 500
+ },
+ { 0, 10072459, 141, 5000, 500, 500, 25000,
+ 1, 100, 250000, 500, 500, 0, 100, 1, 2500
+ },
+ { 0, 55728492, 142, 5000, 500, 500, 25000,
+ 1, 100, 250000, 500, 500, 0, 100, 1, 5000
+ },
+ { 0, 593043, 143, 5000, 500, 500, 25000,
+ 1, 100, 250000, 500, 500, 0, 0, 1, 1000
+ },
+ { 0, 94236572, 144, 5000, 500, 500, 25000,
+ 1, 10, 250000, 500, 500, 0, 100, 1, 1000
+ },
+ { 0, 94882955, 145, 5000, 500, 500, 25000,
+ 1, 1000, 250000, 500, 500, 0, 100, 1, 1000
+ },
+ { 0, 48489922, 146, 5000, 500, 500, 25000,
+ 1, 10000, 250000, 500, 500, 0, 100, 1, 1000
+ },
+ { 0, 75578374, 147, 5000, 500, 500, 25000,
+ -100, -1, 250000, 500, 500, 0, 100, 1, 1000
+ },
+ { 0, 44821152, 148, 5000, 500, 500, 25000,
+ -50, 49, 250000, 500, 500, 0, 100, 1, 1000
+ },
+ { 0, 45224103, 149, 5000, 500, 500, 25000,
+ 101, 200, 250000, 500, 500, 0, 100, 1, 1000
+ },
+ { 0, 63491741, 150, 5000, 500, 500, 25000,
+ 1001, 1100, 250000, 500, 500, 0, 100, 1, 1000
+ },
+};
+
+void glp_netgen_prob(int nprob, int parm[1+15])
+{ int k;
+ if (!(101 <= nprob && nprob <= 150))
+ xerror("glp_netgen_prob: nprob = %d; invalid problem instance "
+ "number\n", nprob);
+ for (k = 1; k <= 15; k++)
+ parm[k] = data[nprob-101][k];
+ return;
+}
+
+/**********************************************************************/
+
+#if 0
+static int scan(char card[80+1], int pos, int len)
+{ char buf[10+1];
+ memcpy(buf, &card[pos-1], len);
+ buf[len] = '\0';
+ return atoi(buf);
+}
+
+int main(void)
+{ int parm[1+15];
+ char card[80+1];
+ xassert(fgets(card, sizeof(card), stdin) == card);
+ parm[1] = scan(card, 1, 8);
+ parm[2] = scan(card, 9, 8);
+ xassert(fgets(card, sizeof(card), stdin) == card);
+ parm[3] = scan(card, 1, 5);
+ parm[4] = scan(card, 6, 5);
+ parm[5] = scan(card, 11, 5);
+ parm[6] = scan(card, 16, 5);
+ parm[7] = scan(card, 21, 5);
+ parm[8] = scan(card, 26, 5);
+ parm[9] = scan(card, 31, 10);
+ parm[10] = scan(card, 41, 5);
+ parm[11] = scan(card, 46, 5);
+ parm[12] = scan(card, 51, 5);
+ parm[13] = scan(card, 56, 5);
+ parm[14] = scan(card, 61, 10);
+ parm[15] = scan(card, 71, 10);
+ glp_netgen(NULL, 0, 0, 0, parm);
+ return 0;
+}
+#endif
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/api/npp.c b/test/monniaux/glpk-4.65/src/api/npp.c
new file mode 100644
index 00000000..a7ae07c1
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/api/npp.c
@@ -0,0 +1,143 @@
+/* npp.c (LP/MIP preprocessing) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* Copyright (C) 2017 Andrew Makhorin, Department for Applied
+* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights
+* reserved. E-mail: <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 "env.h"
+#include "npp.h"
+
+glp_prep *glp_npp_alloc_wksp(void)
+{ /* allocate the preprocessor workspace */
+ glp_prep *prep;
+ prep = npp_create_wksp();
+ return prep;
+}
+
+void glp_npp_load_prob(glp_prep *prep, glp_prob *P, int sol, int names)
+{ /* load original problem instance */
+ if (prep->sol != 0)
+ xerror("glp_npp_load_prob: invalid call sequence (original ins"
+ "tance already loaded)\n");
+ if (!(sol == GLP_SOL || sol == GLP_IPT || sol == GLP_MIP))
+ xerror("glp_npp_load_prob: sol = %d; invalid parameter\n",
+ sol);
+ if (!(names == GLP_ON || names == GLP_OFF))
+ xerror("glp_npp_load_prob: names = %d; invalid parameter\n",
+ names);
+ npp_load_prob(prep, P, names, sol, GLP_OFF);
+ return;
+}
+
+int glp_npp_preprocess1(glp_prep *prep, int hard)
+{ /* perform basic LP/MIP preprocessing */
+ if (prep->sol == 0)
+ xerror("glp_npp_preprocess1: invalid call sequence (original i"
+ "nstance not loaded yet)\n");
+ if (prep->pool == NULL)
+ xerror("glp_npp_preprocess1: invalid call sequence (preprocess"
+ "ing already finished)\n");
+ if (!(hard == GLP_ON || hard == GLP_OFF))
+ xerror("glp_npp_preprocess1: hard = %d; invalid parameter\n",
+ hard);
+ return npp_process_prob(prep, hard);
+}
+
+void glp_npp_build_prob(glp_prep *prep, glp_prob *Q)
+{ /* build resultant problem instance */
+ if (prep->sol == 0)
+ xerror("glp_npp_build_prob: invalid call sequence (original in"
+ "stance not loaded yet)\n");
+ if (prep->pool == NULL)
+ xerror("glp_npp_build_prob: invalid call sequence (resultant i"
+ "nstance already built)\n");
+ npp_build_prob(prep, Q);
+ return;
+}
+
+void glp_npp_postprocess(glp_prep *prep, glp_prob *Q)
+{ /* postprocess solution to resultant problem */
+ if (prep->pool != NULL)
+ xerror("glp_npp_postprocess: invalid call sequence (resultant "
+ "instance not built yet)\n");
+ if (!(prep->m == Q->m && prep->n == Q->n && prep->nnz == Q->nnz))
+ xerror("glp_npp_postprocess: resultant instance mismatch\n");
+ switch (prep->sol)
+ { case GLP_SOL:
+ if (glp_get_status(Q) != GLP_OPT)
+ xerror("glp_npp_postprocess: unable to recover non-optim"
+ "al basic solution\n");
+ break;
+ case GLP_IPT:
+ if (glp_ipt_status(Q) != GLP_OPT)
+ xerror("glp_npp_postprocess: unable to recover non-optim"
+ "al interior-point solution\n");
+ break;
+ case GLP_MIP:
+ if (!(glp_mip_status(Q) == GLP_OPT || glp_mip_status(Q) ==
+ GLP_FEAS))
+ xerror("glp_npp_postprocess: unable to recover integer n"
+ "on-feasible solution\n");
+ break;
+ default:
+ xassert(prep != prep);
+ }
+ npp_postprocess(prep, Q);
+ return;
+}
+
+void glp_npp_obtain_sol(glp_prep *prep, glp_prob *P)
+{ /* obtain solution to original problem */
+ if (prep->pool != NULL)
+ xerror("glp_npp_obtain_sol: invalid call sequence (resultant i"
+ "nstance not built yet)\n");
+ switch (prep->sol)
+ { case GLP_SOL:
+ if (prep->p_stat == 0 || prep->d_stat == 0)
+ xerror("glp_npp_obtain_sol: invalid call sequence (basic"
+ " solution not provided yet)\n");
+ break;
+ case GLP_IPT:
+ if (prep->t_stat == 0)
+ xerror("glp_npp_obtain_sol: invalid call sequence (inter"
+ "ior-point solution not provided yet)\n");
+ break;
+ case GLP_MIP:
+ if (prep->i_stat == 0)
+ xerror("glp_npp_obtain_sol: invalid call sequence (MIP s"
+ "olution not provided yet)\n");
+ break;
+ default:
+ xassert(prep != prep);
+ }
+ if (!(prep->orig_dir == P->dir && prep->orig_m == P->m &&
+ prep->orig_n == P->n && prep->orig_nnz == P->nnz))
+ xerror("glp_npp_obtain_sol: original instance mismatch\n");
+ npp_unload_sol(prep, P);
+ return;
+}
+
+void glp_npp_free_wksp(glp_prep *prep)
+{ /* free the preprocessor workspace */
+ npp_delete_wksp(prep);
+ return;
+}
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/api/pript.c b/test/monniaux/glpk-4.65/src/api/pript.c
new file mode 100644
index 00000000..f123089d
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/api/pript.c
@@ -0,0 +1,186 @@
+/* pript.c (write interior-point solution in printable format) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* Copyright (C) 2009-2016 Andrew Makhorin, Department for Applied
+* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights
+* reserved. E-mail: <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 "env.h"
+#include "prob.h"
+
+#define xfprintf glp_format
+
+int glp_print_ipt(glp_prob *P, const char *fname)
+{ /* write interior-point solution in printable format */
+ glp_file *fp;
+ GLPROW *row;
+ GLPCOL *col;
+ int i, j, t, ae_ind, re_ind, ret;
+ double ae_max, re_max;
+ xprintf("Writing interior-point solution to '%s'...\n", fname);
+ fp = glp_open(fname, "w");
+ if (fp == NULL)
+ { xprintf("Unable to create '%s' - %s\n", fname, get_err_msg());
+ ret = 1;
+ goto done;
+ }
+ xfprintf(fp, "%-12s%s\n", "Problem:",
+ P->name == NULL ? "" : P->name);
+ xfprintf(fp, "%-12s%d\n", "Rows:", P->m);
+ xfprintf(fp, "%-12s%d\n", "Columns:", P->n);
+ xfprintf(fp, "%-12s%d\n", "Non-zeros:", P->nnz);
+ t = glp_ipt_status(P);
+ xfprintf(fp, "%-12s%s\n", "Status:",
+ t == GLP_OPT ? "OPTIMAL" :
+ t == GLP_UNDEF ? "UNDEFINED" :
+ t == GLP_INFEAS ? "INFEASIBLE (INTERMEDIATE)" :
+ t == GLP_NOFEAS ? "INFEASIBLE (FINAL)" : "???");
+ xfprintf(fp, "%-12s%s%s%.10g (%s)\n", "Objective:",
+ P->obj == NULL ? "" : P->obj,
+ P->obj == NULL ? "" : " = ", P->ipt_obj,
+ P->dir == GLP_MIN ? "MINimum" :
+ P->dir == GLP_MAX ? "MAXimum" : "???");
+ xfprintf(fp, "\n");
+ xfprintf(fp, " No. Row name Activity Lower bound "
+ " Upper bound Marginal\n");
+ xfprintf(fp, "------ ------------ ------------- ------------- "
+ "------------- -------------\n");
+ for (i = 1; i <= P->m; i++)
+ { row = P->row[i];
+ xfprintf(fp, "%6d ", i);
+ if (row->name == NULL || strlen(row->name) <= 12)
+ xfprintf(fp, "%-12s ", row->name == NULL ? "" : row->name);
+ else
+ xfprintf(fp, "%s\n%20s", row->name, "");
+ xfprintf(fp, "%3s", "");
+ xfprintf(fp, "%13.6g ",
+ fabs(row->pval) <= 1e-9 ? 0.0 : row->pval);
+ if (row->type == GLP_LO || row->type == GLP_DB ||
+ row->type == GLP_FX)
+ xfprintf(fp, "%13.6g ", row->lb);
+ else
+ xfprintf(fp, "%13s ", "");
+ if (row->type == GLP_UP || row->type == GLP_DB)
+ xfprintf(fp, "%13.6g ", row->ub);
+ else
+ xfprintf(fp, "%13s ", row->type == GLP_FX ? "=" : "");
+ if (fabs(row->dval) <= 1e-9)
+ xfprintf(fp, "%13s", "< eps");
+ else
+ xfprintf(fp, "%13.6g ", row->dval);
+ xfprintf(fp, "\n");
+ }
+ xfprintf(fp, "\n");
+ xfprintf(fp, " No. Column name Activity Lower bound "
+ " Upper bound Marginal\n");
+ xfprintf(fp, "------ ------------ ------------- ------------- "
+ "------------- -------------\n");
+ for (j = 1; j <= P->n; j++)
+ { col = P->col[j];
+ xfprintf(fp, "%6d ", j);
+ if (col->name == NULL || strlen(col->name) <= 12)
+ xfprintf(fp, "%-12s ", col->name == NULL ? "" : col->name);
+ else
+ xfprintf(fp, "%s\n%20s", col->name, "");
+ xfprintf(fp, "%3s", "");
+ xfprintf(fp, "%13.6g ",
+ fabs(col->pval) <= 1e-9 ? 0.0 : col->pval);
+ if (col->type == GLP_LO || col->type == GLP_DB ||
+ col->type == GLP_FX)
+ xfprintf(fp, "%13.6g ", col->lb);
+ else
+ xfprintf(fp, "%13s ", "");
+ if (col->type == GLP_UP || col->type == GLP_DB)
+ xfprintf(fp, "%13.6g ", col->ub);
+ else
+ xfprintf(fp, "%13s ", col->type == GLP_FX ? "=" : "");
+ if (fabs(col->dval) <= 1e-9)
+ xfprintf(fp, "%13s", "< eps");
+ else
+ xfprintf(fp, "%13.6g ", col->dval);
+ xfprintf(fp, "\n");
+ }
+ xfprintf(fp, "\n");
+ xfprintf(fp, "Karush-Kuhn-Tucker optimality conditions:\n");
+ xfprintf(fp, "\n");
+ glp_check_kkt(P, GLP_IPT, GLP_KKT_PE, &ae_max, &ae_ind, &re_max,
+ &re_ind);
+ xfprintf(fp, "KKT.PE: max.abs.err = %.2e on row %d\n",
+ ae_max, ae_ind);
+ xfprintf(fp, " max.rel.err = %.2e on row %d\n",
+ re_max, re_ind);
+ xfprintf(fp, "%8s%s\n", "",
+ re_max <= 1e-9 ? "High quality" :
+ re_max <= 1e-6 ? "Medium quality" :
+ re_max <= 1e-3 ? "Low quality" : "PRIMAL SOLUTION IS WRONG");
+ xfprintf(fp, "\n");
+ glp_check_kkt(P, GLP_IPT, GLP_KKT_PB, &ae_max, &ae_ind, &re_max,
+ &re_ind);
+ xfprintf(fp, "KKT.PB: max.abs.err = %.2e on %s %d\n",
+ ae_max, ae_ind <= P->m ? "row" : "column",
+ ae_ind <= P->m ? ae_ind : ae_ind - P->m);
+ xfprintf(fp, " max.rel.err = %.2e on %s %d\n",
+ re_max, re_ind <= P->m ? "row" : "column",
+ re_ind <= P->m ? re_ind : re_ind - P->m);
+ xfprintf(fp, "%8s%s\n", "",
+ re_max <= 1e-9 ? "High quality" :
+ re_max <= 1e-6 ? "Medium quality" :
+ re_max <= 1e-3 ? "Low quality" : "PRIMAL SOLUTION IS INFEASIBL"
+ "E");
+ xfprintf(fp, "\n");
+ glp_check_kkt(P, GLP_IPT, GLP_KKT_DE, &ae_max, &ae_ind, &re_max,
+ &re_ind);
+ xfprintf(fp, "KKT.DE: max.abs.err = %.2e on column %d\n",
+ ae_max, ae_ind == 0 ? 0 : ae_ind - P->m);
+ xfprintf(fp, " max.rel.err = %.2e on column %d\n",
+ re_max, re_ind == 0 ? 0 : re_ind - P->m);
+ xfprintf(fp, "%8s%s\n", "",
+ re_max <= 1e-9 ? "High quality" :
+ re_max <= 1e-6 ? "Medium quality" :
+ re_max <= 1e-3 ? "Low quality" : "DUAL SOLUTION IS WRONG");
+ xfprintf(fp, "\n");
+ glp_check_kkt(P, GLP_IPT, GLP_KKT_DB, &ae_max, &ae_ind, &re_max,
+ &re_ind);
+ xfprintf(fp, "KKT.DB: max.abs.err = %.2e on %s %d\n",
+ ae_max, ae_ind <= P->m ? "row" : "column",
+ ae_ind <= P->m ? ae_ind : ae_ind - P->m);
+ xfprintf(fp, " max.rel.err = %.2e on %s %d\n",
+ re_max, re_ind <= P->m ? "row" : "column",
+ re_ind <= P->m ? re_ind : re_ind - P->m);
+ xfprintf(fp, "%8s%s\n", "",
+ re_max <= 1e-9 ? "High quality" :
+ re_max <= 1e-6 ? "Medium quality" :
+ re_max <= 1e-3 ? "Low quality" : "DUAL SOLUTION IS INFEASIBLE")
+ ;
+ xfprintf(fp, "\n");
+ xfprintf(fp, "End of output\n");
+#if 0 /* FIXME */
+ xfflush(fp);
+#endif
+ if (glp_ioerr(fp))
+ { xprintf("Write error on '%s' - %s\n", fname, get_err_msg());
+ ret = 1;
+ goto done;
+ }
+ ret = 0;
+done: if (fp != NULL) glp_close(fp);
+ return ret;
+}
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/api/prmip.c b/test/monniaux/glpk-4.65/src/api/prmip.c
new file mode 100644
index 00000000..885ed82a
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/api/prmip.c
@@ -0,0 +1,155 @@
+/* prmip.c (write MIP solution in printable format) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* Copyright (C) 2009-2016 Andrew Makhorin, Department for Applied
+* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights
+* reserved. E-mail: <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 "env.h"
+#include "prob.h"
+
+#define xfprintf glp_format
+
+int glp_print_mip(glp_prob *P, const char *fname)
+{ /* write MIP solution in printable format */
+ glp_file *fp;
+ GLPROW *row;
+ GLPCOL *col;
+ int i, j, t, ae_ind, re_ind, ret;
+ double ae_max, re_max;
+ xprintf("Writing MIP solution to '%s'...\n", fname);
+ fp = glp_open(fname, "w");
+ if (fp == NULL)
+ { xprintf("Unable to create '%s' - %s\n", fname, get_err_msg());
+ ret = 1;
+ goto done;
+ }
+ xfprintf(fp, "%-12s%s\n", "Problem:",
+ P->name == NULL ? "" : P->name);
+ xfprintf(fp, "%-12s%d\n", "Rows:", P->m);
+ xfprintf(fp, "%-12s%d (%d integer, %d binary)\n", "Columns:",
+ P->n, glp_get_num_int(P), glp_get_num_bin(P));
+ xfprintf(fp, "%-12s%d\n", "Non-zeros:", P->nnz);
+ t = glp_mip_status(P);
+ xfprintf(fp, "%-12s%s\n", "Status:",
+ t == GLP_OPT ? "INTEGER OPTIMAL" :
+ t == GLP_FEAS ? "INTEGER NON-OPTIMAL" :
+ t == GLP_NOFEAS ? "INTEGER EMPTY" :
+ t == GLP_UNDEF ? "INTEGER UNDEFINED" : "???");
+ xfprintf(fp, "%-12s%s%s%.10g (%s)\n", "Objective:",
+ P->obj == NULL ? "" : P->obj,
+ P->obj == NULL ? "" : " = ", P->mip_obj,
+ P->dir == GLP_MIN ? "MINimum" :
+ P->dir == GLP_MAX ? "MAXimum" : "???");
+ xfprintf(fp, "\n");
+ xfprintf(fp, " No. Row name Activity Lower bound "
+ " Upper bound\n");
+ xfprintf(fp, "------ ------------ ------------- ------------- "
+ "-------------\n");
+ for (i = 1; i <= P->m; i++)
+ { row = P->row[i];
+ xfprintf(fp, "%6d ", i);
+ if (row->name == NULL || strlen(row->name) <= 12)
+ xfprintf(fp, "%-12s ", row->name == NULL ? "" : row->name);
+ else
+ xfprintf(fp, "%s\n%20s", row->name, "");
+ xfprintf(fp, "%3s", "");
+ xfprintf(fp, "%13.6g ",
+ fabs(row->mipx) <= 1e-9 ? 0.0 : row->mipx);
+ if (row->type == GLP_LO || row->type == GLP_DB ||
+ row->type == GLP_FX)
+ xfprintf(fp, "%13.6g ", row->lb);
+ else
+ xfprintf(fp, "%13s ", "");
+ if (row->type == GLP_UP || row->type == GLP_DB)
+ xfprintf(fp, "%13.6g ", row->ub);
+ else
+ xfprintf(fp, "%13s ", row->type == GLP_FX ? "=" : "");
+ xfprintf(fp, "\n");
+ }
+ xfprintf(fp, "\n");
+ xfprintf(fp, " No. Column name Activity Lower bound "
+ " Upper bound\n");
+ xfprintf(fp, "------ ------------ ------------- ------------- "
+ "-------------\n");
+ for (j = 1; j <= P->n; j++)
+ { col = P->col[j];
+ xfprintf(fp, "%6d ", j);
+ if (col->name == NULL || strlen(col->name) <= 12)
+ xfprintf(fp, "%-12s ", col->name == NULL ? "" : col->name);
+ else
+ xfprintf(fp, "%s\n%20s", col->name, "");
+ xfprintf(fp, "%s ",
+ col->kind == GLP_CV ? " " :
+ col->kind == GLP_IV ? "*" : "?");
+ xfprintf(fp, "%13.6g ",
+ fabs(col->mipx) <= 1e-9 ? 0.0 : col->mipx);
+ if (col->type == GLP_LO || col->type == GLP_DB ||
+ col->type == GLP_FX)
+ xfprintf(fp, "%13.6g ", col->lb);
+ else
+ xfprintf(fp, "%13s ", "");
+ if (col->type == GLP_UP || col->type == GLP_DB)
+ xfprintf(fp, "%13.6g ", col->ub);
+ else
+ xfprintf(fp, "%13s ", col->type == GLP_FX ? "=" : "");
+ xfprintf(fp, "\n");
+ }
+ xfprintf(fp, "\n");
+ xfprintf(fp, "Integer feasibility conditions:\n");
+ xfprintf(fp, "\n");
+ glp_check_kkt(P, GLP_MIP, GLP_KKT_PE, &ae_max, &ae_ind, &re_max,
+ &re_ind);
+ xfprintf(fp, "KKT.PE: max.abs.err = %.2e on row %d\n",
+ ae_max, ae_ind);
+ xfprintf(fp, " max.rel.err = %.2e on row %d\n",
+ re_max, re_ind);
+ xfprintf(fp, "%8s%s\n", "",
+ re_max <= 1e-9 ? "High quality" :
+ re_max <= 1e-6 ? "Medium quality" :
+ re_max <= 1e-3 ? "Low quality" : "SOLUTION IS WRONG");
+ xfprintf(fp, "\n");
+ glp_check_kkt(P, GLP_MIP, GLP_KKT_PB, &ae_max, &ae_ind, &re_max,
+ &re_ind);
+ xfprintf(fp, "KKT.PB: max.abs.err = %.2e on %s %d\n",
+ ae_max, ae_ind <= P->m ? "row" : "column",
+ ae_ind <= P->m ? ae_ind : ae_ind - P->m);
+ xfprintf(fp, " max.rel.err = %.2e on %s %d\n",
+ re_max, re_ind <= P->m ? "row" : "column",
+ re_ind <= P->m ? re_ind : re_ind - P->m);
+ xfprintf(fp, "%8s%s\n", "",
+ re_max <= 1e-9 ? "High quality" :
+ re_max <= 1e-6 ? "Medium quality" :
+ re_max <= 1e-3 ? "Low quality" : "SOLUTION IS INFEASIBLE");
+ xfprintf(fp, "\n");
+ xfprintf(fp, "End of output\n");
+#if 0 /* FIXME */
+ xfflush(fp);
+#endif
+ if (glp_ioerr(fp))
+ { xprintf("Write error on '%s' - %s\n", fname, get_err_msg());
+ ret = 1;
+ goto done;
+ }
+ ret = 0;
+done: if (fp != NULL) glp_close(fp);
+ return ret;
+}
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/api/prob.h b/test/monniaux/glpk-4.65/src/api/prob.h
new file mode 100644
index 00000000..cc9389b5
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/api/prob.h
@@ -0,0 +1,286 @@
+/* prob.h (LP/MIP problem object) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* Copyright (C) 2000-2013 Andrew Makhorin, Department for Applied
+* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights
+* reserved. E-mail: <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 PROB_H
+#define PROB_H
+
+#include "avl.h"
+#include "bfd.h"
+#include "dmp.h"
+#if 1 /* 28/III-2016 */
+#define GLP_UNDOC 1
+#endif
+#include "glpk.h"
+
+typedef struct GLPROW GLPROW;
+typedef struct GLPCOL GLPCOL;
+typedef struct GLPAIJ GLPAIJ;
+
+#if 0 /* 04/IV-2016 */
+#define GLP_PROB_MAGIC 0xD7D9D6C2
+#endif
+
+struct glp_prob
+{ /* LP/MIP problem object */
+#if 0 /* 04/IV-2016 */
+ unsigned magic;
+ /* magic value used for debugging */
+#endif
+ DMP *pool;
+ /* memory pool to store problem object components */
+ glp_tree *tree;
+ /* pointer to the search tree; set by the MIP solver when this
+ object is used in the tree as a core MIP object */
+#if 0 /* 08/III-2014 */
+ void *parms;
+ /* reserved for backward compatibility */
+#endif
+ /*--------------------------------------------------------------*/
+ /* LP/MIP data */
+ char *name;
+ /* problem name (1 to 255 chars); NULL means no name is assigned
+ to the problem */
+ char *obj;
+ /* objective function name (1 to 255 chars); NULL means no name
+ is assigned to the objective function */
+ int dir;
+ /* optimization direction flag (objective "sense"):
+ GLP_MIN - minimization
+ GLP_MAX - maximization */
+ double c0;
+ /* constant term of the objective function ("shift") */
+ int m_max;
+ /* length of the array of rows (enlarged automatically) */
+ int n_max;
+ /* length of the array of columns (enlarged automatically) */
+ int m;
+ /* number of rows, 0 <= m <= m_max */
+ int n;
+ /* number of columns, 0 <= n <= n_max */
+ int nnz;
+ /* number of non-zero constraint coefficients, nnz >= 0 */
+ GLPROW **row; /* GLPROW *row[1+m_max]; */
+ /* row[i], 1 <= i <= m, is a pointer to i-th row */
+ GLPCOL **col; /* GLPCOL *col[1+n_max]; */
+ /* col[j], 1 <= j <= n, is a pointer to j-th column */
+ AVL *r_tree;
+ /* row index to find rows by their names; NULL means this index
+ does not exist */
+ AVL *c_tree;
+ /* column index to find columns by their names; NULL means this
+ index does not exist */
+ /*--------------------------------------------------------------*/
+ /* basis factorization (LP) */
+ int valid;
+ /* the factorization is valid only if this flag is set */
+ int *head; /* int head[1+m_max]; */
+ /* basis header (valid only if the factorization is valid);
+ head[i] = k is the ordinal number of auxiliary (1 <= k <= m)
+ or structural (m+1 <= k <= m+n) variable which corresponds to
+ i-th basic variable xB[i], 1 <= i <= m */
+#if 0 /* 08/III-2014 */
+ glp_bfcp *bfcp;
+ /* basis factorization control parameters; may be NULL */
+#endif
+ BFD *bfd; /* BFD bfd[1:m,1:m]; */
+ /* basis factorization driver; may be NULL */
+ /*--------------------------------------------------------------*/
+ /* basic solution (LP) */
+ int pbs_stat;
+ /* primal basic solution status:
+ GLP_UNDEF - primal solution is undefined
+ GLP_FEAS - primal solution is feasible
+ GLP_INFEAS - primal solution is infeasible
+ GLP_NOFEAS - no primal feasible solution exists */
+ int dbs_stat;
+ /* dual basic solution status:
+ GLP_UNDEF - dual solution is undefined
+ GLP_FEAS - dual solution is feasible
+ GLP_INFEAS - dual solution is infeasible
+ GLP_NOFEAS - no dual feasible solution exists */
+ double obj_val;
+ /* objective function value */
+ int it_cnt;
+ /* simplex method iteration count; increases by one on performing
+ one simplex iteration */
+ int some;
+ /* ordinal number of some auxiliary or structural variable having
+ certain property, 0 <= some <= m+n */
+ /*--------------------------------------------------------------*/
+ /* interior-point solution (LP) */
+ int ipt_stat;
+ /* interior-point solution status:
+ GLP_UNDEF - interior solution is undefined
+ GLP_OPT - interior solution is optimal
+ GLP_INFEAS - interior solution is infeasible
+ GLP_NOFEAS - no feasible solution exists */
+ double ipt_obj;
+ /* objective function value */
+ /*--------------------------------------------------------------*/
+ /* integer solution (MIP) */
+ int mip_stat;
+ /* integer solution status:
+ GLP_UNDEF - integer solution is undefined
+ GLP_OPT - integer solution is optimal
+ GLP_FEAS - integer solution is feasible
+ GLP_NOFEAS - no integer solution exists */
+ double mip_obj;
+ /* objective function value */
+};
+
+struct GLPROW
+{ /* LP/MIP row (auxiliary variable) */
+ int i;
+ /* ordinal number (1 to m) assigned to this row */
+ char *name;
+ /* row name (1 to 255 chars); NULL means no name is assigned to
+ this row */
+ AVLNODE *node;
+ /* pointer to corresponding node in the row index; NULL means
+ that either the row index does not exist or this row has no
+ name assigned */
+#if 1 /* 20/IX-2008 */
+ int level;
+ unsigned char origin;
+ unsigned char klass;
+#endif
+ int type;
+ /* type of the auxiliary variable:
+ GLP_FR - free variable
+ GLP_LO - variable with lower bound
+ GLP_UP - variable with upper bound
+ GLP_DB - double-bounded variable
+ GLP_FX - fixed variable */
+ double lb; /* non-scaled */
+ /* lower bound; if the row has no lower bound, lb is zero */
+ double ub; /* non-scaled */
+ /* upper bound; if the row has no upper bound, ub is zero */
+ /* if the row type is GLP_FX, ub is equal to lb */
+ GLPAIJ *ptr; /* non-scaled */
+ /* pointer to doubly linked list of constraint coefficients which
+ are placed in this row */
+ double rii;
+ /* diagonal element r[i,i] of scaling matrix R for this row;
+ if the scaling is not used, r[i,i] is 1 */
+ int stat;
+ /* status of the auxiliary variable:
+ GLP_BS - basic variable
+ GLP_NL - non-basic variable on lower bound
+ GLP_NU - non-basic variable on upper bound
+ GLP_NF - non-basic free variable
+ GLP_NS - non-basic fixed variable */
+ int bind;
+ /* if the auxiliary variable is basic, head[bind] refers to this
+ row, otherwise, bind is 0; this attribute is valid only if the
+ basis factorization is valid */
+ double prim; /* non-scaled */
+ /* primal value of the auxiliary variable in basic solution */
+ double dual; /* non-scaled */
+ /* dual value of the auxiliary variable in basic solution */
+ double pval; /* non-scaled */
+ /* primal value of the auxiliary variable in interior solution */
+ double dval; /* non-scaled */
+ /* dual value of the auxiliary variable in interior solution */
+ double mipx; /* non-scaled */
+ /* primal value of the auxiliary variable in integer solution */
+};
+
+struct GLPCOL
+{ /* LP/MIP column (structural variable) */
+ int j;
+ /* ordinal number (1 to n) assigned to this column */
+ char *name;
+ /* column name (1 to 255 chars); NULL means no name is assigned
+ to this column */
+ AVLNODE *node;
+ /* pointer to corresponding node in the column index; NULL means
+ that either the column index does not exist or the column has
+ no name assigned */
+ int kind;
+ /* kind of the structural variable:
+ GLP_CV - continuous variable
+ GLP_IV - integer or binary variable */
+ int type;
+ /* type of the structural variable:
+ GLP_FR - free variable
+ GLP_LO - variable with lower bound
+ GLP_UP - variable with upper bound
+ GLP_DB - double-bounded variable
+ GLP_FX - fixed variable */
+ double lb; /* non-scaled */
+ /* lower bound; if the column has no lower bound, lb is zero */
+ double ub; /* non-scaled */
+ /* upper bound; if the column has no upper bound, ub is zero */
+ /* if the column type is GLP_FX, ub is equal to lb */
+ double coef; /* non-scaled */
+ /* objective coefficient at the structural variable */
+ GLPAIJ *ptr; /* non-scaled */
+ /* pointer to doubly linked list of constraint coefficients which
+ are placed in this column */
+ double sjj;
+ /* diagonal element s[j,j] of scaling matrix S for this column;
+ if the scaling is not used, s[j,j] is 1 */
+ int stat;
+ /* status of the structural variable:
+ GLP_BS - basic variable
+ GLP_NL - non-basic variable on lower bound
+ GLP_NU - non-basic variable on upper bound
+ GLP_NF - non-basic free variable
+ GLP_NS - non-basic fixed variable */
+ int bind;
+ /* if the structural variable is basic, head[bind] refers to
+ this column; otherwise, bind is 0; this attribute is valid only
+ if the basis factorization is valid */
+ double prim; /* non-scaled */
+ /* primal value of the structural variable in basic solution */
+ double dual; /* non-scaled */
+ /* dual value of the structural variable in basic solution */
+ double pval; /* non-scaled */
+ /* primal value of the structural variable in interior solution */
+ double dval; /* non-scaled */
+ /* dual value of the structural variable in interior solution */
+ double mipx; /* non-scaled */
+ /* primal value of the structural variable in integer solution */
+};
+
+struct GLPAIJ
+{ /* constraint coefficient a[i,j] */
+ GLPROW *row;
+ /* pointer to row, where this coefficient is placed */
+ GLPCOL *col;
+ /* pointer to column, where this coefficient is placed */
+ double val;
+ /* numeric (non-zero) value of this coefficient */
+ GLPAIJ *r_prev;
+ /* pointer to previous coefficient in the same row */
+ GLPAIJ *r_next;
+ /* pointer to next coefficient in the same row */
+ GLPAIJ *c_prev;
+ /* pointer to previous coefficient in the same column */
+ GLPAIJ *c_next;
+ /* pointer to next coefficient in the same column */
+};
+
+#endif
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/api/prob1.c b/test/monniaux/glpk-4.65/src/api/prob1.c
new file mode 100644
index 00000000..6afad442
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/api/prob1.c
@@ -0,0 +1,1588 @@
+/* prob1.c (problem creating and modifying routines) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* Copyright (C) 2000-2018 Andrew Makhorin, Department for Applied
+* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights
+* reserved. E-mail: <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 "env.h"
+#include "ios.h"
+
+/* CAUTION: DO NOT CHANGE THE LIMITS BELOW */
+
+#define M_MAX 100000000 /* = 100*10^6 */
+/* maximal number of rows in the problem object */
+
+#define N_MAX 100000000 /* = 100*10^6 */
+/* maximal number of columns in the problem object */
+
+#define NNZ_MAX 500000000 /* = 500*10^6 */
+/* maximal number of constraint coefficients in the problem object */
+
+/***********************************************************************
+* NAME
+*
+* glp_create_prob - create problem object
+*
+* SYNOPSIS
+*
+* glp_prob *glp_create_prob(void);
+*
+* DESCRIPTION
+*
+* The routine glp_create_prob creates a new problem object, which is
+* initially "empty", i.e. has no rows and columns.
+*
+* RETURNS
+*
+* The routine returns a pointer to the object created, which should be
+* used in any subsequent operations on this object. */
+
+static void create_prob(glp_prob *lp)
+#if 0 /* 04/IV-2016 */
+{ lp->magic = GLP_PROB_MAGIC;
+#else
+{
+#endif
+ lp->pool = dmp_create_pool();
+#if 0 /* 08/III-2014 */
+#if 0 /* 17/XI-2009 */
+ lp->cps = xmalloc(sizeof(struct LPXCPS));
+ lpx_reset_parms(lp);
+#else
+ lp->parms = NULL;
+#endif
+#endif
+ lp->tree = NULL;
+#if 0
+ lp->lwa = 0;
+ lp->cwa = NULL;
+#endif
+ /* LP/MIP data */
+ lp->name = NULL;
+ lp->obj = NULL;
+ lp->dir = GLP_MIN;
+ lp->c0 = 0.0;
+ lp->m_max = 100;
+ lp->n_max = 200;
+ lp->m = lp->n = 0;
+ lp->nnz = 0;
+ lp->row = xcalloc(1+lp->m_max, sizeof(GLPROW *));
+ lp->col = xcalloc(1+lp->n_max, sizeof(GLPCOL *));
+ lp->r_tree = lp->c_tree = NULL;
+ /* basis factorization */
+ lp->valid = 0;
+ lp->head = xcalloc(1+lp->m_max, sizeof(int));
+#if 0 /* 08/III-2014 */
+ lp->bfcp = NULL;
+#endif
+ lp->bfd = NULL;
+ /* basic solution (LP) */
+ lp->pbs_stat = lp->dbs_stat = GLP_UNDEF;
+ lp->obj_val = 0.0;
+ lp->it_cnt = 0;
+ lp->some = 0;
+ /* interior-point solution (LP) */
+ lp->ipt_stat = GLP_UNDEF;
+ lp->ipt_obj = 0.0;
+ /* integer solution (MIP) */
+ lp->mip_stat = GLP_UNDEF;
+ lp->mip_obj = 0.0;
+ return;
+}
+
+glp_prob *glp_create_prob(void)
+{ glp_prob *lp;
+ lp = xmalloc(sizeof(glp_prob));
+ create_prob(lp);
+ return lp;
+}
+
+/***********************************************************************
+* NAME
+*
+* glp_set_prob_name - assign (change) problem name
+*
+* SYNOPSIS
+*
+* void glp_set_prob_name(glp_prob *lp, const char *name);
+*
+* DESCRIPTION
+*
+* The routine glp_set_prob_name assigns a given symbolic name (1 up to
+* 255 characters) to the specified problem object.
+*
+* If the parameter name is NULL or empty string, the routine erases an
+* existing symbolic name of the problem object. */
+
+void glp_set_prob_name(glp_prob *lp, const char *name)
+{ glp_tree *tree = lp->tree;
+ if (tree != NULL && tree->reason != 0)
+ xerror("glp_set_prob_name: operation not allowed\n");
+ if (lp->name != NULL)
+ { dmp_free_atom(lp->pool, lp->name, strlen(lp->name)+1);
+ lp->name = NULL;
+ }
+ if (!(name == NULL || name[0] == '\0'))
+ { int k;
+ for (k = 0; name[k] != '\0'; k++)
+ { if (k == 256)
+ xerror("glp_set_prob_name: problem name too long\n");
+ if (iscntrl((unsigned char)name[k]))
+ xerror("glp_set_prob_name: problem name contains invalid"
+ " character(s)\n");
+ }
+ lp->name = dmp_get_atom(lp->pool, strlen(name)+1);
+ strcpy(lp->name, name);
+ }
+ return;
+}
+
+/***********************************************************************
+* NAME
+*
+* glp_set_obj_name - assign (change) objective function name
+*
+* SYNOPSIS
+*
+* void glp_set_obj_name(glp_prob *lp, const char *name);
+*
+* DESCRIPTION
+*
+* The routine glp_set_obj_name assigns a given symbolic name (1 up to
+* 255 characters) to the objective function of the specified problem
+* object.
+*
+* If the parameter name is NULL or empty string, the routine erases an
+* existing name of the objective function. */
+
+void glp_set_obj_name(glp_prob *lp, const char *name)
+{ glp_tree *tree = lp->tree;
+ if (tree != NULL && tree->reason != 0)
+ xerror("glp_set_obj_name: operation not allowed\n");
+ if (lp->obj != NULL)
+ { dmp_free_atom(lp->pool, lp->obj, strlen(lp->obj)+1);
+ lp->obj = NULL;
+ }
+ if (!(name == NULL || name[0] == '\0'))
+ { int k;
+ for (k = 0; name[k] != '\0'; k++)
+ { if (k == 256)
+ xerror("glp_set_obj_name: objective name too long\n");
+ if (iscntrl((unsigned char)name[k]))
+ xerror("glp_set_obj_name: objective name contains invali"
+ "d character(s)\n");
+ }
+ lp->obj = dmp_get_atom(lp->pool, strlen(name)+1);
+ strcpy(lp->obj, name);
+ }
+ return;
+}
+
+/***********************************************************************
+* NAME
+*
+* glp_set_obj_dir - set (change) optimization direction flag
+*
+* SYNOPSIS
+*
+* void glp_set_obj_dir(glp_prob *lp, int dir);
+*
+* DESCRIPTION
+*
+* The routine glp_set_obj_dir sets (changes) optimization direction
+* flag (i.e. "sense" of the objective function) as specified by the
+* parameter dir:
+*
+* GLP_MIN - minimization;
+* GLP_MAX - maximization. */
+
+void glp_set_obj_dir(glp_prob *lp, int dir)
+{ glp_tree *tree = lp->tree;
+ if (tree != NULL && tree->reason != 0)
+ xerror("glp_set_obj_dir: operation not allowed\n");
+ if (!(dir == GLP_MIN || dir == GLP_MAX))
+ xerror("glp_set_obj_dir: dir = %d; invalid direction flag\n",
+ dir);
+ lp->dir = dir;
+ return;
+}
+
+/***********************************************************************
+* NAME
+*
+* glp_add_rows - add new rows to problem object
+*
+* SYNOPSIS
+*
+* int glp_add_rows(glp_prob *lp, int nrs);
+*
+* DESCRIPTION
+*
+* The routine glp_add_rows adds nrs rows (constraints) to the specified
+* problem object. New rows are always added to the end of the row list,
+* so the ordinal numbers of existing rows remain unchanged.
+*
+* Being added each new row is initially free (unbounded) and has empty
+* list of the constraint coefficients.
+*
+* RETURNS
+*
+* The routine glp_add_rows returns the ordinal number of the first new
+* row added to the problem object. */
+
+int glp_add_rows(glp_prob *lp, int nrs)
+{ glp_tree *tree = lp->tree;
+ GLPROW *row;
+ int m_new, i;
+ /* determine new number of rows */
+ if (nrs < 1)
+ xerror("glp_add_rows: nrs = %d; invalid number of rows\n",
+ nrs);
+ if (nrs > M_MAX - lp->m)
+ xerror("glp_add_rows: nrs = %d; too many rows\n", nrs);
+ m_new = lp->m + nrs;
+ /* increase the room, if necessary */
+ if (lp->m_max < m_new)
+ { GLPROW **save = lp->row;
+ while (lp->m_max < m_new)
+ { lp->m_max += lp->m_max;
+ xassert(lp->m_max > 0);
+ }
+ lp->row = xcalloc(1+lp->m_max, sizeof(GLPROW *));
+ memcpy(&lp->row[1], &save[1], lp->m * sizeof(GLPROW *));
+ xfree(save);
+ /* do not forget about the basis header */
+ xfree(lp->head);
+ lp->head = xcalloc(1+lp->m_max, sizeof(int));
+ }
+ /* add new rows to the end of the row list */
+ for (i = lp->m+1; i <= m_new; i++)
+ { /* create row descriptor */
+ lp->row[i] = row = dmp_get_atom(lp->pool, sizeof(GLPROW));
+ row->i = i;
+ row->name = NULL;
+ row->node = NULL;
+#if 1 /* 20/IX-2008 */
+ row->level = 0;
+ row->origin = 0;
+ row->klass = 0;
+ if (tree != NULL)
+ { switch (tree->reason)
+ { case 0:
+ break;
+ case GLP_IROWGEN:
+ xassert(tree->curr != NULL);
+ row->level = tree->curr->level;
+ row->origin = GLP_RF_LAZY;
+ break;
+ case GLP_ICUTGEN:
+ xassert(tree->curr != NULL);
+ row->level = tree->curr->level;
+ row->origin = GLP_RF_CUT;
+ break;
+ default:
+ xassert(tree != tree);
+ }
+ }
+#endif
+ row->type = GLP_FR;
+ row->lb = row->ub = 0.0;
+ row->ptr = NULL;
+ row->rii = 1.0;
+ row->stat = GLP_BS;
+#if 0
+ row->bind = -1;
+#else
+ row->bind = 0;
+#endif
+ row->prim = row->dual = 0.0;
+ row->pval = row->dval = 0.0;
+ row->mipx = 0.0;
+ }
+ /* set new number of rows */
+ lp->m = m_new;
+ /* invalidate the basis factorization */
+ lp->valid = 0;
+#if 1
+ if (tree != NULL && tree->reason != 0) tree->reopt = 1;
+#endif
+ /* return the ordinal number of the first row added */
+ return m_new - nrs + 1;
+}
+
+/***********************************************************************
+* NAME
+*
+* glp_add_cols - add new columns to problem object
+*
+* SYNOPSIS
+*
+* int glp_add_cols(glp_prob *lp, int ncs);
+*
+* DESCRIPTION
+*
+* The routine glp_add_cols adds ncs columns (structural variables) to
+* the specified problem object. New columns are always added to the end
+* of the column list, so the ordinal numbers of existing columns remain
+* unchanged.
+*
+* Being added each new column is initially fixed at zero and has empty
+* list of the constraint coefficients.
+*
+* RETURNS
+*
+* The routine glp_add_cols returns the ordinal number of the first new
+* column added to the problem object. */
+
+int glp_add_cols(glp_prob *lp, int ncs)
+{ glp_tree *tree = lp->tree;
+ GLPCOL *col;
+ int n_new, j;
+ if (tree != NULL && tree->reason != 0)
+ xerror("glp_add_cols: operation not allowed\n");
+ /* determine new number of columns */
+ if (ncs < 1)
+ xerror("glp_add_cols: ncs = %d; invalid number of columns\n",
+ ncs);
+ if (ncs > N_MAX - lp->n)
+ xerror("glp_add_cols: ncs = %d; too many columns\n", ncs);
+ n_new = lp->n + ncs;
+ /* increase the room, if necessary */
+ if (lp->n_max < n_new)
+ { GLPCOL **save = lp->col;
+ while (lp->n_max < n_new)
+ { lp->n_max += lp->n_max;
+ xassert(lp->n_max > 0);
+ }
+ lp->col = xcalloc(1+lp->n_max, sizeof(GLPCOL *));
+ memcpy(&lp->col[1], &save[1], lp->n * sizeof(GLPCOL *));
+ xfree(save);
+ }
+ /* add new columns to the end of the column list */
+ for (j = lp->n+1; j <= n_new; j++)
+ { /* create column descriptor */
+ lp->col[j] = col = dmp_get_atom(lp->pool, sizeof(GLPCOL));
+ col->j = j;
+ col->name = NULL;
+ col->node = NULL;
+ col->kind = GLP_CV;
+ col->type = GLP_FX;
+ col->lb = col->ub = 0.0;
+ col->coef = 0.0;
+ col->ptr = NULL;
+ col->sjj = 1.0;
+ col->stat = GLP_NS;
+#if 0
+ col->bind = -1;
+#else
+ col->bind = 0; /* the basis may remain valid */
+#endif
+ col->prim = col->dual = 0.0;
+ col->pval = col->dval = 0.0;
+ col->mipx = 0.0;
+ }
+ /* set new number of columns */
+ lp->n = n_new;
+ /* return the ordinal number of the first column added */
+ return n_new - ncs + 1;
+}
+
+/***********************************************************************
+* NAME
+*
+* glp_set_row_name - assign (change) row name
+*
+* SYNOPSIS
+*
+* void glp_set_row_name(glp_prob *lp, int i, const char *name);
+*
+* DESCRIPTION
+*
+* The routine glp_set_row_name assigns a given symbolic name (1 up to
+* 255 characters) to i-th row (auxiliary variable) of the specified
+* problem object.
+*
+* If the parameter name is NULL or empty string, the routine erases an
+* existing name of i-th row. */
+
+void glp_set_row_name(glp_prob *lp, int i, const char *name)
+{ glp_tree *tree = lp->tree;
+ GLPROW *row;
+ if (!(1 <= i && i <= lp->m))
+ xerror("glp_set_row_name: i = %d; row number out of range\n",
+ i);
+ row = lp->row[i];
+ if (tree != NULL && tree->reason != 0)
+ { xassert(tree->curr != NULL);
+ xassert(row->level == tree->curr->level);
+ }
+ if (row->name != NULL)
+ { if (row->node != NULL)
+ { xassert(lp->r_tree != NULL);
+ avl_delete_node(lp->r_tree, row->node);
+ row->node = NULL;
+ }
+ dmp_free_atom(lp->pool, row->name, strlen(row->name)+1);
+ row->name = NULL;
+ }
+ if (!(name == NULL || name[0] == '\0'))
+ { int k;
+ for (k = 0; name[k] != '\0'; k++)
+ { if (k == 256)
+ xerror("glp_set_row_name: i = %d; row name too long\n",
+ i);
+ if (iscntrl((unsigned char)name[k]))
+ xerror("glp_set_row_name: i = %d: row name contains inva"
+ "lid character(s)\n", i);
+ }
+ row->name = dmp_get_atom(lp->pool, strlen(name)+1);
+ strcpy(row->name, name);
+ if (lp->r_tree != NULL)
+ { xassert(row->node == NULL);
+ row->node = avl_insert_node(lp->r_tree, row->name);
+ avl_set_node_link(row->node, row);
+ }
+ }
+ return;
+}
+
+/***********************************************************************
+* NAME
+*
+* glp_set_col_name - assign (change) column name
+*
+* SYNOPSIS
+*
+* void glp_set_col_name(glp_prob *lp, int j, const char *name);
+*
+* DESCRIPTION
+*
+* The routine glp_set_col_name assigns a given symbolic name (1 up to
+* 255 characters) to j-th column (structural variable) of the specified
+* problem object.
+*
+* If the parameter name is NULL or empty string, the routine erases an
+* existing name of j-th column. */
+
+void glp_set_col_name(glp_prob *lp, int j, const char *name)
+{ glp_tree *tree = lp->tree;
+ GLPCOL *col;
+ if (tree != NULL && tree->reason != 0)
+ xerror("glp_set_col_name: operation not allowed\n");
+ if (!(1 <= j && j <= lp->n))
+ xerror("glp_set_col_name: j = %d; column number out of range\n"
+ , j);
+ col = lp->col[j];
+ if (col->name != NULL)
+ { if (col->node != NULL)
+ { xassert(lp->c_tree != NULL);
+ avl_delete_node(lp->c_tree, col->node);
+ col->node = NULL;
+ }
+ dmp_free_atom(lp->pool, col->name, strlen(col->name)+1);
+ col->name = NULL;
+ }
+ if (!(name == NULL || name[0] == '\0'))
+ { int k;
+ for (k = 0; name[k] != '\0'; k++)
+ { if (k == 256)
+ xerror("glp_set_col_name: j = %d; column name too long\n"
+ , j);
+ if (iscntrl((unsigned char)name[k]))
+ xerror("glp_set_col_name: j = %d: column name contains i"
+ "nvalid character(s)\n", j);
+ }
+ col->name = dmp_get_atom(lp->pool, strlen(name)+1);
+ strcpy(col->name, name);
+ if (lp->c_tree != NULL && col->name != NULL)
+ { xassert(col->node == NULL);
+ col->node = avl_insert_node(lp->c_tree, col->name);
+ avl_set_node_link(col->node, col);
+ }
+ }
+ return;
+}
+
+/***********************************************************************
+* NAME
+*
+* glp_set_row_bnds - set (change) row bounds
+*
+* SYNOPSIS
+*
+* void glp_set_row_bnds(glp_prob *lp, int i, int type, double lb,
+* double ub);
+*
+* DESCRIPTION
+*
+* The routine glp_set_row_bnds sets (changes) the type and bounds of
+* i-th row (auxiliary variable) of the specified problem object.
+*
+* Parameters type, lb, and ub specify the type, lower bound, and upper
+* bound, respectively, as follows:
+*
+* Type Bounds Comments
+* ------------------------------------------------------
+* GLP_FR -inf < x < +inf Free variable
+* GLP_LO lb <= x < +inf Variable with lower bound
+* GLP_UP -inf < x <= ub Variable with upper bound
+* GLP_DB lb <= x <= ub Double-bounded variable
+* GLP_FX x = lb Fixed variable
+*
+* where x is the auxiliary variable associated with i-th row.
+*
+* If the row has no lower bound, the parameter lb is ignored. If the
+* row has no upper bound, the parameter ub is ignored. If the row is
+* an equality constraint (i.e. the corresponding auxiliary variable is
+* of fixed type), only the parameter lb is used while the parameter ub
+* is ignored. */
+
+void glp_set_row_bnds(glp_prob *lp, int i, int type, double lb,
+ double ub)
+{ GLPROW *row;
+ if (!(1 <= i && i <= lp->m))
+ xerror("glp_set_row_bnds: i = %d; row number out of range\n",
+ i);
+ row = lp->row[i];
+ row->type = type;
+ switch (type)
+ { case GLP_FR:
+ row->lb = row->ub = 0.0;
+ if (row->stat != GLP_BS) row->stat = GLP_NF;
+ break;
+ case GLP_LO:
+ row->lb = lb, row->ub = 0.0;
+ if (row->stat != GLP_BS) row->stat = GLP_NL;
+ break;
+ case GLP_UP:
+ row->lb = 0.0, row->ub = ub;
+ if (row->stat != GLP_BS) row->stat = GLP_NU;
+ break;
+ case GLP_DB:
+ row->lb = lb, row->ub = ub;
+ if (!(row->stat == GLP_BS ||
+ row->stat == GLP_NL || row->stat == GLP_NU))
+ row->stat = (fabs(lb) <= fabs(ub) ? GLP_NL : GLP_NU);
+ break;
+ case GLP_FX:
+ row->lb = row->ub = lb;
+ if (row->stat != GLP_BS) row->stat = GLP_NS;
+ break;
+ default:
+ xerror("glp_set_row_bnds: i = %d; type = %d; invalid row ty"
+ "pe\n", i, type);
+ }
+ return;
+}
+
+/***********************************************************************
+* NAME
+*
+* glp_set_col_bnds - set (change) column bounds
+*
+* SYNOPSIS
+*
+* void glp_set_col_bnds(glp_prob *lp, int j, int type, double lb,
+* double ub);
+*
+* DESCRIPTION
+*
+* The routine glp_set_col_bnds sets (changes) the type and bounds of
+* j-th column (structural variable) of the specified problem object.
+*
+* Parameters type, lb, and ub specify the type, lower bound, and upper
+* bound, respectively, as follows:
+*
+* Type Bounds Comments
+* ------------------------------------------------------
+* GLP_FR -inf < x < +inf Free variable
+* GLP_LO lb <= x < +inf Variable with lower bound
+* GLP_UP -inf < x <= ub Variable with upper bound
+* GLP_DB lb <= x <= ub Double-bounded variable
+* GLP_FX x = lb Fixed variable
+*
+* where x is the structural variable associated with j-th column.
+*
+* If the column has no lower bound, the parameter lb is ignored. If the
+* column has no upper bound, the parameter ub is ignored. If the column
+* is of fixed type, only the parameter lb is used while the parameter
+* ub is ignored. */
+
+void glp_set_col_bnds(glp_prob *lp, int j, int type, double lb,
+ double ub)
+{ GLPCOL *col;
+ if (!(1 <= j && j <= lp->n))
+ xerror("glp_set_col_bnds: j = %d; column number out of range\n"
+ , j);
+ col = lp->col[j];
+ col->type = type;
+ switch (type)
+ { case GLP_FR:
+ col->lb = col->ub = 0.0;
+ if (col->stat != GLP_BS) col->stat = GLP_NF;
+ break;
+ case GLP_LO:
+ col->lb = lb, col->ub = 0.0;
+ if (col->stat != GLP_BS) col->stat = GLP_NL;
+ break;
+ case GLP_UP:
+ col->lb = 0.0, col->ub = ub;
+ if (col->stat != GLP_BS) col->stat = GLP_NU;
+ break;
+ case GLP_DB:
+ col->lb = lb, col->ub = ub;
+ if (!(col->stat == GLP_BS ||
+ col->stat == GLP_NL || col->stat == GLP_NU))
+ col->stat = (fabs(lb) <= fabs(ub) ? GLP_NL : GLP_NU);
+ break;
+ case GLP_FX:
+ col->lb = col->ub = lb;
+ if (col->stat != GLP_BS) col->stat = GLP_NS;
+ break;
+ default:
+ xerror("glp_set_col_bnds: j = %d; type = %d; invalid column"
+ " type\n", j, type);
+ }
+ return;
+}
+
+/***********************************************************************
+* NAME
+*
+* glp_set_obj_coef - set (change) obj. coefficient or constant term
+*
+* SYNOPSIS
+*
+* void glp_set_obj_coef(glp_prob *lp, int j, double coef);
+*
+* DESCRIPTION
+*
+* The routine glp_set_obj_coef sets (changes) objective coefficient at
+* j-th column (structural variable) of the specified problem object.
+*
+* If the parameter j is 0, the routine sets (changes) the constant term
+* ("shift") of the objective function. */
+
+void glp_set_obj_coef(glp_prob *lp, int j, double coef)
+{ glp_tree *tree = lp->tree;
+ if (tree != NULL && tree->reason != 0)
+ xerror("glp_set_obj_coef: operation not allowed\n");
+ if (!(0 <= j && j <= lp->n))
+ xerror("glp_set_obj_coef: j = %d; column number out of range\n"
+ , j);
+ if (j == 0)
+ lp->c0 = coef;
+ else
+ lp->col[j]->coef = coef;
+ return;
+}
+
+/***********************************************************************
+* NAME
+*
+* glp_set_mat_row - set (replace) row of the constraint matrix
+*
+* SYNOPSIS
+*
+* void glp_set_mat_row(glp_prob *lp, int i, int len, const int ind[],
+* const double val[]);
+*
+* DESCRIPTION
+*
+* The routine glp_set_mat_row stores (replaces) the contents of i-th
+* row of the constraint matrix of the specified problem object.
+*
+* Column indices and numeric values of new row elements must be placed
+* in locations ind[1], ..., ind[len] and val[1], ..., val[len], where
+* 0 <= len <= n is the new length of i-th row, n is the current number
+* of columns in the problem object. Elements with identical column
+* indices are not allowed. Zero elements are allowed, but they are not
+* stored in the constraint matrix.
+*
+* If the parameter len is zero, the parameters ind and/or val can be
+* specified as NULL. */
+
+void glp_set_mat_row(glp_prob *lp, int i, int len, const int ind[],
+ const double val[])
+{ glp_tree *tree = lp->tree;
+ GLPROW *row;
+ GLPCOL *col;
+ GLPAIJ *aij, *next;
+ int j, k;
+ /* obtain pointer to i-th row */
+ if (!(1 <= i && i <= lp->m))
+ xerror("glp_set_mat_row: i = %d; row number out of range\n",
+ i);
+ row = lp->row[i];
+ if (tree != NULL && tree->reason != 0)
+ { xassert(tree->curr != NULL);
+ xassert(row->level == tree->curr->level);
+ }
+ /* remove all existing elements from i-th row */
+ while (row->ptr != NULL)
+ { /* take next element in the row */
+ aij = row->ptr;
+ /* remove the element from the row list */
+ row->ptr = aij->r_next;
+ /* obtain pointer to corresponding column */
+ col = aij->col;
+ /* remove the element from the column list */
+ if (aij->c_prev == NULL)
+ col->ptr = aij->c_next;
+ else
+ aij->c_prev->c_next = aij->c_next;
+ if (aij->c_next == NULL)
+ ;
+ else
+ aij->c_next->c_prev = aij->c_prev;
+ /* return the element to the memory pool */
+ dmp_free_atom(lp->pool, aij, sizeof(GLPAIJ)), lp->nnz--;
+ /* if the corresponding column is basic, invalidate the basis
+ factorization */
+ if (col->stat == GLP_BS) lp->valid = 0;
+ }
+ /* store new contents of i-th row */
+ if (!(0 <= len && len <= lp->n))
+ xerror("glp_set_mat_row: i = %d; len = %d; invalid row length "
+ "\n", i, len);
+ if (len > NNZ_MAX - lp->nnz)
+ xerror("glp_set_mat_row: i = %d; len = %d; too many constraint"
+ " coefficients\n", i, len);
+ for (k = 1; k <= len; k++)
+ { /* take number j of corresponding column */
+ j = ind[k];
+ /* obtain pointer to j-th column */
+ if (!(1 <= j && j <= lp->n))
+ xerror("glp_set_mat_row: i = %d; ind[%d] = %d; column index"
+ " out of range\n", i, k, j);
+ col = lp->col[j];
+ /* if there is element with the same column index, it can only
+ be found in the beginning of j-th column list */
+ if (col->ptr != NULL && col->ptr->row->i == i)
+ xerror("glp_set_mat_row: i = %d; ind[%d] = %d; duplicate co"
+ "lumn indices not allowed\n", i, k, j);
+ /* create new element */
+ aij = dmp_get_atom(lp->pool, sizeof(GLPAIJ)), lp->nnz++;
+ aij->row = row;
+ aij->col = col;
+ aij->val = val[k];
+ /* add the new element to the beginning of i-th row and j-th
+ column lists */
+ aij->r_prev = NULL;
+ aij->r_next = row->ptr;
+ aij->c_prev = NULL;
+ aij->c_next = col->ptr;
+ if (aij->r_next != NULL) aij->r_next->r_prev = aij;
+ if (aij->c_next != NULL) aij->c_next->c_prev = aij;
+ row->ptr = col->ptr = aij;
+ /* if the corresponding column is basic, invalidate the basis
+ factorization */
+ if (col->stat == GLP_BS && aij->val != 0.0) lp->valid = 0;
+ }
+ /* remove zero elements from i-th row */
+ for (aij = row->ptr; aij != NULL; aij = next)
+ { next = aij->r_next;
+ if (aij->val == 0.0)
+ { /* remove the element from the row list */
+ if (aij->r_prev == NULL)
+ row->ptr = next;
+ else
+ aij->r_prev->r_next = next;
+ if (next == NULL)
+ ;
+ else
+ next->r_prev = aij->r_prev;
+ /* remove the element from the column list */
+ xassert(aij->c_prev == NULL);
+ aij->col->ptr = aij->c_next;
+ if (aij->c_next != NULL) aij->c_next->c_prev = NULL;
+ /* return the element to the memory pool */
+ dmp_free_atom(lp->pool, aij, sizeof(GLPAIJ)), lp->nnz--;
+ }
+ }
+ return;
+}
+
+/***********************************************************************
+* NAME
+*
+* glp_set_mat_col - set (replace) column of the constraint matrix
+*
+* SYNOPSIS
+*
+* void glp_set_mat_col(glp_prob *lp, int j, int len, const int ind[],
+* const double val[]);
+*
+* DESCRIPTION
+*
+* The routine glp_set_mat_col stores (replaces) the contents of j-th
+* column of the constraint matrix of the specified problem object.
+*
+* Row indices and numeric values of new column elements must be placed
+* in locations ind[1], ..., ind[len] and val[1], ..., val[len], where
+* 0 <= len <= m is the new length of j-th column, m is the current
+* number of rows in the problem object. Elements with identical column
+* indices are not allowed. Zero elements are allowed, but they are not
+* stored in the constraint matrix.
+*
+* If the parameter len is zero, the parameters ind and/or val can be
+* specified as NULL. */
+
+void glp_set_mat_col(glp_prob *lp, int j, int len, const int ind[],
+ const double val[])
+{ glp_tree *tree = lp->tree;
+ GLPROW *row;
+ GLPCOL *col;
+ GLPAIJ *aij, *next;
+ int i, k;
+ if (tree != NULL && tree->reason != 0)
+ xerror("glp_set_mat_col: operation not allowed\n");
+ /* obtain pointer to j-th column */
+ if (!(1 <= j && j <= lp->n))
+ xerror("glp_set_mat_col: j = %d; column number out of range\n",
+ j);
+ col = lp->col[j];
+ /* remove all existing elements from j-th column */
+ while (col->ptr != NULL)
+ { /* take next element in the column */
+ aij = col->ptr;
+ /* remove the element from the column list */
+ col->ptr = aij->c_next;
+ /* obtain pointer to corresponding row */
+ row = aij->row;
+ /* remove the element from the row list */
+ if (aij->r_prev == NULL)
+ row->ptr = aij->r_next;
+ else
+ aij->r_prev->r_next = aij->r_next;
+ if (aij->r_next == NULL)
+ ;
+ else
+ aij->r_next->r_prev = aij->r_prev;
+ /* return the element to the memory pool */
+ dmp_free_atom(lp->pool, aij, sizeof(GLPAIJ)), lp->nnz--;
+ }
+ /* store new contents of j-th column */
+ if (!(0 <= len && len <= lp->m))
+ xerror("glp_set_mat_col: j = %d; len = %d; invalid column leng"
+ "th\n", j, len);
+ if (len > NNZ_MAX - lp->nnz)
+ xerror("glp_set_mat_col: j = %d; len = %d; too many constraint"
+ " coefficients\n", j, len);
+ for (k = 1; k <= len; k++)
+ { /* take number i of corresponding row */
+ i = ind[k];
+ /* obtain pointer to i-th row */
+ if (!(1 <= i && i <= lp->m))
+ xerror("glp_set_mat_col: j = %d; ind[%d] = %d; row index ou"
+ "t of range\n", j, k, i);
+ row = lp->row[i];
+ /* if there is element with the same row index, it can only be
+ found in the beginning of i-th row list */
+ if (row->ptr != NULL && row->ptr->col->j == j)
+ xerror("glp_set_mat_col: j = %d; ind[%d] = %d; duplicate ro"
+ "w indices not allowed\n", j, k, i);
+ /* create new element */
+ aij = dmp_get_atom(lp->pool, sizeof(GLPAIJ)), lp->nnz++;
+ aij->row = row;
+ aij->col = col;
+ aij->val = val[k];
+ /* add the new element to the beginning of i-th row and j-th
+ column lists */
+ aij->r_prev = NULL;
+ aij->r_next = row->ptr;
+ aij->c_prev = NULL;
+ aij->c_next = col->ptr;
+ if (aij->r_next != NULL) aij->r_next->r_prev = aij;
+ if (aij->c_next != NULL) aij->c_next->c_prev = aij;
+ row->ptr = col->ptr = aij;
+ }
+ /* remove zero elements from j-th column */
+ for (aij = col->ptr; aij != NULL; aij = next)
+ { next = aij->c_next;
+ if (aij->val == 0.0)
+ { /* remove the element from the row list */
+ xassert(aij->r_prev == NULL);
+ aij->row->ptr = aij->r_next;
+ if (aij->r_next != NULL) aij->r_next->r_prev = NULL;
+ /* remove the element from the column list */
+ if (aij->c_prev == NULL)
+ col->ptr = next;
+ else
+ aij->c_prev->c_next = next;
+ if (next == NULL)
+ ;
+ else
+ next->c_prev = aij->c_prev;
+ /* return the element to the memory pool */
+ dmp_free_atom(lp->pool, aij, sizeof(GLPAIJ)), lp->nnz--;
+ }
+ }
+ /* if j-th column is basic, invalidate the basis factorization */
+ if (col->stat == GLP_BS) lp->valid = 0;
+ return;
+}
+
+/***********************************************************************
+* NAME
+*
+* glp_load_matrix - load (replace) the whole constraint matrix
+*
+* SYNOPSIS
+*
+* void glp_load_matrix(glp_prob *lp, int ne, const int ia[],
+* const int ja[], const double ar[]);
+*
+* DESCRIPTION
+*
+* The routine glp_load_matrix loads the constraint matrix passed in
+* the arrays ia, ja, and ar into the specified problem object. Before
+* loading the current contents of the constraint matrix is destroyed.
+*
+* Constraint coefficients (elements of the constraint matrix) must be
+* specified as triplets (ia[k], ja[k], ar[k]) for k = 1, ..., ne,
+* where ia[k] is the row index, ja[k] is the column index, ar[k] is a
+* numeric value of corresponding constraint coefficient. The parameter
+* ne specifies the total number of (non-zero) elements in the matrix
+* to be loaded. Coefficients with identical indices are not allowed.
+* Zero coefficients are allowed, however, they are not stored in the
+* constraint matrix.
+*
+* If the parameter ne is zero, the parameters ia, ja, and ar can be
+* specified as NULL. */
+
+void glp_load_matrix(glp_prob *lp, int ne, const int ia[],
+ const int ja[], const double ar[])
+{ glp_tree *tree = lp->tree;
+ GLPROW *row;
+ GLPCOL *col;
+ GLPAIJ *aij, *next;
+ int i, j, k;
+ if (tree != NULL && tree->reason != 0)
+ xerror("glp_load_matrix: operation not allowed\n");
+ /* clear the constraint matrix */
+ for (i = 1; i <= lp->m; i++)
+ { row = lp->row[i];
+ while (row->ptr != NULL)
+ { aij = row->ptr;
+ row->ptr = aij->r_next;
+ dmp_free_atom(lp->pool, aij, sizeof(GLPAIJ)), lp->nnz--;
+ }
+ }
+ xassert(lp->nnz == 0);
+ for (j = 1; j <= lp->n; j++) lp->col[j]->ptr = NULL;
+ /* load the new contents of the constraint matrix and build its
+ row lists */
+ if (ne < 0)
+ xerror("glp_load_matrix: ne = %d; invalid number of constraint"
+ " coefficients\n", ne);
+ if (ne > NNZ_MAX)
+ xerror("glp_load_matrix: ne = %d; too many constraint coeffici"
+ "ents\n", ne);
+ for (k = 1; k <= ne; k++)
+ { /* take indices of new element */
+ i = ia[k], j = ja[k];
+ /* obtain pointer to i-th row */
+ if (!(1 <= i && i <= lp->m))
+ xerror("glp_load_matrix: ia[%d] = %d; row index out of rang"
+ "e\n", k, i);
+ row = lp->row[i];
+ /* obtain pointer to j-th column */
+ if (!(1 <= j && j <= lp->n))
+ xerror("glp_load_matrix: ja[%d] = %d; column index out of r"
+ "ange\n", k, j);
+ col = lp->col[j];
+ /* create new element */
+ aij = dmp_get_atom(lp->pool, sizeof(GLPAIJ)), lp->nnz++;
+ aij->row = row;
+ aij->col = col;
+ aij->val = ar[k];
+ /* add the new element to the beginning of i-th row list */
+ aij->r_prev = NULL;
+ aij->r_next = row->ptr;
+ if (aij->r_next != NULL) aij->r_next->r_prev = aij;
+ row->ptr = aij;
+ }
+ xassert(lp->nnz == ne);
+ /* build column lists of the constraint matrix and check elements
+ with identical indices */
+ for (i = 1; i <= lp->m; i++)
+ { for (aij = lp->row[i]->ptr; aij != NULL; aij = aij->r_next)
+ { /* obtain pointer to corresponding column */
+ col = aij->col;
+ /* if there is element with identical indices, it can only
+ be found in the beginning of j-th column list */
+ if (col->ptr != NULL && col->ptr->row->i == i)
+ { for (k = 1; k <= ne; k++)
+ if (ia[k] == i && ja[k] == col->j) break;
+ xerror("glp_load_mat: ia[%d] = %d; ja[%d] = %d; duplicat"
+ "e indices not allowed\n", k, i, k, col->j);
+ }
+ /* add the element to the beginning of j-th column list */
+ aij->c_prev = NULL;
+ aij->c_next = col->ptr;
+ if (aij->c_next != NULL) aij->c_next->c_prev = aij;
+ col->ptr = aij;
+ }
+ }
+ /* remove zero elements from the constraint matrix */
+ for (i = 1; i <= lp->m; i++)
+ { row = lp->row[i];
+ for (aij = row->ptr; aij != NULL; aij = next)
+ { next = aij->r_next;
+ if (aij->val == 0.0)
+ { /* remove the element from the row list */
+ if (aij->r_prev == NULL)
+ row->ptr = next;
+ else
+ aij->r_prev->r_next = next;
+ if (next == NULL)
+ ;
+ else
+ next->r_prev = aij->r_prev;
+ /* remove the element from the column list */
+ if (aij->c_prev == NULL)
+ aij->col->ptr = aij->c_next;
+ else
+ aij->c_prev->c_next = aij->c_next;
+ if (aij->c_next == NULL)
+ ;
+ else
+ aij->c_next->c_prev = aij->c_prev;
+ /* return the element to the memory pool */
+ dmp_free_atom(lp->pool, aij, sizeof(GLPAIJ)), lp->nnz--;
+ }
+ }
+ }
+ /* invalidate the basis factorization */
+ lp->valid = 0;
+ return;
+}
+
+/***********************************************************************
+* NAME
+*
+* glp_check_dup - check for duplicate elements in sparse matrix
+*
+* SYNOPSIS
+*
+* int glp_check_dup(int m, int n, int ne, const int ia[],
+* const int ja[]);
+*
+* DESCRIPTION
+*
+* The routine glp_check_dup checks for duplicate elements (that is,
+* elements with identical indices) in a sparse matrix specified in the
+* coordinate format.
+*
+* The parameters m and n specifies, respectively, the number of rows
+* and columns in the matrix, m >= 0, n >= 0.
+*
+* The parameter ne specifies the number of (structurally) non-zero
+* elements in the matrix, ne >= 0.
+*
+* Elements of the matrix are specified as doublets (ia[k],ja[k]) for
+* k = 1,...,ne, where ia[k] is a row index, ja[k] is a column index.
+*
+* The routine glp_check_dup can be used prior to a call to the routine
+* glp_load_matrix to check that the constraint matrix to be loaded has
+* no duplicate elements.
+*
+* RETURNS
+*
+* The routine glp_check_dup returns one of the following values:
+*
+* 0 - the matrix has no duplicate elements;
+*
+* -k - indices ia[k] or/and ja[k] are out of range;
+*
+* +k - element (ia[k],ja[k]) is duplicate. */
+
+int glp_check_dup(int m, int n, int ne, const int ia[], const int ja[])
+{ int i, j, k, *ptr, *next, ret;
+ char *flag;
+ if (m < 0)
+ xerror("glp_check_dup: m = %d; invalid parameter\n");
+ if (n < 0)
+ xerror("glp_check_dup: n = %d; invalid parameter\n");
+ if (ne < 0)
+ xerror("glp_check_dup: ne = %d; invalid parameter\n");
+ if (ne > 0 && ia == NULL)
+ xerror("glp_check_dup: ia = %p; invalid parameter\n", ia);
+ if (ne > 0 && ja == NULL)
+ xerror("glp_check_dup: ja = %p; invalid parameter\n", ja);
+ for (k = 1; k <= ne; k++)
+ { i = ia[k], j = ja[k];
+ if (!(1 <= i && i <= m && 1 <= j && j <= n))
+ { ret = -k;
+ goto done;
+ }
+ }
+ if (m == 0 || n == 0)
+ { ret = 0;
+ goto done;
+ }
+ /* allocate working arrays */
+ ptr = xcalloc(1+m, sizeof(int));
+ next = xcalloc(1+ne, sizeof(int));
+ flag = xcalloc(1+n, sizeof(char));
+ /* build row lists */
+ for (i = 1; i <= m; i++)
+ ptr[i] = 0;
+ for (k = 1; k <= ne; k++)
+ { i = ia[k];
+ next[k] = ptr[i];
+ ptr[i] = k;
+ }
+ /* clear column flags */
+ for (j = 1; j <= n; j++)
+ flag[j] = 0;
+ /* check for duplicate elements */
+ for (i = 1; i <= m; i++)
+ { for (k = ptr[i]; k != 0; k = next[k])
+ { j = ja[k];
+ if (flag[j])
+ { /* find first element (i,j) */
+ for (k = 1; k <= ne; k++)
+ if (ia[k] == i && ja[k] == j) break;
+ xassert(k <= ne);
+ /* find next (duplicate) element (i,j) */
+ for (k++; k <= ne; k++)
+ if (ia[k] == i && ja[k] == j) break;
+ xassert(k <= ne);
+ ret = +k;
+ goto skip;
+ }
+ flag[j] = 1;
+ }
+ /* clear column flags */
+ for (k = ptr[i]; k != 0; k = next[k])
+ flag[ja[k]] = 0;
+ }
+ /* no duplicate element found */
+ ret = 0;
+skip: /* free working arrays */
+ xfree(ptr);
+ xfree(next);
+ xfree(flag);
+done: return ret;
+}
+
+/***********************************************************************
+* NAME
+*
+* glp_sort_matrix - sort elements of the constraint matrix
+*
+* SYNOPSIS
+*
+* void glp_sort_matrix(glp_prob *P);
+*
+* DESCRIPTION
+*
+* The routine glp_sort_matrix sorts elements of the constraint matrix
+* rebuilding its row and column linked lists. On exit from the routine
+* the constraint matrix is not changed, however, elements in the row
+* linked lists become ordered by ascending column indices, and the
+* elements in the column linked lists become ordered by ascending row
+* indices. */
+
+void glp_sort_matrix(glp_prob *P)
+{ GLPAIJ *aij;
+ int i, j;
+#if 0 /* 04/IV-2016 */
+ if (P == NULL || P->magic != GLP_PROB_MAGIC)
+ xerror("glp_sort_matrix: P = %p; invalid problem object\n",
+ P);
+#endif
+ /* rebuild row linked lists */
+ for (i = P->m; i >= 1; i--)
+ P->row[i]->ptr = NULL;
+ for (j = P->n; j >= 1; j--)
+ { for (aij = P->col[j]->ptr; aij != NULL; aij = aij->c_next)
+ { i = aij->row->i;
+ aij->r_prev = NULL;
+ aij->r_next = P->row[i]->ptr;
+ if (aij->r_next != NULL) aij->r_next->r_prev = aij;
+ P->row[i]->ptr = aij;
+ }
+ }
+ /* rebuild column linked lists */
+ for (j = P->n; j >= 1; j--)
+ P->col[j]->ptr = NULL;
+ for (i = P->m; i >= 1; i--)
+ { for (aij = P->row[i]->ptr; aij != NULL; aij = aij->r_next)
+ { j = aij->col->j;
+ aij->c_prev = NULL;
+ aij->c_next = P->col[j]->ptr;
+ if (aij->c_next != NULL) aij->c_next->c_prev = aij;
+ P->col[j]->ptr = aij;
+ }
+ }
+ return;
+}
+
+/***********************************************************************
+* NAME
+*
+* glp_del_rows - delete rows from problem object
+*
+* SYNOPSIS
+*
+* void glp_del_rows(glp_prob *lp, int nrs, const int num[]);
+*
+* DESCRIPTION
+*
+* The routine glp_del_rows deletes rows from the specified problem
+* object. Ordinal numbers of rows to be deleted should be placed in
+* locations num[1], ..., num[nrs], where nrs > 0.
+*
+* Note that deleting rows involves changing ordinal numbers of other
+* rows remaining in the problem object. New ordinal numbers of the
+* remaining rows are assigned under the assumption that the original
+* order of rows is not changed. */
+
+void glp_del_rows(glp_prob *lp, int nrs, const int num[])
+{ glp_tree *tree = lp->tree;
+ GLPROW *row;
+ int i, k, m_new;
+ /* mark rows to be deleted */
+ if (!(1 <= nrs && nrs <= lp->m))
+ xerror("glp_del_rows: nrs = %d; invalid number of rows\n",
+ nrs);
+ for (k = 1; k <= nrs; k++)
+ { /* take the number of row to be deleted */
+ i = num[k];
+ /* obtain pointer to i-th row */
+ if (!(1 <= i && i <= lp->m))
+ xerror("glp_del_rows: num[%d] = %d; row number out of range"
+ "\n", k, i);
+ row = lp->row[i];
+ if (tree != NULL && tree->reason != 0)
+ { if (!(tree->reason == GLP_IROWGEN ||
+ tree->reason == GLP_ICUTGEN))
+ xerror("glp_del_rows: operation not allowed\n");
+ xassert(tree->curr != NULL);
+ if (row->level != tree->curr->level)
+ xerror("glp_del_rows: num[%d] = %d; invalid attempt to d"
+ "elete row created not in current subproblem\n", k,i);
+ if (row->stat != GLP_BS)
+ xerror("glp_del_rows: num[%d] = %d; invalid attempt to d"
+ "elete active row (constraint)\n", k, i);
+ tree->reinv = 1;
+ }
+ /* check that the row is not marked yet */
+ if (row->i == 0)
+ xerror("glp_del_rows: num[%d] = %d; duplicate row numbers n"
+ "ot allowed\n", k, i);
+ /* erase symbolic name assigned to the row */
+ glp_set_row_name(lp, i, NULL);
+ xassert(row->node == NULL);
+ /* erase corresponding row of the constraint matrix */
+ glp_set_mat_row(lp, i, 0, NULL, NULL);
+ xassert(row->ptr == NULL);
+ /* mark the row to be deleted */
+ row->i = 0;
+ }
+ /* delete all marked rows from the row list */
+ m_new = 0;
+ for (i = 1; i <= lp->m; i++)
+ { /* obtain pointer to i-th row */
+ row = lp->row[i];
+ /* check if the row is marked */
+ if (row->i == 0)
+ { /* it is marked, delete it */
+ dmp_free_atom(lp->pool, row, sizeof(GLPROW));
+ }
+ else
+ { /* it is not marked; keep it */
+ row->i = ++m_new;
+ lp->row[row->i] = row;
+ }
+ }
+ /* set new number of rows */
+ lp->m = m_new;
+ /* invalidate the basis factorization */
+ lp->valid = 0;
+ return;
+}
+
+/***********************************************************************
+* NAME
+*
+* glp_del_cols - delete columns from problem object
+*
+* SYNOPSIS
+*
+* void glp_del_cols(glp_prob *lp, int ncs, const int num[]);
+*
+* DESCRIPTION
+*
+* The routine glp_del_cols deletes columns from the specified problem
+* object. Ordinal numbers of columns to be deleted should be placed in
+* locations num[1], ..., num[ncs], where ncs > 0.
+*
+* Note that deleting columns involves changing ordinal numbers of
+* other columns remaining in the problem object. New ordinal numbers
+* of the remaining columns are assigned under the assumption that the
+* original order of columns is not changed. */
+
+void glp_del_cols(glp_prob *lp, int ncs, const int num[])
+{ glp_tree *tree = lp->tree;
+ GLPCOL *col;
+ int j, k, n_new;
+ if (tree != NULL && tree->reason != 0)
+ xerror("glp_del_cols: operation not allowed\n");
+ /* mark columns to be deleted */
+ if (!(1 <= ncs && ncs <= lp->n))
+ xerror("glp_del_cols: ncs = %d; invalid number of columns\n",
+ ncs);
+ for (k = 1; k <= ncs; k++)
+ { /* take the number of column to be deleted */
+ j = num[k];
+ /* obtain pointer to j-th column */
+ if (!(1 <= j && j <= lp->n))
+ xerror("glp_del_cols: num[%d] = %d; column number out of ra"
+ "nge", k, j);
+ col = lp->col[j];
+ /* check that the column is not marked yet */
+ if (col->j == 0)
+ xerror("glp_del_cols: num[%d] = %d; duplicate column number"
+ "s not allowed\n", k, j);
+ /* erase symbolic name assigned to the column */
+ glp_set_col_name(lp, j, NULL);
+ xassert(col->node == NULL);
+ /* erase corresponding column of the constraint matrix */
+ glp_set_mat_col(lp, j, 0, NULL, NULL);
+ xassert(col->ptr == NULL);
+ /* mark the column to be deleted */
+ col->j = 0;
+ /* if it is basic, invalidate the basis factorization */
+ if (col->stat == GLP_BS) lp->valid = 0;
+ }
+ /* delete all marked columns from the column list */
+ n_new = 0;
+ for (j = 1; j <= lp->n; j++)
+ { /* obtain pointer to j-th column */
+ col = lp->col[j];
+ /* check if the column is marked */
+ if (col->j == 0)
+ { /* it is marked; delete it */
+ dmp_free_atom(lp->pool, col, sizeof(GLPCOL));
+ }
+ else
+ { /* it is not marked; keep it */
+ col->j = ++n_new;
+ lp->col[col->j] = col;
+ }
+ }
+ /* set new number of columns */
+ lp->n = n_new;
+ /* if the basis header is still valid, adjust it */
+ if (lp->valid)
+ { int m = lp->m;
+ int *head = lp->head;
+ for (j = 1; j <= n_new; j++)
+ { k = lp->col[j]->bind;
+ if (k != 0)
+ { xassert(1 <= k && k <= m);
+ head[k] = m + j;
+ }
+ }
+ }
+ return;
+}
+
+/***********************************************************************
+* NAME
+*
+* glp_copy_prob - copy problem object content
+*
+* SYNOPSIS
+*
+* void glp_copy_prob(glp_prob *dest, glp_prob *prob, int names);
+*
+* DESCRIPTION
+*
+* The routine glp_copy_prob copies the content of the problem object
+* prob to the problem object dest.
+*
+* The parameter names is a flag. If it is non-zero, the routine also
+* copies all symbolic names; otherwise, if it is zero, symbolic names
+* are not copied. */
+
+void glp_copy_prob(glp_prob *dest, glp_prob *prob, int names)
+{ glp_tree *tree = dest->tree;
+ glp_bfcp bfcp;
+ int i, j, len, *ind;
+ double *val;
+ if (tree != NULL && tree->reason != 0)
+ xerror("glp_copy_prob: operation not allowed\n");
+ if (dest == prob)
+ xerror("glp_copy_prob: copying problem object to itself not al"
+ "lowed\n");
+ if (!(names == GLP_ON || names == GLP_OFF))
+ xerror("glp_copy_prob: names = %d; invalid parameter\n",
+ names);
+ glp_erase_prob(dest);
+ if (names && prob->name != NULL)
+ glp_set_prob_name(dest, prob->name);
+ if (names && prob->obj != NULL)
+ glp_set_obj_name(dest, prob->obj);
+ dest->dir = prob->dir;
+ dest->c0 = prob->c0;
+ if (prob->m > 0)
+ glp_add_rows(dest, prob->m);
+ if (prob->n > 0)
+ glp_add_cols(dest, prob->n);
+ glp_get_bfcp(prob, &bfcp);
+ glp_set_bfcp(dest, &bfcp);
+ dest->pbs_stat = prob->pbs_stat;
+ dest->dbs_stat = prob->dbs_stat;
+ dest->obj_val = prob->obj_val;
+ dest->some = prob->some;
+ dest->ipt_stat = prob->ipt_stat;
+ dest->ipt_obj = prob->ipt_obj;
+ dest->mip_stat = prob->mip_stat;
+ dest->mip_obj = prob->mip_obj;
+ for (i = 1; i <= prob->m; i++)
+ { GLPROW *to = dest->row[i];
+ GLPROW *from = prob->row[i];
+ if (names && from->name != NULL)
+ glp_set_row_name(dest, i, from->name);
+ to->type = from->type;
+ to->lb = from->lb;
+ to->ub = from->ub;
+ to->rii = from->rii;
+ to->stat = from->stat;
+ to->prim = from->prim;
+ to->dual = from->dual;
+ to->pval = from->pval;
+ to->dval = from->dval;
+ to->mipx = from->mipx;
+ }
+ ind = xcalloc(1+prob->m, sizeof(int));
+ val = xcalloc(1+prob->m, sizeof(double));
+ for (j = 1; j <= prob->n; j++)
+ { GLPCOL *to = dest->col[j];
+ GLPCOL *from = prob->col[j];
+ if (names && from->name != NULL)
+ glp_set_col_name(dest, j, from->name);
+ to->kind = from->kind;
+ to->type = from->type;
+ to->lb = from->lb;
+ to->ub = from->ub;
+ to->coef = from->coef;
+ len = glp_get_mat_col(prob, j, ind, val);
+ glp_set_mat_col(dest, j, len, ind, val);
+ to->sjj = from->sjj;
+ to->stat = from->stat;
+ to->prim = from->prim;
+ to->dual = from->dual;
+ to->pval = from->pval;
+ to->dval = from->dval;
+ to->mipx = from->mipx;
+ }
+ xfree(ind);
+ xfree(val);
+ return;
+}
+
+/***********************************************************************
+* NAME
+*
+* glp_erase_prob - erase problem object content
+*
+* SYNOPSIS
+*
+* void glp_erase_prob(glp_prob *lp);
+*
+* DESCRIPTION
+*
+* The routine glp_erase_prob erases the content of the specified
+* problem object. The effect of this operation is the same as if the
+* problem object would be deleted with the routine glp_delete_prob and
+* then created anew with the routine glp_create_prob, with exception
+* that the handle (pointer) to the problem object remains valid. */
+
+static void delete_prob(glp_prob *lp);
+
+void glp_erase_prob(glp_prob *lp)
+{ glp_tree *tree = lp->tree;
+ if (tree != NULL && tree->reason != 0)
+ xerror("glp_erase_prob: operation not allowed\n");
+ delete_prob(lp);
+ create_prob(lp);
+ return;
+}
+
+/***********************************************************************
+* NAME
+*
+* glp_delete_prob - delete problem object
+*
+* SYNOPSIS
+*
+* void glp_delete_prob(glp_prob *lp);
+*
+* DESCRIPTION
+*
+* The routine glp_delete_prob deletes the specified problem object and
+* frees all the memory allocated to it. */
+
+static void delete_prob(glp_prob *lp)
+#if 0 /* 04/IV-2016 */
+{ lp->magic = 0x3F3F3F3F;
+#else
+{
+#endif
+ dmp_delete_pool(lp->pool);
+#if 0 /* 08/III-2014 */
+#if 0 /* 17/XI-2009 */
+ xfree(lp->cps);
+#else
+ if (lp->parms != NULL) xfree(lp->parms);
+#endif
+#endif
+ xassert(lp->tree == NULL);
+#if 0
+ if (lp->cwa != NULL) xfree(lp->cwa);
+#endif
+ xfree(lp->row);
+ xfree(lp->col);
+ if (lp->r_tree != NULL) avl_delete_tree(lp->r_tree);
+ if (lp->c_tree != NULL) avl_delete_tree(lp->c_tree);
+ xfree(lp->head);
+#if 0 /* 08/III-2014 */
+ if (lp->bfcp != NULL) xfree(lp->bfcp);
+#endif
+ if (lp->bfd != NULL) bfd_delete_it(lp->bfd);
+ return;
+}
+
+void glp_delete_prob(glp_prob *lp)
+{ glp_tree *tree = lp->tree;
+ if (tree != NULL && tree->reason != 0)
+ xerror("glp_delete_prob: operation not allowed\n");
+ delete_prob(lp);
+ xfree(lp);
+ return;
+}
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/api/prob2.c b/test/monniaux/glpk-4.65/src/api/prob2.c
new file mode 100644
index 00000000..d352db12
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/api/prob2.c
@@ -0,0 +1,491 @@
+/* prob2.c (problem retrieving routines) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* Copyright (C) 2000-2013 Andrew Makhorin, Department for Applied
+* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights
+* reserved. E-mail: <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 "env.h"
+#include "prob.h"
+
+/***********************************************************************
+* NAME
+*
+* glp_get_prob_name - retrieve problem name
+*
+* SYNOPSIS
+*
+* const char *glp_get_prob_name(glp_prob *lp);
+*
+* RETURNS
+*
+* The routine glp_get_prob_name returns a pointer to an internal
+* buffer, which contains symbolic name of the problem. However, if the
+* problem has no assigned name, the routine returns NULL. */
+
+const char *glp_get_prob_name(glp_prob *lp)
+{ char *name;
+ name = lp->name;
+ return name;
+}
+
+/***********************************************************************
+* NAME
+*
+* glp_get_obj_name - retrieve objective function name
+*
+* SYNOPSIS
+*
+* const char *glp_get_obj_name(glp_prob *lp);
+*
+* RETURNS
+*
+* The routine glp_get_obj_name returns a pointer to an internal
+* buffer, which contains a symbolic name of the objective function.
+* However, if the objective function has no assigned name, the routine
+* returns NULL. */
+
+const char *glp_get_obj_name(glp_prob *lp)
+{ char *name;
+ name = lp->obj;
+ return name;
+}
+
+/***********************************************************************
+* NAME
+*
+* glp_get_obj_dir - retrieve optimization direction flag
+*
+* SYNOPSIS
+*
+* int glp_get_obj_dir(glp_prob *lp);
+*
+* RETURNS
+*
+* The routine glp_get_obj_dir returns the optimization direction flag
+* (i.e. "sense" of the objective function):
+*
+* GLP_MIN - minimization;
+* GLP_MAX - maximization. */
+
+int glp_get_obj_dir(glp_prob *lp)
+{ int dir = lp->dir;
+ return dir;
+}
+
+/***********************************************************************
+* NAME
+*
+* glp_get_num_rows - retrieve number of rows
+*
+* SYNOPSIS
+*
+* int glp_get_num_rows(glp_prob *lp);
+*
+* RETURNS
+*
+* The routine glp_get_num_rows returns the current number of rows in
+* the specified problem object. */
+
+int glp_get_num_rows(glp_prob *lp)
+{ int m = lp->m;
+ return m;
+}
+
+/***********************************************************************
+* NAME
+*
+* glp_get_num_cols - retrieve number of columns
+*
+* SYNOPSIS
+*
+* int glp_get_num_cols(glp_prob *lp);
+*
+* RETURNS
+*
+* The routine glp_get_num_cols returns the current number of columns
+* in the specified problem object. */
+
+int glp_get_num_cols(glp_prob *lp)
+{ int n = lp->n;
+ return n;
+}
+
+/***********************************************************************
+* NAME
+*
+* glp_get_row_name - retrieve row name
+*
+* SYNOPSIS
+*
+* const char *glp_get_row_name(glp_prob *lp, int i);
+*
+* RETURNS
+*
+* The routine glp_get_row_name returns a pointer to an internal
+* buffer, which contains symbolic name of i-th row. However, if i-th
+* row has no assigned name, the routine returns NULL. */
+
+const char *glp_get_row_name(glp_prob *lp, int i)
+{ char *name;
+ if (!(1 <= i && i <= lp->m))
+ xerror("glp_get_row_name: i = %d; row number out of range\n",
+ i);
+ name = lp->row[i]->name;
+ return name;
+}
+
+/***********************************************************************
+* NAME
+*
+* glp_get_col_name - retrieve column name
+*
+* SYNOPSIS
+*
+* const char *glp_get_col_name(glp_prob *lp, int j);
+*
+* RETURNS
+*
+* The routine glp_get_col_name returns a pointer to an internal
+* buffer, which contains symbolic name of j-th column. However, if j-th
+* column has no assigned name, the routine returns NULL. */
+
+const char *glp_get_col_name(glp_prob *lp, int j)
+{ char *name;
+ if (!(1 <= j && j <= lp->n))
+ xerror("glp_get_col_name: j = %d; column number out of range\n"
+ , j);
+ name = lp->col[j]->name;
+ return name;
+}
+
+/***********************************************************************
+* NAME
+*
+* glp_get_row_type - retrieve row type
+*
+* SYNOPSIS
+*
+* int glp_get_row_type(glp_prob *lp, int i);
+*
+* RETURNS
+*
+* The routine glp_get_row_type returns the type of i-th row, i.e. the
+* type of corresponding auxiliary variable, as follows:
+*
+* GLP_FR - free (unbounded) variable;
+* GLP_LO - variable with lower bound;
+* GLP_UP - variable with upper bound;
+* GLP_DB - double-bounded variable;
+* GLP_FX - fixed variable. */
+
+int glp_get_row_type(glp_prob *lp, int i)
+{ if (!(1 <= i && i <= lp->m))
+ xerror("glp_get_row_type: i = %d; row number out of range\n",
+ i);
+ return lp->row[i]->type;
+}
+
+/***********************************************************************
+* NAME
+*
+* glp_get_row_lb - retrieve row lower bound
+*
+* SYNOPSIS
+*
+* double glp_get_row_lb(glp_prob *lp, int i);
+*
+* RETURNS
+*
+* The routine glp_get_row_lb returns the lower bound of i-th row, i.e.
+* the lower bound of corresponding auxiliary variable. However, if the
+* row has no lower bound, the routine returns -DBL_MAX. */
+
+double glp_get_row_lb(glp_prob *lp, int i)
+{ double lb;
+ if (!(1 <= i && i <= lp->m))
+ xerror("glp_get_row_lb: i = %d; row number out of range\n", i);
+ switch (lp->row[i]->type)
+ { case GLP_FR:
+ case GLP_UP:
+ lb = -DBL_MAX; break;
+ case GLP_LO:
+ case GLP_DB:
+ case GLP_FX:
+ lb = lp->row[i]->lb; break;
+ default:
+ xassert(lp != lp);
+ }
+ return lb;
+}
+
+/***********************************************************************
+* NAME
+*
+* glp_get_row_ub - retrieve row upper bound
+*
+* SYNOPSIS
+*
+* double glp_get_row_ub(glp_prob *lp, int i);
+*
+* RETURNS
+*
+* The routine glp_get_row_ub returns the upper bound of i-th row, i.e.
+* the upper bound of corresponding auxiliary variable. However, if the
+* row has no upper bound, the routine returns +DBL_MAX. */
+
+double glp_get_row_ub(glp_prob *lp, int i)
+{ double ub;
+ if (!(1 <= i && i <= lp->m))
+ xerror("glp_get_row_ub: i = %d; row number out of range\n", i);
+ switch (lp->row[i]->type)
+ { case GLP_FR:
+ case GLP_LO:
+ ub = +DBL_MAX; break;
+ case GLP_UP:
+ case GLP_DB:
+ case GLP_FX:
+ ub = lp->row[i]->ub; break;
+ default:
+ xassert(lp != lp);
+ }
+ return ub;
+}
+
+/***********************************************************************
+* NAME
+*
+* glp_get_col_type - retrieve column type
+*
+* SYNOPSIS
+*
+* int glp_get_col_type(glp_prob *lp, int j);
+*
+* RETURNS
+*
+* The routine glp_get_col_type returns the type of j-th column, i.e.
+* the type of corresponding structural variable, as follows:
+*
+* GLP_FR - free (unbounded) variable;
+* GLP_LO - variable with lower bound;
+* GLP_UP - variable with upper bound;
+* GLP_DB - double-bounded variable;
+* GLP_FX - fixed variable. */
+
+int glp_get_col_type(glp_prob *lp, int j)
+{ if (!(1 <= j && j <= lp->n))
+ xerror("glp_get_col_type: j = %d; column number out of range\n"
+ , j);
+ return lp->col[j]->type;
+}
+
+/***********************************************************************
+* NAME
+*
+* glp_get_col_lb - retrieve column lower bound
+*
+* SYNOPSIS
+*
+* double glp_get_col_lb(glp_prob *lp, int j);
+*
+* RETURNS
+*
+* The routine glp_get_col_lb returns the lower bound of j-th column,
+* i.e. the lower bound of corresponding structural variable. However,
+* if the column has no lower bound, the routine returns -DBL_MAX. */
+
+double glp_get_col_lb(glp_prob *lp, int j)
+{ double lb;
+ if (!(1 <= j && j <= lp->n))
+ xerror("glp_get_col_lb: j = %d; column number out of range\n",
+ j);
+ switch (lp->col[j]->type)
+ { case GLP_FR:
+ case GLP_UP:
+ lb = -DBL_MAX; break;
+ case GLP_LO:
+ case GLP_DB:
+ case GLP_FX:
+ lb = lp->col[j]->lb; break;
+ default:
+ xassert(lp != lp);
+ }
+ return lb;
+}
+
+/***********************************************************************
+* NAME
+*
+* glp_get_col_ub - retrieve column upper bound
+*
+* SYNOPSIS
+*
+* double glp_get_col_ub(glp_prob *lp, int j);
+*
+* RETURNS
+*
+* The routine glp_get_col_ub returns the upper bound of j-th column,
+* i.e. the upper bound of corresponding structural variable. However,
+* if the column has no upper bound, the routine returns +DBL_MAX. */
+
+double glp_get_col_ub(glp_prob *lp, int j)
+{ double ub;
+ if (!(1 <= j && j <= lp->n))
+ xerror("glp_get_col_ub: j = %d; column number out of range\n",
+ j);
+ switch (lp->col[j]->type)
+ { case GLP_FR:
+ case GLP_LO:
+ ub = +DBL_MAX; break;
+ case GLP_UP:
+ case GLP_DB:
+ case GLP_FX:
+ ub = lp->col[j]->ub; break;
+ default:
+ xassert(lp != lp);
+ }
+ return ub;
+}
+
+/***********************************************************************
+* NAME
+*
+* glp_get_obj_coef - retrieve obj. coefficient or constant term
+*
+* SYNOPSIS
+*
+* double glp_get_obj_coef(glp_prob *lp, int j);
+*
+* RETURNS
+*
+* The routine glp_get_obj_coef returns the objective coefficient at
+* j-th structural variable (column) of the specified problem object.
+*
+* If the parameter j is zero, the routine returns the constant term
+* ("shift") of the objective function. */
+
+double glp_get_obj_coef(glp_prob *lp, int j)
+{ if (!(0 <= j && j <= lp->n))
+ xerror("glp_get_obj_coef: j = %d; column number out of range\n"
+ , j);
+ return j == 0 ? lp->c0 : lp->col[j]->coef;
+}
+
+/***********************************************************************
+* NAME
+*
+* glp_get_num_nz - retrieve number of constraint coefficients
+*
+* SYNOPSIS
+*
+* int glp_get_num_nz(glp_prob *lp);
+*
+* RETURNS
+*
+* The routine glp_get_num_nz returns the number of (non-zero) elements
+* in the constraint matrix of the specified problem object. */
+
+int glp_get_num_nz(glp_prob *lp)
+{ int nnz = lp->nnz;
+ return nnz;
+}
+
+/***********************************************************************
+* NAME
+*
+* glp_get_mat_row - retrieve row of the constraint matrix
+*
+* SYNOPSIS
+*
+* int glp_get_mat_row(glp_prob *lp, int i, int ind[], double val[]);
+*
+* DESCRIPTION
+*
+* The routine glp_get_mat_row scans (non-zero) elements of i-th row
+* of the constraint matrix of the specified problem object and stores
+* their column indices and numeric values to locations ind[1], ...,
+* ind[len] and val[1], ..., val[len], respectively, where 0 <= len <= n
+* is the number of elements in i-th row, n is the number of columns.
+*
+* The parameter ind and/or val can be specified as NULL, in which case
+* corresponding information is not stored.
+*
+* RETURNS
+*
+* The routine glp_get_mat_row returns the length len, i.e. the number
+* of (non-zero) elements in i-th row. */
+
+int glp_get_mat_row(glp_prob *lp, int i, int ind[], double val[])
+{ GLPAIJ *aij;
+ int len;
+ if (!(1 <= i && i <= lp->m))
+ xerror("glp_get_mat_row: i = %d; row number out of range\n",
+ i);
+ len = 0;
+ for (aij = lp->row[i]->ptr; aij != NULL; aij = aij->r_next)
+ { len++;
+ if (ind != NULL) ind[len] = aij->col->j;
+ if (val != NULL) val[len] = aij->val;
+ }
+ xassert(len <= lp->n);
+ return len;
+}
+
+/***********************************************************************
+* NAME
+*
+* glp_get_mat_col - retrieve column of the constraint matrix
+*
+* SYNOPSIS
+*
+* int glp_get_mat_col(glp_prob *lp, int j, int ind[], double val[]);
+*
+* DESCRIPTION
+*
+* The routine glp_get_mat_col scans (non-zero) elements of j-th column
+* of the constraint matrix of the specified problem object and stores
+* their row indices and numeric values to locations ind[1], ...,
+* ind[len] and val[1], ..., val[len], respectively, where 0 <= len <= m
+* is the number of elements in j-th column, m is the number of rows.
+*
+* The parameter ind or/and val can be specified as NULL, in which case
+* corresponding information is not stored.
+*
+* RETURNS
+*
+* The routine glp_get_mat_col returns the length len, i.e. the number
+* of (non-zero) elements in j-th column. */
+
+int glp_get_mat_col(glp_prob *lp, int j, int ind[], double val[])
+{ GLPAIJ *aij;
+ int len;
+ if (!(1 <= j && j <= lp->n))
+ xerror("glp_get_mat_col: j = %d; column number out of range\n",
+ j);
+ len = 0;
+ for (aij = lp->col[j]->ptr; aij != NULL; aij = aij->c_next)
+ { len++;
+ if (ind != NULL) ind[len] = aij->row->i;
+ if (val != NULL) val[len] = aij->val;
+ }
+ xassert(len <= lp->m);
+ return len;
+}
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/api/prob3.c b/test/monniaux/glpk-4.65/src/api/prob3.c
new file mode 100644
index 00000000..d7edbd33
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/api/prob3.c
@@ -0,0 +1,166 @@
+/* prob3.c (problem row/column searching routines) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* Copyright (C) 2000-2013 Andrew Makhorin, Department for Applied
+* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights
+* reserved. E-mail: <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 "env.h"
+#include "prob.h"
+
+/***********************************************************************
+* NAME
+*
+* glp_create_index - create the name index
+*
+* SYNOPSIS
+*
+* void glp_create_index(glp_prob *lp);
+*
+* DESCRIPTION
+*
+* The routine glp_create_index creates the name index for the
+* specified problem object. The name index is an auxiliary data
+* structure, which is intended to quickly (i.e. for logarithmic time)
+* find rows and columns by their names.
+*
+* This routine can be called at any time. If the name index already
+* exists, the routine does nothing. */
+
+void glp_create_index(glp_prob *lp)
+{ GLPROW *row;
+ GLPCOL *col;
+ int i, j;
+ /* create row name index */
+ if (lp->r_tree == NULL)
+ { lp->r_tree = avl_create_tree(avl_strcmp, NULL);
+ for (i = 1; i <= lp->m; i++)
+ { row = lp->row[i];
+ xassert(row->node == NULL);
+ if (row->name != NULL)
+ { row->node = avl_insert_node(lp->r_tree, row->name);
+ avl_set_node_link(row->node, row);
+ }
+ }
+ }
+ /* create column name index */
+ if (lp->c_tree == NULL)
+ { lp->c_tree = avl_create_tree(avl_strcmp, NULL);
+ for (j = 1; j <= lp->n; j++)
+ { col = lp->col[j];
+ xassert(col->node == NULL);
+ if (col->name != NULL)
+ { col->node = avl_insert_node(lp->c_tree, col->name);
+ avl_set_node_link(col->node, col);
+ }
+ }
+ }
+ return;
+}
+
+/***********************************************************************
+* NAME
+*
+* glp_find_row - find row by its name
+*
+* SYNOPSIS
+*
+* int glp_find_row(glp_prob *lp, const char *name);
+*
+* RETURNS
+*
+* The routine glp_find_row returns the ordinal number of a row,
+* which is assigned (by the routine glp_set_row_name) the specified
+* symbolic name. If no such row exists, the routine returns 0. */
+
+int glp_find_row(glp_prob *lp, const char *name)
+{ AVLNODE *node;
+ int i = 0;
+ if (lp->r_tree == NULL)
+ xerror("glp_find_row: row name index does not exist\n");
+ if (!(name == NULL || name[0] == '\0' || strlen(name) > 255))
+ { node = avl_find_node(lp->r_tree, name);
+ if (node != NULL)
+ i = ((GLPROW *)avl_get_node_link(node))->i;
+ }
+ return i;
+}
+
+/***********************************************************************
+* NAME
+*
+* glp_find_col - find column by its name
+*
+* SYNOPSIS
+*
+* int glp_find_col(glp_prob *lp, const char *name);
+*
+* RETURNS
+*
+* The routine glp_find_col returns the ordinal number of a column,
+* which is assigned (by the routine glp_set_col_name) the specified
+* symbolic name. If no such column exists, the routine returns 0. */
+
+int glp_find_col(glp_prob *lp, const char *name)
+{ AVLNODE *node;
+ int j = 0;
+ if (lp->c_tree == NULL)
+ xerror("glp_find_col: column name index does not exist\n");
+ if (!(name == NULL || name[0] == '\0' || strlen(name) > 255))
+ { node = avl_find_node(lp->c_tree, name);
+ if (node != NULL)
+ j = ((GLPCOL *)avl_get_node_link(node))->j;
+ }
+ return j;
+}
+
+/***********************************************************************
+* NAME
+*
+* glp_delete_index - delete the name index
+*
+* SYNOPSIS
+*
+* void glp_delete_index(glp_prob *lp);
+*
+* DESCRIPTION
+*
+* The routine glp_delete_index deletes the name index previously
+* created by the routine glp_create_index and frees the memory
+* allocated to this auxiliary data structure.
+*
+* This routine can be called at any time. If the name index does not
+* exist, the routine does nothing. */
+
+void glp_delete_index(glp_prob *lp)
+{ int i, j;
+ /* delete row name index */
+ if (lp->r_tree != NULL)
+ { for (i = 1; i <= lp->m; i++) lp->row[i]->node = NULL;
+ avl_delete_tree(lp->r_tree), lp->r_tree = NULL;
+ }
+ /* delete column name index */
+ if (lp->c_tree != NULL)
+ { for (j = 1; j <= lp->n; j++) lp->col[j]->node = NULL;
+ avl_delete_tree(lp->c_tree), lp->c_tree = NULL;
+ }
+ return;
+}
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/api/prob4.c b/test/monniaux/glpk-4.65/src/api/prob4.c
new file mode 100644
index 00000000..8c2b5ae5
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/api/prob4.c
@@ -0,0 +1,156 @@
+/* prob4.c (problem scaling routines) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* Copyright (C) 2000-2013 Andrew Makhorin, Department for Applied
+* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights
+* reserved. E-mail: <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 "env.h"
+#include "prob.h"
+
+/***********************************************************************
+* NAME
+*
+* glp_set_rii - set (change) row scale factor
+*
+* SYNOPSIS
+*
+* void glp_set_rii(glp_prob *lp, int i, double rii);
+*
+* DESCRIPTION
+*
+* The routine glp_set_rii sets (changes) the scale factor r[i,i] for
+* i-th row of the specified problem object. */
+
+void glp_set_rii(glp_prob *lp, int i, double rii)
+{ if (!(1 <= i && i <= lp->m))
+ xerror("glp_set_rii: i = %d; row number out of range\n", i);
+ if (rii <= 0.0)
+ xerror("glp_set_rii: i = %d; rii = %g; invalid scale factor\n",
+ i, rii);
+ if (lp->valid && lp->row[i]->rii != rii)
+ { GLPAIJ *aij;
+ for (aij = lp->row[i]->ptr; aij != NULL; aij = aij->r_next)
+ { if (aij->col->stat == GLP_BS)
+ { /* invalidate the basis factorization */
+ lp->valid = 0;
+ break;
+ }
+ }
+ }
+ lp->row[i]->rii = rii;
+ return;
+}
+
+/***********************************************************************
+* NAME
+*
+* glp_set sjj - set (change) column scale factor
+*
+* SYNOPSIS
+*
+* void glp_set_sjj(glp_prob *lp, int j, double sjj);
+*
+* DESCRIPTION
+*
+* The routine glp_set_sjj sets (changes) the scale factor s[j,j] for
+* j-th column of the specified problem object. */
+
+void glp_set_sjj(glp_prob *lp, int j, double sjj)
+{ if (!(1 <= j && j <= lp->n))
+ xerror("glp_set_sjj: j = %d; column number out of range\n", j);
+ if (sjj <= 0.0)
+ xerror("glp_set_sjj: j = %d; sjj = %g; invalid scale factor\n",
+ j, sjj);
+ if (lp->valid && lp->col[j]->sjj != sjj && lp->col[j]->stat ==
+ GLP_BS)
+ { /* invalidate the basis factorization */
+ lp->valid = 0;
+ }
+ lp->col[j]->sjj = sjj;
+ return;
+}
+
+/***********************************************************************
+* NAME
+*
+* glp_get_rii - retrieve row scale factor
+*
+* SYNOPSIS
+*
+* double glp_get_rii(glp_prob *lp, int i);
+*
+* RETURNS
+*
+* The routine glp_get_rii returns current scale factor r[i,i] for i-th
+* row of the specified problem object. */
+
+double glp_get_rii(glp_prob *lp, int i)
+{ if (!(1 <= i && i <= lp->m))
+ xerror("glp_get_rii: i = %d; row number out of range\n", i);
+ return lp->row[i]->rii;
+}
+
+/***********************************************************************
+* NAME
+*
+* glp_get_sjj - retrieve column scale factor
+*
+* SYNOPSIS
+*
+* double glp_get_sjj(glp_prob *lp, int j);
+*
+* RETURNS
+*
+* The routine glp_get_sjj returns current scale factor s[j,j] for j-th
+* column of the specified problem object. */
+
+double glp_get_sjj(glp_prob *lp, int j)
+{ if (!(1 <= j && j <= lp->n))
+ xerror("glp_get_sjj: j = %d; column number out of range\n", j);
+ return lp->col[j]->sjj;
+}
+
+/***********************************************************************
+* NAME
+*
+* glp_unscale_prob - unscale problem data
+*
+* SYNOPSIS
+*
+* void glp_unscale_prob(glp_prob *lp);
+*
+* DESCRIPTION
+*
+* The routine glp_unscale_prob performs unscaling of problem data for
+* the specified problem object.
+*
+* "Unscaling" means replacing the current scaling matrices R and S by
+* unity matrices that cancels the scaling effect. */
+
+void glp_unscale_prob(glp_prob *lp)
+{ int m = glp_get_num_rows(lp);
+ int n = glp_get_num_cols(lp);
+ int i, j;
+ for (i = 1; i <= m; i++) glp_set_rii(lp, i, 1.0);
+ for (j = 1; j <= n; j++) glp_set_sjj(lp, j, 1.0);
+ return;
+}
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/api/prob5.c b/test/monniaux/glpk-4.65/src/api/prob5.c
new file mode 100644
index 00000000..1c1d3160
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/api/prob5.c
@@ -0,0 +1,168 @@
+/* prob5.c (LP problem basis constructing routines) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* Copyright (C) 2000-2013 Andrew Makhorin, Department for Applied
+* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights
+* reserved. E-mail: <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 "env.h"
+#include "prob.h"
+
+/***********************************************************************
+* NAME
+*
+* glp_set_row_stat - set (change) row status
+*
+* SYNOPSIS
+*
+* void glp_set_row_stat(glp_prob *lp, int i, int stat);
+*
+* DESCRIPTION
+*
+* The routine glp_set_row_stat sets (changes) status of the auxiliary
+* variable associated with i-th row.
+*
+* The new status of the auxiliary variable should be specified by the
+* parameter stat as follows:
+*
+* GLP_BS - basic variable;
+* GLP_NL - non-basic variable;
+* GLP_NU - non-basic variable on its upper bound; if the variable is
+* not double-bounded, this means the same as GLP_NL (only in
+* case of this routine);
+* GLP_NF - the same as GLP_NL (only in case of this routine);
+* GLP_NS - the same as GLP_NL (only in case of this routine). */
+
+void glp_set_row_stat(glp_prob *lp, int i, int stat)
+{ GLPROW *row;
+ if (!(1 <= i && i <= lp->m))
+ xerror("glp_set_row_stat: i = %d; row number out of range\n",
+ i);
+ if (!(stat == GLP_BS || stat == GLP_NL || stat == GLP_NU ||
+ stat == GLP_NF || stat == GLP_NS))
+ xerror("glp_set_row_stat: i = %d; stat = %d; invalid status\n",
+ i, stat);
+ row = lp->row[i];
+ if (stat != GLP_BS)
+ { switch (row->type)
+ { case GLP_FR: stat = GLP_NF; break;
+ case GLP_LO: stat = GLP_NL; break;
+ case GLP_UP: stat = GLP_NU; break;
+ case GLP_DB: if (stat != GLP_NU) stat = GLP_NL; break;
+ case GLP_FX: stat = GLP_NS; break;
+ default: xassert(row != row);
+ }
+ }
+ if (row->stat == GLP_BS && stat != GLP_BS ||
+ row->stat != GLP_BS && stat == GLP_BS)
+ { /* invalidate the basis factorization */
+ lp->valid = 0;
+ }
+ row->stat = stat;
+ return;
+}
+
+/***********************************************************************
+* NAME
+*
+* glp_set_col_stat - set (change) column status
+*
+* SYNOPSIS
+*
+* void glp_set_col_stat(glp_prob *lp, int j, int stat);
+*
+* DESCRIPTION
+*
+* The routine glp_set_col_stat sets (changes) status of the structural
+* variable associated with j-th column.
+*
+* The new status of the structural variable should be specified by the
+* parameter stat as follows:
+*
+* GLP_BS - basic variable;
+* GLP_NL - non-basic variable;
+* GLP_NU - non-basic variable on its upper bound; if the variable is
+* not double-bounded, this means the same as GLP_NL (only in
+* case of this routine);
+* GLP_NF - the same as GLP_NL (only in case of this routine);
+* GLP_NS - the same as GLP_NL (only in case of this routine). */
+
+void glp_set_col_stat(glp_prob *lp, int j, int stat)
+{ GLPCOL *col;
+ if (!(1 <= j && j <= lp->n))
+ xerror("glp_set_col_stat: j = %d; column number out of range\n"
+ , j);
+ if (!(stat == GLP_BS || stat == GLP_NL || stat == GLP_NU ||
+ stat == GLP_NF || stat == GLP_NS))
+ xerror("glp_set_col_stat: j = %d; stat = %d; invalid status\n",
+ j, stat);
+ col = lp->col[j];
+ if (stat != GLP_BS)
+ { switch (col->type)
+ { case GLP_FR: stat = GLP_NF; break;
+ case GLP_LO: stat = GLP_NL; break;
+ case GLP_UP: stat = GLP_NU; break;
+ case GLP_DB: if (stat != GLP_NU) stat = GLP_NL; break;
+ case GLP_FX: stat = GLP_NS; break;
+ default: xassert(col != col);
+ }
+ }
+ if (col->stat == GLP_BS && stat != GLP_BS ||
+ col->stat != GLP_BS && stat == GLP_BS)
+ { /* invalidate the basis factorization */
+ lp->valid = 0;
+ }
+ col->stat = stat;
+ return;
+}
+
+/***********************************************************************
+* NAME
+*
+* glp_std_basis - construct standard initial LP basis
+*
+* SYNOPSIS
+*
+* void glp_std_basis(glp_prob *lp);
+*
+* DESCRIPTION
+*
+* The routine glp_std_basis builds the "standard" (trivial) initial
+* basis for the specified problem object.
+*
+* In the "standard" basis all auxiliary variables are basic, and all
+* structural variables are non-basic. */
+
+void glp_std_basis(glp_prob *lp)
+{ int i, j;
+ /* make all auxiliary variables basic */
+ for (i = 1; i <= lp->m; i++)
+ glp_set_row_stat(lp, i, GLP_BS);
+ /* make all structural variables non-basic */
+ for (j = 1; j <= lp->n; j++)
+ { GLPCOL *col = lp->col[j];
+ if (col->type == GLP_DB && fabs(col->lb) > fabs(col->ub))
+ glp_set_col_stat(lp, j, GLP_NU);
+ else
+ glp_set_col_stat(lp, j, GLP_NL);
+ }
+ return;
+}
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/api/prrngs.c b/test/monniaux/glpk-4.65/src/api/prrngs.c
new file mode 100644
index 00000000..41a141ff
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/api/prrngs.c
@@ -0,0 +1,302 @@
+/* prrngs.c (print sensitivity analysis report) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* Copyright (C) 2010-2016 Andrew Makhorin, Department for Applied
+* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights
+* reserved. E-mail: <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 "env.h"
+#include "prob.h"
+
+#define xfprintf glp_format
+
+static char *format(char buf[13+1], double x)
+{ /* format floating-point number in MPS/360-like style */
+ if (x == -DBL_MAX)
+ strcpy(buf, " -Inf");
+ else if (x == +DBL_MAX)
+ strcpy(buf, " +Inf");
+ else if (fabs(x) <= 999999.99998)
+ { sprintf(buf, "%13.5f", x);
+#if 1
+ if (strcmp(buf, " 0.00000") == 0 ||
+ strcmp(buf, " -0.00000") == 0)
+ strcpy(buf, " . ");
+ else if (memcmp(buf, " 0.", 8) == 0)
+ memcpy(buf, " .", 8);
+ else if (memcmp(buf, " -0.", 8) == 0)
+ memcpy(buf, " -.", 8);
+#endif
+ }
+ else
+ sprintf(buf, "%13.6g", x);
+ return buf;
+}
+
+int glp_print_ranges(glp_prob *P, int len, const int list[],
+ int flags, const char *fname)
+{ /* print sensitivity analysis report */
+ glp_file *fp = NULL;
+ GLPROW *row;
+ GLPCOL *col;
+ int m, n, pass, k, t, numb, type, stat, var1, var2, count, page,
+ ret;
+ double lb, ub, slack, coef, prim, dual, value1, value2, coef1,
+ coef2, obj1, obj2;
+ const char *name, *limit;
+ char buf[13+1];
+ /* sanity checks */
+#if 0 /* 04/IV-2016 */
+ if (P == NULL || P->magic != GLP_PROB_MAGIC)
+ xerror("glp_print_ranges: P = %p; invalid problem object\n",
+ P);
+#endif
+ m = P->m, n = P->n;
+ if (len < 0)
+ xerror("glp_print_ranges: len = %d; invalid list length\n",
+ len);
+ if (len > 0)
+ { if (list == NULL)
+ xerror("glp_print_ranges: list = %p: invalid parameter\n",
+ list);
+ for (t = 1; t <= len; t++)
+ { k = list[t];
+ if (!(1 <= k && k <= m+n))
+ xerror("glp_print_ranges: list[%d] = %d; row/column numb"
+ "er out of range\n", t, k);
+ }
+ }
+ if (flags != 0)
+ xerror("glp_print_ranges: flags = %d; invalid parameter\n",
+ flags);
+ if (fname == NULL)
+ xerror("glp_print_ranges: fname = %p; invalid parameter\n",
+ fname);
+ if (glp_get_status(P) != GLP_OPT)
+ { xprintf("glp_print_ranges: optimal basic solution required\n");
+ ret = 1;
+ goto done;
+ }
+ if (!glp_bf_exists(P))
+ { xprintf("glp_print_ranges: basis factorization required\n");
+ ret = 2;
+ goto done;
+ }
+ /* start reporting */
+ xprintf("Write sensitivity analysis report to '%s'...\n", fname);
+ fp = glp_open(fname, "w");
+ if (fp == NULL)
+ { xprintf("Unable to create '%s' - %s\n", fname, get_err_msg());
+ ret = 3;
+ goto done;
+ }
+ page = count = 0;
+ for (pass = 1; pass <= 2; pass++)
+ for (t = 1; t <= (len == 0 ? m+n : len); t++)
+ { if (t == 1) count = 0;
+ k = (len == 0 ? t : list[t]);
+ if (pass == 1 && k > m || pass == 2 && k <= m)
+ continue;
+ if (count == 0)
+ { xfprintf(fp, "GLPK %-4s - SENSITIVITY ANALYSIS REPORT%73sPa"
+ "ge%4d\n", glp_version(), "", ++page);
+ xfprintf(fp, "\n");
+ xfprintf(fp, "%-12s%s\n", "Problem:",
+ P->name == NULL ? "" : P->name);
+ xfprintf(fp, "%-12s%s%s%.10g (%s)\n", "Objective:",
+ P->obj == NULL ? "" : P->obj,
+ P->obj == NULL ? "" : " = ", P->obj_val,
+ P->dir == GLP_MIN ? "MINimum" :
+ P->dir == GLP_MAX ? "MAXimum" : "???");
+ xfprintf(fp, "\n");
+ xfprintf(fp, "%6s %-12s %2s %13s %13s %13s %13s %13s %13s "
+ "%s\n", "No.", pass == 1 ? "Row name" : "Column name",
+ "St", "Activity", pass == 1 ? "Slack" : "Obj coef",
+ "Lower bound", "Activity", "Obj coef", "Obj value at",
+ "Limiting");
+ xfprintf(fp, "%6s %-12s %2s %13s %13s %13s %13s %13s %13s "
+ "%s\n", "", "", "", "", "Marginal", "Upper bound",
+ "range", "range", "break point", "variable");
+ xfprintf(fp, "------ ------------ -- ------------- --------"
+ "----- ------------- ------------- ------------- ------"
+ "------- ------------\n");
+ }
+ if (pass == 1)
+ { numb = k;
+ xassert(1 <= numb && numb <= m);
+ row = P->row[numb];
+ name = row->name;
+ type = row->type;
+ lb = glp_get_row_lb(P, numb);
+ ub = glp_get_row_ub(P, numb);
+ coef = 0.0;
+ stat = row->stat;
+ prim = row->prim;
+ if (type == GLP_FR)
+ slack = - prim;
+ else if (type == GLP_LO)
+ slack = lb - prim;
+ else if (type == GLP_UP || type == GLP_DB || type == GLP_FX)
+ slack = ub - prim;
+ dual = row->dual;
+ }
+ else
+ { numb = k - m;
+ xassert(1 <= numb && numb <= n);
+ col = P->col[numb];
+ name = col->name;
+ lb = glp_get_col_lb(P, numb);
+ ub = glp_get_col_ub(P, numb);
+ coef = col->coef;
+ stat = col->stat;
+ prim = col->prim;
+ slack = 0.0;
+ dual = col->dual;
+ }
+ if (stat != GLP_BS)
+ { glp_analyze_bound(P, k, &value1, &var1, &value2, &var2);
+ if (stat == GLP_NF)
+ coef1 = coef2 = coef;
+ else if (stat == GLP_NS)
+ coef1 = -DBL_MAX, coef2 = +DBL_MAX;
+ else if (stat == GLP_NL && P->dir == GLP_MIN ||
+ stat == GLP_NU && P->dir == GLP_MAX)
+ coef1 = coef - dual, coef2 = +DBL_MAX;
+ else
+ coef1 = -DBL_MAX, coef2 = coef - dual;
+ if (value1 == -DBL_MAX)
+ { if (dual < -1e-9)
+ obj1 = +DBL_MAX;
+ else if (dual > +1e-9)
+ obj1 = -DBL_MAX;
+ else
+ obj1 = P->obj_val;
+ }
+ else
+ obj1 = P->obj_val + dual * (value1 - prim);
+ if (value2 == +DBL_MAX)
+ { if (dual < -1e-9)
+ obj2 = -DBL_MAX;
+ else if (dual > +1e-9)
+ obj2 = +DBL_MAX;
+ else
+ obj2 = P->obj_val;
+ }
+ else
+ obj2 = P->obj_val + dual * (value2 - prim);
+ }
+ else
+ { glp_analyze_coef(P, k, &coef1, &var1, &value1, &coef2,
+ &var2, &value2);
+ if (coef1 == -DBL_MAX)
+ { if (prim < -1e-9)
+ obj1 = +DBL_MAX;
+ else if (prim > +1e-9)
+ obj1 = -DBL_MAX;
+ else
+ obj1 = P->obj_val;
+ }
+ else
+ obj1 = P->obj_val + (coef1 - coef) * prim;
+ if (coef2 == +DBL_MAX)
+ { if (prim < -1e-9)
+ obj2 = -DBL_MAX;
+ else if (prim > +1e-9)
+ obj2 = +DBL_MAX;
+ else
+ obj2 = P->obj_val;
+ }
+ else
+ obj2 = P->obj_val + (coef2 - coef) * prim;
+ }
+ /*** first line ***/
+ /* row/column number */
+ xfprintf(fp, "%6d", numb);
+ /* row/column name */
+ xfprintf(fp, " %-12.12s", name == NULL ? "" : name);
+ if (name != NULL && strlen(name) > 12)
+ xfprintf(fp, "%s\n%6s %12s", name+12, "", "");
+ /* row/column status */
+ xfprintf(fp, " %2s",
+ stat == GLP_BS ? "BS" : stat == GLP_NL ? "NL" :
+ stat == GLP_NU ? "NU" : stat == GLP_NF ? "NF" :
+ stat == GLP_NS ? "NS" : "??");
+ /* row/column activity */
+ xfprintf(fp, " %s", format(buf, prim));
+ /* row slack, column objective coefficient */
+ xfprintf(fp, " %s", format(buf, k <= m ? slack : coef));
+ /* row/column lower bound */
+ xfprintf(fp, " %s", format(buf, lb));
+ /* row/column activity range */
+ xfprintf(fp, " %s", format(buf, value1));
+ /* row/column objective coefficient range */
+ xfprintf(fp, " %s", format(buf, coef1));
+ /* objective value at break point */
+ xfprintf(fp, " %s", format(buf, obj1));
+ /* limiting variable name */
+ if (var1 != 0)
+ { if (var1 <= m)
+ limit = glp_get_row_name(P, var1);
+ else
+ limit = glp_get_col_name(P, var1 - m);
+ if (limit != NULL)
+ xfprintf(fp, " %s", limit);
+ }
+ xfprintf(fp, "\n");
+ /*** second line ***/
+ xfprintf(fp, "%6s %-12s %2s %13s", "", "", "", "");
+ /* row/column reduced cost */
+ xfprintf(fp, " %s", format(buf, dual));
+ /* row/column upper bound */
+ xfprintf(fp, " %s", format(buf, ub));
+ /* row/column activity range */
+ xfprintf(fp, " %s", format(buf, value2));
+ /* row/column objective coefficient range */
+ xfprintf(fp, " %s", format(buf, coef2));
+ /* objective value at break point */
+ xfprintf(fp, " %s", format(buf, obj2));
+ /* limiting variable name */
+ if (var2 != 0)
+ { if (var2 <= m)
+ limit = glp_get_row_name(P, var2);
+ else
+ limit = glp_get_col_name(P, var2 - m);
+ if (limit != NULL)
+ xfprintf(fp, " %s", limit);
+ }
+ xfprintf(fp, "\n");
+ xfprintf(fp, "\n");
+ /* print 10 items per page */
+ count = (count + 1) % 10;
+ }
+ xfprintf(fp, "End of report\n");
+#if 0 /* FIXME */
+ xfflush(fp);
+#endif
+ if (glp_ioerr(fp))
+ { xprintf("Write error on '%s' - %s\n", fname, get_err_msg());
+ ret = 4;
+ goto done;
+ }
+ ret = 0;
+done: if (fp != NULL) glp_close(fp);
+ return ret;
+}
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/api/prsol.c b/test/monniaux/glpk-4.65/src/api/prsol.c
new file mode 100644
index 00000000..d785dc2e
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/api/prsol.c
@@ -0,0 +1,202 @@
+/* prsol.c (write basic solution in printable format) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* Copyright (C) 2009-2016 Andrew Makhorin, Department for Applied
+* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights
+* reserved. E-mail: <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 "env.h"
+#include "prob.h"
+
+#define xfprintf glp_format
+
+int glp_print_sol(glp_prob *P, const char *fname)
+{ /* write basic solution in printable format */
+ glp_file *fp;
+ GLPROW *row;
+ GLPCOL *col;
+ int i, j, t, ae_ind, re_ind, ret;
+ double ae_max, re_max;
+ xprintf("Writing basic solution to '%s'...\n", fname);
+ fp = glp_open(fname, "w");
+ if (fp == NULL)
+ { xprintf("Unable to create '%s' - %s\n", fname, get_err_msg());
+ ret = 1;
+ goto done;
+ }
+ xfprintf(fp, "%-12s%s\n", "Problem:",
+ P->name == NULL ? "" : P->name);
+ xfprintf(fp, "%-12s%d\n", "Rows:", P->m);
+ xfprintf(fp, "%-12s%d\n", "Columns:", P->n);
+ xfprintf(fp, "%-12s%d\n", "Non-zeros:", P->nnz);
+ t = glp_get_status(P);
+ xfprintf(fp, "%-12s%s\n", "Status:",
+ t == GLP_OPT ? "OPTIMAL" :
+ t == GLP_FEAS ? "FEASIBLE" :
+ t == GLP_INFEAS ? "INFEASIBLE (INTERMEDIATE)" :
+ t == GLP_NOFEAS ? "INFEASIBLE (FINAL)" :
+ t == GLP_UNBND ? "UNBOUNDED" :
+ t == GLP_UNDEF ? "UNDEFINED" : "???");
+ xfprintf(fp, "%-12s%s%s%.10g (%s)\n", "Objective:",
+ P->obj == NULL ? "" : P->obj,
+ P->obj == NULL ? "" : " = ", P->obj_val,
+ P->dir == GLP_MIN ? "MINimum" :
+ P->dir == GLP_MAX ? "MAXimum" : "???");
+ xfprintf(fp, "\n");
+ xfprintf(fp, " No. Row name St Activity Lower bound "
+ " Upper bound Marginal\n");
+ xfprintf(fp, "------ ------------ -- ------------- ------------- "
+ "------------- -------------\n");
+ for (i = 1; i <= P->m; i++)
+ { row = P->row[i];
+ xfprintf(fp, "%6d ", i);
+ if (row->name == NULL || strlen(row->name) <= 12)
+ xfprintf(fp, "%-12s ", row->name == NULL ? "" : row->name);
+ else
+ xfprintf(fp, "%s\n%20s", row->name, "");
+ xfprintf(fp, "%s ",
+ row->stat == GLP_BS ? "B " :
+ row->stat == GLP_NL ? "NL" :
+ row->stat == GLP_NU ? "NU" :
+ row->stat == GLP_NF ? "NF" :
+ row->stat == GLP_NS ? "NS" : "??");
+ xfprintf(fp, "%13.6g ",
+ fabs(row->prim) <= 1e-9 ? 0.0 : row->prim);
+ if (row->type == GLP_LO || row->type == GLP_DB ||
+ row->type == GLP_FX)
+ xfprintf(fp, "%13.6g ", row->lb);
+ else
+ xfprintf(fp, "%13s ", "");
+ if (row->type == GLP_UP || row->type == GLP_DB)
+ xfprintf(fp, "%13.6g ", row->ub);
+ else
+ xfprintf(fp, "%13s ", row->type == GLP_FX ? "=" : "");
+ if (row->stat != GLP_BS)
+ { if (fabs(row->dual) <= 1e-9)
+ xfprintf(fp, "%13s", "< eps");
+ else
+ xfprintf(fp, "%13.6g ", row->dual);
+ }
+ xfprintf(fp, "\n");
+ }
+ xfprintf(fp, "\n");
+ xfprintf(fp, " No. Column name St Activity Lower bound "
+ " Upper bound Marginal\n");
+ xfprintf(fp, "------ ------------ -- ------------- ------------- "
+ "------------- -------------\n");
+ for (j = 1; j <= P->n; j++)
+ { col = P->col[j];
+ xfprintf(fp, "%6d ", j);
+ if (col->name == NULL || strlen(col->name) <= 12)
+ xfprintf(fp, "%-12s ", col->name == NULL ? "" : col->name);
+ else
+ xfprintf(fp, "%s\n%20s", col->name, "");
+ xfprintf(fp, "%s ",
+ col->stat == GLP_BS ? "B " :
+ col->stat == GLP_NL ? "NL" :
+ col->stat == GLP_NU ? "NU" :
+ col->stat == GLP_NF ? "NF" :
+ col->stat == GLP_NS ? "NS" : "??");
+ xfprintf(fp, "%13.6g ",
+ fabs(col->prim) <= 1e-9 ? 0.0 : col->prim);
+ if (col->type == GLP_LO || col->type == GLP_DB ||
+ col->type == GLP_FX)
+ xfprintf(fp, "%13.6g ", col->lb);
+ else
+ xfprintf(fp, "%13s ", "");
+ if (col->type == GLP_UP || col->type == GLP_DB)
+ xfprintf(fp, "%13.6g ", col->ub);
+ else
+ xfprintf(fp, "%13s ", col->type == GLP_FX ? "=" : "");
+ if (col->stat != GLP_BS)
+ { if (fabs(col->dual) <= 1e-9)
+ xfprintf(fp, "%13s", "< eps");
+ else
+ xfprintf(fp, "%13.6g ", col->dual);
+ }
+ xfprintf(fp, "\n");
+ }
+ xfprintf(fp, "\n");
+ xfprintf(fp, "Karush-Kuhn-Tucker optimality conditions:\n");
+ xfprintf(fp, "\n");
+ glp_check_kkt(P, GLP_SOL, GLP_KKT_PE, &ae_max, &ae_ind, &re_max,
+ &re_ind);
+ xfprintf(fp, "KKT.PE: max.abs.err = %.2e on row %d\n",
+ ae_max, ae_ind);
+ xfprintf(fp, " max.rel.err = %.2e on row %d\n",
+ re_max, re_ind);
+ xfprintf(fp, "%8s%s\n", "",
+ re_max <= 1e-9 ? "High quality" :
+ re_max <= 1e-6 ? "Medium quality" :
+ re_max <= 1e-3 ? "Low quality" : "PRIMAL SOLUTION IS WRONG");
+ xfprintf(fp, "\n");
+ glp_check_kkt(P, GLP_SOL, GLP_KKT_PB, &ae_max, &ae_ind, &re_max,
+ &re_ind);
+ xfprintf(fp, "KKT.PB: max.abs.err = %.2e on %s %d\n",
+ ae_max, ae_ind <= P->m ? "row" : "column",
+ ae_ind <= P->m ? ae_ind : ae_ind - P->m);
+ xfprintf(fp, " max.rel.err = %.2e on %s %d\n",
+ re_max, re_ind <= P->m ? "row" : "column",
+ re_ind <= P->m ? re_ind : re_ind - P->m);
+ xfprintf(fp, "%8s%s\n", "",
+ re_max <= 1e-9 ? "High quality" :
+ re_max <= 1e-6 ? "Medium quality" :
+ re_max <= 1e-3 ? "Low quality" : "PRIMAL SOLUTION IS INFEASIBL"
+ "E");
+ xfprintf(fp, "\n");
+ glp_check_kkt(P, GLP_SOL, GLP_KKT_DE, &ae_max, &ae_ind, &re_max,
+ &re_ind);
+ xfprintf(fp, "KKT.DE: max.abs.err = %.2e on column %d\n",
+ ae_max, ae_ind == 0 ? 0 : ae_ind - P->m);
+ xfprintf(fp, " max.rel.err = %.2e on column %d\n",
+ re_max, re_ind == 0 ? 0 : re_ind - P->m);
+ xfprintf(fp, "%8s%s\n", "",
+ re_max <= 1e-9 ? "High quality" :
+ re_max <= 1e-6 ? "Medium quality" :
+ re_max <= 1e-3 ? "Low quality" : "DUAL SOLUTION IS WRONG");
+ xfprintf(fp, "\n");
+ glp_check_kkt(P, GLP_SOL, GLP_KKT_DB, &ae_max, &ae_ind, &re_max,
+ &re_ind);
+ xfprintf(fp, "KKT.DB: max.abs.err = %.2e on %s %d\n",
+ ae_max, ae_ind <= P->m ? "row" : "column",
+ ae_ind <= P->m ? ae_ind : ae_ind - P->m);
+ xfprintf(fp, " max.rel.err = %.2e on %s %d\n",
+ re_max, re_ind <= P->m ? "row" : "column",
+ re_ind <= P->m ? re_ind : re_ind - P->m);
+ xfprintf(fp, "%8s%s\n", "",
+ re_max <= 1e-9 ? "High quality" :
+ re_max <= 1e-6 ? "Medium quality" :
+ re_max <= 1e-3 ? "Low quality" : "DUAL SOLUTION IS INFEASIBLE")
+ ;
+ xfprintf(fp, "\n");
+ xfprintf(fp, "End of output\n");
+#if 0 /* FIXME */
+ xfflush(fp);
+#endif
+ if (glp_ioerr(fp))
+ { xprintf("Write error on '%s' - %s\n", fname, get_err_msg());
+ ret = 1;
+ goto done;
+ }
+ ret = 0;
+done: if (fp != NULL) glp_close(fp);
+ return ret;
+}
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/api/rdasn.c b/test/monniaux/glpk-4.65/src/api/rdasn.c
new file mode 100644
index 00000000..05dcb9fc
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/api/rdasn.c
@@ -0,0 +1,164 @@
+/* rdasn.c (read assignment problem data in DIMACS format) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* Copyright (C) 2009-2016 Andrew Makhorin, Department for Applied
+* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights
+* reserved. E-mail: <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 "dimacs.h"
+#include "glpk.h"
+#include "misc.h"
+
+#define error dmx_error
+#define warning dmx_warning
+#define read_char dmx_read_char
+#define read_designator dmx_read_designator
+#define read_field dmx_read_field
+#define end_of_line dmx_end_of_line
+#define check_int dmx_check_int
+
+/***********************************************************************
+* NAME
+*
+* glp_read_asnprob - read assignment problem data in DIMACS format
+*
+* SYNOPSIS
+*
+* int glp_read_asnprob(glp_graph *G, int v_set, int a_cost,
+* const char *fname);
+*
+* DESCRIPTION
+*
+* The routine glp_read_asnprob reads assignment problem data in DIMACS
+* format from a text file.
+*
+* RETURNS
+*
+* If the operation was successful, the routine returns zero. Otherwise
+* it prints an error message and returns non-zero. */
+
+int glp_read_asnprob(glp_graph *G, int v_set, int a_cost, const char
+ *fname)
+{ DMX _csa, *csa = &_csa;
+ glp_vertex *v;
+ glp_arc *a;
+ int nv, na, n1, i, j, k, ret = 0;
+ double cost;
+ char *flag = NULL;
+ if (v_set >= 0 && v_set > G->v_size - (int)sizeof(int))
+ xerror("glp_read_asnprob: v_set = %d; invalid offset\n",
+ v_set);
+ if (a_cost >= 0 && a_cost > G->a_size - (int)sizeof(double))
+ xerror("glp_read_asnprob: a_cost = %d; invalid offset\n",
+ a_cost);
+ glp_erase_graph(G, G->v_size, G->a_size);
+ if (setjmp(csa->jump))
+ { ret = 1;
+ goto done;
+ }
+ csa->fname = fname;
+ csa->fp = NULL;
+ csa->count = 0;
+ csa->c = '\n';
+ csa->field[0] = '\0';
+ csa->empty = csa->nonint = 0;
+ xprintf("Reading assignment problem data from '%s'...\n", fname);
+ csa->fp = glp_open(fname, "r");
+ if (csa->fp == NULL)
+ { xprintf("Unable to open '%s' - %s\n", fname, get_err_msg());
+ longjmp(csa->jump, 1);
+ }
+ /* read problem line */
+ read_designator(csa);
+ if (strcmp(csa->field, "p") != 0)
+ error(csa, "problem line missing or invalid");
+ read_field(csa);
+ if (strcmp(csa->field, "asn") != 0)
+ error(csa, "wrong problem designator; 'asn' expected");
+ read_field(csa);
+ if (!(str2int(csa->field, &nv) == 0 && nv >= 0))
+ error(csa, "number of nodes missing or invalid");
+ read_field(csa);
+ if (!(str2int(csa->field, &na) == 0 && na >= 0))
+ error(csa, "number of arcs missing or invalid");
+ if (nv > 0) glp_add_vertices(G, nv);
+ end_of_line(csa);
+ /* read node descriptor lines */
+ flag = xcalloc(1+nv, sizeof(char));
+ memset(&flag[1], 0, nv * sizeof(char));
+ n1 = 0;
+ for (;;)
+ { read_designator(csa);
+ if (strcmp(csa->field, "n") != 0) break;
+ read_field(csa);
+ if (str2int(csa->field, &i) != 0)
+ error(csa, "node number missing or invalid");
+ if (!(1 <= i && i <= nv))
+ error(csa, "node number %d out of range", i);
+ if (flag[i])
+ error(csa, "duplicate descriptor of node %d", i);
+ flag[i] = 1, n1++;
+ end_of_line(csa);
+ }
+ xprintf(
+ "Assignment problem has %d + %d = %d node%s and %d arc%s\n",
+ n1, nv - n1, nv, nv == 1 ? "" : "s", na, na == 1 ? "" : "s");
+ if (v_set >= 0)
+ { for (i = 1; i <= nv; i++)
+ { v = G->v[i];
+ k = (flag[i] ? 0 : 1);
+ memcpy((char *)v->data + v_set, &k, sizeof(int));
+ }
+ }
+ /* read arc descriptor lines */
+ for (k = 1; k <= na; k++)
+ { if (k > 1) read_designator(csa);
+ if (strcmp(csa->field, "a") != 0)
+ error(csa, "wrong line designator; 'a' expected");
+ read_field(csa);
+ if (str2int(csa->field, &i) != 0)
+ error(csa, "starting node number missing or invalid");
+ if (!(1 <= i && i <= nv))
+ error(csa, "starting node number %d out of range", i);
+ if (!flag[i])
+ error(csa, "node %d cannot be a starting node", i);
+ read_field(csa);
+ if (str2int(csa->field, &j) != 0)
+ error(csa, "ending node number missing or invalid");
+ if (!(1 <= j && j <= nv))
+ error(csa, "ending node number %d out of range", j);
+ if (flag[j])
+ error(csa, "node %d cannot be an ending node", j);
+ read_field(csa);
+ if (str2num(csa->field, &cost) != 0)
+ error(csa, "arc cost missing or invalid");
+ check_int(csa, cost);
+ a = glp_add_arc(G, i, j);
+ if (a_cost >= 0)
+ memcpy((char *)a->data + a_cost, &cost, sizeof(double));
+ end_of_line(csa);
+ }
+ xprintf("%d lines were read\n", csa->count);
+done: if (ret) glp_erase_graph(G, G->v_size, G->a_size);
+ if (csa->fp != NULL) glp_close(csa->fp);
+ if (flag != NULL) xfree(flag);
+ return ret;
+}
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/api/rdcc.c b/test/monniaux/glpk-4.65/src/api/rdcc.c
new file mode 100644
index 00000000..c63d60d8
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/api/rdcc.c
@@ -0,0 +1,162 @@
+/* rdcc.c (read graph in DIMACS clique/coloring format) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* Copyright (C) 2009-2016 Andrew Makhorin, Department for Applied
+* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights
+* reserved. E-mail: <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 "dimacs.h"
+#include "glpk.h"
+#include "misc.h"
+
+#define error dmx_error
+#define warning dmx_warning
+#define read_char dmx_read_char
+#define read_designator dmx_read_designator
+#define read_field dmx_read_field
+#define end_of_line dmx_end_of_line
+#define check_int dmx_check_int
+
+/***********************************************************************
+* NAME
+*
+* glp_read_ccdata - read graph in DIMACS clique/coloring format
+*
+* SYNOPSIS
+*
+* int glp_read_ccdata(glp_graph *G, int v_wgt, const char *fname);
+*
+* DESCRIPTION
+*
+* The routine glp_read_ccdata reads an (undirected) graph in DIMACS
+* clique/coloring format from a text file.
+*
+* RETURNS
+*
+* If the operation was successful, the routine returns zero. Otherwise
+* it prints an error message and returns non-zero. */
+
+int glp_read_ccdata(glp_graph *G, int v_wgt, const char *fname)
+{ DMX _csa, *csa = &_csa;
+ glp_vertex *v;
+ int i, j, k, nv, ne, ret = 0;
+ double w;
+ char *flag = NULL;
+ if (v_wgt >= 0 && v_wgt > G->v_size - (int)sizeof(double))
+ xerror("glp_read_ccdata: v_wgt = %d; invalid offset\n",
+ v_wgt);
+ glp_erase_graph(G, G->v_size, G->a_size);
+ if (setjmp(csa->jump))
+ { ret = 1;
+ goto done;
+ }
+ csa->fname = fname;
+ csa->fp = NULL;
+ csa->count = 0;
+ csa->c = '\n';
+ csa->field[0] = '\0';
+ csa->empty = csa->nonint = 0;
+ xprintf("Reading graph from '%s'...\n", fname);
+ csa->fp = glp_open(fname, "r");
+ if (csa->fp == NULL)
+ { xprintf("Unable to open '%s' - %s\n", fname, get_err_msg());
+ longjmp(csa->jump, 1);
+ }
+ /* read problem line */
+ read_designator(csa);
+ if (strcmp(csa->field, "p") != 0)
+ error(csa, "problem line missing or invalid");
+ read_field(csa);
+ if (strcmp(csa->field, "edge") != 0)
+ error(csa, "wrong problem designator; 'edge' expected");
+ read_field(csa);
+ if (!(str2int(csa->field, &nv) == 0 && nv >= 0))
+ error(csa, "number of vertices missing or invalid");
+ read_field(csa);
+ if (!(str2int(csa->field, &ne) == 0 && ne >= 0))
+ error(csa, "number of edges missing or invalid");
+ xprintf("Graph has %d vert%s and %d edge%s\n",
+ nv, nv == 1 ? "ex" : "ices", ne, ne == 1 ? "" : "s");
+ if (nv > 0) glp_add_vertices(G, nv);
+ end_of_line(csa);
+ /* read node descriptor lines */
+ flag = xcalloc(1+nv, sizeof(char));
+ memset(&flag[1], 0, nv * sizeof(char));
+ if (v_wgt >= 0)
+ { w = 1.0;
+ for (i = 1; i <= nv; i++)
+ { v = G->v[i];
+ memcpy((char *)v->data + v_wgt, &w, sizeof(double));
+ }
+ }
+ for (;;)
+ { read_designator(csa);
+ if (strcmp(csa->field, "n") != 0) break;
+ read_field(csa);
+ if (str2int(csa->field, &i) != 0)
+ error(csa, "vertex number missing or invalid");
+ if (!(1 <= i && i <= nv))
+ error(csa, "vertex number %d out of range", i);
+ if (flag[i])
+ error(csa, "duplicate descriptor of vertex %d", i);
+ read_field(csa);
+ if (str2num(csa->field, &w) != 0)
+ error(csa, "vertex weight missing or invalid");
+ check_int(csa, w);
+ if (v_wgt >= 0)
+ { v = G->v[i];
+ memcpy((char *)v->data + v_wgt, &w, sizeof(double));
+ }
+ flag[i] = 1;
+ end_of_line(csa);
+ }
+ xfree(flag), flag = NULL;
+ /* read edge descriptor lines */
+ for (k = 1; k <= ne; k++)
+ { if (k > 1) read_designator(csa);
+ if (strcmp(csa->field, "e") != 0)
+ error(csa, "wrong line designator; 'e' expected");
+ read_field(csa);
+ if (str2int(csa->field, &i) != 0)
+ error(csa, "first vertex number missing or invalid");
+ if (!(1 <= i && i <= nv))
+ error(csa, "first vertex number %d out of range", i);
+ read_field(csa);
+ if (str2int(csa->field, &j) != 0)
+ error(csa, "second vertex number missing or invalid");
+ if (!(1 <= j && j <= nv))
+ error(csa, "second vertex number %d out of range", j);
+ glp_add_arc(G, i, j);
+ end_of_line(csa);
+ }
+ xprintf("%d lines were read\n", csa->count);
+done: if (ret) glp_erase_graph(G, G->v_size, G->a_size);
+ if (csa->fp != NULL) glp_close(csa->fp);
+ if (flag != NULL) xfree(flag);
+ return ret;
+}
+
+/**********************************************************************/
+
+int glp_read_graph(glp_graph *G, const char *fname)
+{ return
+ glp_read_ccdata(G, -1, fname);
+}
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/api/rdcnf.c b/test/monniaux/glpk-4.65/src/api/rdcnf.c
new file mode 100644
index 00000000..acab50fe
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/api/rdcnf.c
@@ -0,0 +1,136 @@
+/* rdcnf.c (read CNF-SAT problem data in DIMACS format) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* Copyright (C) 2010-2016 Andrew Makhorin, Department for Applied
+* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights
+* reserved. E-mail: <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 "dimacs.h"
+#include "misc.h"
+#include "prob.h"
+
+#define xfprintf glp_format
+#define error dmx_error
+#define warning dmx_warning
+#define read_char dmx_read_char
+#define read_designator dmx_read_designator
+#define read_field dmx_read_field
+#define end_of_line dmx_end_of_line
+#define check_int dmx_check_int
+
+int glp_read_cnfsat(glp_prob *P, const char *fname)
+{ /* read CNF-SAT problem data in DIMACS format */
+ DMX _csa, *csa = &_csa;
+ int m, n, i, j, len, neg, rhs, ret = 0, *ind = NULL;
+ double *val = NULL;
+ char *map = NULL;
+#if 0 /* 04/IV-2016 */
+ if (P == NULL || P->magic != GLP_PROB_MAGIC)
+ xerror("glp_read_cnfsat: P = %p; invalid problem object\n",
+ P);
+#endif
+ if (fname == NULL)
+ xerror("glp_read_cnfsat: fname = %p; invalid parameter\n",
+ fname);
+ glp_erase_prob(P);
+ if (setjmp(csa->jump))
+ { ret = 1;
+ goto done;
+ }
+ csa->fname = fname;
+ csa->fp = NULL;
+ csa->count = 0;
+ csa->c = '\n';
+ csa->field[0] = '\0';
+ csa->empty = csa->nonint = 0;
+ xprintf("Reading CNF-SAT problem data from '%s'...\n", fname);
+ csa->fp = glp_open(fname, "r");
+ if (csa->fp == NULL)
+ { xprintf("Unable to open '%s' - %s\n", fname, get_err_msg());
+ longjmp(csa->jump, 1);
+ }
+ /* read problem line */
+ read_designator(csa);
+ if (strcmp(csa->field, "p") != 0)
+ error(csa, "problem line missing or invalid");
+ read_field(csa);
+ if (strcmp(csa->field, "cnf") != 0)
+ error(csa, "wrong problem designator; 'cnf' expected\n");
+ read_field(csa);
+ if (!(str2int(csa->field, &n) == 0 && n >= 0))
+ error(csa, "number of variables missing or invalid\n");
+ read_field(csa);
+ if (!(str2int(csa->field, &m) == 0 && m >= 0))
+ error(csa, "number of clauses missing or invalid\n");
+ xprintf("Instance has %d variable%s and %d clause%s\n",
+ n, n == 1 ? "" : "s", m, m == 1 ? "" : "s");
+ end_of_line(csa);
+ if (m > 0)
+ glp_add_rows(P, m);
+ if (n > 0)
+ { glp_add_cols(P, n);
+ for (j = 1; j <= n; j++)
+ glp_set_col_kind(P, j, GLP_BV);
+ }
+ /* allocate working arrays */
+ ind = xcalloc(1+n, sizeof(int));
+ val = xcalloc(1+n, sizeof(double));
+ map = xcalloc(1+n, sizeof(char));
+ for (j = 1; j <= n; j++) map[j] = 0;
+ /* read clauses */
+ for (i = 1; i <= m; i++)
+ { /* read i-th clause */
+ len = 0, rhs = 1;
+ for (;;)
+ { /* skip white-space characters */
+ while (csa->c == ' ' || csa->c == '\n')
+ read_char(csa);
+ /* read term */
+ read_field(csa);
+ if (str2int(csa->field, &j) != 0)
+ error(csa, "variable number missing or invalid\n");
+ if (j > 0)
+ neg = 0;
+ else if (j < 0)
+ neg = 1, j = -j, rhs--;
+ else
+ break;
+ if (!(1 <= j && j <= n))
+ error(csa, "variable number out of range\n");
+ if (map[j])
+ error(csa, "duplicate variable number\n");
+ len++, ind[len] = j, val[len] = (neg ? -1.0 : +1.0);
+ map[j] = 1;
+ }
+ glp_set_row_bnds(P, i, GLP_LO, (double)rhs, 0.0);
+ glp_set_mat_row(P, i, len, ind, val);
+ while (len > 0) map[ind[len--]] = 0;
+ }
+ xprintf("%d lines were read\n", csa->count);
+ /* problem data has been successfully read */
+ glp_sort_matrix(P);
+done: if (csa->fp != NULL) glp_close(csa->fp);
+ if (ind != NULL) xfree(ind);
+ if (val != NULL) xfree(val);
+ if (map != NULL) xfree(map);
+ if (ret) glp_erase_prob(P);
+ return ret;
+}
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/api/rdipt.c b/test/monniaux/glpk-4.65/src/api/rdipt.c
new file mode 100644
index 00000000..aaf8e9d4
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/api/rdipt.c
@@ -0,0 +1,185 @@
+/* rdipt.c (read interior-point solution in GLPK format) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* Copyright (C) 2010-2016 Andrew Makhorin, Department for Applied
+* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights
+* reserved. E-mail: <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 "dimacs.h"
+#include "env.h"
+#include "misc.h"
+#include "prob.h"
+
+/***********************************************************************
+* NAME
+*
+* glp_read_ipt - read interior-point solution in GLPK format
+*
+* SYNOPSIS
+*
+* int glp_read_ipt(glp_prob *P, const char *fname);
+*
+* DESCRIPTION
+*
+* The routine glp_read_ipt reads interior-point solution from a text
+* file in GLPK format.
+*
+* RETURNS
+*
+* If the operation was successful, the routine returns zero. Otherwise
+* it prints an error message and returns non-zero. */
+
+int glp_read_ipt(glp_prob *P, const char *fname)
+{ DMX dmx_, *dmx = &dmx_;
+ int i, j, k, m, n, sst, ret = 1;
+ char *stat = NULL;
+ double obj, *prim = NULL, *dual = NULL;
+#if 0 /* 04/IV-2016 */
+ if (P == NULL || P->magic != GLP_PROB_MAGIC)
+ xerror("glp_read_ipt: P = %p; invalid problem object\n", P);
+#endif
+ if (fname == NULL)
+ xerror("glp_read_ipt: fname = %d; invalid parameter\n", fname);
+ if (setjmp(dmx->jump))
+ goto done;
+ dmx->fname = fname;
+ dmx->fp = NULL;
+ dmx->count = 0;
+ dmx->c = '\n';
+ dmx->field[0] = '\0';
+ dmx->empty = dmx->nonint = 0;
+ xprintf("Reading interior-point solution from '%s'...\n", fname);
+ dmx->fp = glp_open(fname, "r");
+ if (dmx->fp == NULL)
+ { xprintf("Unable to open '%s' - %s\n", fname, get_err_msg());
+ goto done;
+ }
+ /* read solution line */
+ dmx_read_designator(dmx);
+ if (strcmp(dmx->field, "s") != 0)
+ dmx_error(dmx, "solution line missing or invalid");
+ dmx_read_field(dmx);
+ if (strcmp(dmx->field, "ipt") != 0)
+ dmx_error(dmx, "wrong solution designator; 'ipt' expected");
+ dmx_read_field(dmx);
+ if (!(str2int(dmx->field, &m) == 0 && m >= 0))
+ dmx_error(dmx, "number of rows missing or invalid");
+ if (m != P->m)
+ dmx_error(dmx, "number of rows mismatch");
+ dmx_read_field(dmx);
+ if (!(str2int(dmx->field, &n) == 0 && n >= 0))
+ dmx_error(dmx, "number of columns missing or invalid");
+ if (n != P->n)
+ dmx_error(dmx, "number of columns mismatch");
+ dmx_read_field(dmx);
+ if (strcmp(dmx->field, "o") == 0)
+ sst = GLP_OPT;
+ else if (strcmp(dmx->field, "i") == 0)
+ sst = GLP_INFEAS;
+ else if (strcmp(dmx->field, "n") == 0)
+ sst = GLP_NOFEAS;
+ else if (strcmp(dmx->field, "u") == 0)
+ sst = GLP_UNDEF;
+ else
+ dmx_error(dmx, "solution status missing or invalid");
+ dmx_read_field(dmx);
+ if (str2num(dmx->field, &obj) != 0)
+ dmx_error(dmx, "objective value missing or invalid");
+ dmx_end_of_line(dmx);
+ /* allocate working arrays */
+ stat = xalloc(1+m+n, sizeof(stat[0]));
+ for (k = 1; k <= m+n; k++)
+ stat[k] = '?';
+ prim = xalloc(1+m+n, sizeof(prim[0]));
+ dual = xalloc(1+m+n, sizeof(dual[0]));
+ /* read solution descriptor lines */
+ for (;;)
+ { dmx_read_designator(dmx);
+ if (strcmp(dmx->field, "i") == 0)
+ { /* row solution descriptor */
+ dmx_read_field(dmx);
+ if (str2int(dmx->field, &i) != 0)
+ dmx_error(dmx, "row number missing or invalid");
+ if (!(1 <= i && i <= m))
+ dmx_error(dmx, "row number out of range");
+ if (stat[i] != '?')
+ dmx_error(dmx, "duplicate row solution descriptor");
+ stat[i] = GLP_BS;
+ dmx_read_field(dmx);
+ if (str2num(dmx->field, &prim[i]) != 0)
+ dmx_error(dmx, "row primal value missing or invalid");
+ dmx_read_field(dmx);
+ if (str2num(dmx->field, &dual[i]) != 0)
+ dmx_error(dmx, "row dual value missing or invalid");
+ dmx_end_of_line(dmx);
+ }
+ else if (strcmp(dmx->field, "j") == 0)
+ { /* column solution descriptor */
+ dmx_read_field(dmx);
+ if (str2int(dmx->field, &j) != 0)
+ dmx_error(dmx, "column number missing or invalid");
+ if (!(1 <= j && j <= n))
+ dmx_error(dmx, "column number out of range");
+ if (stat[m+j] != '?')
+ dmx_error(dmx, "duplicate column solution descriptor");
+ stat[m+j] = GLP_BS;
+ dmx_read_field(dmx);
+ if (str2num(dmx->field, &prim[m+j]) != 0)
+ dmx_error(dmx, "column primal value missing or invalid");
+ dmx_read_field(dmx);
+ if (str2num(dmx->field, &dual[m+j]) != 0)
+ dmx_error(dmx, "column dual value missing or invalid");
+ dmx_end_of_line(dmx);
+ }
+ else if (strcmp(dmx->field, "e") == 0)
+ break;
+ else
+ dmx_error(dmx, "line designator missing or invalid");
+ dmx_end_of_line(dmx);
+ }
+ /* store solution components into problem object */
+ for (k = 1; k <= m+n; k++)
+ { if (stat[k] == '?')
+ dmx_error(dmx, "incomplete interior-point solution");
+ }
+ P->ipt_stat = sst;
+ P->ipt_obj = obj;
+ for (i = 1; i <= m; i++)
+ { P->row[i]->pval = prim[i];
+ P->row[i]->dval = dual[i];
+ }
+ for (j = 1; j <= n; j++)
+ { P->col[j]->pval = prim[m+j];
+ P->col[j]->dval = dual[m+j];
+ }
+ /* interior-point solution has been successfully read */
+ xprintf("%d lines were read\n", dmx->count);
+ ret = 0;
+done: if (dmx->fp != NULL)
+ glp_close(dmx->fp);
+ if (stat != NULL)
+ xfree(stat);
+ if (prim != NULL)
+ xfree(prim);
+ if (dual != NULL)
+ xfree(dual);
+ return ret;
+}
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/api/rdmaxf.c b/test/monniaux/glpk-4.65/src/api/rdmaxf.c
new file mode 100644
index 00000000..a45405c9
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/api/rdmaxf.c
@@ -0,0 +1,163 @@
+/* rdmaxf.c (read maximum flow problem data in DIMACS format) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* Copyright (C) 2009-2016 Andrew Makhorin, Department for Applied
+* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights
+* reserved. E-mail: <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 "dimacs.h"
+#include "glpk.h"
+#include "misc.h"
+
+#define error dmx_error
+#define warning dmx_warning
+#define read_char dmx_read_char
+#define read_designator dmx_read_designator
+#define read_field dmx_read_field
+#define end_of_line dmx_end_of_line
+#define check_int dmx_check_int
+
+/***********************************************************************
+* NAME
+*
+* glp_read_maxflow - read maximum flow problem data in DIMACS format
+*
+* SYNOPSIS
+*
+* int glp_read_maxflow(glp_graph *G, int *s, int *t, int a_cap,
+* const char *fname);
+*
+* DESCRIPTION
+*
+* The routine glp_read_maxflow reads maximum flow problem data in
+* DIMACS format from a text file.
+*
+* RETURNS
+*
+* If the operation was successful, the routine returns zero. Otherwise
+* it prints an error message and returns non-zero. */
+
+int glp_read_maxflow(glp_graph *G, int *_s, int *_t, int a_cap,
+ const char *fname)
+{ DMX _csa, *csa = &_csa;
+ glp_arc *a;
+ int i, j, k, s, t, nv, na, ret = 0;
+ double cap;
+ if (a_cap >= 0 && a_cap > G->a_size - (int)sizeof(double))
+ xerror("glp_read_maxflow: a_cap = %d; invalid offset\n",
+ a_cap);
+ glp_erase_graph(G, G->v_size, G->a_size);
+ if (setjmp(csa->jump))
+ { ret = 1;
+ goto done;
+ }
+ csa->fname = fname;
+ csa->fp = NULL;
+ csa->count = 0;
+ csa->c = '\n';
+ csa->field[0] = '\0';
+ csa->empty = csa->nonint = 0;
+ xprintf("Reading maximum flow problem data from '%s'...\n",
+ fname);
+ csa->fp = glp_open(fname, "r");
+ if (csa->fp == NULL)
+ { xprintf("Unable to open '%s' - %s\n", fname, get_err_msg());
+ longjmp(csa->jump, 1);
+ }
+ /* read problem line */
+ read_designator(csa);
+ if (strcmp(csa->field, "p") != 0)
+ error(csa, "problem line missing or invalid");
+ read_field(csa);
+ if (strcmp(csa->field, "max") != 0)
+ error(csa, "wrong problem designator; 'max' expected");
+ read_field(csa);
+ if (!(str2int(csa->field, &nv) == 0 && nv >= 2))
+ error(csa, "number of nodes missing or invalid");
+ read_field(csa);
+ if (!(str2int(csa->field, &na) == 0 && na >= 0))
+ error(csa, "number of arcs missing or invalid");
+ xprintf("Flow network has %d node%s and %d arc%s\n",
+ nv, nv == 1 ? "" : "s", na, na == 1 ? "" : "s");
+ if (nv > 0) glp_add_vertices(G, nv);
+ end_of_line(csa);
+ /* read node descriptor lines */
+ s = t = 0;
+ for (;;)
+ { read_designator(csa);
+ if (strcmp(csa->field, "n") != 0) break;
+ read_field(csa);
+ if (str2int(csa->field, &i) != 0)
+ error(csa, "node number missing or invalid");
+ if (!(1 <= i && i <= nv))
+ error(csa, "node number %d out of range", i);
+ read_field(csa);
+ if (strcmp(csa->field, "s") == 0)
+ { if (s > 0)
+ error(csa, "only one source node allowed");
+ s = i;
+ }
+ else if (strcmp(csa->field, "t") == 0)
+ { if (t > 0)
+ error(csa, "only one sink node allowed");
+ t = i;
+ }
+ else
+ error(csa, "wrong node designator; 's' or 't' expected");
+ if (s > 0 && s == t)
+ error(csa, "source and sink nodes must be distinct");
+ end_of_line(csa);
+ }
+ if (s == 0)
+ error(csa, "source node descriptor missing\n");
+ if (t == 0)
+ error(csa, "sink node descriptor missing\n");
+ if (_s != NULL) *_s = s;
+ if (_t != NULL) *_t = t;
+ /* read arc descriptor lines */
+ for (k = 1; k <= na; k++)
+ { if (k > 1) read_designator(csa);
+ if (strcmp(csa->field, "a") != 0)
+ error(csa, "wrong line designator; 'a' expected");
+ read_field(csa);
+ if (str2int(csa->field, &i) != 0)
+ error(csa, "starting node number missing or invalid");
+ if (!(1 <= i && i <= nv))
+ error(csa, "starting node number %d out of range", i);
+ read_field(csa);
+ if (str2int(csa->field, &j) != 0)
+ error(csa, "ending node number missing or invalid");
+ if (!(1 <= j && j <= nv))
+ error(csa, "ending node number %d out of range", j);
+ read_field(csa);
+ if (!(str2num(csa->field, &cap) == 0 && cap >= 0.0))
+ error(csa, "arc capacity missing or invalid");
+ check_int(csa, cap);
+ a = glp_add_arc(G, i, j);
+ if (a_cap >= 0)
+ memcpy((char *)a->data + a_cap, &cap, sizeof(double));
+ end_of_line(csa);
+ }
+ xprintf("%d lines were read\n", csa->count);
+done: if (ret) glp_erase_graph(G, G->v_size, G->a_size);
+ if (csa->fp != NULL) glp_close(csa->fp);
+ return ret;
+}
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/api/rdmcf.c b/test/monniaux/glpk-4.65/src/api/rdmcf.c
new file mode 100644
index 00000000..bab1ec79
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/api/rdmcf.c
@@ -0,0 +1,186 @@
+/* rdmcf.c (read min-cost flow problem data in DIMACS format) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* Copyright (C) 2009-2016 Andrew Makhorin, Department for Applied
+* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights
+* reserved. E-mail: <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 "dimacs.h"
+#include "glpk.h"
+#include "misc.h"
+
+#define error dmx_error
+#define warning dmx_warning
+#define read_char dmx_read_char
+#define read_designator dmx_read_designator
+#define read_field dmx_read_field
+#define end_of_line dmx_end_of_line
+#define check_int dmx_check_int
+
+/***********************************************************************
+* NAME
+*
+* glp_read_mincost - read min-cost flow problem data in DIMACS format
+*
+* SYNOPSIS
+*
+* int glp_read_mincost(glp_graph *G, int v_rhs, int a_low, int a_cap,
+* int a_cost, const char *fname);
+*
+* DESCRIPTION
+*
+* The routine glp_read_mincost reads minimum cost flow problem data in
+* DIMACS format from a text file.
+*
+* RETURNS
+*
+* If the operation was successful, the routine returns zero. Otherwise
+* it prints an error message and returns non-zero. */
+
+int glp_read_mincost(glp_graph *G, int v_rhs, int a_low, int a_cap,
+ int a_cost, const char *fname)
+{ DMX _csa, *csa = &_csa;
+ glp_vertex *v;
+ glp_arc *a;
+ int i, j, k, nv, na, ret = 0;
+ double rhs, low, cap, cost;
+ char *flag = NULL;
+ if (v_rhs >= 0 && v_rhs > G->v_size - (int)sizeof(double))
+ xerror("glp_read_mincost: v_rhs = %d; invalid offset\n",
+ v_rhs);
+ if (a_low >= 0 && a_low > G->a_size - (int)sizeof(double))
+ xerror("glp_read_mincost: a_low = %d; invalid offset\n",
+ a_low);
+ if (a_cap >= 0 && a_cap > G->a_size - (int)sizeof(double))
+ xerror("glp_read_mincost: a_cap = %d; invalid offset\n",
+ a_cap);
+ if (a_cost >= 0 && a_cost > G->a_size - (int)sizeof(double))
+ xerror("glp_read_mincost: a_cost = %d; invalid offset\n",
+ a_cost);
+ glp_erase_graph(G, G->v_size, G->a_size);
+ if (setjmp(csa->jump))
+ { ret = 1;
+ goto done;
+ }
+ csa->fname = fname;
+ csa->fp = NULL;
+ csa->count = 0;
+ csa->c = '\n';
+ csa->field[0] = '\0';
+ csa->empty = csa->nonint = 0;
+ xprintf("Reading min-cost flow problem data from '%s'...\n",
+ fname);
+ csa->fp = glp_open(fname, "r");
+ if (csa->fp == NULL)
+ { xprintf("Unable to open '%s' - %s\n", fname, get_err_msg());
+ longjmp(csa->jump, 1);
+ }
+ /* read problem line */
+ read_designator(csa);
+ if (strcmp(csa->field, "p") != 0)
+ error(csa, "problem line missing or invalid");
+ read_field(csa);
+ if (strcmp(csa->field, "min") != 0)
+ error(csa, "wrong problem designator; 'min' expected");
+ read_field(csa);
+ if (!(str2int(csa->field, &nv) == 0 && nv >= 0))
+ error(csa, "number of nodes missing or invalid");
+ read_field(csa);
+ if (!(str2int(csa->field, &na) == 0 && na >= 0))
+ error(csa, "number of arcs missing or invalid");
+ xprintf("Flow network has %d node%s and %d arc%s\n",
+ nv, nv == 1 ? "" : "s", na, na == 1 ? "" : "s");
+ if (nv > 0) glp_add_vertices(G, nv);
+ end_of_line(csa);
+ /* read node descriptor lines */
+ flag = xcalloc(1+nv, sizeof(char));
+ memset(&flag[1], 0, nv * sizeof(char));
+ if (v_rhs >= 0)
+ { rhs = 0.0;
+ for (i = 1; i <= nv; i++)
+ { v = G->v[i];
+ memcpy((char *)v->data + v_rhs, &rhs, sizeof(double));
+ }
+ }
+ for (;;)
+ { read_designator(csa);
+ if (strcmp(csa->field, "n") != 0) break;
+ read_field(csa);
+ if (str2int(csa->field, &i) != 0)
+ error(csa, "node number missing or invalid");
+ if (!(1 <= i && i <= nv))
+ error(csa, "node number %d out of range", i);
+ if (flag[i])
+ error(csa, "duplicate descriptor of node %d", i);
+ read_field(csa);
+ if (str2num(csa->field, &rhs) != 0)
+ error(csa, "node supply/demand missing or invalid");
+ check_int(csa, rhs);
+ if (v_rhs >= 0)
+ { v = G->v[i];
+ memcpy((char *)v->data + v_rhs, &rhs, sizeof(double));
+ }
+ flag[i] = 1;
+ end_of_line(csa);
+ }
+ xfree(flag), flag = NULL;
+ /* read arc descriptor lines */
+ for (k = 1; k <= na; k++)
+ { if (k > 1) read_designator(csa);
+ if (strcmp(csa->field, "a") != 0)
+ error(csa, "wrong line designator; 'a' expected");
+ read_field(csa);
+ if (str2int(csa->field, &i) != 0)
+ error(csa, "starting node number missing or invalid");
+ if (!(1 <= i && i <= nv))
+ error(csa, "starting node number %d out of range", i);
+ read_field(csa);
+ if (str2int(csa->field, &j) != 0)
+ error(csa, "ending node number missing or invalid");
+ if (!(1 <= j && j <= nv))
+ error(csa, "ending node number %d out of range", j);
+ read_field(csa);
+ if (!(str2num(csa->field, &low) == 0 && low >= 0.0))
+ error(csa, "lower bound of arc flow missing or invalid");
+ check_int(csa, low);
+ read_field(csa);
+ if (!(str2num(csa->field, &cap) == 0 && cap >= low))
+ error(csa, "upper bound of arc flow missing or invalid");
+ check_int(csa, cap);
+ read_field(csa);
+ if (str2num(csa->field, &cost) != 0)
+ error(csa, "per-unit cost of arc flow missing or invalid");
+ check_int(csa, cost);
+ a = glp_add_arc(G, i, j);
+ if (a_low >= 0)
+ memcpy((char *)a->data + a_low, &low, sizeof(double));
+ if (a_cap >= 0)
+ memcpy((char *)a->data + a_cap, &cap, sizeof(double));
+ if (a_cost >= 0)
+ memcpy((char *)a->data + a_cost, &cost, sizeof(double));
+ end_of_line(csa);
+ }
+ xprintf("%d lines were read\n", csa->count);
+done: if (ret) glp_erase_graph(G, G->v_size, G->a_size);
+ if (csa->fp != NULL) glp_close(csa->fp);
+ if (flag != NULL) xfree(flag);
+ return ret;
+}
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/api/rdmip.c b/test/monniaux/glpk-4.65/src/api/rdmip.c
new file mode 100644
index 00000000..7aec26b3
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/api/rdmip.c
@@ -0,0 +1,172 @@
+/* rdmip.c (read MIP solution in GLPK format) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* Copyright (C) 2010-2016 Andrew Makhorin, Department for Applied
+* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights
+* reserved. E-mail: <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 "dimacs.h"
+#include "env.h"
+#include "misc.h"
+#include "prob.h"
+
+/***********************************************************************
+* NAME
+*
+* glp_read_mip - read MIP solution in GLPK format
+*
+* SYNOPSIS
+*
+* int glp_read_mip(glp_prob *P, const char *fname);
+*
+* DESCRIPTION
+*
+* The routine glp_read_mip reads MIP solution from a text file in GLPK
+* format.
+*
+* RETURNS
+*
+* If the operation was successful, the routine returns zero. Otherwise
+* it prints an error message and returns non-zero. */
+
+int glp_read_mip(glp_prob *P, const char *fname)
+{ DMX dmx_, *dmx = &dmx_;
+ int i, j, k, m, n, sst, ret = 1;
+ char *stat = NULL;
+ double obj, *prim = NULL;
+#if 0 /* 04/IV-2016 */
+ if (P == NULL || P->magic != GLP_PROB_MAGIC)
+ xerror("glp_read_mip: P = %p; invalid problem object\n", P);
+#endif
+ if (fname == NULL)
+ xerror("glp_read_mip: fname = %d; invalid parameter\n", fname);
+ if (setjmp(dmx->jump))
+ goto done;
+ dmx->fname = fname;
+ dmx->fp = NULL;
+ dmx->count = 0;
+ dmx->c = '\n';
+ dmx->field[0] = '\0';
+ dmx->empty = dmx->nonint = 0;
+ xprintf("Reading MIP solution from '%s'...\n", fname);
+ dmx->fp = glp_open(fname, "r");
+ if (dmx->fp == NULL)
+ { xprintf("Unable to open '%s' - %s\n", fname, get_err_msg());
+ goto done;
+ }
+ /* read solution line */
+ dmx_read_designator(dmx);
+ if (strcmp(dmx->field, "s") != 0)
+ dmx_error(dmx, "solution line missing or invalid");
+ dmx_read_field(dmx);
+ if (strcmp(dmx->field, "mip") != 0)
+ dmx_error(dmx, "wrong solution designator; 'mip' expected");
+ dmx_read_field(dmx);
+ if (!(str2int(dmx->field, &m) == 0 && m >= 0))
+ dmx_error(dmx, "number of rows missing or invalid");
+ if (m != P->m)
+ dmx_error(dmx, "number of rows mismatch");
+ dmx_read_field(dmx);
+ if (!(str2int(dmx->field, &n) == 0 && n >= 0))
+ dmx_error(dmx, "number of columns missing or invalid");
+ if (n != P->n)
+ dmx_error(dmx, "number of columns mismatch");
+ dmx_read_field(dmx);
+ if (strcmp(dmx->field, "o") == 0)
+ sst = GLP_OPT;
+ else if (strcmp(dmx->field, "f") == 0)
+ sst = GLP_FEAS;
+ else if (strcmp(dmx->field, "n") == 0)
+ sst = GLP_NOFEAS;
+ else if (strcmp(dmx->field, "u") == 0)
+ sst = GLP_UNDEF;
+ else
+ dmx_error(dmx, "solution status missing or invalid");
+ dmx_read_field(dmx);
+ if (str2num(dmx->field, &obj) != 0)
+ dmx_error(dmx, "objective value missing or invalid");
+ dmx_end_of_line(dmx);
+ /* allocate working arrays */
+ stat = xalloc(1+m+n, sizeof(stat[0]));
+ for (k = 1; k <= m+n; k++)
+ stat[k] = '?';
+ prim = xalloc(1+m+n, sizeof(prim[0]));
+ /* read solution descriptor lines */
+ for (;;)
+ { dmx_read_designator(dmx);
+ if (strcmp(dmx->field, "i") == 0)
+ { /* row solution descriptor */
+ dmx_read_field(dmx);
+ if (str2int(dmx->field, &i) != 0)
+ dmx_error(dmx, "row number missing or invalid");
+ if (!(1 <= i && i <= m))
+ dmx_error(dmx, "row number out of range");
+ if (stat[i] != '?')
+ dmx_error(dmx, "duplicate row solution descriptor");
+ stat[i] = GLP_BS;
+ dmx_read_field(dmx);
+ if (str2num(dmx->field, &prim[i]) != 0)
+ dmx_error(dmx, "row value missing or invalid");
+ dmx_end_of_line(dmx);
+ }
+ else if (strcmp(dmx->field, "j") == 0)
+ { /* column solution descriptor */
+ dmx_read_field(dmx);
+ if (str2int(dmx->field, &j) != 0)
+ dmx_error(dmx, "column number missing or invalid");
+ if (!(1 <= j && j <= n))
+ dmx_error(dmx, "column number out of range");
+ if (stat[m+j] != '?')
+ dmx_error(dmx, "duplicate column solution descriptor");
+ stat[m+j] = GLP_BS;
+ dmx_read_field(dmx);
+ if (str2num(dmx->field, &prim[m+j]) != 0)
+ dmx_error(dmx, "column value missing or invalid");
+ dmx_end_of_line(dmx);
+ }
+ else if (strcmp(dmx->field, "e") == 0)
+ break;
+ else
+ dmx_error(dmx, "line designator missing or invalid");
+ dmx_end_of_line(dmx);
+ }
+ /* store solution components into problem object */
+ for (k = 1; k <= m+n; k++)
+ { if (stat[k] == '?')
+ dmx_error(dmx, "incomplete MIP solution");
+ }
+ P->mip_stat = sst;
+ P->mip_obj = obj;
+ for (i = 1; i <= m; i++)
+ P->row[i]->mipx = prim[i];
+ for (j = 1; j <= n; j++)
+ P->col[j]->mipx = prim[m+j];
+ /* MIP solution has been successfully read */
+ xprintf("%d lines were read\n", dmx->count);
+ ret = 0;
+done: if (dmx->fp != NULL)
+ glp_close(dmx->fp);
+ if (stat != NULL)
+ xfree(stat);
+ if (prim != NULL)
+ xfree(prim);
+ return ret;
+}
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/api/rdprob.c b/test/monniaux/glpk-4.65/src/api/rdprob.c
new file mode 100644
index 00000000..1ad544a5
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/api/rdprob.c
@@ -0,0 +1,377 @@
+/* rdprob.c (read problem data in GLPK format) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* Copyright (C) 2010-2016 Andrew Makhorin, Department for Applied
+* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights
+* reserved. E-mail: <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 "dimacs.h"
+#include "misc.h"
+#include "prob.h"
+
+#define xfprintf glp_format
+#define error dmx_error
+#define warning dmx_warning
+#define read_char dmx_read_char
+#define read_designator dmx_read_designator
+#define read_field dmx_read_field
+#define end_of_line dmx_end_of_line
+#define check_int dmx_check_int
+
+/***********************************************************************
+* NAME
+*
+* glp_read_prob - read problem data in GLPK format
+*
+* SYNOPSIS
+*
+* int glp_read_prob(glp_prob *P, int flags, const char *fname);
+*
+* The routine glp_read_prob reads problem data in GLPK LP/MIP format
+* from a text file.
+*
+* RETURNS
+*
+* If the operation was successful, the routine returns zero. Otherwise
+* it prints an error message and returns non-zero. */
+
+int glp_read_prob(glp_prob *P, int flags, const char *fname)
+{ DMX _csa, *csa = &_csa;
+ int mip, m, n, nnz, ne, i, j, k, type, kind, ret, *ln = NULL,
+ *ia = NULL, *ja = NULL;
+ double lb, ub, temp, *ar = NULL;
+ char *rf = NULL, *cf = NULL;
+#if 0 /* 04/IV-2016 */
+ if (P == NULL || P->magic != GLP_PROB_MAGIC)
+ xerror("glp_read_prob: P = %p; invalid problem object\n",
+ P);
+#endif
+ if (flags != 0)
+ xerror("glp_read_prob: flags = %d; invalid parameter\n",
+ flags);
+ if (fname == NULL)
+ xerror("glp_read_prob: fname = %d; invalid parameter\n",
+ fname);
+ glp_erase_prob(P);
+ if (setjmp(csa->jump))
+ { ret = 1;
+ goto done;
+ }
+ csa->fname = fname;
+ csa->fp = NULL;
+ csa->count = 0;
+ csa->c = '\n';
+ csa->field[0] = '\0';
+ csa->empty = csa->nonint = 0;
+ xprintf("Reading problem data from '%s'...\n", fname);
+ csa->fp = glp_open(fname, "r");
+ if (csa->fp == NULL)
+ { xprintf("Unable to open '%s' - %s\n", fname, get_err_msg());
+ longjmp(csa->jump, 1);
+ }
+ /* read problem line */
+ read_designator(csa);
+ if (strcmp(csa->field, "p") != 0)
+ error(csa, "problem line missing or invalid");
+ read_field(csa);
+ if (strcmp(csa->field, "lp") == 0)
+ mip = 0;
+ else if (strcmp(csa->field, "mip") == 0)
+ mip = 1;
+ else
+ error(csa, "wrong problem designator; 'lp' or 'mip' expected");
+ read_field(csa);
+ if (strcmp(csa->field, "min") == 0)
+ glp_set_obj_dir(P, GLP_MIN);
+ else if (strcmp(csa->field, "max") == 0)
+ glp_set_obj_dir(P, GLP_MAX);
+ else
+ error(csa, "objective sense missing or invalid");
+ read_field(csa);
+ if (!(str2int(csa->field, &m) == 0 && m >= 0))
+ error(csa, "number of rows missing or invalid");
+ read_field(csa);
+ if (!(str2int(csa->field, &n) == 0 && n >= 0))
+ error(csa, "number of columns missing or invalid");
+ read_field(csa);
+ if (!(str2int(csa->field, &nnz) == 0 && nnz >= 0))
+ error(csa, "number of constraint coefficients missing or inval"
+ "id");
+ if (m > 0)
+ { glp_add_rows(P, m);
+ for (i = 1; i <= m; i++)
+ glp_set_row_bnds(P, i, GLP_FX, 0.0, 0.0);
+ }
+ if (n > 0)
+ { glp_add_cols(P, n);
+ for (j = 1; j <= n; j++)
+ { if (!mip)
+ glp_set_col_bnds(P, j, GLP_LO, 0.0, 0.0);
+ else
+ glp_set_col_kind(P, j, GLP_BV);
+ }
+ }
+ end_of_line(csa);
+ /* allocate working arrays */
+ rf = xcalloc(1+m, sizeof(char));
+ memset(rf, 0, 1+m);
+ cf = xcalloc(1+n, sizeof(char));
+ memset(cf, 0, 1+n);
+ ln = xcalloc(1+nnz, sizeof(int));
+ ia = xcalloc(1+nnz, sizeof(int));
+ ja = xcalloc(1+nnz, sizeof(int));
+ ar = xcalloc(1+nnz, sizeof(double));
+ /* read descriptor lines */
+ ne = 0;
+ for (;;)
+ { read_designator(csa);
+ if (strcmp(csa->field, "i") == 0)
+ { /* row descriptor */
+ read_field(csa);
+ if (str2int(csa->field, &i) != 0)
+ error(csa, "row number missing or invalid");
+ if (!(1 <= i && i <= m))
+ error(csa, "row number out of range");
+ read_field(csa);
+ if (strcmp(csa->field, "f") == 0)
+ type = GLP_FR;
+ else if (strcmp(csa->field, "l") == 0)
+ type = GLP_LO;
+ else if (strcmp(csa->field, "u") == 0)
+ type = GLP_UP;
+ else if (strcmp(csa->field, "d") == 0)
+ type = GLP_DB;
+ else if (strcmp(csa->field, "s") == 0)
+ type = GLP_FX;
+ else
+ error(csa, "row type missing or invalid");
+ if (type == GLP_LO || type == GLP_DB || type == GLP_FX)
+ { read_field(csa);
+ if (str2num(csa->field, &lb) != 0)
+ error(csa, "row lower bound/fixed value missing or in"
+ "valid");
+ }
+ else
+ lb = 0.0;
+ if (type == GLP_UP || type == GLP_DB)
+ { read_field(csa);
+ if (str2num(csa->field, &ub) != 0)
+ error(csa, "row upper bound missing or invalid");
+ }
+ else
+ ub = 0.0;
+ if (rf[i] & 0x01)
+ error(csa, "duplicate row descriptor");
+ glp_set_row_bnds(P, i, type, lb, ub), rf[i] |= 0x01;
+ }
+ else if (strcmp(csa->field, "j") == 0)
+ { /* column descriptor */
+ read_field(csa);
+ if (str2int(csa->field, &j) != 0)
+ error(csa, "column number missing or invalid");
+ if (!(1 <= j && j <= n))
+ error(csa, "column number out of range");
+ if (!mip)
+ kind = GLP_CV;
+ else
+ { read_field(csa);
+ if (strcmp(csa->field, "c") == 0)
+ kind = GLP_CV;
+ else if (strcmp(csa->field, "i") == 0)
+ kind = GLP_IV;
+ else if (strcmp(csa->field, "b") == 0)
+ { kind = GLP_IV;
+ type = GLP_DB, lb = 0.0, ub = 1.0;
+ goto skip;
+ }
+ else
+ error(csa, "column kind missing or invalid");
+ }
+ read_field(csa);
+ if (strcmp(csa->field, "f") == 0)
+ type = GLP_FR;
+ else if (strcmp(csa->field, "l") == 0)
+ type = GLP_LO;
+ else if (strcmp(csa->field, "u") == 0)
+ type = GLP_UP;
+ else if (strcmp(csa->field, "d") == 0)
+ type = GLP_DB;
+ else if (strcmp(csa->field, "s") == 0)
+ type = GLP_FX;
+ else
+ error(csa, "column type missing or invalid");
+ if (type == GLP_LO || type == GLP_DB || type == GLP_FX)
+ { read_field(csa);
+ if (str2num(csa->field, &lb) != 0)
+ error(csa, "column lower bound/fixed value missing or"
+ " invalid");
+ }
+ else
+ lb = 0.0;
+ if (type == GLP_UP || type == GLP_DB)
+ { read_field(csa);
+ if (str2num(csa->field, &ub) != 0)
+ error(csa, "column upper bound missing or invalid");
+ }
+ else
+ ub = 0.0;
+skip: if (cf[j] & 0x01)
+ error(csa, "duplicate column descriptor");
+ glp_set_col_kind(P, j, kind);
+ glp_set_col_bnds(P, j, type, lb, ub), cf[j] |= 0x01;
+ }
+ else if (strcmp(csa->field, "a") == 0)
+ { /* coefficient descriptor */
+ read_field(csa);
+ if (str2int(csa->field, &i) != 0)
+ error(csa, "row number missing or invalid");
+ if (!(0 <= i && i <= m))
+ error(csa, "row number out of range");
+ read_field(csa);
+ if (str2int(csa->field, &j) != 0)
+ error(csa, "column number missing or invalid");
+ if (!((i == 0 ? 0 : 1) <= j && j <= n))
+ error(csa, "column number out of range");
+ read_field(csa);
+ if (i == 0)
+ { if (str2num(csa->field, &temp) != 0)
+ error(csa, "objective %s missing or invalid",
+ j == 0 ? "constant term" : "coefficient");
+ if (cf[j] & 0x10)
+ error(csa, "duplicate objective %s",
+ j == 0 ? "constant term" : "coefficient");
+ glp_set_obj_coef(P, j, temp), cf[j] |= 0x10;
+ }
+ else
+ { if (str2num(csa->field, &temp) != 0)
+ error(csa, "constraint coefficient missing or invalid"
+ );
+ if (ne == nnz)
+ error(csa, "too many constraint coefficient descripto"
+ "rs");
+ ln[++ne] = csa->count;
+ ia[ne] = i, ja[ne] = j, ar[ne] = temp;
+ }
+ }
+ else if (strcmp(csa->field, "n") == 0)
+ { /* symbolic name descriptor */
+ read_field(csa);
+ if (strcmp(csa->field, "p") == 0)
+ { /* problem name */
+ read_field(csa);
+ if (P->name != NULL)
+ error(csa, "duplicate problem name");
+ glp_set_prob_name(P, csa->field);
+ }
+ else if (strcmp(csa->field, "z") == 0)
+ { /* objective name */
+ read_field(csa);
+ if (P->obj != NULL)
+ error(csa, "duplicate objective name");
+ glp_set_obj_name(P, csa->field);
+ }
+ else if (strcmp(csa->field, "i") == 0)
+ { /* row name */
+ read_field(csa);
+ if (str2int(csa->field, &i) != 0)
+ error(csa, "row number missing or invalid");
+ if (!(1 <= i && i <= m))
+ error(csa, "row number out of range");
+ read_field(csa);
+ if (P->row[i]->name != NULL)
+ error(csa, "duplicate row name");
+ glp_set_row_name(P, i, csa->field);
+ }
+ else if (strcmp(csa->field, "j") == 0)
+ { /* column name */
+ read_field(csa);
+ if (str2int(csa->field, &j) != 0)
+ error(csa, "column number missing or invalid");
+ if (!(1 <= j && j <= n))
+ error(csa, "column number out of range");
+ read_field(csa);
+ if (P->col[j]->name != NULL)
+ error(csa, "duplicate column name");
+ glp_set_col_name(P, j, csa->field);
+ }
+ else
+ error(csa, "object designator missing or invalid");
+ }
+ else if (strcmp(csa->field, "e") == 0)
+ break;
+ else
+ error(csa, "line designator missing or invalid");
+ end_of_line(csa);
+ }
+ if (ne < nnz)
+ error(csa, "too few constraint coefficient descriptors");
+ xassert(ne == nnz);
+ k = glp_check_dup(m, n, ne, ia, ja);
+ xassert(0 <= k && k <= nnz);
+ if (k > 0)
+ { csa->count = ln[k];
+ error(csa, "duplicate constraint coefficient");
+ }
+ glp_load_matrix(P, ne, ia, ja, ar);
+ /* print some statistics */
+ if (P->name != NULL)
+ xprintf("Problem: %s\n", P->name);
+ if (P->obj != NULL)
+ xprintf("Objective: %s\n", P->obj);
+ xprintf("%d row%s, %d column%s, %d non-zero%s\n",
+ m, m == 1 ? "" : "s", n, n == 1 ? "" : "s", nnz, nnz == 1 ?
+ "" : "s");
+ if (glp_get_num_int(P) > 0)
+ { int ni = glp_get_num_int(P);
+ int nb = glp_get_num_bin(P);
+ if (ni == 1)
+ { if (nb == 0)
+ xprintf("One variable is integer\n");
+ else
+ xprintf("One variable is binary\n");
+ }
+ else
+ { xprintf("%d integer variables, ", ni);
+ if (nb == 0)
+ xprintf("none");
+ else if (nb == 1)
+ xprintf("one");
+ else if (nb == ni)
+ xprintf("all");
+ else
+ xprintf("%d", nb);
+ xprintf(" of which %s binary\n", nb == 1 ? "is" : "are");
+ }
+ }
+ xprintf("%d lines were read\n", csa->count);
+ /* problem data has been successfully read */
+ glp_sort_matrix(P);
+ ret = 0;
+done: if (csa->fp != NULL) glp_close(csa->fp);
+ if (rf != NULL) xfree(rf);
+ if (cf != NULL) xfree(cf);
+ if (ln != NULL) xfree(ln);
+ if (ia != NULL) xfree(ia);
+ if (ja != NULL) xfree(ja);
+ if (ar != NULL) xfree(ar);
+ if (ret) glp_erase_prob(P);
+ return ret;
+}
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/api/rdsol.c b/test/monniaux/glpk-4.65/src/api/rdsol.c
new file mode 100644
index 00000000..d85a2562
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/api/rdsol.c
@@ -0,0 +1,225 @@
+/* rdsol.c (read basic solution in GLPK format) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* Copyright (C) 2010-2016 Andrew Makhorin, Department for Applied
+* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights
+* reserved. E-mail: <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 "dimacs.h"
+#include "env.h"
+#include "misc.h"
+#include "prob.h"
+
+/***********************************************************************
+* NAME
+*
+* glp_read_sol - read basic solution in GLPK format
+*
+* SYNOPSIS
+*
+* int glp_read_sol(glp_prob *P, const char *fname);
+*
+* DESCRIPTION
+*
+* The routine glp_read_sol reads basic solution from a text file in
+* GLPK format.
+*
+* RETURNS
+*
+* If the operation was successful, the routine returns zero. Otherwise
+* it prints an error message and returns non-zero. */
+
+int glp_read_sol(glp_prob *P, const char *fname)
+{ DMX dmx_, *dmx = &dmx_;
+ int i, j, k, m, n, pst, dst, ret = 1;
+ char *stat = NULL;
+ double obj, *prim = NULL, *dual = NULL;
+#if 0 /* 04/IV-2016 */
+ if (P == NULL || P->magic != GLP_PROB_MAGIC)
+ xerror("glp_read_sol: P = %p; invalid problem object\n", P);
+#endif
+ if (fname == NULL)
+ xerror("glp_read_sol: fname = %d; invalid parameter\n", fname);
+ if (setjmp(dmx->jump))
+ goto done;
+ dmx->fname = fname;
+ dmx->fp = NULL;
+ dmx->count = 0;
+ dmx->c = '\n';
+ dmx->field[0] = '\0';
+ dmx->empty = dmx->nonint = 0;
+ xprintf("Reading basic solution from '%s'...\n", fname);
+ dmx->fp = glp_open(fname, "r");
+ if (dmx->fp == NULL)
+ { xprintf("Unable to open '%s' - %s\n", fname, get_err_msg());
+ goto done;
+ }
+ /* read solution line */
+ dmx_read_designator(dmx);
+ if (strcmp(dmx->field, "s") != 0)
+ dmx_error(dmx, "solution line missing or invalid");
+ dmx_read_field(dmx);
+ if (strcmp(dmx->field, "bas") != 0)
+ dmx_error(dmx, "wrong solution designator; 'bas' expected");
+ dmx_read_field(dmx);
+ if (!(str2int(dmx->field, &m) == 0 && m >= 0))
+ dmx_error(dmx, "number of rows missing or invalid");
+ if (m != P->m)
+ dmx_error(dmx, "number of rows mismatch");
+ dmx_read_field(dmx);
+ if (!(str2int(dmx->field, &n) == 0 && n >= 0))
+ dmx_error(dmx, "number of columns missing or invalid");
+ if (n != P->n)
+ dmx_error(dmx, "number of columns mismatch");
+ dmx_read_field(dmx);
+ if (strcmp(dmx->field, "u") == 0)
+ pst = GLP_UNDEF;
+ else if (strcmp(dmx->field, "f") == 0)
+ pst = GLP_FEAS;
+ else if (strcmp(dmx->field, "i") == 0)
+ pst = GLP_INFEAS;
+ else if (strcmp(dmx->field, "n") == 0)
+ pst = GLP_NOFEAS;
+ else
+ dmx_error(dmx, "primal solution status missing or invalid");
+ dmx_read_field(dmx);
+ if (strcmp(dmx->field, "u") == 0)
+ dst = GLP_UNDEF;
+ else if (strcmp(dmx->field, "f") == 0)
+ dst = GLP_FEAS;
+ else if (strcmp(dmx->field, "i") == 0)
+ dst = GLP_INFEAS;
+ else if (strcmp(dmx->field, "n") == 0)
+ dst = GLP_NOFEAS;
+ else
+ dmx_error(dmx, "dual solution status missing or invalid");
+ dmx_read_field(dmx);
+ if (str2num(dmx->field, &obj) != 0)
+ dmx_error(dmx, "objective value missing or invalid");
+ dmx_end_of_line(dmx);
+ /* allocate working arrays */
+ stat = xalloc(1+m+n, sizeof(stat[0]));
+ for (k = 1; k <= m+n; k++)
+ stat[k] = '?';
+ prim = xalloc(1+m+n, sizeof(prim[0]));
+ dual = xalloc(1+m+n, sizeof(dual[0]));
+ /* read solution descriptor lines */
+ for (;;)
+ { dmx_read_designator(dmx);
+ if (strcmp(dmx->field, "i") == 0)
+ { /* row solution descriptor */
+ dmx_read_field(dmx);
+ if (str2int(dmx->field, &i) != 0)
+ dmx_error(dmx, "row number missing or invalid");
+ if (!(1 <= i && i <= m))
+ dmx_error(dmx, "row number out of range");
+ if (stat[i] != '?')
+ dmx_error(dmx, "duplicate row solution descriptor");
+ dmx_read_field(dmx);
+ if (strcmp(dmx->field, "b") == 0)
+ stat[i] = GLP_BS;
+ else if (strcmp(dmx->field, "l") == 0)
+ stat[i] = GLP_NL;
+ else if (strcmp(dmx->field, "u") == 0)
+ stat[i] = GLP_NU;
+ else if (strcmp(dmx->field, "f") == 0)
+ stat[i] = GLP_NF;
+ else if (strcmp(dmx->field, "s") == 0)
+ stat[i] = GLP_NS;
+ else
+ dmx_error(dmx, "row status missing or invalid");
+ dmx_read_field(dmx);
+ if (str2num(dmx->field, &prim[i]) != 0)
+ dmx_error(dmx, "row primal value missing or invalid");
+ dmx_read_field(dmx);
+ if (str2num(dmx->field, &dual[i]) != 0)
+ dmx_error(dmx, "row dual value missing or invalid");
+ dmx_end_of_line(dmx);
+ }
+ else if (strcmp(dmx->field, "j") == 0)
+ { /* column solution descriptor */
+ dmx_read_field(dmx);
+ if (str2int(dmx->field, &j) != 0)
+ dmx_error(dmx, "column number missing or invalid");
+ if (!(1 <= j && j <= n))
+ dmx_error(dmx, "column number out of range");
+ if (stat[m+j] != '?')
+ dmx_error(dmx, "duplicate column solution descriptor");
+ dmx_read_field(dmx);
+ if (strcmp(dmx->field, "b") == 0)
+ stat[m+j] = GLP_BS;
+ else if (strcmp(dmx->field, "l") == 0)
+ stat[m+j] = GLP_NL;
+ else if (strcmp(dmx->field, "u") == 0)
+ stat[m+j] = GLP_NU;
+ else if (strcmp(dmx->field, "f") == 0)
+ stat[m+j] = GLP_NF;
+ else if (strcmp(dmx->field, "s") == 0)
+ stat[m+j] = GLP_NS;
+ else
+ dmx_error(dmx, "column status missing or invalid");
+ dmx_read_field(dmx);
+ if (str2num(dmx->field, &prim[m+j]) != 0)
+ dmx_error(dmx, "column primal value missing or invalid");
+ dmx_read_field(dmx);
+ if (str2num(dmx->field, &dual[m+j]) != 0)
+ dmx_error(dmx, "column dual value missing or invalid");
+ dmx_end_of_line(dmx);
+ }
+ else if (strcmp(dmx->field, "e") == 0)
+ break;
+ else
+ dmx_error(dmx, "line designator missing or invalid");
+ dmx_end_of_line(dmx);
+ }
+ /* store solution components into problem object */
+ for (k = 1; k <= m+n; k++)
+ { if (stat[k] == '?')
+ dmx_error(dmx, "incomplete basic solution");
+ }
+ P->pbs_stat = pst;
+ P->dbs_stat = dst;
+ P->obj_val = obj;
+ P->it_cnt = 0;
+ P->some = 0;
+ for (i = 1; i <= m; i++)
+ { glp_set_row_stat(P, i, stat[i]);
+ P->row[i]->prim = prim[i];
+ P->row[i]->dual = dual[i];
+ }
+ for (j = 1; j <= n; j++)
+ { glp_set_col_stat(P, j, stat[m+j]);
+ P->col[j]->prim = prim[m+j];
+ P->col[j]->dual = dual[m+j];
+ }
+ /* basic solution has been successfully read */
+ xprintf("%d lines were read\n", dmx->count);
+ ret = 0;
+done: if (dmx->fp != NULL)
+ glp_close(dmx->fp);
+ if (stat != NULL)
+ xfree(stat);
+ if (prim != NULL)
+ xfree(prim);
+ if (dual != NULL)
+ xfree(dual);
+ return ret;
+}
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/api/rmfgen.c b/test/monniaux/glpk-4.65/src/api/rmfgen.c
new file mode 100644
index 00000000..a1ba27bb
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/api/rmfgen.c
@@ -0,0 +1,368 @@
+/* rmfgen.c (Goldfarb's maximum flow problem generator) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* This code is a modified version of the program RMFGEN, a maxflow
+* problem generator developed by D.Goldfarb and M.Grigoriadis, and
+* originally implemented by Tamas Badics <badics@rutcor.rutgers.edu>.
+* The original code is publically available on the DIMACS ftp site at:
+* <ftp://dimacs.rutgers.edu/pub/netflow/generators/network/genrmf>.
+*
+* All changes concern only the program interface, so this modified
+* version produces exactly the same instances as the original version.
+*
+* Changes were made 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 "env.h"
+#include "glpk.h"
+#include "rng.h"
+
+/***********************************************************************
+* NAME
+*
+* glp_rmfgen - Goldfarb's maximum flow problem generator
+*
+* SYNOPSIS
+*
+* int glp_rmfgen(glp_graph *G, int *s, int *t, int a_cap,
+* const int parm[1+5]);
+*
+* DESCRIPTION
+*
+* The routine glp_rmfgen is a maximum flow problem generator developed
+* by D.Goldfarb and M.Grigoriadis.
+*
+* The parameter G specifies the graph object, to which the generated
+* problem data have to be stored. Note that on entry the graph object
+* is erased with the routine glp_erase_graph.
+*
+* The pointer s specifies a location, to which the routine stores the
+* source node number. If s is NULL, the node number is not stored.
+*
+* The pointer t specifies a location, to which the routine stores the
+* sink node number. If t is NULL, the node number is not stored.
+*
+* The parameter a_cap specifies an offset of the field of type double
+* in the arc data block, to which the routine stores the arc capacity.
+* If a_cap < 0, the capacity is not stored.
+*
+* The array parm contains description of the network to be generated:
+*
+* parm[0] not used
+* parm[1] (seed) random number seed (a positive integer)
+* parm[2] (a) frame size
+* parm[3] (b) depth
+* parm[4] (c1) minimal arc capacity
+* parm[5] (c2) maximal arc capacity
+*
+* RETURNS
+*
+* If the instance was successfully generated, the routine glp_netgen
+* returns zero; otherwise, if specified parameters are inconsistent,
+* the routine returns a non-zero error code.
+*
+* COMMENTS
+*
+* The generated network is as follows. It has b pieces of frames of
+* size a * a. (So alltogether the number of vertices is a * a * b)
+*
+* In each frame all the vertices are connected with their neighbours
+* (forth and back). In addition the vertices of a frame are connected
+* one to one with the vertices of next frame using a random permutation
+* of those vertices.
+*
+* The source is the lower left vertex of the first frame, the sink is
+* the upper right vertex of the b'th frame.
+*
+* t
+* +-------+
+* | .|
+* | . |
+* / | / |
+* +-------+/ -+ b
+* | | |/.
+* a | -v- |/
+* | | |/
+* +-------+ 1
+* s a
+*
+* The capacities are randomly chosen integers from the range of [c1,c2]
+* in the case of interconnecting edges, and c2 * a * a for the in-frame
+* edges.
+*
+* REFERENCES
+*
+* D.Goldfarb and M.D.Grigoriadis, "A computational comparison of the
+* Dinic and network simplex methods for maximum flow." Annals of Op.
+* Res. 13 (1988), pp. 83-123.
+*
+* U.Derigs and W.Meier, "Implementing Goldberg's max-flow algorithm:
+* A computational investigation." Zeitschrift fuer Operations Research
+* 33 (1989), pp. 383-403. */
+
+typedef struct VERTEX
+{ struct EDGE **edgelist;
+ /* Pointer to the list of pointers to the adjacent edges.
+ (No matter that to or from edges) */
+ struct EDGE **current;
+ /* Pointer to the current edge */
+ int degree;
+ /* Number of adjacent edges (both direction) */
+ int index;
+} vertex;
+
+typedef struct EDGE
+{ int from;
+ int to;
+ int cap;
+ /* Capacity */
+} edge;
+
+typedef struct NETWORK
+{ struct NETWORK *next, *prev;
+ int vertnum;
+ int edgenum;
+ vertex *verts;
+ /* Vertex array[1..vertnum] */
+ edge *edges;
+ /* Edge array[1..edgenum] */
+ int source;
+ /* Pointer to the source */
+ int sink;
+ /* Pointer to the sink */
+} network;
+
+struct csa
+{ /* common storage area */
+ glp_graph *G;
+ int *s, *t, a_cap;
+ RNG *rand;
+ network *N;
+ int *Parr;
+ int A, AA, C2AA, Ec;
+};
+
+#define G (csa->G)
+#define s (csa->s)
+#define t (csa->t)
+#define a_cap (csa->a_cap)
+#define N (csa->N)
+#define Parr (csa->Parr)
+#define A (csa->A)
+#define AA (csa->AA)
+#define C2AA (csa->C2AA)
+#define Ec (csa->Ec)
+
+#undef random
+#define random(A) (int)(rng_unif_01(csa->rand) * (double)(A))
+#define RANDOM(A, B) (int)(random((B) - (A) + 1) + (A))
+#define sgn(A) (((A) > 0) ? 1 : ((A) == 0) ? 0 : -1)
+
+static void make_edge(struct csa *csa, int from, int to, int c1, int c2)
+{ Ec++;
+ N->edges[Ec].from = from;
+ N->edges[Ec].to = to;
+ N->edges[Ec].cap = RANDOM(c1, c2);
+ return;
+}
+
+static void permute(struct csa *csa)
+{ int i, j, tmp;
+ for (i = 1; i < AA; i++)
+ { j = RANDOM(i, AA);
+ tmp = Parr[i];
+ Parr[i] = Parr[j];
+ Parr[j] = tmp;
+ }
+ return;
+}
+
+static void connect(struct csa *csa, int offset, int cv, int x1, int y1)
+{ int cv1;
+ cv1 = offset + (x1 - 1) * A + y1;
+ Ec++;
+ N->edges[Ec].from = cv;
+ N->edges[Ec].to = cv1;
+ N->edges[Ec].cap = C2AA;
+ return;
+}
+
+static network *gen_rmf(struct csa *csa, int a, int b, int c1, int c2)
+{ /* generates a network with a*a*b nodes and 6a*a*b-4ab-2a*a edges
+ random_frame network:
+ Derigs & Meier, Methods & Models of OR (1989), 33:383-403 */
+ int x, y, z, offset, cv;
+ A = a;
+ AA = a * a;
+ C2AA = c2 * AA;
+ Ec = 0;
+ N = (network *)xmalloc(sizeof(network));
+ N->vertnum = AA * b;
+ N->edgenum = 5 * AA * b - 4 * A * b - AA;
+ N->edges = (edge *)xcalloc(N->edgenum + 1, sizeof(edge));
+ N->source = 1;
+ N->sink = N->vertnum;
+ Parr = (int *)xcalloc(AA + 1, sizeof(int));
+ for (x = 1; x <= AA; x++)
+ Parr[x] = x;
+ for (z = 1; z <= b; z++)
+ { offset = AA * (z - 1);
+ if (z != b)
+ permute(csa);
+ for (x = 1; x <= A; x++)
+ { for (y = 1; y <= A; y++)
+ { cv = offset + (x - 1) * A + y;
+ if (z != b)
+ make_edge(csa, cv, offset + AA + Parr[cv - offset],
+ c1, c2); /* the intermediate edges */
+ if (y < A)
+ connect(csa, offset, cv, x, y + 1);
+ if (y > 1)
+ connect(csa, offset, cv, x, y - 1);
+ if (x < A)
+ connect(csa, offset, cv, x + 1, y);
+ if (x > 1)
+ connect(csa, offset, cv, x - 1, y);
+ }
+ }
+ }
+ xfree(Parr);
+ return N;
+}
+
+static void print_max_format(struct csa *csa, network *n, char *comm[],
+ int dim)
+{ /* prints a network heading with dim lines of comments (no \n
+ needs at the ends) */
+ int i, vnum, e_num;
+ edge *e;
+ vnum = n->vertnum;
+ e_num = n->edgenum;
+ if (G == NULL)
+ { for (i = 0; i < dim; i++)
+ xprintf("c %s\n", comm[i]);
+ xprintf("p max %7d %10d\n", vnum, e_num);
+ xprintf("n %7d s\n", n->source);
+ xprintf("n %7d t\n", n->sink);
+ }
+ else
+ { glp_add_vertices(G, vnum);
+ if (s != NULL) *s = n->source;
+ if (t != NULL) *t = n->sink;
+ }
+ for (i = 1; i <= e_num; i++)
+ { e = &n->edges[i];
+ if (G == NULL)
+ xprintf("a %7d %7d %10d\n", e->from, e->to, (int)e->cap);
+ else
+ { glp_arc *a = glp_add_arc(G, e->from, e->to);
+ if (a_cap >= 0)
+ { double temp = (double)e->cap;
+ memcpy((char *)a->data + a_cap, &temp, sizeof(double));
+ }
+ }
+ }
+ return;
+}
+
+static void gen_free_net(network *n)
+{ xfree(n->edges);
+ xfree(n);
+ return;
+}
+
+int glp_rmfgen(glp_graph *G_, int *_s, int *_t, int _a_cap,
+ const int parm[1+5])
+{ struct csa _csa, *csa = &_csa;
+ network *n;
+ char comm[10][80], *com1[10];
+ int seed, a, b, c1, c2, ret;
+ G = G_;
+ s = _s;
+ t = _t;
+ a_cap = _a_cap;
+ if (G != NULL)
+ { if (a_cap >= 0 && a_cap > G->a_size - (int)sizeof(double))
+ xerror("glp_rmfgen: a_cap = %d; invalid offset\n", a_cap);
+ }
+ seed = parm[1];
+ a = parm[2];
+ b = parm[3];
+ c1 = parm[4];
+ c2 = parm[5];
+ if (!(seed > 0 && 1 <= a && a <= 1000 && 1 <= b && b <= 1000 &&
+ 0 <= c1 && c1 <= c2 && c2 <= 1000))
+ { ret = 1;
+ goto done;
+ }
+ if (G != NULL)
+ { glp_erase_graph(G, G->v_size, G->a_size);
+ glp_set_graph_name(G, "RMFGEN");
+ }
+ csa->rand = rng_create_rand();
+ rng_init_rand(csa->rand, seed);
+ n = gen_rmf(csa, a, b, c1, c2);
+ sprintf(comm[0], "This file was generated by genrmf.");
+ sprintf(comm[1], "The parameters are: a: %d b: %d c1: %d c2: %d",
+ a, b, c1, c2);
+ com1[0] = comm[0];
+ com1[1] = comm[1];
+ print_max_format(csa, n, com1, 2);
+ gen_free_net(n);
+ rng_delete_rand(csa->rand);
+ ret = 0;
+done: return ret;
+}
+
+/**********************************************************************/
+
+#if 0
+int main(int argc, char *argv[])
+{ int seed, a, b, c1, c2, i, parm[1+5];
+ seed = 123;
+ a = b = c1 = c2 = -1;
+ for (i = 1; i < argc; i++)
+ { if (strcmp(argv[i], "-seed") == 0)
+ seed = atoi(argv[++i]);
+ else if (strcmp(argv[i], "-a") == 0)
+ a = atoi(argv[++i]);
+ else if (strcmp(argv[i], "-b") == 0)
+ b = atoi(argv[++i]);
+ else if (strcmp(argv[i], "-c1") == 0)
+ c1 = atoi(argv[++i]);
+ else if (strcmp(argv[i], "-c2") == 0)
+ c2 = atoi(argv[++i]);
+ }
+ if (a < 0 || b < 0 || c1 < 0 || c2 < 0)
+ { xprintf("Usage:\n");
+ xprintf("genrmf [-seed seed] -a frame_size -b depth\n");
+ xprintf(" -c1 cap_range1 -c2 cap_range2\n");
+ }
+ else
+ { parm[1] = seed;
+ parm[2] = a;
+ parm[3] = b;
+ parm[4] = c1;
+ parm[5] = c2;
+ glp_rmfgen(NULL, NULL, NULL, 0, parm);
+ }
+ return 0;
+}
+#endif
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/api/strong.c b/test/monniaux/glpk-4.65/src/api/strong.c
new file mode 100644
index 00000000..9ddcacfb
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/api/strong.c
@@ -0,0 +1,110 @@
+/* strong.c (find all strongly connected components of graph) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* Copyright (C) 2009-2016 Andrew Makhorin, Department for Applied
+* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights
+* reserved. E-mail: <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 "env.h"
+#include "glpk.h"
+#include "mc13d.h"
+
+/***********************************************************************
+* NAME
+*
+* glp_strong_comp - find all strongly connected components of graph
+*
+* SYNOPSIS
+*
+* int glp_strong_comp(glp_graph *G, int v_num);
+*
+* DESCRIPTION
+*
+* The routine glp_strong_comp finds all strongly connected components
+* of the specified graph.
+*
+* The parameter v_num specifies an offset of the field of type int
+* in the vertex data block, to which the routine stores the number of
+* a strongly connected component containing that vertex. If v_num < 0,
+* no component numbers are stored.
+*
+* The components are numbered in arbitrary order from 1 to nc, where
+* nc is the total number of components found, 0 <= nc <= |V|. However,
+* the component numbering has the property that for every arc (i->j)
+* in the graph the condition num(i) >= num(j) holds.
+*
+* RETURNS
+*
+* The routine returns nc, the total number of components found. */
+
+int glp_strong_comp(glp_graph *G, int v_num)
+{ glp_vertex *v;
+ glp_arc *a;
+ int i, k, last, n, na, nc, *icn, *ip, *lenr, *ior, *ib, *lowl,
+ *numb, *prev;
+ if (v_num >= 0 && v_num > G->v_size - (int)sizeof(int))
+ xerror("glp_strong_comp: v_num = %d; invalid offset\n",
+ v_num);
+ n = G->nv;
+ if (n == 0)
+ { nc = 0;
+ goto done;
+ }
+ na = G->na;
+ icn = xcalloc(1+na, sizeof(int));
+ ip = xcalloc(1+n, sizeof(int));
+ lenr = xcalloc(1+n, sizeof(int));
+ ior = xcalloc(1+n, sizeof(int));
+ ib = xcalloc(1+n, sizeof(int));
+ lowl = xcalloc(1+n, sizeof(int));
+ numb = xcalloc(1+n, sizeof(int));
+ prev = xcalloc(1+n, sizeof(int));
+ k = 1;
+ for (i = 1; i <= n; i++)
+ { v = G->v[i];
+ ip[i] = k;
+ for (a = v->out; a != NULL; a = a->t_next)
+ icn[k++] = a->head->i;
+ lenr[i] = k - ip[i];
+ }
+ xassert(na == k-1);
+ nc = mc13d(n, icn, ip, lenr, ior, ib, lowl, numb, prev);
+ if (v_num >= 0)
+ { xassert(ib[1] == 1);
+ for (k = 1; k <= nc; k++)
+ { last = (k < nc ? ib[k+1] : n+1);
+ xassert(ib[k] < last);
+ for (i = ib[k]; i < last; i++)
+ { v = G->v[ior[i]];
+ memcpy((char *)v->data + v_num, &k, sizeof(int));
+ }
+ }
+ }
+ xfree(icn);
+ xfree(ip);
+ xfree(lenr);
+ xfree(ior);
+ xfree(ib);
+ xfree(lowl);
+ xfree(numb);
+ xfree(prev);
+done: return nc;
+}
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/api/topsort.c b/test/monniaux/glpk-4.65/src/api/topsort.c
new file mode 100644
index 00000000..971937f2
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/api/topsort.c
@@ -0,0 +1,123 @@
+/* topsort.c (topological sorting of acyclic digraph) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* Copyright (C) 2010-2016 Andrew Makhorin, Department for Applied
+* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights
+* reserved. E-mail: <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 "env.h"
+#include "glpk.h"
+
+/***********************************************************************
+* NAME
+*
+* glp_top_sort - topological sorting of acyclic digraph
+*
+* SYNOPSIS
+*
+* int glp_top_sort(glp_graph *G, int v_num);
+*
+* DESCRIPTION
+*
+* The routine glp_top_sort performs topological sorting of vertices of
+* the specified acyclic digraph.
+*
+* The parameter v_num specifies an offset of the field of type int in
+* the vertex data block, to which the routine stores the vertex number
+* assigned. If v_num < 0, vertex numbers are not stored.
+*
+* The vertices are numbered from 1 to n, where n is the total number
+* of vertices in the graph. The vertex numbering has the property that
+* for every arc (i->j) in the graph the condition num(i) < num(j)
+* holds. Special case num(i) = 0 means that vertex i is not assigned a
+* number, because the graph is *not* acyclic.
+*
+* RETURNS
+*
+* If the graph is acyclic and therefore all the vertices have been
+* assigned numbers, the routine glp_top_sort returns zero. Otherwise,
+* if the graph is not acyclic, the routine returns the number of
+* vertices which have not been numbered, i.e. for which num(i) = 0. */
+
+static int top_sort(glp_graph *G, int num[])
+{ glp_arc *a;
+ int i, j, cnt, top, *stack, *indeg;
+ /* allocate working arrays */
+ indeg = xcalloc(1+G->nv, sizeof(int));
+ stack = xcalloc(1+G->nv, sizeof(int));
+ /* determine initial indegree of each vertex; push into the stack
+ the vertices having zero indegree */
+ top = 0;
+ for (i = 1; i <= G->nv; i++)
+ { num[i] = indeg[i] = 0;
+ for (a = G->v[i]->in; a != NULL; a = a->h_next)
+ indeg[i]++;
+ if (indeg[i] == 0)
+ stack[++top] = i;
+ }
+ /* assign numbers to vertices in the sorted order */
+ cnt = 0;
+ while (top > 0)
+ { /* pull vertex i from the stack */
+ i = stack[top--];
+ /* it has zero indegree in the current graph */
+ xassert(indeg[i] == 0);
+ /* so assign it a next number */
+ xassert(num[i] == 0);
+ num[i] = ++cnt;
+ /* remove vertex i from the current graph, update indegree of
+ its adjacent vertices, and push into the stack new vertices
+ whose indegree becomes zero */
+ for (a = G->v[i]->out; a != NULL; a = a->t_next)
+ { j = a->head->i;
+ /* there exists arc (i->j) in the graph */
+ xassert(indeg[j] > 0);
+ indeg[j]--;
+ if (indeg[j] == 0)
+ stack[++top] = j;
+ }
+ }
+ /* free working arrays */
+ xfree(indeg);
+ xfree(stack);
+ return G->nv - cnt;
+}
+
+int glp_top_sort(glp_graph *G, int v_num)
+{ glp_vertex *v;
+ int i, cnt, *num;
+ if (v_num >= 0 && v_num > G->v_size - (int)sizeof(int))
+ xerror("glp_top_sort: v_num = %d; invalid offset\n", v_num);
+ if (G->nv == 0)
+ { cnt = 0;
+ goto done;
+ }
+ num = xcalloc(1+G->nv, sizeof(int));
+ cnt = top_sort(G, num);
+ if (v_num >= 0)
+ { for (i = 1; i <= G->nv; i++)
+ { v = G->v[i];
+ memcpy((char *)v->data + v_num, &num[i], sizeof(int));
+ }
+ }
+ xfree(num);
+done: return cnt;
+}
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/api/wcliqex.c b/test/monniaux/glpk-4.65/src/api/wcliqex.c
new file mode 100644
index 00000000..53c2d521
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/api/wcliqex.c
@@ -0,0 +1,122 @@
+/* wcliqex.c (find maximum weight clique with exact algorithm) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* Copyright (C) 2009-2016 Andrew Makhorin, Department for Applied
+* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights
+* reserved. E-mail: <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 "env.h"
+#include "glpk.h"
+#include "wclique.h"
+
+static void set_edge(int nv, unsigned char a[], int i, int j)
+{ int k;
+ xassert(1 <= j && j < i && i <= nv);
+ k = ((i - 1) * (i - 2)) / 2 + (j - 1);
+ a[k / CHAR_BIT] |=
+ (unsigned char)(1 << ((CHAR_BIT - 1) - k % CHAR_BIT));
+ return;
+}
+
+int glp_wclique_exact(glp_graph *G, int v_wgt, double *sol, int v_set)
+{ /* find maximum weight clique with exact algorithm */
+ glp_arc *e;
+ int i, j, k, len, x, *w, *ind, ret = 0;
+ unsigned char *a;
+ double s, t;
+ if (v_wgt >= 0 && v_wgt > G->v_size - (int)sizeof(double))
+ xerror("glp_wclique_exact: v_wgt = %d; invalid parameter\n",
+ v_wgt);
+ if (v_set >= 0 && v_set > G->v_size - (int)sizeof(int))
+ xerror("glp_wclique_exact: v_set = %d; invalid parameter\n",
+ v_set);
+ if (G->nv == 0)
+ { /* empty graph has only empty clique */
+ if (sol != NULL) *sol = 0.0;
+ return 0;
+ }
+ /* allocate working arrays */
+ w = xcalloc(1+G->nv, sizeof(int));
+ ind = xcalloc(1+G->nv, sizeof(int));
+ len = G->nv; /* # vertices */
+ len = len * (len - 1) / 2; /* # entries in lower triangle */
+ len = (len + (CHAR_BIT - 1)) / CHAR_BIT; /* # bytes needed */
+ a = xcalloc(len, sizeof(char));
+ memset(a, 0, len * sizeof(char));
+ /* determine vertex weights */
+ s = 0.0;
+ for (i = 1; i <= G->nv; i++)
+ { if (v_wgt >= 0)
+ { memcpy(&t, (char *)G->v[i]->data + v_wgt, sizeof(double));
+ if (!(0.0 <= t && t <= (double)INT_MAX && t == floor(t)))
+ { ret = GLP_EDATA;
+ goto done;
+ }
+ w[i] = (int)t;
+ }
+ else
+ w[i] = 1;
+ s += (double)w[i];
+ }
+ if (s > (double)INT_MAX)
+ { ret = GLP_EDATA;
+ goto done;
+ }
+ /* build the adjacency matrix */
+ for (i = 1; i <= G->nv; i++)
+ { for (e = G->v[i]->in; e != NULL; e = e->h_next)
+ { j = e->tail->i;
+ /* there exists edge (j,i) in the graph */
+ if (i > j) set_edge(G->nv, a, i, j);
+ }
+ for (e = G->v[i]->out; e != NULL; e = e->t_next)
+ { j = e->head->i;
+ /* there exists edge (i,j) in the graph */
+ if (i > j) set_edge(G->nv, a, i, j);
+ }
+ }
+ /* find maximum weight clique in the graph */
+ len = wclique(G->nv, w, a, ind);
+ /* compute the clique weight */
+ s = 0.0;
+ for (k = 1; k <= len; k++)
+ { i = ind[k];
+ xassert(1 <= i && i <= G->nv);
+ s += (double)w[i];
+ }
+ if (sol != NULL) *sol = s;
+ /* mark vertices included in the clique */
+ if (v_set >= 0)
+ { x = 0;
+ for (i = 1; i <= G->nv; i++)
+ memcpy((char *)G->v[i]->data + v_set, &x, sizeof(int));
+ x = 1;
+ for (k = 1; k <= len; k++)
+ { i = ind[k];
+ memcpy((char *)G->v[i]->data + v_set, &x, sizeof(int));
+ }
+ }
+done: /* free working arrays */
+ xfree(w);
+ xfree(ind);
+ xfree(a);
+ return ret;
+}
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/api/weak.c b/test/monniaux/glpk-4.65/src/api/weak.c
new file mode 100644
index 00000000..027c09c1
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/api/weak.c
@@ -0,0 +1,150 @@
+/* weak.c (find all weakly connected components of graph) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* Copyright (C) 2009-2016 Andrew Makhorin, Department for Applied
+* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights
+* reserved. E-mail: <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 "env.h"
+#include "glpk.h"
+
+/***********************************************************************
+* NAME
+*
+* glp_weak_comp - find all weakly connected components of graph
+*
+* SYNOPSIS
+*
+* int glp_weak_comp(glp_graph *G, int v_num);
+*
+* DESCRIPTION
+*
+* The routine glp_weak_comp finds all weakly connected components of
+* the specified graph.
+*
+* The parameter v_num specifies an offset of the field of type int
+* in the vertex data block, to which the routine stores the number of
+* a (weakly) connected component containing that vertex. If v_num < 0,
+* no component numbers are stored.
+*
+* The components are numbered in arbitrary order from 1 to nc, where
+* nc is the total number of components found, 0 <= nc <= |V|.
+*
+* RETURNS
+*
+* The routine returns nc, the total number of components found. */
+
+int glp_weak_comp(glp_graph *G, int v_num)
+{ glp_vertex *v;
+ glp_arc *a;
+ int f, i, j, nc, nv, pos1, pos2, *prev, *next, *list;
+ if (v_num >= 0 && v_num > G->v_size - (int)sizeof(int))
+ xerror("glp_weak_comp: v_num = %d; invalid offset\n", v_num);
+ nv = G->nv;
+ if (nv == 0)
+ { nc = 0;
+ goto done;
+ }
+ /* allocate working arrays */
+ prev = xcalloc(1+nv, sizeof(int));
+ next = xcalloc(1+nv, sizeof(int));
+ list = xcalloc(1+nv, sizeof(int));
+ /* if vertex i is unlabelled, prev[i] is the index of previous
+ unlabelled vertex, and next[i] is the index of next unlabelled
+ vertex; if vertex i is labelled, then prev[i] < 0, and next[i]
+ is the connected component number */
+ /* initially all vertices are unlabelled */
+ f = 1;
+ for (i = 1; i <= nv; i++)
+ prev[i] = i - 1, next[i] = i + 1;
+ next[nv] = 0;
+ /* main loop (until all vertices have been labelled) */
+ nc = 0;
+ while (f != 0)
+ { /* take an unlabelled vertex */
+ i = f;
+ /* and remove it from the list of unlabelled vertices */
+ f = next[i];
+ if (f != 0) prev[f] = 0;
+ /* label the vertex; it begins a new component */
+ prev[i] = -1, next[i] = ++nc;
+ /* breadth first search */
+ list[1] = i, pos1 = pos2 = 1;
+ while (pos1 <= pos2)
+ { /* dequeue vertex i */
+ i = list[pos1++];
+ /* consider all arcs incoming to vertex i */
+ for (a = G->v[i]->in; a != NULL; a = a->h_next)
+ { /* vertex j is adjacent to vertex i */
+ j = a->tail->i;
+ if (prev[j] >= 0)
+ { /* vertex j is unlabelled */
+ /* remove it from the list of unlabelled vertices */
+ if (prev[j] == 0)
+ f = next[j];
+ else
+ next[prev[j]] = next[j];
+ if (next[j] == 0)
+ ;
+ else
+ prev[next[j]] = prev[j];
+ /* label the vertex */
+ prev[j] = -1, next[j] = nc;
+ /* and enqueue it for further consideration */
+ list[++pos2] = j;
+ }
+ }
+ /* consider all arcs outgoing from vertex i */
+ for (a = G->v[i]->out; a != NULL; a = a->t_next)
+ { /* vertex j is adjacent to vertex i */
+ j = a->head->i;
+ if (prev[j] >= 0)
+ { /* vertex j is unlabelled */
+ /* remove it from the list of unlabelled vertices */
+ if (prev[j] == 0)
+ f = next[j];
+ else
+ next[prev[j]] = next[j];
+ if (next[j] == 0)
+ ;
+ else
+ prev[next[j]] = prev[j];
+ /* label the vertex */
+ prev[j] = -1, next[j] = nc;
+ /* and enqueue it for further consideration */
+ list[++pos2] = j;
+ }
+ }
+ }
+ }
+ /* store component numbers */
+ if (v_num >= 0)
+ { for (i = 1; i <= nv; i++)
+ { v = G->v[i];
+ memcpy((char *)v->data + v_num, &next[i], sizeof(int));
+ }
+ }
+ /* free working arrays */
+ xfree(prev);
+ xfree(next);
+ xfree(list);
+done: return nc;
+}
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/api/wrasn.c b/test/monniaux/glpk-4.65/src/api/wrasn.c
new file mode 100644
index 00000000..81433da8
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/api/wrasn.c
@@ -0,0 +1,107 @@
+/* wrasn.c (write assignment problem data in DIMACS format) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* Copyright (C) 2009-2016 Andrew Makhorin, Department for Applied
+* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights
+* reserved. E-mail: <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 "env.h"
+#include "glpk.h"
+
+#define xfprintf glp_format
+
+/***********************************************************************
+* NAME
+*
+* glp_write_asnprob - write assignment problem data in DIMACS format
+*
+* SYNOPSIS
+*
+* int glp_write_asnprob(glp_graph *G, int v_set, int a_cost,
+* const char *fname);
+*
+* DESCRIPTION
+*
+* The routine glp_write_asnprob writes assignment problem data in
+* DIMACS format to a text file.
+*
+* RETURNS
+*
+* If the operation was successful, the routine returns zero. Otherwise
+* it prints an error message and returns non-zero. */
+
+int glp_write_asnprob(glp_graph *G, int v_set, int a_cost, const char
+ *fname)
+{ glp_file *fp;
+ glp_vertex *v;
+ glp_arc *a;
+ int i, k, count = 0, ret;
+ double cost;
+ if (v_set >= 0 && v_set > G->v_size - (int)sizeof(int))
+ xerror("glp_write_asnprob: v_set = %d; invalid offset\n",
+ v_set);
+ if (a_cost >= 0 && a_cost > G->a_size - (int)sizeof(double))
+ xerror("glp_write_asnprob: a_cost = %d; invalid offset\n",
+ a_cost);
+ xprintf("Writing assignment problem data to '%s'...\n", fname);
+ fp = glp_open(fname, "w");
+ if (fp == NULL)
+ { xprintf("Unable to create '%s' - %s\n", fname, get_err_msg());
+ ret = 1;
+ goto done;
+ }
+ xfprintf(fp, "c %s\n",
+ G->name == NULL ? "unknown" : G->name), count++;
+ xfprintf(fp, "p asn %d %d\n", G->nv, G->na), count++;
+ for (i = 1; i <= G->nv; i++)
+ { v = G->v[i];
+ if (v_set >= 0)
+ memcpy(&k, (char *)v->data + v_set, sizeof(int));
+ else
+ k = (v->out != NULL ? 0 : 1);
+ if (k == 0)
+ xfprintf(fp, "n %d\n", i), count++;
+ }
+ for (i = 1; i <= G->nv; i++)
+ { v = G->v[i];
+ for (a = v->out; a != NULL; a = a->t_next)
+ { if (a_cost >= 0)
+ memcpy(&cost, (char *)a->data + a_cost, sizeof(double));
+ else
+ cost = 1.0;
+ xfprintf(fp, "a %d %d %.*g\n",
+ a->tail->i, a->head->i, DBL_DIG, cost), count++;
+ }
+ }
+ xfprintf(fp, "c eof\n"), count++;
+#if 0 /* FIXME */
+ xfflush(fp);
+#endif
+ if (glp_ioerr(fp))
+ { xprintf("Write error on '%s' - %s\n", fname, get_err_msg());
+ ret = 1;
+ goto done;
+ }
+ xprintf("%d lines were written\n", count);
+ ret = 0;
+done: if (fp != NULL) glp_close(fp);
+ return ret;
+}
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/api/wrcc.c b/test/monniaux/glpk-4.65/src/api/wrcc.c
new file mode 100644
index 00000000..2069c8ac
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/api/wrcc.c
@@ -0,0 +1,102 @@
+/* wrcc.c (write graph in DIMACS clique/coloring format) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* Copyright (C) 2009-2016 Andrew Makhorin, Department for Applied
+* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights
+* reserved. E-mail: <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 "env.h"
+#include "glpk.h"
+
+#define xfprintf glp_format
+
+/***********************************************************************
+* NAME
+*
+* glp_write_ccdata - write graph in DIMACS clique/coloring format
+*
+* SYNOPSIS
+*
+* int glp_write_ccdata(glp_graph *G, int v_wgt, const char *fname);
+*
+* DESCRIPTION
+*
+* The routine glp_write_ccdata writes the specified graph in DIMACS
+* clique/coloring format to a text file.
+*
+* RETURNS
+*
+* If the operation was successful, the routine returns zero. Otherwise
+* it prints an error message and returns non-zero. */
+
+int glp_write_ccdata(glp_graph *G, int v_wgt, const char *fname)
+{ glp_file *fp;
+ glp_vertex *v;
+ glp_arc *e;
+ int i, count = 0, ret;
+ double w;
+ if (v_wgt >= 0 && v_wgt > G->v_size - (int)sizeof(double))
+ xerror("glp_write_ccdata: v_wgt = %d; invalid offset\n",
+ v_wgt);
+ xprintf("Writing graph to '%s'\n", fname);
+ fp = glp_open(fname, "w");
+ if (fp == NULL)
+ { xprintf("Unable to create '%s' - %s\n", fname, get_err_msg());
+ ret = 1;
+ goto done;
+ }
+ xfprintf(fp, "c %s\n",
+ G->name == NULL ? "unknown" : G->name), count++;
+ xfprintf(fp, "p edge %d %d\n", G->nv, G->na), count++;
+ if (v_wgt >= 0)
+ { for (i = 1; i <= G->nv; i++)
+ { v = G->v[i];
+ memcpy(&w, (char *)v->data + v_wgt, sizeof(double));
+ if (w != 1.0)
+ xfprintf(fp, "n %d %.*g\n", i, DBL_DIG, w), count++;
+ }
+ }
+ for (i = 1; i <= G->nv; i++)
+ { v = G->v[i];
+ for (e = v->out; e != NULL; e = e->t_next)
+ xfprintf(fp, "e %d %d\n", e->tail->i, e->head->i), count++;
+ }
+ xfprintf(fp, "c eof\n"), count++;
+#if 0 /* FIXME */
+ xfflush(fp);
+#endif
+ if (glp_ioerr(fp))
+ { xprintf("Write error on '%s' - %s\n", fname, get_err_msg());
+ ret = 1;
+ goto done;
+ }
+ xprintf("%d lines were written\n", count);
+ ret = 0;
+done: if (fp != NULL) glp_close(fp);
+ return ret;
+}
+
+/**********************************************************************/
+
+int glp_write_graph(glp_graph *G, const char *fname)
+{ return
+ glp_write_ccdata(G, -1, fname);
+}
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/api/wrcnf.c b/test/monniaux/glpk-4.65/src/api/wrcnf.c
new file mode 100644
index 00000000..c7974386
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/api/wrcnf.c
@@ -0,0 +1,87 @@
+/* wrcnf.c (write CNF-SAT problem data in DIMACS format) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* Copyright (C) 2010-2016 Andrew Makhorin, Department for Applied
+* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights
+* reserved. E-mail: <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 "env.h"
+#include "prob.h"
+
+#define xfprintf glp_format
+
+int glp_write_cnfsat(glp_prob *P, const char *fname)
+{ /* write CNF-SAT problem data in DIMACS format */
+ glp_file *fp = NULL;
+ GLPAIJ *aij;
+ int i, j, len, count = 0, ret;
+ char s[50];
+#if 0 /* 04/IV-2016 */
+ if (P == NULL || P->magic != GLP_PROB_MAGIC)
+ xerror("glp_write_cnfsat: P = %p; invalid problem object\n",
+ P);
+#endif
+ if (glp_check_cnfsat(P) != 0)
+ { xprintf("glp_write_cnfsat: problem object does not encode CNF-"
+ "SAT instance\n");
+ ret = 1;
+ goto done;
+ }
+ xprintf("Writing CNF-SAT problem data to '%s'...\n", fname);
+ fp = glp_open(fname, "w");
+ if (fp == NULL)
+ { xprintf("Unable to create '%s' - %s\n", fname, get_err_msg());
+ ret = 1;
+ goto done;
+ }
+ xfprintf(fp, "c %s\n",
+ P->name == NULL ? "unknown" : P->name), count++;
+ xfprintf(fp, "p cnf %d %d\n", P->n, P->m), count++;
+ for (i = 1; i <= P->m; i++)
+ { len = 0;
+ for (aij = P->row[i]->ptr; aij != NULL; aij = aij->r_next)
+ { j = aij->col->j;
+ if (aij->val < 0.0) j = -j;
+ sprintf(s, "%d", j);
+ if (len > 0 && len + 1 + strlen(s) > 72)
+ xfprintf(fp, "\n"), count++, len = 0;
+ xfprintf(fp, "%s%s", len == 0 ? "" : " ", s);
+ if (len > 0) len++;
+ len += strlen(s);
+ }
+ if (len > 0 && len + 1 + 1 > 72)
+ xfprintf(fp, "\n"), count++, len = 0;
+ xfprintf(fp, "%s0\n", len == 0 ? "" : " "), count++;
+ }
+ xfprintf(fp, "c eof\n"), count++;
+#if 0 /* FIXME */
+ xfflush(fp);
+#endif
+ if (glp_ioerr(fp))
+ { xprintf("Write error on '%s' - %s\n", fname, get_err_msg());
+ ret = 1;
+ goto done;
+ }
+ xprintf("%d lines were written\n", count);
+ ret = 0;
+done: if (fp != NULL) glp_close(fp);
+ return ret;
+}
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/api/wript.c b/test/monniaux/glpk-4.65/src/api/wript.c
new file mode 100644
index 00000000..f2ca802c
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/api/wript.c
@@ -0,0 +1,124 @@
+/* wript.c (write interior-point solution in GLPK format) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* Copyright (C) 2010-2016 Andrew Makhorin, Department for Applied
+* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights
+* reserved. E-mail: <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 "env.h"
+#include "prob.h"
+
+/***********************************************************************
+* NAME
+*
+* glp_write_ipt - write interior-point solution in GLPK format
+*
+* SYNOPSIS
+*
+* int glp_write_ipt(glp_prob *P, const char *fname);
+*
+* DESCRIPTION
+*
+* The routine glp_write_ipt writes interior-point solution to a text
+* file in GLPK format.
+*
+* RETURNS
+*
+* If the operation was successful, the routine returns zero. Otherwise
+* it prints an error message and returns non-zero. */
+
+int glp_write_ipt(glp_prob *P, const char *fname)
+{ glp_file *fp;
+ GLPROW *row;
+ GLPCOL *col;
+ int i, j, count, ret = 1;
+ char *s;
+#if 0 /* 04/IV-2016 */
+ if (P == NULL || P->magic != GLP_PROB_MAGIC)
+ xerror("glp_write_ipt: P = %p; invalid problem object\n", P);
+#endif
+ if (fname == NULL)
+ xerror("glp_write_ipt: fname = %d; invalid parameter\n", fname)
+ ;
+ xprintf("Writing interior-point solution to '%s'...\n", fname);
+ fp = glp_open(fname, "w"), count = 0;
+ if (fp == NULL)
+ { xprintf("Unable to create '%s' - %s\n", fname, get_err_msg());
+ goto done;
+ }
+ /* write comment lines */
+ glp_format(fp, "c %-12s%s\n", "Problem:",
+ P->name == NULL ? "" : P->name), count++;
+ glp_format(fp, "c %-12s%d\n", "Rows:", P->m), count++;
+ glp_format(fp, "c %-12s%d\n", "Columns:", P->n), count++;
+ glp_format(fp, "c %-12s%d\n", "Non-zeros:", P->nnz), count++;
+ switch (P->ipt_stat)
+ { case GLP_OPT: s = "OPTIMAL"; break;
+ case GLP_INFEAS: s = "INFEASIBLE (INTERMEDIATE)"; break;
+ case GLP_NOFEAS: s = "INFEASIBLE (FINAL)"; break;
+ case GLP_UNDEF: s = "UNDEFINED"; break;
+ default: s = "???"; break;
+ }
+ glp_format(fp, "c %-12s%s\n", "Status:", s), count++;
+ switch (P->dir)
+ { case GLP_MIN: s = "MINimum"; break;
+ case GLP_MAX: s = "MAXimum"; break;
+ default: s = "???"; break;
+ }
+ glp_format(fp, "c %-12s%s%s%.10g (%s)\n", "Objective:",
+ P->obj == NULL ? "" : P->obj,
+ P->obj == NULL ? "" : " = ", P->ipt_obj, s), count++;
+ glp_format(fp, "c\n"), count++;
+ /* write solution line */
+ glp_format(fp, "s ipt %d %d ", P->m, P->n), count++;
+ switch (P->ipt_stat)
+ { case GLP_OPT: glp_format(fp, "o"); break;
+ case GLP_INFEAS: glp_format(fp, "i"); break;
+ case GLP_NOFEAS: glp_format(fp, "n"); break;
+ case GLP_UNDEF: glp_format(fp, "u"); break;
+ default: glp_format(fp, "?"); break;
+ }
+ glp_format(fp, " %.*g\n", DBL_DIG, P->ipt_obj);
+ /* write row solution descriptor lines */
+ for (i = 1; i <= P->m; i++)
+ { row = P->row[i];
+ glp_format(fp, "i %d %.*g %.*g\n", i, DBL_DIG, row->pval,
+ DBL_DIG, row->dval), count++;
+ }
+ /* write column solution descriptor lines */
+ for (j = 1; j <= P->n; j++)
+ { col = P->col[j];
+ glp_format(fp, "j %d %.*g %.*g\n", j, DBL_DIG, col->pval,
+ DBL_DIG, col->dval), count++;
+ }
+ /* write end line */
+ glp_format(fp, "e o f\n"), count++;
+ if (glp_ioerr(fp))
+ { xprintf("Write error on '%s' - %s\n", fname, get_err_msg());
+ goto done;
+ }
+ /* interior-point solution has been successfully written */
+ xprintf("%d lines were written\n", count);
+ ret = 0;
+done: if (fp != NULL)
+ glp_close(fp);
+ return ret;
+}
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/api/wrmaxf.c b/test/monniaux/glpk-4.65/src/api/wrmaxf.c
new file mode 100644
index 00000000..d3101ca8
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/api/wrmaxf.c
@@ -0,0 +1,104 @@
+/* wrmaxf.c (write maximum flow problem data in DIMACS format) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* Copyright (C) 2009-2016 Andrew Makhorin, Department for Applied
+* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights
+* reserved. E-mail: <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 "env.h"
+#include "glpk.h"
+
+#define xfprintf glp_format
+
+/***********************************************************************
+* NAME
+*
+* glp_write_maxflow - write maximum flow problem data in DIMACS format
+*
+* SYNOPSIS
+*
+* int glp_write_maxflow(glp_graph *G, int s, int t, int a_cap,
+* const char *fname);
+*
+* DESCRIPTION
+*
+* The routine glp_write_maxflow writes maximum flow problem data in
+* DIMACS format to a text file.
+*
+* RETURNS
+*
+* If the operation was successful, the routine returns zero. Otherwise
+* it prints an error message and returns non-zero. */
+
+int glp_write_maxflow(glp_graph *G, int s, int t, int a_cap,
+ const char *fname)
+{ glp_file *fp;
+ glp_vertex *v;
+ glp_arc *a;
+ int i, count = 0, ret;
+ double cap;
+ if (!(1 <= s && s <= G->nv))
+ xerror("glp_write_maxflow: s = %d; source node number out of r"
+ "ange\n", s);
+ if (!(1 <= t && t <= G->nv))
+ xerror("glp_write_maxflow: t = %d: sink node number out of ran"
+ "ge\n", t);
+ if (a_cap >= 0 && a_cap > G->a_size - (int)sizeof(double))
+ xerror("glp_write_mincost: a_cap = %d; invalid offset\n",
+ a_cap);
+ xprintf("Writing maximum flow problem data to '%s'...\n",
+ fname);
+ fp = glp_open(fname, "w");
+ if (fp == NULL)
+ { xprintf("Unable to create '%s' - %s\n", fname, get_err_msg());
+ ret = 1;
+ goto done;
+ }
+ xfprintf(fp, "c %s\n",
+ G->name == NULL ? "unknown" : G->name), count++;
+ xfprintf(fp, "p max %d %d\n", G->nv, G->na), count++;
+ xfprintf(fp, "n %d s\n", s), count++;
+ xfprintf(fp, "n %d t\n", t), count++;
+ for (i = 1; i <= G->nv; i++)
+ { v = G->v[i];
+ for (a = v->out; a != NULL; a = a->t_next)
+ { if (a_cap >= 0)
+ memcpy(&cap, (char *)a->data + a_cap, sizeof(double));
+ else
+ cap = 1.0;
+ xfprintf(fp, "a %d %d %.*g\n",
+ a->tail->i, a->head->i, DBL_DIG, cap), count++;
+ }
+ }
+ xfprintf(fp, "c eof\n"), count++;
+#if 0 /* FIXME */
+ xfflush(fp);
+#endif
+ if (glp_ioerr(fp))
+ { xprintf("Write error on '%s' - %s\n", fname, get_err_msg());
+ ret = 1;
+ goto done;
+ }
+ xprintf("%d lines were written\n", count);
+ ret = 0;
+done: if (fp != NULL) glp_close(fp);
+ return ret;
+}
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/api/wrmcf.c b/test/monniaux/glpk-4.65/src/api/wrmcf.c
new file mode 100644
index 00000000..0da37f42
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/api/wrmcf.c
@@ -0,0 +1,122 @@
+/* wrmcf.c (write min-cost flow problem data in DIMACS format) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* Copyright (C) 2009-2016 Andrew Makhorin, Department for Applied
+* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights
+* reserved. E-mail: <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 "env.h"
+#include "glpk.h"
+
+#define xfprintf glp_format
+
+/***********************************************************************
+* NAME
+*
+* glp_write_mincost - write min-cost flow probl. data in DIMACS format
+*
+* SYNOPSIS
+*
+* int glp_write_mincost(glp_graph *G, int v_rhs, int a_low, int a_cap,
+* int a_cost, const char *fname);
+*
+* DESCRIPTION
+*
+* The routine glp_write_mincost writes minimum cost flow problem data
+* in DIMACS format to a text file.
+*
+* RETURNS
+*
+* If the operation was successful, the routine returns zero. Otherwise
+* it prints an error message and returns non-zero. */
+
+int glp_write_mincost(glp_graph *G, int v_rhs, int a_low, int a_cap,
+ int a_cost, const char *fname)
+{ glp_file *fp;
+ glp_vertex *v;
+ glp_arc *a;
+ int i, count = 0, ret;
+ double rhs, low, cap, cost;
+ if (v_rhs >= 0 && v_rhs > G->v_size - (int)sizeof(double))
+ xerror("glp_write_mincost: v_rhs = %d; invalid offset\n",
+ v_rhs);
+ if (a_low >= 0 && a_low > G->a_size - (int)sizeof(double))
+ xerror("glp_write_mincost: a_low = %d; invalid offset\n",
+ a_low);
+ if (a_cap >= 0 && a_cap > G->a_size - (int)sizeof(double))
+ xerror("glp_write_mincost: a_cap = %d; invalid offset\n",
+ a_cap);
+ if (a_cost >= 0 && a_cost > G->a_size - (int)sizeof(double))
+ xerror("glp_write_mincost: a_cost = %d; invalid offset\n",
+ a_cost);
+ xprintf("Writing min-cost flow problem data to '%s'...\n",
+ fname);
+ fp = glp_open(fname, "w");
+ if (fp == NULL)
+ { xprintf("Unable to create '%s' - %s\n", fname, get_err_msg());
+ ret = 1;
+ goto done;
+ }
+ xfprintf(fp, "c %s\n",
+ G->name == NULL ? "unknown" : G->name), count++;
+ xfprintf(fp, "p min %d %d\n", G->nv, G->na), count++;
+ if (v_rhs >= 0)
+ { for (i = 1; i <= G->nv; i++)
+ { v = G->v[i];
+ memcpy(&rhs, (char *)v->data + v_rhs, sizeof(double));
+ if (rhs != 0.0)
+ xfprintf(fp, "n %d %.*g\n", i, DBL_DIG, rhs), count++;
+ }
+ }
+ for (i = 1; i <= G->nv; i++)
+ { v = G->v[i];
+ for (a = v->out; a != NULL; a = a->t_next)
+ { if (a_low >= 0)
+ memcpy(&low, (char *)a->data + a_low, sizeof(double));
+ else
+ low = 0.0;
+ if (a_cap >= 0)
+ memcpy(&cap, (char *)a->data + a_cap, sizeof(double));
+ else
+ cap = 1.0;
+ if (a_cost >= 0)
+ memcpy(&cost, (char *)a->data + a_cost, sizeof(double));
+ else
+ cost = 0.0;
+ xfprintf(fp, "a %d %d %.*g %.*g %.*g\n",
+ a->tail->i, a->head->i, DBL_DIG, low, DBL_DIG, cap,
+ DBL_DIG, cost), count++;
+ }
+ }
+ xfprintf(fp, "c eof\n"), count++;
+#if 0 /* FIXME */
+ xfflush(fp);
+#endif
+ if (glp_ioerr(fp))
+ { xprintf("Write error on '%s' - %s\n", fname, get_err_msg());
+ ret = 1;
+ goto done;
+ }
+ xprintf("%d lines were written\n", count);
+ ret = 0;
+done: if (fp != NULL) glp_close(fp);
+ return ret;
+}
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/api/wrmip.c b/test/monniaux/glpk-4.65/src/api/wrmip.c
new file mode 100644
index 00000000..407a5fec
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/api/wrmip.c
@@ -0,0 +1,122 @@
+/* wrmip.c (write MIP solution in GLPK format) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* Copyright (C) 2010-2016 Andrew Makhorin, Department for Applied
+* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights
+* reserved. E-mail: <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 "env.h"
+#include "prob.h"
+
+/***********************************************************************
+* NAME
+*
+* glp_write_mip - write MIP solution in GLPK format
+*
+* SYNOPSIS
+*
+* int glp_write_mip(glp_prob *P, const char *fname);
+*
+* DESCRIPTION
+*
+* The routine glp_write_mip writes MIP solution to a text file in GLPK
+* format.
+*
+* RETURNS
+*
+* If the operation was successful, the routine returns zero. Otherwise
+* it prints an error message and returns non-zero. */
+
+int glp_write_mip(glp_prob *P, const char *fname)
+{ glp_file *fp;
+ GLPROW *row;
+ GLPCOL *col;
+ int i, j, count, ret = 1;
+ char *s;
+#if 0 /* 04/IV-2016 */
+ if (P == NULL || P->magic != GLP_PROB_MAGIC)
+ xerror("glp_write_mip: P = %p; invalid problem object\n", P);
+#endif
+ if (fname == NULL)
+ xerror("glp_write_mip: fname = %d; invalid parameter\n", fname)
+ ;
+ xprintf("Writing MIP solution to '%s'...\n", fname);
+ fp = glp_open(fname, "w"), count = 0;
+ if (fp == NULL)
+ { xprintf("Unable to create '%s' - %s\n", fname, get_err_msg());
+ goto done;
+ }
+ /* write comment lines */
+ glp_format(fp, "c %-12s%s\n", "Problem:",
+ P->name == NULL ? "" : P->name), count++;
+ glp_format(fp, "c %-12s%d\n", "Rows:", P->m), count++;
+ glp_format(fp, "c %-12s%d\n", "Columns:", P->n), count++;
+ glp_format(fp, "c %-12s%d\n", "Non-zeros:", P->nnz), count++;
+ switch (P->mip_stat)
+ { case GLP_OPT: s = "INTEGER OPTIMAL"; break;
+ case GLP_FEAS: s = "INTEGER NON-OPTIMAL"; break;
+ case GLP_NOFEAS: s = "INTEGER EMPTY"; break;
+ case GLP_UNDEF: s = "INTEGER UNDEFINED"; break;
+ default: s = "???"; break;
+ }
+ glp_format(fp, "c %-12s%s\n", "Status:", s), count++;
+ switch (P->dir)
+ { case GLP_MIN: s = "MINimum"; break;
+ case GLP_MAX: s = "MAXimum"; break;
+ default: s = "???"; break;
+ }
+ glp_format(fp, "c %-12s%s%s%.10g (%s)\n", "Objective:",
+ P->obj == NULL ? "" : P->obj,
+ P->obj == NULL ? "" : " = ", P->mip_obj, s), count++;
+ glp_format(fp, "c\n"), count++;
+ /* write solution line */
+ glp_format(fp, "s mip %d %d ", P->m, P->n), count++;
+ switch (P->mip_stat)
+ { case GLP_OPT: glp_format(fp, "o"); break;
+ case GLP_FEAS: glp_format(fp, "f"); break;
+ case GLP_NOFEAS: glp_format(fp, "n"); break;
+ case GLP_UNDEF: glp_format(fp, "u"); break;
+ default: glp_format(fp, "?"); break;
+ }
+ glp_format(fp, " %.*g\n", DBL_DIG, P->mip_obj);
+ /* write row solution descriptor lines */
+ for (i = 1; i <= P->m; i++)
+ { row = P->row[i];
+ glp_format(fp, "i %d %.*g\n", i, DBL_DIG, row->mipx), count++;
+ }
+ /* write column solution descriptor lines */
+ for (j = 1; j <= P->n; j++)
+ { col = P->col[j];
+ glp_format(fp, "j %d %.*g\n", j, DBL_DIG, col->mipx), count++;
+ }
+ /* write end line */
+ glp_format(fp, "e o f\n"), count++;
+ if (glp_ioerr(fp))
+ { xprintf("Write error on '%s' - %s\n", fname, get_err_msg());
+ goto done;
+ }
+ /* MIP solution has been successfully written */
+ xprintf("%d lines were written\n", count);
+ ret = 0;
+done: if (fp != NULL)
+ glp_close(fp);
+ return ret;
+}
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/api/wrprob.c b/test/monniaux/glpk-4.65/src/api/wrprob.c
new file mode 100644
index 00000000..99983d35
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/api/wrprob.c
@@ -0,0 +1,166 @@
+/* wrprob.c (write problem data in GLPK format) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* Copyright (C) 2010-2016 Andrew Makhorin, Department for Applied
+* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights
+* reserved. E-mail: <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 "env.h"
+#include "prob.h"
+
+#define xfprintf glp_format
+
+/***********************************************************************
+* NAME
+*
+* glp_write_prob - write problem data in GLPK format
+*
+* SYNOPSIS
+*
+* int glp_write_prob(glp_prob *P, int flags, const char *fname);
+*
+* The routine glp_write_prob writes problem data in GLPK LP/MIP format
+* to a text file.
+*
+* RETURNS
+*
+* If the operation was successful, the routine returns zero. Otherwise
+* it prints an error message and returns non-zero. */
+
+int glp_write_prob(glp_prob *P, int flags, const char *fname)
+{ glp_file *fp;
+ GLPROW *row;
+ GLPCOL *col;
+ GLPAIJ *aij;
+ int mip, i, j, count, ret;
+#if 0 /* 04/IV-2016 */
+ if (P == NULL || P->magic != GLP_PROB_MAGIC)
+ xerror("glp_write_prob: P = %p; invalid problem object\n",
+ P);
+#endif
+ if (flags != 0)
+ xerror("glp_write_prob: flags = %d; invalid parameter\n",
+ flags);
+ if (fname == NULL)
+ xerror("glp_write_prob: fname = %d; invalid parameter\n",
+ fname);
+ xprintf("Writing problem data to '%s'...\n", fname);
+ fp = glp_open(fname, "w"), count = 0;
+ if (fp == NULL)
+ { xprintf("Unable to create '%s' - %s\n", fname, get_err_msg());
+ ret = 1;
+ goto done;
+ }
+ /* write problem line */
+ mip = (glp_get_num_int(P) > 0);
+ xfprintf(fp, "p %s %s %d %d %d\n", !mip ? "lp" : "mip",
+ P->dir == GLP_MIN ? "min" : P->dir == GLP_MAX ? "max" : "???",
+ P->m, P->n, P->nnz), count++;
+ if (P->name != NULL)
+ xfprintf(fp, "n p %s\n", P->name), count++;
+ if (P->obj != NULL)
+ xfprintf(fp, "n z %s\n", P->obj), count++;
+ /* write row descriptors */
+ for (i = 1; i <= P->m; i++)
+ { row = P->row[i];
+ if (row->type == GLP_FX && row->lb == 0.0)
+ goto skip1;
+ xfprintf(fp, "i %d ", i), count++;
+ if (row->type == GLP_FR)
+ xfprintf(fp, "f\n");
+ else if (row->type == GLP_LO)
+ xfprintf(fp, "l %.*g\n", DBL_DIG, row->lb);
+ else if (row->type == GLP_UP)
+ xfprintf(fp, "u %.*g\n", DBL_DIG, row->ub);
+ else if (row->type == GLP_DB)
+ xfprintf(fp, "d %.*g %.*g\n", DBL_DIG, row->lb, DBL_DIG,
+ row->ub);
+ else if (row->type == GLP_FX)
+ xfprintf(fp, "s %.*g\n", DBL_DIG, row->lb);
+ else
+ xassert(row != row);
+skip1: if (row->name != NULL)
+ xfprintf(fp, "n i %d %s\n", i, row->name), count++;
+ }
+ /* write column descriptors */
+ for (j = 1; j <= P->n; j++)
+ { col = P->col[j];
+ if (!mip && col->type == GLP_LO && col->lb == 0.0)
+ goto skip2;
+ if (mip && col->kind == GLP_IV && col->type == GLP_DB &&
+ col->lb == 0.0 && col->ub == 1.0)
+ goto skip2;
+ xfprintf(fp, "j %d ", j), count++;
+ if (mip)
+ { if (col->kind == GLP_CV)
+ xfprintf(fp, "c ");
+ else if (col->kind == GLP_IV)
+ xfprintf(fp, "i ");
+ else
+ xassert(col != col);
+ }
+ if (col->type == GLP_FR)
+ xfprintf(fp, "f\n");
+ else if (col->type == GLP_LO)
+ xfprintf(fp, "l %.*g\n", DBL_DIG, col->lb);
+ else if (col->type == GLP_UP)
+ xfprintf(fp, "u %.*g\n", DBL_DIG, col->ub);
+ else if (col->type == GLP_DB)
+ xfprintf(fp, "d %.*g %.*g\n", DBL_DIG, col->lb, DBL_DIG,
+ col->ub);
+ else if (col->type == GLP_FX)
+ xfprintf(fp, "s %.*g\n", DBL_DIG, col->lb);
+ else
+ xassert(col != col);
+skip2: if (col->name != NULL)
+ xfprintf(fp, "n j %d %s\n", j, col->name), count++;
+ }
+ /* write objective coefficient descriptors */
+ if (P->c0 != 0.0)
+ xfprintf(fp, "a 0 0 %.*g\n", DBL_DIG, P->c0), count++;
+ for (j = 1; j <= P->n; j++)
+ { col = P->col[j];
+ if (col->coef != 0.0)
+ xfprintf(fp, "a 0 %d %.*g\n", j, DBL_DIG, col->coef),
+ count++;
+ }
+ /* write constraint coefficient descriptors */
+ for (i = 1; i <= P->m; i++)
+ { row = P->row[i];
+ for (aij = row->ptr; aij != NULL; aij = aij->r_next)
+ xfprintf(fp, "a %d %d %.*g\n", i, aij->col->j, DBL_DIG,
+ aij->val), count++;
+ }
+ /* write end line */
+ xfprintf(fp, "e o f\n"), count++;
+#if 0 /* FIXME */
+ xfflush(fp);
+#endif
+ if (glp_ioerr(fp))
+ { xprintf("Write error on '%s' - %s\n", fname, get_err_msg());
+ ret = 1;
+ goto done;
+ }
+ xprintf("%d lines were written\n", count);
+ ret = 0;
+done: if (fp != NULL) glp_close(fp);
+ return ret;
+}
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/api/wrsol.c b/test/monniaux/glpk-4.65/src/api/wrsol.c
new file mode 100644
index 00000000..66c69233
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/api/wrsol.c
@@ -0,0 +1,174 @@
+/* wrsol.c (write basic solution in GLPK format) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* Copyright (C) 2010-2016 Andrew Makhorin, Department for Applied
+* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights
+* reserved. E-mail: <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 "env.h"
+#include "prob.h"
+
+/***********************************************************************
+* NAME
+*
+* glp_write_sol - write basic solution in GLPK format
+*
+* SYNOPSIS
+*
+* int glp_write_sol(glp_prob *P, const char *fname);
+*
+* DESCRIPTION
+*
+* The routine glp_write_sol writes basic solution to a text file in
+* GLPK format.
+*
+* RETURNS
+*
+* If the operation was successful, the routine returns zero. Otherwise
+* it prints an error message and returns non-zero. */
+
+int glp_write_sol(glp_prob *P, const char *fname)
+{ glp_file *fp;
+ GLPROW *row;
+ GLPCOL *col;
+ int i, j, count, ret = 1;
+ char *s;
+#if 0 /* 04/IV-2016 */
+ if (P == NULL || P->magic != GLP_PROB_MAGIC)
+ xerror("glp_write_sol: P = %p; invalid problem object\n", P);
+#endif
+ if (fname == NULL)
+ xerror("glp_write_sol: fname = %d; invalid parameter\n", fname)
+ ;
+ xprintf("Writing basic solution to '%s'...\n", fname);
+ fp = glp_open(fname, "w"), count = 0;
+ if (fp == NULL)
+ { xprintf("Unable to create '%s' - %s\n", fname, get_err_msg());
+ goto done;
+ }
+ /* write comment lines */
+ glp_format(fp, "c %-12s%s\n", "Problem:",
+ P->name == NULL ? "" : P->name), count++;
+ glp_format(fp, "c %-12s%d\n", "Rows:", P->m), count++;
+ glp_format(fp, "c %-12s%d\n", "Columns:", P->n), count++;
+ glp_format(fp, "c %-12s%d\n", "Non-zeros:", P->nnz), count++;
+ switch (glp_get_status(P))
+ { case GLP_OPT: s = "OPTIMAL"; break;
+ case GLP_FEAS: s = "FEASIBLE"; break;
+ case GLP_INFEAS: s = "INFEASIBLE (INTERMEDIATE)"; break;
+ case GLP_NOFEAS: s = "INFEASIBLE (FINAL)"; break;
+ case GLP_UNBND: s = "UNBOUNDED"; break;
+ case GLP_UNDEF: s = "UNDEFINED"; break;
+ default: s = "???"; break;
+ }
+ glp_format(fp, "c %-12s%s\n", "Status:", s), count++;
+ switch (P->dir)
+ { case GLP_MIN: s = "MINimum"; break;
+ case GLP_MAX: s = "MAXimum"; break;
+ default: s = "???"; break;
+ }
+ glp_format(fp, "c %-12s%s%s%.10g (%s)\n", "Objective:",
+ P->obj == NULL ? "" : P->obj,
+ P->obj == NULL ? "" : " = ", P->obj_val, s), count++;
+ glp_format(fp, "c\n"), count++;
+ /* write solution line */
+ glp_format(fp, "s bas %d %d ", P->m, P->n), count++;
+ switch (P->pbs_stat)
+ { case GLP_UNDEF: glp_format(fp, "u"); break;
+ case GLP_FEAS: glp_format(fp, "f"); break;
+ case GLP_INFEAS: glp_format(fp, "i"); break;
+ case GLP_NOFEAS: glp_format(fp, "n"); break;
+ default: glp_format(fp, "?"); break;
+ }
+ glp_format(fp, " ");
+ switch (P->dbs_stat)
+ { case GLP_UNDEF: glp_format(fp, "u"); break;
+ case GLP_FEAS: glp_format(fp, "f"); break;
+ case GLP_INFEAS: glp_format(fp, "i"); break;
+ case GLP_NOFEAS: glp_format(fp, "n"); break;
+ default: glp_format(fp, "?"); break;
+ }
+ glp_format(fp, " %.*g\n", DBL_DIG, P->obj_val);
+ /* write row solution descriptor lines */
+ for (i = 1; i <= P->m; i++)
+ { row = P->row[i];
+ glp_format(fp, "i %d ", i), count++;
+ switch (row->stat)
+ { case GLP_BS:
+ glp_format(fp, "b");
+ break;
+ case GLP_NL:
+ glp_format(fp, "l");
+ break;
+ case GLP_NU:
+ glp_format(fp, "u");
+ break;
+ case GLP_NF:
+ glp_format(fp, "f");
+ break;
+ case GLP_NS:
+ glp_format(fp, "s");
+ break;
+ default:
+ xassert(row != row);
+ }
+ glp_format(fp, " %.*g %.*g\n", DBL_DIG, row->prim, DBL_DIG,
+ row->dual);
+ }
+ /* write column solution descriptor lines */
+ for (j = 1; j <= P->n; j++)
+ { col = P->col[j];
+ glp_format(fp, "j %d ", j), count++;
+ switch (col->stat)
+ { case GLP_BS:
+ glp_format(fp, "b");
+ break;
+ case GLP_NL:
+ glp_format(fp, "l");
+ break;
+ case GLP_NU:
+ glp_format(fp, "u");
+ break;
+ case GLP_NF:
+ glp_format(fp, "f");
+ break;
+ case GLP_NS:
+ glp_format(fp, "s");
+ break;
+ default:
+ xassert(col != col);
+ }
+ glp_format(fp, " %.*g %.*g\n", DBL_DIG, col->prim, DBL_DIG,
+ col->dual);
+ }
+ /* write end line */
+ glp_format(fp, "e o f\n"), count++;
+ if (glp_ioerr(fp))
+ { xprintf("Write error on '%s' - %s\n", fname, get_err_msg());
+ goto done;
+ }
+ /* basic solution has been successfully written */
+ xprintf("%d lines were written\n", count);
+ ret = 0;
+done: if (fp != NULL)
+ glp_close(fp);
+ return ret;
+}
+
+/* eof */