Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagesmc
Path: blob/master/src/sage/numerical/backends/glpk_backend.pyx
8817 views
1
"""
2
GLPK Backend
3
4
AUTHORS:
5
6
- Nathann Cohen (2010-10): initial implementation
7
- John Perry (2012-01): glp_simplex preprocessing
8
- John Perry and Raniere Gaia Silva (2012-03): solver parameters
9
- Christian Kuper (2012-10): Additions for sensitivity analysis
10
"""
11
12
##############################################################################
13
# Copyright (C) 2010 Nathann Cohen <[email protected]>
14
# Distributed under the terms of the GNU General Public License (GPL)
15
# The full text of the GPL is available at:
16
# http://www.gnu.org/licenses/
17
##############################################################################
18
19
from sage.numerical.mip import MIPSolverException
20
21
include "sage/ext/interrupt.pxi"
22
23
cdef class GLPKBackend(GenericBackend):
24
25
def __cinit__(self, maximization = True):
26
"""
27
Constructor
28
29
EXAMPLE::
30
31
sage: p = MixedIntegerLinearProgram(solver="GLPK")
32
"""
33
self.lp = glp_create_prob()
34
self.simplex_or_intopt = glp_intopt_only
35
self.smcp = <c_glp_smcp* > sage_malloc(sizeof(c_glp_smcp))
36
glp_init_smcp(self.smcp)
37
self.iocp = <c_glp_iocp* > sage_malloc(sizeof(c_glp_iocp))
38
glp_init_iocp(self.iocp)
39
self.iocp.presolve = GLP_ON
40
self.set_verbosity(0)
41
self.obj_constant_term = 0.0
42
43
if maximization:
44
self.set_sense(+1)
45
else:
46
self.set_sense(-1)
47
48
cpdef int add_variable(self, lower_bound=0.0, upper_bound=None, binary=False, continuous=False, integer=False, obj=0.0, name=None) except -1:
49
"""
50
Add a variable.
51
52
This amounts to adding a new column to the matrix. By default,
53
the variable is both positive, real and the coefficient in the
54
objective function is 0.0.
55
56
INPUT:
57
58
- ``lower_bound`` - the lower bound of the variable (default: 0)
59
60
- ``upper_bound`` - the upper bound of the variable (default: ``None``)
61
62
- ``binary`` - ``True`` if the variable is binary (default: ``False``).
63
64
- ``continuous`` - ``True`` if the variable is binary (default: ``True``).
65
66
- ``integer`` - ``True`` if the variable is binary (default: ``False``).
67
68
- ``obj`` - (optional) coefficient of this variable in the objective function (default: 0.0)
69
70
- ``name`` - an optional name for the newly added variable (default: ``None``).
71
72
OUTPUT: The index of the newly created variable
73
74
EXAMPLE::
75
76
sage: from sage.numerical.backends.generic_backend import get_solver
77
sage: p = get_solver(solver = "GLPK")
78
sage: p.ncols()
79
0
80
sage: p.add_variable()
81
0
82
sage: p.ncols()
83
1
84
sage: p.add_variable(binary=True)
85
1
86
sage: p.add_variable(lower_bound=-2.0, integer=True)
87
2
88
sage: p.add_variable(continuous=True, integer=True)
89
Traceback (most recent call last):
90
...
91
ValueError: ...
92
sage: p.add_variable(name='x',obj=1.0)
93
3
94
sage: p.col_name(3)
95
'x'
96
sage: p.objective_coefficient(3)
97
1.0
98
"""
99
cdef int vtype = int(bool(binary)) + int(bool(continuous)) + int(bool(integer))
100
if vtype == 0:
101
continuous = True
102
elif vtype != 1:
103
raise ValueError("Exactly one parameter of 'binary', 'integer' and 'continuous' must be 'True'.")
104
105
glp_add_cols(self.lp, 1)
106
cdef int n_var = glp_get_num_cols(self.lp)
107
108
self.variable_lower_bound(n_var - 1, lower_bound)
109
self.variable_upper_bound(n_var - 1, upper_bound)
110
111
if continuous:
112
glp_set_col_kind(self.lp, n_var, GLP_CV)
113
elif binary:
114
glp_set_col_kind(self.lp, n_var, GLP_BV)
115
elif integer:
116
glp_set_col_kind(self.lp, n_var, GLP_IV)
117
118
if name is not None:
119
glp_set_col_name(self.lp, n_var, name)
120
121
if obj:
122
self.objective_coefficient(n_var - 1, obj)
123
124
return n_var - 1
125
126
cpdef int add_variables(self, int number, lower_bound=0.0, upper_bound=None, binary=False, continuous=False, integer=False, obj=0.0, names=None) except -1:
127
"""
128
Add ``number`` new variables.
129
130
This amounts to adding new columns to the matrix. By default,
131
the variables are both positive, real and theor coefficient in
132
the objective function is 0.0.
133
134
INPUT:
135
136
- ``n`` - the number of new variables (must be > 0)
137
138
- ``lower_bound`` - the lower bound of the variable (default: 0)
139
140
- ``upper_bound`` - the upper bound of the variable (default: ``None``)
141
142
- ``binary`` - ``True`` if the variable is binary (default: ``False``).
143
144
- ``continuous`` - ``True`` if the variable is binary (default: ``True``).
145
146
- ``integer`` - ``True`` if the variable is binary (default: ``False``).
147
148
- ``obj`` - (optional) coefficient of all variables in the objective function (default: 0.0)
149
150
- ``names`` - optional list of names (default: ``None``)
151
152
OUTPUT: The index of the variable created last.
153
154
EXAMPLE::
155
156
sage: from sage.numerical.backends.generic_backend import get_solver
157
sage: p = get_solver(solver = "GLPK")
158
sage: p.ncols()
159
0
160
sage: p.add_variables(5)
161
4
162
sage: p.ncols()
163
5
164
sage: p.add_variables(2, lower_bound=-2.0, integer=True, names=['a','b'])
165
6
166
"""
167
cdef int vtype = int(bool(binary)) + int(bool(continuous)) + int(bool(integer))
168
if vtype == 0:
169
continuous = True
170
elif vtype != 1:
171
raise ValueError("Exactly one parameter of 'binary', 'integer' and 'continuous' must be 'True'.")
172
173
glp_add_cols(self.lp, number)
174
175
cdef int n_var
176
n_var = glp_get_num_cols(self.lp)
177
178
cdef int i
179
180
for 0<= i < number:
181
self.variable_lower_bound(n_var - i - 1, lower_bound)
182
self.variable_upper_bound(n_var - i - 1, upper_bound)
183
if continuous:
184
glp_set_col_kind(self.lp, n_var - i, GLP_CV)
185
elif binary:
186
glp_set_col_kind(self.lp, n_var - i, GLP_BV)
187
elif integer:
188
glp_set_col_kind(self.lp, n_var - i, GLP_IV)
189
190
if obj:
191
self.objective_coefficient(n_var - i - 1, obj)
192
193
if names is not None:
194
glp_set_col_name(self.lp, n_var, names[number - i - 1])
195
196
return n_var - 1
197
198
cpdef set_variable_type(self, int variable, int vtype):
199
"""
200
Set the type of a variable
201
202
INPUT:
203
204
- ``variable`` (integer) -- the variable's id
205
206
- ``vtype`` (integer) :
207
208
* 1 Integer
209
* 0 Binary
210
* -1 Real
211
212
EXAMPLE::
213
214
sage: from sage.numerical.backends.generic_backend import get_solver
215
sage: p = get_solver(solver = "GLPK")
216
sage: p.ncols()
217
0
218
sage: p.add_variable()
219
0
220
sage: p.set_variable_type(0,1)
221
sage: p.is_variable_integer(0)
222
True
223
"""
224
225
if vtype==1:
226
glp_set_col_kind(self.lp, variable+1, GLP_IV)
227
228
elif vtype==0:
229
glp_set_col_kind(self.lp, variable+1, GLP_BV)
230
231
else:
232
glp_set_col_kind(self.lp, variable+1, GLP_CV)
233
234
cpdef set_sense(self, int sense):
235
"""
236
Set the direction (maximization/minimization).
237
238
INPUT:
239
240
- ``sense`` (integer) :
241
242
* +1 => Maximization
243
* -1 => Minimization
244
245
EXAMPLE::
246
247
sage: from sage.numerical.backends.generic_backend import get_solver
248
sage: p = get_solver(solver = "GLPK")
249
sage: p.is_maximization()
250
True
251
sage: p.set_sense(-1)
252
sage: p.is_maximization()
253
False
254
"""
255
if sense == 1:
256
glp_set_obj_dir(self.lp, GLP_MAX)
257
else:
258
glp_set_obj_dir(self.lp, GLP_MIN)
259
260
cpdef objective_coefficient(self, int variable, coeff=None):
261
"""
262
Set or get the coefficient of a variable in the objective function
263
264
INPUT:
265
266
- ``variable`` (integer) -- the variable's id
267
268
- ``coeff`` (double) -- its coefficient or ``None`` for
269
reading (default: ``None``)
270
271
EXAMPLE::
272
273
sage: from sage.numerical.backends.generic_backend import get_solver
274
sage: p = get_solver(solver = "GLPK")
275
sage: p.add_variable()
276
0
277
sage: p.objective_coefficient(0)
278
0.0
279
sage: p.objective_coefficient(0,2)
280
sage: p.objective_coefficient(0)
281
2.0
282
"""
283
if coeff is None:
284
return glp_get_obj_coef(self.lp, variable + 1)
285
else:
286
glp_set_obj_coef(self.lp, variable + 1, coeff)
287
288
cpdef problem_name(self, char * name = NULL):
289
"""
290
Return or define the problem's name
291
292
INPUT:
293
294
- ``name`` (``char *``) -- the problem's name. When set to
295
``NULL`` (default), the method returns the problem's name.
296
297
EXAMPLE::
298
299
sage: from sage.numerical.backends.generic_backend import get_solver
300
sage: p = get_solver(solver = "GLPK")
301
sage: p.problem_name("There once was a french fry")
302
sage: print p.problem_name()
303
There once was a french fry
304
"""
305
cdef char * n
306
307
if name == NULL:
308
n = <char *> glp_get_prob_name(self.lp)
309
if n == NULL:
310
return ""
311
else:
312
return n
313
314
else:
315
if len(name) > 255:
316
raise ValueError("Problem name for GLPK must not be longer than 255 characters.")
317
glp_set_prob_name(self.lp, name)
318
319
cpdef set_objective(self, list coeff, d = 0.0):
320
"""
321
Set the objective function.
322
323
INPUT:
324
325
- ``coeff`` - a list of real values, whose ith element is the
326
coefficient of the ith variable in the objective function.
327
328
- ``d`` (double) -- the constant term in the linear function (set to `0` by default)
329
330
EXAMPLE::
331
332
sage: from sage.numerical.backends.generic_backend import get_solver
333
sage: p = get_solver(solver = "GLPK")
334
sage: p.add_variables(5)
335
4
336
sage: p.set_objective([1, 1, 2, 1, 3])
337
sage: map(lambda x :p.objective_coefficient(x), range(5))
338
[1.0, 1.0, 2.0, 1.0, 3.0]
339
"""
340
cdef int i
341
342
for i,v in enumerate(coeff):
343
glp_set_obj_coef(self.lp, i+1, v)
344
345
glp_set_obj_coef(self.lp, 0, d)
346
347
self.obj_constant_term = d
348
349
cpdef set_verbosity(self, int level):
350
"""
351
Set the verbosity level
352
353
INPUT:
354
355
- ``level`` (integer) -- From 0 (no verbosity) to 3.
356
357
EXAMPLE::
358
359
sage: from sage.numerical.backends.generic_backend import get_solver
360
sage: p = get_solver(solver = "GLPK")
361
sage: p.set_verbosity(2)
362
363
"""
364
if level == 0:
365
self.iocp.msg_lev = GLP_MSG_OFF
366
self.smcp.msg_lev = GLP_MSG_OFF
367
elif level == 1:
368
self.iocp.msg_lev = GLP_MSG_ERR
369
self.smcp.msg_lev = GLP_MSG_ERR
370
elif level == 2:
371
self.iocp.msg_lev = GLP_MSG_ON
372
self.smcp.msg_lev = GLP_MSG_ON
373
else:
374
self.iocp.msg_lev = GLP_MSG_ALL
375
self.smcp.msg_lev = GLP_MSG_ALL
376
377
cpdef remove_constraint(self, int i):
378
r"""
379
Remove a constraint from self.
380
381
INPUT:
382
383
- ``i`` -- index of the constraint to remove
384
385
EXAMPLE::
386
387
sage: p = MixedIntegerLinearProgram(solver='GLPK')
388
sage: x,y = p[0], p[1]
389
sage: p.add_constraint(2*x + 3*y, max = 6)
390
sage: p.add_constraint(3*x + 2*y, max = 6)
391
sage: p.set_objective(x + y + 7)
392
sage: p.set_integer(x); p.set_integer(y)
393
sage: p.solve()
394
9.0
395
sage: p.remove_constraint(0)
396
sage: p.solve()
397
10.0
398
399
Removing fancy constraints does not make Sage crash::
400
401
sage: MixedIntegerLinearProgram(solver = "GLPK").remove_constraint(-2)
402
Traceback (most recent call last):
403
...
404
ValueError: The constraint's index i must satisfy 0 <= i < number_of_constraints
405
"""
406
cdef int rows[2]
407
408
if i < 0 or i >= glp_get_num_rows(self.lp):
409
raise ValueError("The constraint's index i must satisfy 0 <= i < number_of_constraints")
410
411
rows[1] = i + 1
412
glp_del_rows(self.lp, 1, rows)
413
glp_std_basis(self.lp)
414
415
cpdef remove_constraints(self, constraints):
416
r"""
417
Remove several constraints.
418
419
INPUT:
420
421
- ``constraints`` -- an iterable containing the indices of the rows to remove.
422
423
EXAMPLE::
424
425
sage: p = MixedIntegerLinearProgram(solver='GLPK')
426
sage: x,y = p[0], p[1]
427
sage: p.add_constraint(2*x + 3*y, max = 6)
428
sage: p.add_constraint(3*x + 2*y, max = 6)
429
sage: p.set_objective(x + y + 7)
430
sage: p.set_integer(x); p.set_integer(y)
431
sage: p.solve()
432
9.0
433
sage: p.remove_constraints([1])
434
sage: p.solve()
435
10.0
436
sage: p.get_values([x,y])
437
[3.0, 0.0]
438
439
TESTS:
440
441
Removing fancy constraints does not make Sage crash::
442
443
sage: MixedIntegerLinearProgram(solver= "GLPK").remove_constraints([0, -2])
444
Traceback (most recent call last):
445
...
446
ValueError: The constraint's index i must satisfy 0 <= i < number_of_constraints
447
"""
448
cdef int i, c
449
cdef int m = len(constraints)
450
cdef int * rows = <int *>sage_malloc((m + 1) * sizeof(int *))
451
cdef int nrows = glp_get_num_rows(self.lp)
452
453
for i in xrange(m):
454
455
c = constraints[i]
456
if c < 0 or c >= nrows:
457
sage_free(rows)
458
raise ValueError("The constraint's index i must satisfy 0 <= i < number_of_constraints")
459
460
rows[i+1] = c + 1
461
462
glp_del_rows(self.lp, m, rows)
463
sage_free(rows)
464
glp_std_basis(self.lp)
465
466
cpdef add_linear_constraint(self, coefficients, lower_bound, upper_bound, name=None):
467
"""
468
Add a linear constraint.
469
470
INPUT:
471
472
- ``coefficients`` an iterable with ``(c,v)`` pairs where ``c``
473
is a variable index (integer) and ``v`` is a value (real
474
value).
475
476
- ``lower_bound`` - a lower bound, either a real value or ``None``
477
478
- ``upper_bound`` - an upper bound, either a real value or ``None``
479
480
- ``name`` - an optional name for this row (default: ``None``)
481
482
EXAMPLE::
483
484
sage: from sage.numerical.backends.generic_backend import get_solver
485
sage: p = get_solver(solver = "GLPK")
486
sage: p.add_variables(5)
487
4
488
sage: p.add_linear_constraint( zip(range(5), range(5)), 2.0, 2.0)
489
sage: p.row(0)
490
([4, 3, 2, 1], [4.0, 3.0, 2.0, 1.0])
491
sage: p.row_bounds(0)
492
(2.0, 2.0)
493
sage: p.add_linear_constraint( zip(range(5), range(5)), 1.0, 1.0, name='foo')
494
sage: p.row_name(1)
495
'foo'
496
"""
497
if lower_bound is None and upper_bound is None:
498
raise ValueError("At least one of 'upper_bound' or 'lower_bound' must be set.")
499
500
glp_add_rows(self.lp, 1)
501
cdef int n = glp_get_num_rows(self.lp)
502
503
cdef int * row_i
504
cdef double * row_values
505
506
row_i = <int *> sage_malloc((len(coefficients)+1) * sizeof(int))
507
row_values = <double *> sage_malloc((len(coefficients)+1) * sizeof(double))
508
509
for i,(c,v) in enumerate(coefficients):
510
row_i[i+1] = c+1
511
row_values[i+1] = v
512
513
glp_set_mat_row(self.lp, n, len(coefficients), row_i, row_values)
514
515
if upper_bound is not None and lower_bound is None:
516
glp_set_row_bnds(self.lp, n, GLP_UP, upper_bound, upper_bound)
517
elif lower_bound is not None and upper_bound is None:
518
glp_set_row_bnds(self.lp, n, GLP_LO, lower_bound, lower_bound)
519
elif upper_bound is not None and lower_bound is not None:
520
if lower_bound == upper_bound:
521
glp_set_row_bnds(self.lp, n, GLP_FX, lower_bound, upper_bound)
522
else:
523
glp_set_row_bnds(self.lp, n, GLP_DB, lower_bound, upper_bound)
524
525
if name is not None:
526
glp_set_row_name(self.lp, n, name)
527
528
sage_free(row_i)
529
sage_free(row_values)
530
531
cpdef add_linear_constraints(self, int number, lower_bound, upper_bound, names=None):
532
"""
533
Add ``'number`` linear constraints.
534
535
INPUT:
536
537
- ``number`` (integer) -- the number of constraints to add.
538
539
- ``lower_bound`` - a lower bound, either a real value or ``None``
540
541
- ``upper_bound`` - an upper bound, either a real value or ``None``
542
543
- ``names`` - an optional list of names (default: ``None``)
544
545
EXAMPLE::
546
547
sage: from sage.numerical.backends.generic_backend import get_solver
548
sage: p = get_solver(solver = "GLPK")
549
sage: p.add_variables(5)
550
4
551
sage: p.add_linear_constraints(5, None, 2)
552
sage: p.row(4)
553
([], [])
554
sage: p.row_bounds(4)
555
(None, 2.0)
556
sage: p.add_linear_constraints(2, None, 2, names=['foo','bar'])
557
"""
558
if lower_bound is None and upper_bound is None:
559
raise ValueError("At least one of 'upper_bound' or 'lower_bound' must be set.")
560
561
glp_add_rows(self.lp, number)
562
cdef int n = glp_get_num_rows(self.lp)
563
564
cdef int i
565
for 0<= i < number:
566
if upper_bound is not None and lower_bound is None:
567
glp_set_row_bnds(self.lp, n-i, GLP_UP, upper_bound, upper_bound)
568
elif lower_bound is not None and upper_bound is None:
569
glp_set_row_bnds(self.lp, n-i, GLP_LO, lower_bound, lower_bound)
570
elif upper_bound is not None and lower_bound is not None:
571
if lower_bound == upper_bound:
572
glp_set_row_bnds(self.lp, n-i, GLP_FX, lower_bound, upper_bound)
573
else:
574
glp_set_row_bnds(self.lp, n-i, GLP_DB, lower_bound, upper_bound)
575
if names is not None:
576
glp_set_row_name(self.lp, n-i, names[number-i-1])
577
578
cpdef row(self, int index):
579
r"""
580
Return a row
581
582
INPUT:
583
584
- ``index`` (integer) -- the constraint's id.
585
586
OUTPUT:
587
588
A pair ``(indices, coeffs)`` where ``indices`` lists the
589
entries whose coefficient is nonzero, and to which ``coeffs``
590
associates their coefficient on the model of the
591
``add_linear_constraint`` method.
592
593
EXAMPLE::
594
595
sage: from sage.numerical.backends.generic_backend import get_solver
596
sage: p = get_solver(solver = "GLPK")
597
sage: p.add_variables(5)
598
4
599
sage: p.add_linear_constraint(zip(range(5), range(5)), 2, 2)
600
sage: p.row(0)
601
([4, 3, 2, 1], [4.0, 3.0, 2.0, 1.0])
602
sage: p.row_bounds(0)
603
(2.0, 2.0)
604
"""
605
cdef int n = glp_get_num_cols(self.lp)
606
cdef int * c_indices = <int*> sage_malloc((n+1)*sizeof(int))
607
cdef double * c_values = <double*> sage_malloc((n+1)*sizeof(double))
608
cdef list indices = []
609
cdef list values = []
610
cdef int i,j
611
612
i = glp_get_mat_row(self.lp, index + 1, c_indices, c_values)
613
for 0 < j <= i:
614
indices.append(c_indices[j]-1)
615
values.append(c_values[j])
616
617
sage_free(c_indices)
618
sage_free(c_values)
619
620
return (indices, values)
621
622
cpdef row_bounds(self, int index):
623
"""
624
Return the bounds of a specific constraint.
625
626
INPUT:
627
628
- ``index`` (integer) -- the constraint's id.
629
630
OUTPUT:
631
632
A pair ``(lower_bound, upper_bound)``. Each of them can be set
633
to ``None`` if the constraint is not bounded in the
634
corresponding direction, and is a real value otherwise.
635
636
EXAMPLE::
637
638
sage: from sage.numerical.backends.generic_backend import get_solver
639
sage: p = get_solver(solver = "GLPK")
640
sage: p.add_variables(5)
641
4
642
sage: p.add_linear_constraint(zip(range(5), range(5)), 2, 2)
643
sage: p.row(0)
644
([4, 3, 2, 1], [4.0, 3.0, 2.0, 1.0])
645
sage: p.row_bounds(0)
646
(2.0, 2.0)
647
"""
648
cdef double ub
649
cdef double lb
650
651
ub = glp_get_row_ub(self.lp, index + 1)
652
lb = glp_get_row_lb(self.lp, index +1)
653
654
return (
655
(lb if lb != -DBL_MAX else None),
656
(ub if ub != +DBL_MAX else None)
657
)
658
659
cpdef col_bounds(self, int index):
660
"""
661
Return the bounds of a specific variable.
662
663
INPUT:
664
665
- ``index`` (integer) -- the variable's id.
666
667
OUTPUT:
668
669
A pair ``(lower_bound, upper_bound)``. Each of them can be set
670
to ``None`` if the variable is not bounded in the
671
corresponding direction, and is a real value otherwise.
672
673
EXAMPLE::
674
675
sage: from sage.numerical.backends.generic_backend import get_solver
676
sage: p = get_solver(solver = "GLPK")
677
sage: p.add_variable()
678
0
679
sage: p.col_bounds(0)
680
(0.0, None)
681
sage: p.variable_upper_bound(0, 5)
682
sage: p.col_bounds(0)
683
(0.0, 5.0)
684
"""
685
686
cdef double ub
687
cdef double lb
688
689
ub = glp_get_col_ub(self.lp, index +1)
690
lb = glp_get_col_lb(self.lp, index +1)
691
692
return (
693
(lb if lb != -DBL_MAX else None),
694
(ub if ub != +DBL_MAX else None)
695
)
696
697
cpdef add_col(self, list indices, list coeffs):
698
"""
699
Add a column.
700
701
INPUT:
702
703
- ``indices`` (list of integers) -- this list constains the
704
indices of the constraints in which the variable's
705
coefficient is nonzero
706
707
- ``coeffs`` (list of real values) -- associates a coefficient
708
to the variable in each of the constraints in which it
709
appears. Namely, the ith entry of ``coeffs`` corresponds to
710
the coefficient of the variable in the constraint
711
represented by the ith entry in ``indices``.
712
713
.. NOTE::
714
715
``indices`` and ``coeffs`` are expected to be of the same
716
length.
717
718
EXAMPLE::
719
720
sage: from sage.numerical.backends.generic_backend import get_solver
721
sage: p = get_solver(solver = "GLPK")
722
sage: p.ncols()
723
0
724
sage: p.nrows()
725
0
726
sage: p.add_linear_constraints(5, 0, None)
727
sage: p.add_col(range(5), range(5))
728
sage: p.nrows()
729
5
730
"""
731
732
glp_add_cols(self.lp, 1)
733
cdef int n = glp_get_num_cols(self.lp)
734
735
cdef int * col_i
736
cdef double * col_values
737
738
col_i = <int *> sage_malloc((len(indices)+1) * sizeof(int))
739
col_values = <double *> sage_malloc((len(indices)+1) * sizeof(double))
740
741
for i,v in enumerate(indices):
742
col_i[i+1] = v+1
743
for i,v in enumerate(coeffs):
744
col_values[i+1] = v
745
746
glp_set_mat_col(self.lp, n, len(indices), col_i, col_values)
747
glp_set_col_bnds(self.lp, n, GLP_LO, 0,0)
748
749
750
cpdef int solve(self) except -1:
751
"""
752
Solve the problem.
753
754
.. NOTE::
755
756
This method raises ``MIPSolverException`` exceptions when
757
the solution can not be computed for any reason (none
758
exists, or the LP solver was not able to find it, etc...)
759
760
EXAMPLE::
761
762
sage: from sage.numerical.backends.generic_backend import get_solver
763
sage: p = get_solver(solver = "GLPK")
764
sage: p.add_linear_constraints(5, 0, None)
765
sage: p.add_col(range(5), range(5))
766
sage: p.solve()
767
0
768
sage: p.objective_coefficient(0,1)
769
sage: p.solve()
770
Traceback (most recent call last):
771
...
772
MIPSolverException: ...
773
774
.. WARNING::
775
776
Sage uses GLPK's ``glp_intopt`` to find solutions.
777
This routine sometimes FAILS CATASTROPHICALLY
778
when given a system it cannot solve. (Ticket #12309.)
779
Here, "catastrophic" can mean either "infinite loop" or
780
segmentation fault. Upstream considers this behavior
781
"essentially innate" to their design, and suggests
782
preprocessing it with ``glpk_simplex`` first.
783
Thus, if you suspect that your system is infeasible,
784
set the ``preprocessing`` option first.
785
786
EXAMPLE::
787
788
sage: lp = MixedIntegerLinearProgram(solver = "GLPK")
789
sage: lp.add_constraint( lp[1] +lp[2] -2.0 *lp[3] , max =-1.0)
790
sage: lp.add_constraint( lp[0] -4.0/3 *lp[1] +1.0/3 *lp[2] , max =-1.0/3)
791
sage: lp.add_constraint( lp[0] +0.5 *lp[1] -0.5 *lp[2] +0.25 *lp[3] , max =-0.25)
792
sage: lp.solve()
793
0.0
794
sage: lp.add_constraint( lp[0] +4.0 *lp[1] -lp[2] +lp[3] , max =-1.0)
795
sage: lp.solve()
796
Traceback (most recent call last):
797
...
798
RuntimeError: GLPK : Signal sent, try preprocessing option
799
sage: lp.solver_parameter("simplex_or_intopt", "simplex_then_intopt")
800
sage: lp.solve()
801
Traceback (most recent call last):
802
...
803
MIPSolverException: 'GLPK : Simplex cannot find a feasible solution'
804
805
The user can ask sage to solve via ``simplex`` or ``intopt``.
806
The default solver is ``intopt``, so we get integer solutions.
807
808
sage: lp = MixedIntegerLinearProgram(solver = 'GLPK', maximization = False)
809
sage: x, y = lp[0], lp[1]
810
sage: lp.add_constraint(-2*x + y <= 1)
811
sage: lp.add_constraint(x - y <= 1)
812
sage: lp.add_constraint(x + y >= 2)
813
sage: lp.set_objective(x + y)
814
sage: lp.set_integer(x)
815
sage: lp.set_integer(y)
816
sage: lp.solve()
817
2.0
818
sage: lp.get_values([x, y])
819
[1.0, 1.0]
820
821
If we switch to ``simplex``, we get continuous solutions.
822
823
sage: lp.solver_parameter("simplex_or_intopt", "simplex_only") # use simplex only
824
sage: lp.solve()
825
2.0
826
sage: lp.get_values([x, y])
827
[1.5, 0.5]
828
"""
829
830
cdef int status
831
if self.simplex_or_intopt == glp_simplex_only or self.simplex_or_intopt == glp_simplex_then_intopt:
832
status = glp_simplex(self.lp, self.smcp)
833
status = glp_get_prim_stat(self.lp)
834
if status == GLP_OPT or status == GLP_FEAS:
835
pass
836
elif status == GLP_UNDEF or status == GLP_NOFEAS:
837
raise MIPSolverException("GLPK : Simplex cannot find a feasible solution")
838
839
if self.simplex_or_intopt != glp_simplex_only:
840
sig_str('GLPK : Signal sent, try preprocessing option')
841
status = glp_intopt(self.lp, self.iocp)
842
sig_off()
843
# this is necessary to catch errors when certain options are enabled, e.g. tm_lim
844
if status == GLP_ETMLIM: raise MIPSolverException("GLPK : The time limit was reached")
845
elif status == GLP_EITLIM: raise MIPSolverException("GLPK : The iteration limit was reached")
846
847
status = glp_mip_status(self.lp)
848
if status == GLP_OPT:
849
pass
850
elif status == GLP_UNDEF:
851
raise MIPSolverException("GLPK : Solution is undefined")
852
elif status == GLP_FEAS:
853
raise MIPSolverException("GLPK : Feasible solution found, while optimality has not been proven")
854
elif status == GLP_INFEAS:
855
raise MIPSolverException("GLPK : Solution is infeasible")
856
elif status == GLP_UNBND:
857
raise MIPSolverException("GLPK : Problem has unbounded solution")
858
elif status == GLP_NOFEAS:
859
raise MIPSolverException("GLPK : There is no feasible integer solution to this Linear Program")
860
861
return 0
862
863
cpdef get_objective_value(self):
864
"""
865
Returns the value of the objective function.
866
867
.. NOTE::
868
869
Behaviour is undefined unless ``solve`` has been called before.
870
871
EXAMPLE::
872
873
sage: from sage.numerical.backends.generic_backend import get_solver
874
sage: p = get_solver(solver = "GLPK")
875
sage: p.add_variables(2)
876
1
877
sage: p.add_linear_constraint([[0, 1], [1, 2]], None, 3)
878
sage: p.set_objective([2, 5])
879
sage: p.solve()
880
0
881
sage: p.get_objective_value()
882
7.5
883
sage: p.get_variable_value(0)
884
0.0
885
sage: p.get_variable_value(1)
886
1.5
887
"""
888
if self.simplex_or_intopt != glp_simplex_only:
889
return glp_mip_obj_val(self.lp)
890
else:
891
return glp_get_obj_val(self.lp)
892
893
cpdef get_variable_value(self, int variable):
894
"""
895
Returns the value of a variable given by the solver.
896
897
.. NOTE::
898
899
Behaviour is undefined unless ``solve`` has been called before.
900
901
EXAMPLE::
902
903
sage: from sage.numerical.backends.generic_backend import get_solver
904
sage: p = get_solver(solver = "GLPK")
905
sage: p.add_variables(2)
906
1
907
sage: p.add_linear_constraint([[0, 1], [1, 2]], None, 3)
908
sage: p.set_objective([2, 5])
909
sage: p.solve()
910
0
911
sage: p.get_objective_value()
912
7.5
913
sage: p.get_variable_value(0)
914
0.0
915
sage: p.get_variable_value(1)
916
1.5
917
"""
918
if self.simplex_or_intopt != glp_simplex_only:
919
return glp_mip_col_val(self.lp, variable+1)
920
else:
921
return glp_get_col_prim(self.lp, variable+1)
922
923
cpdef int ncols(self):
924
"""
925
Return the number of columns/variables.
926
927
EXAMPLE::
928
929
sage: from sage.numerical.backends.generic_backend import get_solver
930
sage: p = get_solver(solver = "GLPK")
931
sage: p.ncols()
932
0
933
sage: p.add_variables(2)
934
1
935
sage: p.ncols()
936
2
937
"""
938
return glp_get_num_cols(self.lp)
939
940
cpdef int nrows(self):
941
"""
942
Return the number of rows/constraints.
943
944
EXAMPLE::
945
946
sage: from sage.numerical.backends.generic_backend import get_solver
947
sage: p = get_solver(solver = "GLPK")
948
sage: p.nrows()
949
0
950
sage: p.add_linear_constraints(2, 2, None)
951
sage: p.nrows()
952
2
953
"""
954
955
return glp_get_num_rows(self.lp)
956
957
cpdef col_name(self, int index):
958
"""
959
Return the ``index`` th col name
960
961
INPUT:
962
963
- ``index`` (integer) -- the col's id
964
965
EXAMPLE::
966
967
sage: from sage.numerical.backends.generic_backend import get_solver
968
sage: p = get_solver(solver = "GLPK")
969
sage: p.add_variable(name='I am a variable')
970
0
971
sage: p.col_name(0)
972
'I am a variable'
973
"""
974
cdef char * s
975
976
glp_create_index(self.lp)
977
s = <char*> glp_get_col_name(self.lp, index + 1)
978
979
if s != NULL:
980
return s
981
else:
982
return ""
983
984
cpdef row_name(self, int index):
985
"""
986
Return the ``index`` th row name
987
988
INPUT:
989
990
- ``index`` (integer) -- the row's id
991
992
EXAMPLE::
993
994
sage: from sage.numerical.backends.generic_backend import get_solver
995
sage: p = get_solver(solver = "GLPK")
996
sage: p.add_linear_constraints(1, 2, None, names=['Empty constraint 1'])
997
sage: p.row_name(0)
998
'Empty constraint 1'
999
"""
1000
cdef char * s
1001
1002
glp_create_index(self.lp)
1003
s = <char*> glp_get_row_name(self.lp, index + 1)
1004
1005
if s != NULL:
1006
return s
1007
else:
1008
return ""
1009
1010
cpdef bint is_variable_binary(self, int index):
1011
"""
1012
Test whether the given variable is of binary type.
1013
1014
INPUT:
1015
1016
- ``index`` (integer) -- the variable's id
1017
1018
EXAMPLE::
1019
1020
sage: from sage.numerical.backends.generic_backend import get_solver
1021
sage: p = get_solver(solver = "GLPK")
1022
sage: p.ncols()
1023
0
1024
sage: p.add_variable()
1025
0
1026
sage: p.set_variable_type(0,0)
1027
sage: p.is_variable_binary(0)
1028
True
1029
1030
"""
1031
return glp_get_col_kind(self.lp, index + 1) == GLP_BV
1032
1033
cpdef bint is_variable_integer(self, int index):
1034
"""
1035
Test whether the given variable is of integer type.
1036
1037
INPUT:
1038
1039
- ``index`` (integer) -- the variable's id
1040
1041
EXAMPLE::
1042
1043
sage: from sage.numerical.backends.generic_backend import get_solver
1044
sage: p = get_solver(solver = "GLPK")
1045
sage: p.ncols()
1046
0
1047
sage: p.add_variable()
1048
0
1049
sage: p.set_variable_type(0,1)
1050
sage: p.is_variable_integer(0)
1051
True
1052
"""
1053
return glp_get_col_kind(self.lp, index + 1) == GLP_IV
1054
1055
cpdef bint is_variable_continuous(self, int index):
1056
"""
1057
Test whether the given variable is of continuous/real type.
1058
1059
INPUT:
1060
1061
- ``index`` (integer) -- the variable's id
1062
1063
EXAMPLE::
1064
1065
sage: from sage.numerical.backends.generic_backend import get_solver
1066
sage: p = get_solver(solver = "GLPK")
1067
sage: p.ncols()
1068
0
1069
sage: p.add_variable()
1070
0
1071
sage: p.is_variable_continuous(0)
1072
True
1073
sage: p.set_variable_type(0,1)
1074
sage: p.is_variable_continuous(0)
1075
False
1076
1077
"""
1078
return glp_get_col_kind(self.lp, index + 1) == GLP_CV
1079
1080
cpdef bint is_maximization(self):
1081
"""
1082
Test whether the problem is a maximization
1083
1084
EXAMPLE::
1085
1086
sage: from sage.numerical.backends.generic_backend import get_solver
1087
sage: p = get_solver(solver = "GLPK")
1088
sage: p.is_maximization()
1089
True
1090
sage: p.set_sense(-1)
1091
sage: p.is_maximization()
1092
False
1093
"""
1094
1095
return glp_get_obj_dir(self.lp) == GLP_MAX
1096
1097
cpdef variable_upper_bound(self, int index, value = False):
1098
"""
1099
Return or define the upper bound on a variable
1100
1101
INPUT:
1102
1103
- ``index`` (integer) -- the variable's id
1104
1105
- ``value`` -- real value, or ``None`` to mean that the
1106
variable has not upper bound. When set to ``False``
1107
(default), the method returns the current value.
1108
1109
EXAMPLE::
1110
1111
sage: from sage.numerical.backends.generic_backend import get_solver
1112
sage: p = get_solver(solver = "GLPK")
1113
sage: p.add_variable()
1114
0
1115
sage: p.col_bounds(0)
1116
(0.0, None)
1117
sage: p.variable_upper_bound(0, 5)
1118
sage: p.col_bounds(0)
1119
(0.0, 5.0)
1120
1121
TESTS:
1122
1123
:trac:`14581`::
1124
1125
sage: P = MixedIntegerLinearProgram(solver="GLPK")
1126
sage: x = P["x"]
1127
sage: P.set_max(x, 0)
1128
sage: P.get_max(x)
1129
0.0
1130
"""
1131
cdef double x
1132
cdef double min
1133
1134
if value is False:
1135
x = glp_get_col_ub(self.lp, index +1)
1136
if x == DBL_MAX:
1137
return None
1138
else:
1139
return x
1140
else:
1141
min = glp_get_col_lb(self.lp, index + 1)
1142
1143
if value is None and min == -DBL_MAX:
1144
glp_set_col_bnds(self.lp, index + 1, GLP_FR, 0, 0)
1145
1146
elif value is None:
1147
glp_set_col_bnds(self.lp, index + 1, GLP_LO, min, 0)
1148
1149
elif min == -DBL_MAX:
1150
glp_set_col_bnds(self.lp, index + 1, GLP_UP, 0, value)
1151
1152
elif min == value:
1153
glp_set_col_bnds(self.lp, index + 1, GLP_FX, value, value)
1154
1155
else:
1156
glp_set_col_bnds(self.lp, index + 1, GLP_DB, min, value)
1157
1158
cpdef variable_lower_bound(self, int index, value = False):
1159
"""
1160
Return or define the lower bound on a variable
1161
1162
INPUT:
1163
1164
- ``index`` (integer) -- the variable's id
1165
1166
- ``value`` -- real value, or ``None`` to mean that the
1167
variable has not lower bound. When set to ``False``
1168
(default), the method returns the current value.
1169
1170
EXAMPLE::
1171
1172
sage: from sage.numerical.backends.generic_backend import get_solver
1173
sage: p = get_solver(solver = "GLPK")
1174
sage: p.add_variable()
1175
0
1176
sage: p.col_bounds(0)
1177
(0.0, None)
1178
sage: p.variable_lower_bound(0, 5)
1179
sage: p.col_bounds(0)
1180
(5.0, None)
1181
1182
TESTS:
1183
1184
:trac:`14581`::
1185
1186
sage: P = MixedIntegerLinearProgram(solver="GLPK")
1187
sage: x = P["x"]
1188
sage: P.set_min(x, 5)
1189
sage: P.set_min(x, 0)
1190
sage: P.get_min(x)
1191
0.0
1192
"""
1193
cdef double x
1194
cdef double max
1195
1196
if value is False:
1197
x = glp_get_col_lb(self.lp, index +1)
1198
if x == -DBL_MAX:
1199
return None
1200
else:
1201
return x
1202
else:
1203
max = glp_get_col_ub(self.lp, index + 1)
1204
1205
if value is None and max == DBL_MAX:
1206
glp_set_col_bnds(self.lp, index + 1, GLP_FR, 0.0, 0.0)
1207
1208
elif value is None:
1209
glp_set_col_bnds(self.lp, index + 1, GLP_UP, 0.0, max)
1210
1211
elif max == DBL_MAX:
1212
glp_set_col_bnds(self.lp, index + 1, GLP_LO, value, 0.0)
1213
1214
elif max == value:
1215
glp_set_col_bnds(self.lp, index + 1, GLP_FX, value, value)
1216
1217
else:
1218
glp_set_col_bnds(self.lp, index + 1, GLP_DB, value, max)
1219
1220
cpdef write_lp(self, char * filename):
1221
"""
1222
Write the problem to a .lp file
1223
1224
INPUT:
1225
1226
- ``filename`` (string)
1227
1228
EXAMPLE::
1229
1230
sage: from sage.numerical.backends.generic_backend import get_solver
1231
sage: p = get_solver(solver = "GLPK")
1232
sage: p.add_variables(2)
1233
1
1234
sage: p.add_linear_constraint([[0, 1], [1, 2]], None, 3)
1235
sage: p.set_objective([2, 5])
1236
sage: p.write_lp(os.path.join(SAGE_TMP, "lp_problem.lp"))
1237
Writing problem data to ...
1238
9 lines were written
1239
"""
1240
glp_write_lp(self.lp, NULL, filename)
1241
1242
cpdef write_mps(self, char * filename, int modern):
1243
"""
1244
Write the problem to a .mps file
1245
1246
INPUT:
1247
1248
- ``filename`` (string)
1249
1250
EXAMPLE::
1251
1252
sage: from sage.numerical.backends.generic_backend import get_solver
1253
sage: p = get_solver(solver = "GLPK")
1254
sage: p.add_variables(2)
1255
1
1256
sage: p.add_linear_constraint([[0, 1], [1, 2]], None, 3)
1257
sage: p.set_objective([2, 5])
1258
sage: p.write_mps(os.path.join(SAGE_TMP, "lp_problem.mps"), 2)
1259
Writing problem data to...
1260
17 records were written
1261
"""
1262
glp_write_mps(self.lp, modern, NULL, filename)
1263
1264
cpdef GLPKBackend copy(self):
1265
"""
1266
Returns a copy of self.
1267
1268
EXAMPLE::
1269
1270
sage: from sage.numerical.backends.generic_backend import get_solver
1271
sage: p = MixedIntegerLinearProgram(solver = "GLPK")
1272
sage: b = p.new_variable()
1273
sage: p.add_constraint(b[1] + b[2] <= 6)
1274
sage: p.set_objective(b[1] + b[2])
1275
sage: copy(p).solve()
1276
6.0
1277
"""
1278
cdef GLPKBackend p = GLPKBackend(maximization = (1 if self.is_maximization() else -1))
1279
p.simplex_or_intopt = self.simplex_or_intopt
1280
p.iocp.tm_lim = self.iocp.tm_lim
1281
glp_copy_prob(p.lp, self.lp, 1)
1282
return p
1283
1284
1285
cpdef solver_parameter(self, name, value = None):
1286
"""
1287
Return or define a solver parameter
1288
1289
INPUT:
1290
1291
- ``name`` (string) -- the parameter
1292
1293
- ``value`` -- the parameter's value if it is to be defined,
1294
or ``None`` (default) to obtain its current value.
1295
1296
You can supply the name of a parameter and its value using either a
1297
string or a ``glp_`` constant (which are defined as Cython variables of
1298
this module).
1299
1300
In most cases, you can use the same name for a parameter as that given
1301
in the GLPK documentation, which is available by downloading GLPK from
1302
<http://www.gnu.org/software/glpk/>. The exceptions relate to parameters
1303
common to both methods; these require you to append ``_simplex`` or
1304
``_intopt`` to the name to resolve ambiguity, since the interface allows
1305
access to both.
1306
1307
We have also provided more meaningful names, to assist readability.
1308
1309
Parameter **names** are specified in lower case.
1310
To use a constant instead of a string, prepend ``glp_`` to the name.
1311
For example, both ``glp_gmi_cuts`` or ``"gmi_cuts"`` control whether
1312
to solve using Gomory cuts.
1313
1314
Parameter **values** are specificed as strings in upper case,
1315
or as constants in lower case. For example, both ``glp_on`` and ``"GLP_ON"``
1316
specify the same thing.
1317
1318
Naturally, you can use ``True`` and ``False`` in cases where ``glp_on`` and ``glp_off``
1319
would be used.
1320
1321
A list of parameter names, with their possible values:
1322
1323
**General-purpose parameters:**
1324
1325
.. list-table::
1326
:widths: 30 70
1327
1328
* - ``timelimit``
1329
1330
- specify the time limit IN SECONDS. This affects both simplex
1331
and intopt.
1332
1333
* - ``timelimit_simplex`` and ``timelimit_intopt``
1334
1335
- specify the time limit IN MILLISECONDS. (This is glpk's
1336
default.)
1337
1338
* - ``simplex_or_intopt``
1339
1340
- whether to use the ``simplex`` or ``intopt`` routines in
1341
GLPK. This is controlled by using ``glp_simplex_only``,
1342
``glp_intopt_only``, and ``glp_simplex_then_intopt``. The latter
1343
is useful to deal with a problem in GLPK where problems with no
1344
solution hang when using integer optimization; if you specify
1345
``glp_simplex_then_intopt``, sage will try simplex first, then
1346
perform integer optimization only if a solution of the LP
1347
relaxation exists.
1348
1349
* - ``verbosity_intopt`` and ``verbosity_simplex``
1350
1351
- one of ``GLP_MSG_OFF``, ``GLP_MSG_ERR``, ``GLP_MSG_ON``, or
1352
``GLP_MSG_ALL``. The default is ``GLP_MSG_OFF``.
1353
1354
* - ``output_frequency_intopt`` and ``output_frequency_simplex``
1355
1356
- the output frequency, in milliseconds. Default is 5000.
1357
1358
* - ``output_delay_intopt`` and ``output_delay_simplex``
1359
1360
- the output delay, in milliseconds, regarding the use of the
1361
simplex method on the LP relaxation. Default is 10000.
1362
1363
1364
**intopt-specific parameters:**
1365
1366
.. list-table::
1367
:widths: 30 70
1368
1369
* - ``branching``
1370
- - ``GLP_BR_FFV`` first fractional variable
1371
- ``GLP_BR_LFV`` last fractional variable
1372
- ``GLP_BR_MFV`` most fractional variable
1373
- ``GLP_BR_DTH`` Driebeck-Tomlin heuristic (default)
1374
- ``GLP_BR_PCH`` hybrid pseudocost heuristic
1375
1376
* - ``backtracking``
1377
- - ``GLP_BT_DFS`` depth first search
1378
- ``GLP_BT_BFS`` breadth first search
1379
- ``GLP_BT_BLB`` best local bound (default)
1380
- ``GLP_BT_BPH`` best projection heuristic
1381
1382
* - ``preprocessing``
1383
- - ``GLP_PP_NONE``
1384
- ``GLP_PP_ROOT`` preprocessing only at root level
1385
- ``GLP_PP_ALL`` (default)
1386
1387
1388
* - ``feasibility_pump``
1389
1390
- ``GLP_ON`` or ``GLP_OFF`` (default)
1391
1392
* - ``gomory_cuts``
1393
1394
- ``GLP_ON`` or ``GLP_OFF`` (default)
1395
1396
* - ``mixed_int_rounding_cuts``
1397
1398
- ``GLP_ON`` or ``GLP_OFF`` (default)
1399
1400
* - ``mixed_cover_cuts``
1401
1402
- ``GLP_ON`` or ``GLP_OFF`` (default)
1403
1404
* - ``clique_cuts``
1405
1406
- ``GLP_ON`` or ``GLP_OFF`` (default)
1407
1408
* - ``absolute_tolerance``
1409
1410
- (double) used to check if optimal solution to LP relaxation is
1411
integer feasible. GLPK manual advises, "do not change... without
1412
detailed understanding of its purpose."
1413
1414
* - ``relative_tolerance``
1415
1416
- (double) used to check if objective value in LP relaxation is not
1417
better than best known integer solution. GLPK manual advises, "do
1418
not change... without detailed understanding of its purpose."
1419
1420
* - ``mip_gap_tolerance``
1421
1422
- (double) relative mip gap tolerance. Default is 0.0.
1423
1424
* - ``presolve_intopt``
1425
1426
- ``GLP_ON`` (default) or ``GLP_OFF``.
1427
1428
* - ``binarize``
1429
1430
- ``GLP_ON`` or ``GLP_OFF`` (default)
1431
1432
1433
**simplex-specific parameters:**
1434
1435
.. list-table::
1436
:widths: 30 70
1437
1438
* - ``primal_v_dual``
1439
1440
- - ``GLP_PRIMAL`` (default)
1441
- ``GLP_DUAL``
1442
- ``GLP_DUALP``
1443
1444
* - ``pricing``
1445
1446
- - ``GLP_PT_STD`` standard (textbook)
1447
- ``GLP_PT_PSE`` projected steepest edge (default)
1448
1449
* - ``ratio_test``
1450
1451
- - ``GLP_RT_STD`` standard (textbook)
1452
- ``GLP_RT_HAR`` Harris' two-pass ratio test (default)
1453
1454
* - ``tolerance_primal``
1455
1456
- (double) tolerance used to check if basic solution is primal
1457
feasible. GLPK manual advises, "do not change... without
1458
detailed understanding of its purpose."
1459
1460
* - ``tolerance_dual``
1461
1462
- (double) tolerance used to check if basic solution is dual
1463
feasible. GLPK manual advises, "do not change... without
1464
detailed understanding of its purpose."
1465
1466
* - ``tolerance_pivot``
1467
1468
- (double) tolerance used to choose pivot. GLPK manual advises,
1469
"do not change... without detailed understanding of its
1470
purpose."
1471
1472
* - ``obj_lower_limit``
1473
1474
- (double) lower limit of the objective function. The default is
1475
``-DBL_MAX``.
1476
1477
* - ``obj_upper_limit``
1478
1479
- (double) upper limit of the objective function. The default is
1480
``DBL_MAX``.
1481
1482
* - ``iteration_limit``
1483
1484
- (int) iteration limit of the simplex algorithm. The default is
1485
``INT_MAX``.
1486
1487
* - ``presolve_simplex``
1488
1489
- ``GLP_ON`` or ``GLP_OFF`` (default).
1490
1491
.. NOTE::
1492
1493
The coverage for GLPK's control parameters for simplex and integer optimization
1494
is nearly complete. The only thing lacking is a wrapper for callback routines.
1495
1496
To date, no attempt has been made to expose the interior point methods.
1497
1498
EXAMPLE::
1499
1500
sage: from sage.numerical.backends.generic_backend import get_solver
1501
sage: p = get_solver(solver = "GLPK")
1502
sage: p.solver_parameter("timelimit", 60)
1503
sage: p.solver_parameter("timelimit")
1504
60.0
1505
1506
- Don't forget the difference between ``timelimit`` and ``timelimit_intopt``
1507
1508
::
1509
1510
sage: p.solver_parameter("timelimit_intopt")
1511
60000
1512
1513
If you don't care for an integer answer, you can ask for an lp
1514
relaxation instead. The default solver performs integer optimization,
1515
but you can switch to the standard simplex algorithm through the
1516
``glp_simplex_or_intopt`` parameter.
1517
1518
EXAMPLE::
1519
1520
sage: lp = MixedIntegerLinearProgram(solver = 'GLPK', maximization = False)
1521
sage: x, y = lp[0], lp[1]
1522
sage: lp.add_constraint(-2*x + y <= 1)
1523
sage: lp.add_constraint(x - y <= 1)
1524
sage: lp.add_constraint(x + y >= 2)
1525
sage: lp.set_integer(x); lp.set_integer(y)
1526
sage: lp.set_objective(x + y)
1527
sage: lp.solve()
1528
2.0
1529
sage: lp.get_values([x,y])
1530
[1.0, 1.0]
1531
sage: import sage.numerical.backends.glpk_backend as backend
1532
sage: lp.solver_parameter(backend.glp_simplex_or_intopt, backend.glp_simplex_only)
1533
sage: lp.solve()
1534
2.0
1535
sage: lp.get_values([x,y])
1536
[1.5, 0.5]
1537
1538
You can get glpk to spout all sorts of information at you.
1539
The default is to turn this off, but sometimes (debugging) it's very useful::
1540
1541
sage: lp.solver_parameter(backend.glp_simplex_or_intopt, backend.glp_simplex_then_intopt)
1542
sage: lp.solver_parameter(backend.glp_mir_cuts, backend.glp_on)
1543
sage: lp.solver_parameter(backend.glp_msg_lev_intopt, backend.glp_msg_all)
1544
sage: lp.solver_parameter(backend.glp_mir_cuts)
1545
1
1546
1547
If you actually try to solve ``lp``, you will get a lot of detailed information.
1548
"""
1549
1550
if type(name) == str:
1551
if name == "out_frq" or name == "out_dly" or name == "tm_lim" or name == "msg_lev":
1552
raise ValueError("To set parameter " + name + " you must specify the solver. Append either _simplex or _intopt.")
1553
name = solver_parameter_names_dict[name]
1554
1555
if type(value) == str: value = solver_parameter_values[value]
1556
1557
if name == timelimit_intopt:
1558
if value is None: return self.iocp.tm_lim
1559
else: self.iocp.tm_lim = value
1560
1561
if name == timelimit_seconds:
1562
if value is None: return self.iocp.tm_lim / 1000.0
1563
else:
1564
self.iocp.tm_lim = value * 1000.0
1565
self.smcp.tm_lim = value * 1000.0
1566
1567
elif name == timelimit_simplex:
1568
if value is None: return self.smcp.tm_lim
1569
else: self.smcp.tm_lim = value
1570
1571
elif name == simplex_or_intopt:
1572
if value is None: return self.simplex_or_intopt
1573
if not value in (simplex_only,intopt_only,simplex_then_intopt):
1574
raise MIPSolverException, "GLPK: invalid value for simplex_or_intopt; see documentation"
1575
self.simplex_or_intopt = value
1576
1577
elif name == msg_lev_simplex:
1578
if value is None: return self.smcp.msg_lev
1579
else: self.smcp.msg_lev = value
1580
1581
elif name == msg_lev_intopt:
1582
if value is None: return self.iocp.msg_lev
1583
else: self.iocp.msg_lev = value
1584
1585
elif name == br_tech:
1586
if value is None: return self.iocp.br_tech
1587
else: self.iocp.br_tech = value
1588
1589
elif name == bt_tech:
1590
if value is None: return self.iocp.bt_tech
1591
else: self.iocp.bt_tech = value
1592
1593
elif name == pp_tech:
1594
if value is None: return self.iocp.pp_tech
1595
else: self.iocp.pp_tech = value
1596
1597
elif name == fp_heur:
1598
if value is None: return self.iocp.fp_heur
1599
else:
1600
if value: value = GLP_ON
1601
else: value = GLP_OFF
1602
self.iocp.fp_heur = value
1603
1604
elif name == gmi_cuts:
1605
if value is None: return self.iocp.gmi_cuts
1606
else:
1607
if value: value = GLP_ON
1608
else: value = GLP_OFF
1609
self.iocp.gmi_cuts = value
1610
1611
elif name == mir_cuts:
1612
if value is None: return self.iocp.mir_cuts
1613
else:
1614
if value: value = GLP_ON
1615
else: value = GLP_OFF
1616
self.iocp.mir_cuts = value
1617
1618
elif name == cov_cuts:
1619
if value is None: return self.iocp.cov_cuts
1620
else:
1621
if value: value = GLP_ON
1622
else: value = GLP_OFF
1623
self.iocp.cov_cuts = value
1624
1625
elif name == clq_cuts:
1626
if value is None: return self.iocp.clq_cuts
1627
else:
1628
if value: value = GLP_ON
1629
else: value = GLP_OFF
1630
self.iocp.clq_cuts = value
1631
1632
elif name == tol_int:
1633
if value is None: return self.iocp.tol_int
1634
else: self.iocp.tol_int = value
1635
1636
elif name == tol_obj:
1637
if value is None: return self.iocp.tol_obj
1638
else: self.iocp.tol_obj = value
1639
1640
elif name == mip_gap:
1641
if value is None: return self.iocp.mip_gap
1642
else: self.iocp.mip_gap = value
1643
1644
elif name == tm_lim_intopt:
1645
if value is None: return self.iocp.tm_lim
1646
else: self.iocp.tm_lim = value
1647
1648
elif name == out_frq_intopt:
1649
if value is None: return self.iocp.out_frq
1650
else: self.iocp.out_frq = value
1651
1652
elif name == out_dly_intopt:
1653
if value is None: return self.iocp.out_dly
1654
else: self.iocp.out_dly = value
1655
1656
elif name == presolve_intopt:
1657
if value is None: return self.iocp.presolve
1658
else:
1659
if value: value = GLP_ON
1660
else: value = GLP_OFF
1661
self.iocp.presolve = value
1662
1663
elif name == binarize:
1664
if value is None: return self.iocp.binarize
1665
else:
1666
if value: value = GLP_ON
1667
else: value = GLP_OFF
1668
self.iocp.binarize = value
1669
1670
elif name == msg_lev_simplex:
1671
if value is None: return self.smcp.msg_lev
1672
else: self.smcp.msg_lev = value
1673
1674
elif name == meth:
1675
if value is None: return self.smcp.meth
1676
else: self.smcp.meth = value
1677
1678
elif name == pricing:
1679
if value is None: return self.smcp.pricing
1680
else: self.smcp.pricing = value
1681
1682
elif name == r_test:
1683
if value is None: return self.smcp.r_test
1684
else: self.smcp.r_test = value
1685
1686
elif name == tol_bnd:
1687
if value is None: return self.smcp.tol_bnd
1688
else: self.smcp.tol_bnd = value
1689
1690
elif name == tol_dj:
1691
if value is None: return self.smcp.tol_dj
1692
else: self.smcp.tol_dj = value
1693
1694
elif name == tol_piv:
1695
if value is None: return self.smcp.tol_piv
1696
else: self.smcp.tol_piv = value
1697
1698
elif name == obj_ll:
1699
if value is None: return self.smcp.obj_ll
1700
else: self.smcp.obj_ll = value
1701
1702
elif name == obj_ul:
1703
if value is None: return self.smcp.obj_ul
1704
else: self.smcp.obj_ul = value
1705
1706
elif name == it_lim:
1707
if value is None: return self.smcp.it_lim
1708
else: self.smcp.it_lim = value
1709
1710
elif name == tm_lim_simplex:
1711
if value is None: return self.smcp.tm_lim
1712
else: self.smcp.tm_lim = value
1713
1714
elif name == out_frq_simplex:
1715
if value is None: return self.smcp.out_frq
1716
else: self.smcp.out_frq = value
1717
1718
elif name == out_dly_simplex:
1719
if value is None: return self.smcp.out_dly
1720
else: self.smcp.out_dly = value
1721
1722
elif name == presolve_simplex:
1723
if value is None: return self.smcp.presolve
1724
else:
1725
if value: value = GLP_ON
1726
else: value = GLP_OFF
1727
self.smcp.presolve = value
1728
1729
else:
1730
raise ValueError("This parameter is not available.")
1731
1732
1733
cpdef int print_ranges(self, char * filename = NULL) except -1:
1734
r"""
1735
Print results of a sensitivity analysis
1736
1737
If no filename is given as an input the results of the
1738
sensitivity analysis are displayed on the screen. If a
1739
filename is given they are written to a file.
1740
1741
INPUT:
1742
1743
- ``filename`` -- (optional) name of the file
1744
1745
OUTPUT:
1746
1747
Zero if the operations was successful otherwise nonzero.
1748
1749
.. NOTE::
1750
1751
This method is only effective if an optimal solution has been found
1752
for the lp using the simplex algorithm. In all other cases an error
1753
message is printed.
1754
1755
EXAMPLE::
1756
1757
sage: from sage.numerical.backends.generic_backend import get_solver
1758
sage: p = get_solver(solver = "GLPK")
1759
sage: p.add_variables(2)
1760
1
1761
sage: p.add_linear_constraint(zip([0, 1], [1, 2]), None, 3)
1762
sage: p.set_objective([2, 5])
1763
sage: import sage.numerical.backends.glpk_backend as backend
1764
sage: p.solver_parameter(backend.glp_simplex_or_intopt, backend.glp_simplex_only)
1765
sage: p.print_ranges()
1766
glp_print_ranges: optimal basic solution required
1767
1
1768
sage: p.solve()
1769
0
1770
sage: p.print_ranges()
1771
Write sensitivity analysis report to...
1772
GLPK ... - SENSITIVITY ANALYSIS REPORT Page 1
1773
<BLANKLINE>
1774
Problem:
1775
Objective: 7.5 (MAXimum)
1776
<BLANKLINE>
1777
No. Row name St Activity Slack Lower bound Activity Obj coef Obj value at Limiting
1778
Marginal Upper bound range range break point variable
1779
------ ------------ -- ------------- ------------- ------------- ------------- ------------- ------------- ------------
1780
1 NU 3.00000 . -Inf . -2.50000 .
1781
2.50000 3.00000 +Inf +Inf +Inf
1782
<BLANKLINE>
1783
GLPK ... - SENSITIVITY ANALYSIS REPORT Page 2
1784
<BLANKLINE>
1785
Problem:
1786
Objective: 7.5 (MAXimum)
1787
<BLANKLINE>
1788
No. Column name St Activity Obj coef Lower bound Activity Obj coef Obj value at Limiting
1789
Marginal Upper bound range range break point variable
1790
------ ------------ -- ------------- ------------- ------------- ------------- ------------- ------------- ------------
1791
1 NL . 2.00000 . -Inf -Inf +Inf
1792
-.50000 +Inf 3.00000 2.50000 6.00000
1793
<BLANKLINE>
1794
2 BS 1.50000 5.00000 . -Inf 4.00000 6.00000
1795
. +Inf 1.50000 +Inf +Inf
1796
<BLANKLINE>
1797
End of report
1798
<BLANKLINE>
1799
0
1800
"""
1801
1802
from sage.misc.all import SAGE_TMP
1803
1804
if filename == NULL:
1805
fname = SAGE_TMP+"/ranges.tmp"
1806
else:
1807
fname = filename
1808
1809
res = glp_print_ranges(self.lp, 0, 0, 0, fname)
1810
1811
if filename == NULL:
1812
if res == 0:
1813
with open(fname) as f:
1814
for line in f:
1815
print line,
1816
print
1817
1818
return res
1819
1820
cpdef double get_row_dual(self, int variable):
1821
r"""
1822
Returns the dual value of a constraint.
1823
1824
The dual value of the ith row is also the value of the ith variable
1825
of the dual problem.
1826
1827
The dual value of a constraint is the shadow price of the constraint.
1828
The shadow price is the amount by which the objective value will change
1829
if the constraints bounds change by one unit under the precondition
1830
that the basis remains the same.
1831
1832
INPUT:
1833
1834
- ``variable`` -- The number of the constraint
1835
1836
.. NOTE::
1837
1838
Behaviour is undefined unless ``solve`` has been called before.
1839
If the simplex algorithm has not been used for solving 0.0 will
1840
be returned.
1841
1842
EXAMPLE::
1843
1844
sage: from sage.numerical.backends.generic_backend import get_solver
1845
sage: lp = get_solver(solver = "GLPK")
1846
sage: lp.add_variables(3)
1847
2
1848
sage: lp.add_linear_constraint(zip([0, 1, 2], [8, 6, 1]), None, 48)
1849
sage: lp.add_linear_constraint(zip([0, 1, 2], [4, 2, 1.5]), None, 20)
1850
sage: lp.add_linear_constraint(zip([0, 1, 2], [2, 1.5, 0.5]), None, 8)
1851
sage: lp.set_objective([60, 30, 20])
1852
sage: import sage.numerical.backends.glpk_backend as backend
1853
sage: lp.solver_parameter(backend.glp_simplex_or_intopt, backend.glp_simplex_only)
1854
sage: lp.solve()
1855
0
1856
sage: lp.get_row_dual(0) # tolerance 0.00001
1857
0.0
1858
sage: lp.get_row_dual(1) # tolerance 0.00001
1859
10.0
1860
1861
1862
"""
1863
1864
if self.simplex_or_intopt == simplex_only:
1865
return glp_get_row_dual(self.lp, variable+1)
1866
else:
1867
return 0.0
1868
1869
cpdef double get_col_dual(self, int variable):
1870
"""
1871
Returns the dual value (reduced cost) of a variable
1872
1873
The dual value is the reduced cost of a variable.
1874
The reduced cost is the amount by which the objective coefficient
1875
of a non basic variable has to change to become a basic variable.
1876
1877
INPUT:
1878
1879
- ``variable`` -- The number of the variable
1880
1881
.. NOTE::
1882
1883
Behaviour is undefined unless ``solve`` has been called before.
1884
If the simplex algorithm has not been used for solving just a
1885
0.0 will be returned.
1886
1887
1888
EXAMPLE::
1889
1890
sage: from sage.numerical.backends.generic_backend import get_solver
1891
sage: p = get_solver(solver = "GLPK")
1892
sage: p.add_variables(3)
1893
2
1894
sage: p.add_linear_constraint(zip([0, 1, 2], [8, 6, 1]), None, 48)
1895
sage: p.add_linear_constraint(zip([0, 1, 2], [4, 2, 1.5]), None, 20)
1896
sage: p.add_linear_constraint(zip([0, 1, 2], [2, 1.5, 0.5]), None, 8)
1897
sage: p.set_objective([60, 30, 20])
1898
sage: import sage.numerical.backends.glpk_backend as backend
1899
sage: p.solver_parameter(backend.glp_simplex_or_intopt, backend.glp_simplex_only)
1900
sage: p.solve()
1901
0
1902
sage: p.get_col_dual(1)
1903
-5.0
1904
1905
"""
1906
if self.simplex_or_intopt == simplex_only:
1907
return glp_get_col_dual(self.lp, variable+1)
1908
else:
1909
return 0.0
1910
1911
1912
def __dealloc__(self):
1913
"""
1914
Destructor
1915
"""
1916
glp_delete_prob(self.lp)
1917
sage_free(self.iocp)
1918
sage_free(self.smcp)
1919
1920
# parameter names
1921
1922
cdef enum solver_parameter_names:
1923
timelimit_seconds, timelimit_simplex, timelimit_intopt, simplex_or_intopt, msg_lev_simplex,
1924
msg_lev_intopt, br_tech, bt_tech, pp_tech, fp_heur, gmi_cuts,
1925
mir_cuts, cov_cuts, clq_cuts, tol_int, tol_obj, mip_gap,
1926
tm_lim_intopt, out_frq_intopt, out_dly_intopt, presolve_intopt,
1927
binarize, meth, pricing, r_test, tol_bnd, tol_dj, tol_piv, obj_ll,
1928
obj_ul, it_lim, tm_lim_simplex, out_frq_simplex, out_dly_simplex,
1929
presolve_simplex
1930
1931
glp_tm_lim_simplex = timelimit_simplex
1932
glp_tm_lim_intopt = timelimit_intopt
1933
glp_simplex_or_intopt = simplex_or_intopt
1934
glp_msg_lev_intopt = glp_verbosity_intopt = msg_lev_intopt
1935
glp_msg_lev_simplex = glp_verbosity_simplex = msg_lev_simplex
1936
glp_br_tech = glp_branching = br_tech
1937
glp_bt_tech = glp_backtracking = bt_tech
1938
glp_pp_tech = glp_preprocessing = pp_tech
1939
glp_fp_heur = glp_feasibility_pump = fp_heur
1940
glp_gmi_cuts = glp_gomory_cuts = gmi_cuts
1941
glp_mir_cuts = glp_mixed_int_rounding_cuts = mir_cuts
1942
glp_cov_cuts = glp_mixed_cover_cuts = cov_cuts
1943
glp_clq_cuts = glp_clique_cuts = clq_cuts
1944
glp_tol_int = glp_absolute_tolerance = tol_int
1945
glp_tol_obj = glp_relative_tolerance = tol_obj
1946
glp_mip_gap = glp_mip_gap_tolerance = mip_gap
1947
glp_out_frq_intopt = glp_output_frequency_intopt = out_frq_intopt
1948
glp_out_dly_intopt = glp_output_delay_intopt = out_dly_intopt
1949
glp_presolve_intopt = presolve_intopt
1950
glp_binarize = binarize
1951
glp_meth = glp_primal_v_dual = meth
1952
glp_pricing = pricing
1953
glp_r_test = glp_ratio_test = r_test
1954
glp_tol_bnd = glp_tolerance_primal = tol_bnd
1955
glp_tol_dj = glp_tolerance_dual = tol_dj
1956
glp_tol_piv = glp_tolerance_pivot = tol_piv
1957
glp_obj_ll = glp_obj_lower_limit = obj_ll
1958
glp_obj_ul = glp_obj_upper_limit = obj_ul
1959
glp_it_lim = glp_iteration_limit = it_lim
1960
glp_out_frq_simplex = glp_output_frequency_intopt = out_frq_simplex
1961
glp_out_dly_simplex = glp_output_delay_simplex = out_dly_simplex
1962
glp_presolve_simplex = presolve_simplex
1963
1964
solver_parameter_names_dict = {
1965
'timelimit': timelimit_seconds,
1966
'timelimit_intopt': timelimit_intopt,
1967
'tm_lim_intopt': timelimit_intopt,
1968
'timelimit_simplex': timelimit_simplex,
1969
'tm_lim_simplex': timelimit_simplex,
1970
'simplex_or_intopt': simplex_or_intopt,
1971
'msg_lev_simplex': msg_lev_simplex, 'verbosity_simplex': msg_lev_simplex,
1972
'msg_lev_intopt': msg_lev_intopt, 'verbosity_intopt': msg_lev_intopt,
1973
'br_tech': br_tech, 'branching': br_tech,
1974
'bt_tech': bt_tech, 'backtracking': bt_tech,
1975
'pp_tech': pp_tech, 'preprocessing': pp_tech,
1976
'fp_heur': fp_heur, 'feasibility_pump': fp_heur,
1977
'gmi_cuts': gmi_cuts, 'gomory_cuts': gmi_cuts,
1978
'mir_cuts': mir_cuts, 'mixed_int_rounding_cuts': mir_cuts,
1979
'cov_cuts': cov_cuts, 'mixed_cover_cuts': cov_cuts,
1980
'clq_cuts': clq_cuts, 'clique_cuts': clq_cuts,
1981
'tol_int': tol_int, 'absolute_tolerance': tol_int,
1982
'tol_obj': tol_obj, 'relative_tolerance': tol_obj,
1983
'mip_gap': mip_gap, 'mip_gap_tolerance': mip_gap,
1984
'out_frq_intopt': out_frq_intopt, 'output_frequency_intopt': out_frq_intopt,
1985
'out_dly_intopt': out_dly_intopt, 'output_delay_intopt': out_dly_intopt,
1986
'presolve_intopt': presolve_intopt, 'binarize': binarize,
1987
'meth': meth, 'primal_v_dual': meth,
1988
'pricing': pricing,
1989
'r_test': r_test, 'ratio_test': r_test,
1990
'tol_bnd': tol_bnd, 'tolerance_primal': tol_bnd,
1991
'tol_dj': tol_dj, 'tolerance_dual': tol_dj,
1992
'tol_piv': tol_piv, 'tolerance_pivot': tol_piv,
1993
'obj_ll': obj_ll, 'obj_lower_limit': obj_ll,
1994
'obj_ul': obj_ul, 'obj_upper_limit': obj_ul,
1995
'it_lim': it_lim, 'iteration_limit': it_lim,
1996
'out_frq_simplex': out_frq_simplex, 'output_frequency_intopt': out_frq_simplex,
1997
'out_dly_simplex': out_dly_simplex, 'output_delay_simplex': out_dly_simplex,
1998
'presolve_simplex': presolve_simplex
1999
}
2000
2001
# parameter values
2002
2003
glp_msg_off = GLP_MSG_OFF
2004
glp_msg_on = GLP_MSG_ON
2005
glp_msg_err = GLP_MSG_ERR
2006
glp_msg_all = GLP_MSG_ALL
2007
glp_msg_dbg = GLP_MSG_DBG
2008
2009
glp_primal = GLP_PRIMAL
2010
glp_dual = GLP_DUAL
2011
glp_dualp = GLP_DUALP
2012
2013
glp_pt_std = GLP_PT_STD
2014
glp_pt_pse = GLP_PT_PSE
2015
2016
glp_rt_std = GLP_RT_STD
2017
glp_rt_har = GLP_RT_HAR
2018
2019
dbl_max = DBL_MAX
2020
int_max = INT_MAX
2021
2022
glp_on = GLP_ON
2023
glp_off = GLP_OFF
2024
2025
glp_br_ffv = GLP_BR_FFV
2026
glp_br_lfv = GLP_BR_LFV
2027
glp_br_mfv = GLP_BR_MFV
2028
glp_br_dth = GLP_BR_DTH
2029
glp_br_pch = GLP_BR_PCH
2030
2031
glp_bt_dfs = GLP_BT_DFS
2032
glp_bt_bfs = GLP_BT_BFS
2033
glp_bt_blb = GLP_BT_BLB
2034
glp_bt_bph = GLP_BT_BPH
2035
2036
glp_pp_none = GLP_PP_NONE
2037
glp_pp_root = GLP_PP_ROOT
2038
glp_pp_all = GLP_PP_ALL
2039
2040
glp_max = GLP_MAX
2041
glp_min = GLP_MIN
2042
glp_up = GLP_UP
2043
glp_fr = GLP_FR
2044
glp_db = GLP_DB
2045
glp_fx = GLP_FX
2046
glp_lo = GLP_LO
2047
glp_cv = GLP_CV
2048
glp_iv = GLP_IV
2049
glp_bv = GLP_BV
2050
glp_mps_deck = GLP_MPS_DECK
2051
glp_mps_file = GLP_MPS_FILE
2052
2053
glp_undef = GLP_UNDEF
2054
glp_opt = GLP_OPT
2055
glp_feas = GLP_FEAS
2056
glp_nofeas = GLP_NOFEAS
2057
2058
cdef enum more_parameter_values:
2059
simplex_only, simplex_then_intopt, intopt_only
2060
2061
glp_simplex_only = simplex_only
2062
glp_simplex_then_intopt = simplex_then_intopt
2063
glp_intopt_only = intopt_only
2064
2065
# dictionaries for those who prefer to use strings
2066
2067
solver_parameter_values = {
2068
2069
'simplex_only': simplex_only,
2070
'simplex_then_intopt': simplex_then_intopt,
2071
'intopt_only': intopt_only,
2072
2073
'GLP_MSG_OFF' : GLP_MSG_OFF,
2074
'GLP_MSG_ON' : GLP_MSG_ON,
2075
'GLP_MSG_ERR' : GLP_MSG_ERR,
2076
'GLP_MSG_ALL' : GLP_MSG_ALL,
2077
'GLP_MSG_DBG' : GLP_MSG_DBG,
2078
2079
'GLP_PRIMAL' : GLP_PRIMAL,
2080
'GLP_DUAL' : GLP_DUAL,
2081
'GLP_DUALP' : GLP_DUALP,
2082
2083
'GLP_PT_STD' : GLP_PT_STD,
2084
'GLP_PT_PSE' : GLP_PT_PSE,
2085
2086
'GLP_RT_STD' : GLP_RT_STD,
2087
'GLP_RT_HAR' : GLP_RT_HAR,
2088
2089
'DBL_MAX' : DBL_MAX,
2090
'INT_MAX' : INT_MAX,
2091
2092
'GLP_ON' : GLP_ON,
2093
'GLP_OFF' : GLP_OFF,
2094
2095
'GLP_BR_FFV' : GLP_BR_FFV,
2096
'GLP_BR_LFV' : GLP_BR_LFV,
2097
'GLP_BR_MFV' : GLP_BR_MFV,
2098
'GLP_BR_DTH' : GLP_BR_DTH,
2099
'GLP_BR_PCH' : GLP_BR_PCH,
2100
2101
'GLP_BT_DFS' : GLP_BT_DFS,
2102
'GLP_BT_BFS' : GLP_BT_BFS,
2103
'GLP_BT_BLB' : GLP_BT_BLB,
2104
'GLP_BT_BPH' : GLP_BT_BPH,
2105
2106
'GLP_PP_NONE' : GLP_PP_NONE,
2107
'GLP_PP_ROOT' : GLP_PP_ROOT,
2108
'GLP_PP_ALL' : GLP_PP_ALL,
2109
2110
'GLP_MAX' : GLP_MAX,
2111
'GLP_MIN' : GLP_MIN,
2112
'GLP_UP' : GLP_UP,
2113
'GLP_FR' : GLP_FR,
2114
'GLP_DB' : GLP_DB,
2115
'GLP_FX' : GLP_FX,
2116
'GLP_LO' : GLP_LO,
2117
'GLP_CV' : GLP_CV,
2118
'GLP_IV' : GLP_IV,
2119
'GLP_BV' : GLP_BV,
2120
'GLP_MPS_DECK' : GLP_MPS_DECK,
2121
'GLP_MPS_FILE' : GLP_MPS_FILE,
2122
2123
'GLP_UNDEF' : GLP_UNDEF,
2124
'GLP_OPT' : GLP_OPT,
2125
'GLP_FEAS' : GLP_FEAS,
2126
'GLP_NOFEAS' : GLP_NOFEAS
2127
2128
}
2129
2130