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