GNU Octave  6.2.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
__glpk__.cc
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (C) 2005-2021 The Octave Project Developers
4 //
5 // See the file COPYRIGHT.md in the top-level directory of this
6 // distribution or <https://octave.org/copyright/>.
7 //
8 // This file is part of Octave.
9 //
10 // Octave is free software: you can redistribute it and/or modify it
11 // under the terms of the GNU General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // Octave is distributed in the hope that it will be useful, but
16 // WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU General Public License for more details.
19 //
20 // You should have received a copy of the GNU General Public License
21 // along with Octave; see the file COPYING. If not, see
22 // <https://www.gnu.org/licenses/>.
23 //
24 ////////////////////////////////////////////////////////////////////////
25 
26 #if defined (HAVE_CONFIG_H)
27 # include "config.h"
28 #endif
29 
30 #include <ctime>
31 
32 #include <limits>
33 
34 #include "Array.h"
35 #include "chMatrix.h"
36 #include "dColVector.h"
37 #include "dMatrix.h"
38 #include "dSparse.h"
39 #include "lo-ieee.h"
40 
41 #include "defun-dld.h"
42 #include "error.h"
43 #include "errwarn.h"
44 #include "oct-map.h"
45 #include "ov.h"
46 #include "ovl.h"
47 
48 #if defined (HAVE_GLPK)
49 
50 extern "C"
51 {
52 #if defined (HAVE_GLPK_GLPK_H)
53 # include <glpk/glpk.h>
54 #else
55 # include <glpk.h>
56 #endif
57 }
58 
60 {
61  int msglev;
62  int dual;
63  int price;
64  int itlim;
65  int outfrq;
66  int branch;
67  int btrack;
68  int presol;
69  int rtest;
70  int tmlim;
71  int outdly;
72  double tolbnd;
73  double toldj;
74  double tolpiv;
75  double objll;
76  double objul;
77  double tolint;
78  double tolobj;
79 };
80 
81 int
82 glpk (int sense, int n, int m, double *c, int nz, int *rn, int *cn,
83  double *a, double *b, char *ctype, int *freeLB, double *lb,
84  int *freeUB, double *ub, int *vartype, int isMIP, int lpsolver,
85  int save_pb, int scale, const control_params *par,
86  double *xmin, double *fmin, int *status,
87  double *lambda, double *redcosts, double *time)
88 {
89  int typx = 0;
90  int errnum = 0;
91 
92  clock_t t_start = clock ();
93 
94  glp_prob *lp = glp_create_prob ();
95 
96  // Set the sense of optimization
97  if (sense == 1)
98  glp_set_obj_dir (lp, GLP_MIN);
99  else
100  glp_set_obj_dir (lp, GLP_MAX);
101 
102  glp_add_cols (lp, n);
103  for (int i = 0; i < n; i++)
104  {
105  // Define type of the structural variables
106  if (! freeLB[i] && ! freeUB[i])
107  {
108  if (lb[i] != ub[i])
109  glp_set_col_bnds (lp, i+1, GLP_DB, lb[i], ub[i]);
110  else
111  glp_set_col_bnds (lp, i+1, GLP_FX, lb[i], ub[i]);
112  }
113  else
114  {
115  if (! freeLB[i] && freeUB[i])
116  glp_set_col_bnds (lp, i+1, GLP_LO, lb[i], ub[i]);
117  else
118  {
119  if (freeLB[i] && ! freeUB[i])
120  glp_set_col_bnds (lp, i+1, GLP_UP, lb[i], ub[i]);
121  else
122  glp_set_col_bnds (lp, i+1, GLP_FR, lb[i], ub[i]);
123  }
124  }
125 
126  // -- Set the objective coefficient of the corresponding
127  // -- structural variable. No constant term is assumed.
128  glp_set_obj_coef(lp,i+1,c[i]);
129 
130  if (isMIP)
131  glp_set_col_kind (lp, i+1, vartype[i]);
132  }
133 
134  glp_add_rows (lp, m);
135 
136  for (int i = 0; i < m; i++)
137  {
138  // If the i-th row has no lower bound (types F,U), the
139  // corrispondent parameter will be ignored. If the i-th row has
140  // no upper bound (types F,L), the corrispondent parameter will be
141  // ignored. If the i-th row is of S type, the i-th LB is used,
142  // but the i-th UB is ignored.
143 
144  switch (ctype[i])
145  {
146  case 'F':
147  typx = GLP_FR;
148  break;
149 
150  case 'U':
151  typx = GLP_UP;
152  break;
153 
154  case 'L':
155  typx = GLP_LO;
156  break;
157 
158  case 'S':
159  typx = GLP_FX;
160  break;
161 
162  case 'D':
163  typx = GLP_DB;
164  break;
165  }
166 
167  glp_set_row_bnds (lp, i+1, typx, b[i], b[i]);
168 
169  }
170 
171  glp_load_matrix (lp, nz, rn, cn, a);
172 
173  if (save_pb)
174  {
175  static char tmp[] = "outpb.lp";
176  if (glp_write_lp (lp, nullptr, tmp) != 0)
177  error ("__glpk__: unable to write problem");
178  }
179 
180  // scale the problem data
181  if (! par->presol || lpsolver != 1)
182  glp_scale_prob (lp, scale);
183 
184  // build advanced initial basis (if required)
185  if (lpsolver == 1 && ! par->presol)
186  glp_adv_basis (lp, 0);
187 
188  // For MIP problems without a presolver, a first pass with glp_simplex
189  // is required
190  if ((! isMIP && lpsolver == 1)
191  || (isMIP && ! par->presol))
192  {
193  glp_smcp smcp;
194  glp_init_smcp (&smcp);
195  smcp.msg_lev = par->msglev;
196  smcp.meth = par->dual;
197  smcp.pricing = par->price;
198  smcp.r_test = par->rtest;
199  smcp.tol_bnd = par->tolbnd;
200  smcp.tol_dj = par->toldj;
201  smcp.tol_piv = par->tolpiv;
202  smcp.obj_ll = par->objll;
203  smcp.obj_ul = par->objul;
204  smcp.it_lim = par->itlim;
205  smcp.tm_lim = par->tmlim;
206  smcp.out_frq = par->outfrq;
207  smcp.out_dly = par->outdly;
208  smcp.presolve = par->presol;
209  errnum = glp_simplex (lp, &smcp);
210  }
211 
212  if (isMIP)
213  {
214  glp_iocp iocp;
215  glp_init_iocp (&iocp);
216  iocp.msg_lev = par->msglev;
217  iocp.br_tech = par->branch;
218  iocp.bt_tech = par->btrack;
219  iocp.tol_int = par->tolint;
220  iocp.tol_obj = par->tolobj;
221  iocp.tm_lim = par->tmlim;
222  iocp.out_frq = par->outfrq;
223  iocp.out_dly = par->outdly;
224  iocp.presolve = par->presol;
225  errnum = glp_intopt (lp, &iocp);
226  }
227 
228  if (! isMIP && lpsolver == 2)
229  {
230  glp_iptcp iptcp;
231  glp_init_iptcp (&iptcp);
232  iptcp.msg_lev = par->msglev;
233  errnum = glp_interior (lp, &iptcp);
234  }
235 
236  if (errnum == 0)
237  {
238  if (isMIP)
239  {
240  *status = glp_mip_status (lp);
241  *fmin = glp_mip_obj_val (lp);
242  }
243  else
244  {
245  if (lpsolver == 1)
246  {
247  *status = glp_get_status (lp);
248  *fmin = glp_get_obj_val (lp);
249  }
250  else
251  {
252  *status = glp_ipt_status (lp);
253  *fmin = glp_ipt_obj_val (lp);
254  }
255  }
256 
257  if (isMIP)
258  {
259  for (int i = 0; i < n; i++)
260  xmin[i] = glp_mip_col_val (lp, i+1);
261  }
262  else
263  {
264  // Primal values
265  for (int i = 0; i < n; i++)
266  {
267  if (lpsolver == 1)
268  xmin[i] = glp_get_col_prim (lp, i+1);
269  else
270  xmin[i] = glp_ipt_col_prim (lp, i+1);
271  }
272 
273  // Dual values
274  for (int i = 0; i < m; i++)
275  {
276  if (lpsolver == 1)
277  lambda[i] = glp_get_row_dual (lp, i+1);
278  else
279  lambda[i] = glp_ipt_row_dual (lp, i+1);
280  }
281 
282  // Reduced costs
283  for (int i = 0; i < glp_get_num_cols (lp); i++)
284  {
285  if (lpsolver == 1)
286  redcosts[i] = glp_get_col_dual (lp, i+1);
287  else
288  redcosts[i] = glp_ipt_col_dual (lp, i+1);
289  }
290  }
291  }
292 
293  *time = (clock () - t_start) / CLOCKS_PER_SEC;
294 
295  glp_delete_prob (lp);
296  // Request that GLPK free all memory resources.
297  // This prevents reported memory leaks, but isn't strictly necessary.
298  // The memory blocks used are allocated once and don't grow with further
299  // calls to glpk so they would be reclaimed anyways when Octave exits.
300  glp_free_env ();
301 
302  return errnum;
303 }
304 
305 #endif
306 
307 #define OCTAVE_GLPK_GET_REAL_PARAM(NAME, VAL) \
308  do \
309  { \
310  octave_value tmp = PARAM.getfield (NAME); \
311  \
312  if (tmp.is_defined ()) \
313  { \
314  if (! tmp.isempty ()) \
315  VAL = tmp.xscalar_value ("glpk: invalid value in PARAM" NAME); \
316  else \
317  error ("glpk: invalid value in PARAM" NAME); \
318  } \
319  } \
320  while (0)
321 
322 #define OCTAVE_GLPK_GET_INT_PARAM(NAME, VAL) \
323  do \
324  { \
325  octave_value tmp = PARAM.getfield (NAME); \
326  \
327  if (tmp.is_defined ()) \
328  { \
329  if (! tmp.isempty ()) \
330  VAL = tmp.xint_value ("glpk: invalid value in PARAM" NAME); \
331  else \
332  error ("glpk: invalid value in PARAM" NAME); \
333  } \
334  } \
335  while (0)
336 
337 DEFUN_DLD (__glpk__, args, ,
338  doc: /* -*- texinfo -*-
339 @deftypefn {} {[@var{values}] =} __glpk__ (@var{args})
340 Undocumented internal function.
341 @end deftypefn */)
342 {
343 #if defined (HAVE_GLPK)
344 
345  // FIXME: Should we even need checking for an internal function?
346  if (args.length () != 9)
347  print_usage ();
348 
349  // 1st Input. A column array containing the objective function coefficients.
350  int mrowsc = args(0).rows ();
351 
352  Matrix C = args(0).xmatrix_value ("__glpk__: invalid value of C");
353 
354  double *c = C.fortran_vec ();
355  Array<int> rn;
356  Array<int> cn;
357  ColumnVector a;
358  int mrowsA;
359  int nz = 0;
360 
361  // 2nd Input. A matrix containing the constraints coefficients.
362  // If matrix A is NOT a sparse matrix
363  if (args(1).issparse ())
364  {
365  SparseMatrix A = args(1).xsparse_matrix_value ("__glpk__: invalid value of A");
366 
367  mrowsA = A.rows ();
368  octave_idx_type Anc = A.cols ();
369  octave_idx_type Anz = A.nnz ();
370  rn.resize (dim_vector (Anz+1, 1));
371  cn.resize (dim_vector (Anz+1, 1));
372  a.resize (Anz+1, 0.0);
373 
374  if (Anc != mrowsc)
375  error ("__glpk__: invalid value of A");
376 
377  for (octave_idx_type j = 0; j < Anc; j++)
378  for (octave_idx_type i = A.cidx (j); i < A.cidx (j+1); i++)
379  {
380  nz++;
381  rn(nz) = A.ridx (i) + 1;
382  cn(nz) = j + 1;
383  a(nz) = A.data(i);
384  }
385  }
386  else
387  {
388  Matrix A = args(1).xmatrix_value ("__glpk__: invalid value of A");
389 
390  mrowsA = A.rows ();
391  rn.resize (dim_vector (mrowsA*mrowsc+1, 1));
392  cn.resize (dim_vector (mrowsA*mrowsc+1, 1));
393  a.resize (mrowsA*mrowsc+1, 0.0);
394 
395  for (int i = 0; i < mrowsA; i++)
396  {
397  for (int j = 0; j < mrowsc; j++)
398  {
399  if (A(i,j) != 0)
400  {
401  nz++;
402  rn(nz) = i + 1;
403  cn(nz) = j + 1;
404  a(nz) = A(i,j);
405  }
406  }
407  }
408 
409  }
410 
411  // 3rd Input. A column array containing the right-hand side value
412  // for each constraint in the constraint matrix.
413  Matrix B = args(2).xmatrix_value ("__glpk__: invalid value of B");
414 
415  double *b = B.fortran_vec ();
416 
417  // 4th Input. An array of length mrowsc containing the lower
418  // bound on each of the variables.
419  Matrix LB = args(3).xmatrix_value ("__glpk__: invalid value of LB");
420 
421  if (LB.numel () < mrowsc)
422  error ("__glpk__: invalid dimensions for LB");
423 
424  double *lb = LB.fortran_vec ();
425 
426  // LB argument, default: Free
427  Array<int> freeLB (dim_vector (mrowsc, 1));
428  for (int i = 0; i < mrowsc; i++)
429  {
430  if (octave::math::isinf (lb[i]))
431  {
432  freeLB(i) = 1;
434  }
435  else
436  freeLB(i) = 0;
437  }
438 
439  // 5th Input. An array of at least length numcols containing the upper
440  // bound on each of the variables.
441  Matrix UB = args(4).xmatrix_value ("__glpk__: invalid value of UB");
442 
443  if (UB.numel () < mrowsc)
444  error ("__glpk__: invalid dimensions for UB");
445 
446  double *ub = UB.fortran_vec ();
447 
448  Array<int> freeUB (dim_vector (mrowsc, 1));
449  for (int i = 0; i < mrowsc; i++)
450  {
451  if (octave::math::isinf (ub[i]))
452  {
453  freeUB(i) = 1;
455  }
456  else
457  freeUB(i) = 0;
458  }
459 
460  // 6th Input. A column array containing the sense of each constraint
461  // in the constraint matrix.
462  charMatrix CTYPE = args(5).xchar_matrix_value ("__glpk__: invalid value of CTYPE");
463 
464  char *ctype = CTYPE.fortran_vec ();
465 
466  // 7th Input. A column array containing the types of the variables.
467  charMatrix VTYPE = args(6).xchar_matrix_value ("__glpk__: invalid value of VARTYPE");
468 
469  Array<int> vartype (dim_vector (mrowsc, 1));
470  int isMIP = 0;
471  for (int i = 0; i < mrowsc ; i++)
472  {
473  if (VTYPE(i,0) == 'I')
474  {
475  isMIP = 1;
476  vartype(i) = GLP_IV;
477  }
478  else
479  vartype(i) = GLP_CV;
480  }
481 
482  // 8th Input. Sense of optimization.
483  int sense;
484  double SENSE = args(7).xscalar_value ("__glpk__: invalid value of SENSE");
485 
486  if (SENSE >= 0)
487  sense = 1;
488  else
489  sense = -1;
490 
491  // 9th Input. A structure containing the control parameters.
492  octave_scalar_map PARAM = args(8).xscalar_map_value ("__glpk__: invalid value of PARAM");
493 
494  control_params par;
495 
496  // Integer parameters
497 
498  // Level of messages output by the solver
499  par.msglev = 1;
500  OCTAVE_GLPK_GET_INT_PARAM ("msglev", par.msglev);
501  if (par.msglev < 0 || par.msglev > 3)
502  error ("__glpk__: PARAM.msglev must be 0 (no output) or 1 (error and warning messages only [default]) or 2 (normal output) or 3 (full output)");
503 
504  // scaling option
505  int scale = 16;
506  OCTAVE_GLPK_GET_INT_PARAM ("scale", scale);
507  if (scale < 0 || scale > 128)
508  error ("__glpk__: PARAM.scale must either be 128 (automatic selection of scaling options), or a bitwise or of: 1 (geometric mean scaling), 16 (equilibration scaling), 32 (round scale factors to power of two), 64 (skip if problem is well scaled");
509 
510  // Dual simplex option
511  par.dual = 1;
512  OCTAVE_GLPK_GET_INT_PARAM ("dual", par.dual);
513  if (par.dual < 1 || par.dual > 3)
514  error ("__glpk__: PARAM.dual must be 1 (use two-phase primal simplex [default]) or 2 (use two-phase dual simplex) or 3 (use two-phase dual simplex, and if it fails, switch to the primal simplex)");
515 
516  // Pricing option
517  par.price = 34;
518  OCTAVE_GLPK_GET_INT_PARAM ("price", par.price);
519  if (par.price != 17 && par.price != 34)
520  error ("__glpk__: PARAM.price must be 17 (textbook pricing) or 34 (steepest edge pricing [default])");
521 
522  // Simplex iterations limit
524  OCTAVE_GLPK_GET_INT_PARAM ("itlim", par.itlim);
525 
526  // Output frequency, in iterations
527  par.outfrq = 200;
528  OCTAVE_GLPK_GET_INT_PARAM ("outfrq", par.outfrq);
529 
530  // Branching heuristic option
531  par.branch = 4;
532  OCTAVE_GLPK_GET_INT_PARAM ("branch", par.branch);
533  if (par.branch < 1 || par.branch > 5)
534  error ("__glpk__: PARAM.branch must be 1 (first fractional variable) or 2 (last fractional variable) or 3 (most fractional variable) or 4 (heuristic by Driebeck and Tomlin [default]) or 5 (hybrid pseudocost heuristic)");
535 
536  // Backtracking heuristic option
537  par.btrack = 4;
538  OCTAVE_GLPK_GET_INT_PARAM ("btrack", par.btrack);
539  if (par.btrack < 1 || par.btrack > 4)
540  error ("__glpk__: PARAM.btrack must be 1 (depth first search) or 2 (breadth first search) or 3 (best local bound) or 4 (best projection heuristic [default]");
541 
542  // Presolver option
543  par.presol = 1;
544  OCTAVE_GLPK_GET_INT_PARAM ("presol", par.presol);
545  if (par.presol < 0 || par.presol > 1)
546  error ("__glpk__: PARAM.presol must be 0 (do NOT use LP presolver) or 1 (use LP presolver [default])");
547 
548  // LPsolver option
549  int lpsolver = 1;
550  OCTAVE_GLPK_GET_INT_PARAM ("lpsolver", lpsolver);
551  if (lpsolver < 1 || lpsolver > 2)
552  error ("__glpk__: PARAM.lpsolver must be 1 (simplex method) or 2 (interior point method)");
553 
554  // Ratio test option
555  par.rtest = 34;
556  OCTAVE_GLPK_GET_INT_PARAM ("rtest", par.rtest);
557  if (par.rtest != 17 && par.rtest != 34)
558  error ("__glpk__: PARAM.rtest must be 17 (standard ratio test) or 34 (Harris' two-pass ratio test [default])");
559 
561  OCTAVE_GLPK_GET_INT_PARAM ("tmlim", par.tmlim);
562 
563  par.outdly = 0;
564  OCTAVE_GLPK_GET_INT_PARAM ("outdly", par.outdly);
565 
566  // Save option
567  int save_pb = 0;
568  OCTAVE_GLPK_GET_INT_PARAM ("save", save_pb);
569  save_pb = save_pb != 0;
570 
571  // Real parameters
572 
573  // Relative tolerance used to check if the current basic solution
574  // is primal feasible
575  par.tolbnd = 1e-7;
576  OCTAVE_GLPK_GET_REAL_PARAM ("tolbnd", par.tolbnd);
577 
578  // Absolute tolerance used to check if the current basic solution
579  // is dual feasible
580  par.toldj = 1e-7;
581  OCTAVE_GLPK_GET_REAL_PARAM ("toldj", par.toldj);
582 
583  // Relative tolerance used to choose eligible pivotal elements of
584  // the simplex table in the ratio test
585  par.tolpiv = 1e-10;
586  OCTAVE_GLPK_GET_REAL_PARAM ("tolpiv", par.tolpiv);
587 
589  OCTAVE_GLPK_GET_REAL_PARAM ("objll", par.objll);
590 
592  OCTAVE_GLPK_GET_REAL_PARAM ("objul", par.objul);
593 
594  par.tolint = 1e-5;
595  OCTAVE_GLPK_GET_REAL_PARAM ("tolint", par.tolint);
596 
597  par.tolobj = 1e-7;
598  OCTAVE_GLPK_GET_REAL_PARAM ("tolobj", par.tolobj);
599 
600  // Assign pointers to the output parameters
601  ColumnVector xmin (mrowsc, octave_NA);
602  double fmin = octave_NA;
603  ColumnVector lambda (mrowsA, octave_NA);
604  ColumnVector redcosts (mrowsc, octave_NA);
605  double time;
606  int status;
607 
608  int errnum = glpk (sense, mrowsc, mrowsA, c, nz, rn.fortran_vec (),
609  cn.fortran_vec (), a.fortran_vec (), b, ctype,
610  freeLB.fortran_vec (), lb, freeUB.fortran_vec (),
611  ub, vartype.fortran_vec (), isMIP, lpsolver,
612  save_pb, scale, &par, xmin.fortran_vec (), &fmin,
613  &status, lambda.fortran_vec (),
614  redcosts.fortran_vec (), &time);
615 
616  octave_scalar_map extra;
617 
618  if (! isMIP)
619  {
620  extra.assign ("lambda", lambda);
621  extra.assign ("redcosts", redcosts);
622  }
623 
624  extra.assign ("time", time);
625  extra.assign ("status", status);
626 
627  return ovl (xmin, fmin, errnum, extra);
628 
629 #else
630 
631  octave_unused_parameter (args);
632 
633  err_disabled_feature ("glpk", "GNU Linear Programming Kit");
634 
635 #endif
636 }
637 
638 /*
639 ## No test needed for internal helper function.
640 %!assert (1)
641 */
#define Inf
Definition: Faddeeva.cc:247
#define C(a, b)
Definition: Faddeeva.cc:246
#define OCTAVE_GLPK_GET_INT_PARAM(NAME, VAL)
Definition: __glpk__.cc:322
int glpk(int sense, int n, int m, double *c, int nz, int *rn, int *cn, double *a, double *b, char *ctype, int *freeLB, double *lb, int *freeUB, double *ub, int *vartype, int isMIP, int lpsolver, int save_pb, int scale, const control_params *par, double *xmin, double *fmin, int *status, double *lambda, double *redcosts, double *time)
Definition: __glpk__.cc:82
#define OCTAVE_GLPK_GET_REAL_PARAM(NAME, VAL)
Definition: __glpk__.cc:307
charNDArray max(char d, const charNDArray &m)
Definition: chNDArray.cc:230
void resize(const dim_vector &dv, const T &rfv)
Size of the specified dimension.
Definition: Array.cc:1011
octave_idx_type numel(void) const
Number of elements in the array.
Definition: Array.h:377
const T * fortran_vec(void) const
Size of the specified dimension.
Definition: Array.h:583
void resize(octave_idx_type n, const double &rfv=0)
Definition: dColVector.h:109
Definition: dMatrix.h:42
Vector representing the dimensions (size) of an Array.
Definition: dim-vector.h:95
void assign(const std::string &k, const octave_value &val)
Definition: oct-map.h:238
#define DEFUN_DLD(name, args_name, nargout_name, doc)
Macro to define an at run time dynamically loadable builtin function.
Definition: defun-dld.h:61
OCTINTERP_API void print_usage(void)
Definition: defun.cc:53
void error(const char *fmt,...)
Definition: error.cc:968
void err_disabled_feature(const std::string &fcn, const std::string &feature, const std::string &pkg)
Definition: errwarn.cc:53
void scale(Matrix &m, double x, double y, double z)
Definition: graphics.cc:5846
#define octave_NA
Definition: lo-ieee.h:41
F77_RET_T const F77_INT F77_CMPLX const F77_INT F77_CMPLX * B
F77_RET_T const F77_INT F77_CMPLX * A
T octave_idx_type m
Definition: mx-inlines.cc:773
octave_idx_type n
Definition: mx-inlines.cc:753
bool isinf(double x)
Definition: lo-mappers.h:203
octave_int< T > xmin(const octave_int< T > &x, const octave_int< T > &y)
octave_value_list ovl(const OV_Args &... args)
Construct an octave_value_list with less typing.
Definition: ovl.h:211
double tolpiv
Definition: __glpk__.cc:74
double objul
Definition: __glpk__.cc:76
double toldj
Definition: __glpk__.cc:73
double objll
Definition: __glpk__.cc:75
double tolbnd
Definition: __glpk__.cc:72
double tolobj
Definition: __glpk__.cc:78
double tolint
Definition: __glpk__.cc:77