Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagelib
Path: blob/master/sage/numerical/backends/generic_backend.pyx
4059 views
1
r"""
2
Generic Backend for LP solvers
3
4
This class only lists the methods that should be defined by any
5
interface with a LP Solver. All these methods immediately raise
6
``NotImplementedError`` exceptions when called, and are obviously
7
meant to be replaced by the solver-specific method. This file can also
8
be used as a template to create a new interface : one would only need
9
to replace the occurences of ``"Nonexistent_LP_solver"`` by the
10
solver's name, and replace ``GenericBackend`` by
11
``SolverName(GenericBackend)`` so that the new solver extends this
12
class.
13
14
AUTHORS:
15
16
- Nathann Cohen (2010-10): initial implementation
17
18
"""
19
20
##############################################################################
21
# Copyright (C) 2010 Nathann Cohen <[email protected]>
22
# Distributed under the terms of the GNU General Public License (GPL)
23
# The full text of the GPL is available at:
24
# http://www.gnu.org/licenses/
25
##############################################################################
26
27
28
cdef class GenericBackend:
29
30
cpdef int add_variable(self, lower_bound=0.0, upper_bound=None, binary=False, continuous=True, integer=False, obj=0.0, name=None) except -1:
31
"""
32
Add a variable.
33
34
This amounts to adding a new column to the matrix. By default,
35
the variable is both positive and real.
36
37
INPUT:
38
39
- ``lower_bound`` - the lower bound of the variable (default: 0)
40
41
- ``upper_bound`` - the upper bound of the variable (default: ``None``)
42
43
- ``binary`` - ``True`` if the variable is binary (default: ``False``).
44
45
- ``continuous`` - ``True`` if the variable is binary (default: ``True``).
46
47
- ``integer`` - ``True`` if the variable is binary (default: ``False``).
48
49
- ``obj`` - (optional) coefficient of this variable in the objective function (default: 0.0)
50
51
- ``name`` - an optional name for the newly added variable (default: ``None``).
52
53
OUTPUT: The index of the newly created variable
54
55
EXAMPLE::
56
57
sage: from sage.numerical.backends.generic_backend import get_solver
58
sage: p = get_solver(solver = "Nonexistent_LP_solver") # optional - Nonexistent_LP_solver
59
sage: p.ncols() # optional - Nonexistent_LP_solver
60
0
61
sage: p.add_variable() # optional - Nonexistent_LP_solver
62
0
63
sage: p.ncols() # optional - Nonexistent_LP_solver
64
1
65
sage: p.add_variable(binary=True) # optional - Nonexistent_LP_solver
66
1
67
sage: p.add_variable(lower_bound=-2.0, integer=True) # optional - Nonexistent_LP_solver
68
2
69
sage: p.add_variable(continuous=True, integer=True) # optional - Nonexistent_LP_solver
70
Traceback (most recent call last):
71
...
72
ValueError: ...
73
sage: p.add_variable(name='x',obj=1.0) # optional - Nonexistent_LP_solver
74
3
75
sage: p.col_name(3) # optional - Nonexistent_LP_solver
76
'x'
77
sage: p.objective_coefficient(3) # optional - Nonexistent_LP_solver
78
1.0
79
"""
80
raise NotImplementedError()
81
82
cpdef int add_variables(self, int n, lower_bound=0.0, upper_bound=None, binary=False, continuous=True, integer=False, obj=0.0, names=None) except -1:
83
"""
84
Add ``n`` variables.
85
86
This amounts to adding new columns to the matrix. By default,
87
the variables are both positive and real.
88
89
INPUT:
90
91
- ``n`` - the number of new variables (must be > 0)
92
93
- ``lower_bound`` - the lower bound of the variable (default: 0)
94
95
- ``upper_bound`` - the upper bound of the variable (default: ``None``)
96
97
- ``binary`` - ``True`` if the variable is binary (default: ``False``).
98
99
- ``continuous`` - ``True`` if the variable is binary (default: ``True``).
100
101
- ``integer`` - ``True`` if the variable is binary (default: ``False``).
102
103
- ``obj`` - (optional) coefficient of all variables in the objective function (default: 0.0)
104
105
- ``names`` - optional list of names (default: ``None``)
106
107
OUTPUT: The index of the variable created last.
108
109
EXAMPLE::
110
111
sage: from sage.numerical.backends.generic_backend import get_solver
112
sage: p = get_solver(solver = "Nonexistent_LP_solver") # optional - Nonexistent_LP_solver
113
sage: p.ncols() # optional - Nonexistent_LP_solver
114
0
115
sage: p.add_variables(5) # optional - Nonexistent_LP_solver
116
4
117
sage: p.ncols() # optional - Nonexistent_LP_solver
118
5
119
sage: p.add_variables(2, lower_bound=-2.0, integer=True, names=['a','b']) # optional - Nonexistent_LP_solver
120
6
121
"""
122
raise NotImplementedError()
123
124
cpdef set_variable_type(self, int variable, int vtype):
125
"""
126
Set the type of a variable
127
128
INPUT:
129
130
- ``variable`` (integer) -- the variable's id
131
132
- ``vtype`` (integer) :
133
134
* 1 Integer
135
* 0 Binary
136
* -1 Continuous
137
138
EXAMPLE::
139
140
sage: from sage.numerical.backends.generic_backend import get_solver
141
sage: p = get_solver(solver = "Nonexistent_LP_solver") # optional - Nonexistent_LP_solver
142
sage: p.ncols() # optional - Nonexistent_LP_solver
143
0
144
sage: p.add_variable() # optional - Nonexistent_LP_solver
145
1
146
sage: p.set_variable_type(0,1) # optional - Nonexistent_LP_solver
147
sage: p.is_variable_integer(0) # optional - Nonexistent_LP_solver
148
True
149
"""
150
raise NotImplementedError()
151
152
cpdef set_sense(self, int sense):
153
"""
154
Set the direction (maximization/minimization).
155
156
INPUT:
157
158
- ``sense`` (integer) :
159
160
* +1 => Maximization
161
* -1 => Minimization
162
163
EXAMPLE::
164
165
sage: from sage.numerical.backends.generic_backend import get_solver
166
sage: p = get_solver(solver = "Nonexistent_LP_solver") # optional - Nonexistent_LP_solver
167
sage: p.is_maximization() # optional - Nonexistent_LP_solver
168
True
169
sage: p.set_sense(-1) # optional - Nonexistent_LP_solver
170
sage: p.is_maximization() # optional - Nonexistent_LP_solver
171
False
172
"""
173
raise NotImplementedError()
174
175
cpdef objective_coefficient(self, int variable, coeff=None):
176
"""
177
Set or get the coefficient of a variable in the objective
178
function
179
180
INPUT:
181
182
- ``variable`` (integer) -- the variable's id
183
184
- ``coeff`` (double) -- its coefficient
185
186
EXAMPLE::
187
188
sage: from sage.numerical.backends.generic_backend import get_solver
189
sage: p = get_solver(solver = "Nonexistent_LP_solver") # optional - Nonexistent_LP_solver
190
sage: p.add_variable() # optional - Nonexistent_LP_solver
191
1
192
sage: p.objective_coefficient(0) # optional - Nonexistent_LP_solver
193
0.0
194
sage: p.objective_coefficient(0,2) # optional - Nonexistent_LP_solver
195
sage: p.objective_coefficient(0) # optional - Nonexistent_LP_solver
196
2.0
197
"""
198
raise NotImplementedError()
199
200
cpdef set_objective(self, list coeff, double d = 0.0):
201
"""
202
Set the objective function.
203
204
INPUT:
205
206
- ``coeff`` -- a list of real values, whose ith element is the
207
coefficient of the ith variable in the objective function.
208
209
- ``d`` (double) -- the constant term in the linear function (set to `0` by default)
210
211
EXAMPLE::
212
213
sage: from sage.numerical.backends.generic_backend import get_solver
214
sage: p = get_solver(solver = "Nonexistent_LP_solver") # optional - Nonexistent_LP_solver
215
sage: p.add_variables(5) # optional - Nonexistent_LP_solver
216
5
217
sage: p.set_objective([1, 1, 2, 1, 3]) # optional - Nonexistent_LP_solver
218
sage: map(lambda x :p.objective_coefficient(x), range(5)) # optional - Nonexistent_LP_solver
219
[1.0, 1.0, 2.0, 1.0, 3.0]
220
221
Constants in the objective function are respected::
222
223
sage: p = MixedIntegerLinearProgram(solver='Nonexistent_LP_solver') # optional - Nonexistent_LP_solver
224
sage: x,y = p[0], p[1] # optional - Nonexistent_LP_solver
225
sage: p.add_constraint(2*x + 3*y, max = 6) # optional - Nonexistent_LP_solver
226
sage: p.add_constraint(3*x + 2*y, max = 6) # optional - Nonexistent_LP_solver
227
sage: p.set_objective(x + y + 7) # optional - Nonexistent_LP_solver
228
sage: p.set_integer(x); p.set_integer(y) # optional - Nonexistent_LP_solver
229
sage: p.solve() # optional - Nonexistent_LP_solver
230
9.0
231
"""
232
raise NotImplementedError()
233
234
cpdef set_verbosity(self, int level):
235
"""
236
Set the log (verbosity) level
237
238
INPUT:
239
240
- ``level`` (integer) -- From 0 (no verbosity) to 3.
241
242
EXAMPLE::
243
244
sage: from sage.numerical.backends.generic_backend import get_solver
245
sage: p = get_solver(solver = "Nonexistent_LP_solver") # optional - Nonexistent_LP_solver
246
sage: p.set_verbosity(2) # optional - Nonexistent_LP_solver
247
"""
248
raise NotImplementedError()
249
250
cpdef remove_constraint(self, int i):
251
r"""
252
Remove a constraint.
253
254
INPUT::
255
256
- ``i`` -- index of the constraint to remove.
257
258
EXAMPLE::
259
260
sage: from sage.numerical.backends.generic_backend import get_solver
261
sage: p = get_solver(solver = "Nonexistent_LP_solver") # optional - Nonexistent_LP_solver
262
sage: p.add_constraint(p[0] + p[1], max = 10) # optional - Nonexistent_LP_solver
263
sage: p.remove_constraint(0) # optional - Nonexistent_LP_solver
264
"""
265
raise NotImplementedError()
266
267
cpdef remove_constraints(self, constraints):
268
r"""
269
Remove several constraints.
270
271
INPUT:
272
273
- ``constraints`` -- an iterable containing the indices of the rows to remove.
274
275
EXAMPLE::
276
277
sage: from sage.numerical.backends.generic_backend import get_solver
278
sage: p = get_solver(solver = "Nonexistent_LP_solver") # optional - Nonexistent_LP_solver
279
sage: p.add_constraint(p[0] + p[1], max = 10) # optional - Nonexistent_LP_solver
280
sage: p.remove_constraints([0]) # optional - Nonexistent_LP_solver
281
"""
282
if type(constraints) == int: self.remove_constraint(constraints)
283
284
cdef int last = self.nrows() + 1
285
286
for c in sorted(constraints, reverse=True):
287
if c != last:
288
self.remove_constraint(c)
289
last = c
290
291
cpdef add_linear_constraint(self, coefficients, lower_bound, upper_bound, name=None):
292
"""
293
Add a linear constraint.
294
295
INPUT:
296
297
- ``coefficients`` an iterable with ``(c,v)`` pairs where ``c``
298
is a variable index (integer) and ``v`` is a value (real
299
value).
300
301
- ``lower_bound`` - a lower bound, either a real value or ``None``
302
303
- ``upper_bound`` - an upper bound, either a real value or ``None``
304
305
- ``name`` - an optional name for this row (default: ``None``)
306
307
EXAMPLE::
308
309
sage: from sage.numerical.backends.generic_backend import get_solver
310
sage: p = get_solver(solver = "Nonexistent_LP_solver") # optional - Nonexistent_LP_solver
311
sage: p.add_variables(5) # optional - Nonexistent_LP_solver
312
4
313
sage: p.add_linear_constraint(zip(range(5), range(5)), 2.0, 2.0) # optional - Nonexistent_LP_solver
314
sage: p.row(0) # optional - Nonexistent_LP_solver
315
([4, 3, 2, 1], [4.0, 3.0, 2.0, 1.0]) # optional - Nonexistent_LP_solver
316
sage: p.row_bounds(0) # optional - Nonexistent_LP_solver
317
(2.0, 2.0)
318
sage: p.add_linear_constraint( zip(range(5), range(5)), 1.0, 1.0, name='foo') # optional - Nonexistent_LP_solver
319
sage: p.row_name(-1) # optional - Nonexistent_LP_solver
320
"foo"
321
"""
322
raise NotImplementedError()
323
324
cpdef add_col(self, list indices, list coeffs):
325
"""
326
Add a column.
327
328
INPUT:
329
330
- ``indices`` (list of integers) -- this list constains the
331
indices of the constraints in which the variable's
332
coefficient is nonzero
333
334
- ``coeffs`` (list of real values) -- associates a coefficient
335
to the variable in each of the constraints in which it
336
appears. Namely, the ith entry of ``coeffs`` corresponds to
337
the coefficient of the variable in the constraint
338
represented by the ith entry in ``indices``.
339
340
.. NOTE::
341
342
``indices`` and ``coeffs`` are expected to be of the same
343
length.
344
345
EXAMPLE::
346
347
sage: from sage.numerical.backends.generic_backend import get_solver
348
sage: p = get_solver(solver = "Nonexistent_LP_solver") # optional - Nonexistent_LP_solver
349
sage: p.ncols() # optional - Nonexistent_LP_solver
350
0
351
sage: p.nrows() # optional - Nonexistent_LP_solver
352
0
353
sage: p.add_linear_constraints(5, 0, None) # optional - Nonexistent_LP_solver
354
sage: p.add_col(range(5), range(5)) # optional - Nonexistent_LP_solver
355
sage: p.nrows() # optional - Nonexistent_LP_solver
356
5
357
"""
358
raise NotImplementedError()
359
360
cpdef add_linear_constraints(self, int number, lower_bound, upper_bound, names=None):
361
"""
362
Add constraints.
363
364
INPUT:
365
366
- ``number`` (integer) -- the number of constraints to add.
367
368
- ``lower_bound`` - a lower bound, either a real value or ``None``
369
370
- ``upper_bound`` - an upper bound, either a real value or ``None``
371
372
- ``names`` - an optional list of names (default: ``None``)
373
374
EXAMPLE::
375
376
sage: from sage.numerical.backends.generic_backend import get_solver
377
sage: p = get_solver(solver = "Nonexistent_LP_solver") # optional - Nonexistent_LP_solver
378
sage: p.add_variables(5) # optional - Nonexistent_LP_solver
379
5
380
sage: p.add_linear_constraints(5, None, 2) # optional - Nonexistent_LP_solver
381
sage: p.row(4) # optional - Nonexistent_LP_solver
382
([], [])
383
sage: p.row_bounds(4) # optional - Nonexistent_LP_solver
384
(None, 2.0)
385
"""
386
raise NotImplementedError()
387
388
cpdef int solve(self) except -1:
389
"""
390
Solve the problem.
391
392
.. NOTE::
393
394
This method raises ``MIPSolverException`` exceptions when
395
the solution can not be computed for any reason (none
396
exists, or the LP solver was not able to find it, etc...)
397
398
EXAMPLE::
399
400
sage: from sage.numerical.backends.generic_backend import get_solver
401
sage: p = get_solver(solver = "Nonexistent_LP_solver") # optional - Nonexistent_LP_solver
402
sage: p.add_linear_constraints(5, 0, None) # optional - Nonexistent_LP_solver
403
sage: p.add_col(range(5), range(5)) # optional - Nonexistent_LP_solver
404
sage: p.solve() # optional - Nonexistent_LP_solver
405
0
406
sage: p.objective_coefficient(0,1) # optional - Nonexistent_LP_solver
407
sage: p.solve() # optional - Nonexistent_LP_solver
408
Traceback (most recent call last):
409
...
410
MIPSolverException: ...
411
"""
412
raise NotImplementedError()
413
414
cpdef double get_objective_value(self):
415
"""
416
Return the value of the objective function.
417
418
.. NOTE::
419
420
Behaviour is undefined unless ``solve`` has been called before.
421
422
EXAMPLE::
423
424
sage: from sage.numerical.backends.generic_backend import get_solver
425
sage: p = get_solver(solver = "Nonexistent_LP_solver") # optional - Nonexistent_LP_solver
426
sage: p.add_variables(2) # optional - Nonexistent_LP_solver
427
2
428
sage: p.add_linear_constraint([(0,1), (1,2)], None, 3) # optional - Nonexistent_LP_solver
429
sage: p.set_objective([2, 5]) # optional - Nonexistent_LP_solver
430
sage: p.solve() # optional - Nonexistent_LP_solver
431
0
432
sage: p.get_objective_value() # optional - Nonexistent_LP_solver
433
7.5
434
sage: p.get_variable_value(0) # optional - Nonexistent_LP_solver
435
0.0
436
sage: p.get_variable_value(1) # optional - Nonexistent_LP_solver
437
1.5
438
"""
439
440
raise NotImplementedError()
441
442
cpdef double get_variable_value(self, int variable):
443
"""
444
Return the value of a variable given by the solver.
445
446
.. NOTE::
447
448
Behaviour is undefined unless ``solve`` has been called before.
449
450
EXAMPLE::
451
452
sage: from sage.numerical.backends.generic_backend import get_solver
453
sage: p = get_solver(solver = "Nonexistent_LP_solver") # optional - Nonexistent_LP_solver
454
sage: p.add_variables(2) # optional - Nonexistent_LP_solver
455
2
456
sage: p.add_linear_constraint([(0,1), (1, 2)], None, 3) # optional - Nonexistent_LP_solver
457
sage: p.set_objective([2, 5]) # optional - Nonexistent_LP_solver
458
sage: p.solve() # optional - Nonexistent_LP_solver
459
0
460
sage: p.get_objective_value() # optional - Nonexistent_LP_solver
461
7.5
462
sage: p.get_variable_value(0) # optional - Nonexistent_LP_solver
463
0.0
464
sage: p.get_variable_value(1) # optional - Nonexistent_LP_solver
465
1.5
466
"""
467
468
raise NotImplementedError()
469
470
cpdef int ncols(self):
471
"""
472
Return the number of columns/variables.
473
474
EXAMPLE::
475
476
sage: from sage.numerical.backends.generic_backend import get_solver
477
sage: p = get_solver(solver = "Nonexistent_LP_solver") # optional - Nonexistent_LP_solver
478
sage: p.ncols() # optional - Nonexistent_LP_solver
479
0
480
sage: p.add_variables(2) # optional - Nonexistent_LP_solver
481
2
482
sage: p.ncols() # optional - Nonexistent_LP_solver
483
2
484
"""
485
486
raise NotImplementedError()
487
488
cpdef int nrows(self):
489
"""
490
Return the number of rows/constraints.
491
492
EXAMPLE::
493
494
sage: from sage.numerical.backends.generic_backend import get_solver
495
sage: p = get_solver(solver = "Nonexistent_LP_solver") # optional - Nonexistent_LP_solver
496
sage: p.nrows() # optional - Nonexistent_LP_solver
497
0
498
sage: p.add_linear_constraints(2, 2.0, None) # optional - Nonexistent_LP_solver
499
sage: p.nrows() # optional - Nonexistent_LP_solver
500
2
501
"""
502
503
raise NotImplementedError()
504
505
cpdef bint is_maximization(self):
506
"""
507
Test whether the problem is a maximization
508
509
EXAMPLE::
510
511
sage: from sage.numerical.backends.generic_backend import get_solver
512
sage: p = get_solver(solver = "Nonexistent_LP_solver") # optional - Nonexistent_LP_solver
513
sage: p.is_maximization() # optional - Nonexistent_LP_solver
514
True
515
sage: p.set_sense(-1) # optional - Nonexistent_LP_solver
516
sage: p.is_maximization() # optional - Nonexistent_LP_solver
517
False
518
"""
519
raise NotImplementedError()
520
521
cpdef problem_name(self, char * name = NULL):
522
"""
523
Return or define the problem's name
524
525
INPUT:
526
527
- ``name`` (``char *``) -- the problem's name. When set to
528
``NULL`` (default), the method returns the problem's name.
529
530
EXAMPLE::
531
532
sage: from sage.numerical.backends.generic_backend import get_solver
533
sage: p = get_solver(solver = "Nonexistent_LP_solver") # optional - Nonexistent_LP_solver
534
sage: p.problem_name("There once was a french fry") # optional - Nonexistent_LP_solver
535
sage: print p.get_problem_name() # optional - Nonexistent_LP_solver
536
There once was a french fry
537
"""
538
539
raise NotImplementedError()
540
541
cpdef write_lp(self, char * name):
542
"""
543
Write the problem to a .lp file
544
545
INPUT:
546
547
- ``filename`` (string)
548
549
EXAMPLE::
550
551
sage: from sage.numerical.backends.generic_backend import get_solver
552
sage: p = get_solver(solver = "Nonexistent_LP_solver") # optional - Nonexistent_LP_solver
553
sage: p.add_variables(2) # optional - Nonexistent_LP_solver
554
2
555
sage: p.add_linear_constraint([(0, 1], (1, 2)], None, 3) # optional - Nonexistent_LP_solver
556
sage: p.set_objective([2, 5]) # optional - Nonexistent_LP_solver
557
sage: p.write_lp(SAGE_TMP+"/lp_problem.lp") # optional - Nonexistent_LP_solver
558
"""
559
raise NotImplementedError()
560
561
cpdef write_mps(self, char * name, int modern):
562
"""
563
Write the problem to a .mps file
564
565
INPUT:
566
567
- ``filename`` (string)
568
569
EXAMPLE::
570
571
sage: from sage.numerical.backends.generic_backend import get_solver
572
sage: p = get_solver(solver = "Nonexistent_LP_solver") # optional - Nonexistent_LP_solver
573
sage: p.add_variables(2) # optional - Nonexistent_LP_solver
574
2
575
sage: p.add_linear_constraint([(0, 1), (1, 2)], None, 3) # optional - Nonexistent_LP_solver
576
sage: p.set_objective([2, 5]) # optional - Nonexistent_LP_solver
577
sage: p.write_lp(SAGE_TMP+"/lp_problem.lp") # optional - Nonexistent_LP_solver
578
"""
579
raise NotImplementedError()
580
581
cpdef row(self, int i):
582
"""
583
Return a row
584
585
INPUT:
586
587
- ``index`` (integer) -- the constraint's id.
588
589
OUTPUT:
590
591
A pair ``(indices, coeffs)`` where ``indices`` lists the
592
entries whose coefficient is nonzero, and to which ``coeffs``
593
associates their coefficient on the model of the
594
``add_linear_constraint`` method.
595
596
EXAMPLE::
597
598
sage: from sage.numerical.backends.generic_backend import get_solver
599
sage: p = get_solver(solver = "Nonexistent_LP_solver") # optional - Nonexistent_LP_solver
600
sage: p.add_variables(5) # optional - Nonexistent_LP_solver
601
5
602
sage: p.add_linear_constraint(zip(range(5), range(5)), 2, 2) # optional - Nonexistent_LP_solver
603
sage: p.row(0) # optional - Nonexistent_LP_solver
604
([4, 3, 2, 1], [4.0, 3.0, 2.0, 1.0])
605
sage: p.row_bounds(0) # optional - Nonexistent_LP_solver
606
(2.0, 2.0)
607
"""
608
raise NotImplementedError()
609
610
cpdef row_bounds(self, int index):
611
"""
612
Return the bounds of a specific constraint.
613
614
INPUT:
615
616
- ``index`` (integer) -- the constraint's id.
617
618
OUTPUT:
619
620
A pair ``(lower_bound, upper_bound)``. Each of them can be set
621
to ``None`` if the constraint is not bounded in the
622
corresponding direction, and is a real value otherwise.
623
624
EXAMPLE::
625
626
sage: from sage.numerical.backends.generic_backend import get_solver
627
sage: p = get_solver(solver = "Nonexistent_LP_solver") # optional - Nonexistent_LP_solver
628
sage: p.add_variables(5) # optional - Nonexistent_LP_solver
629
5
630
sage: p.add_linear_constraint(range(5), range(5), 2, 2) # optional - Nonexistent_LP_solver
631
sage: p.row(0) # optional - Nonexistent_LP_solver
632
([4, 3, 2, 1], [4.0, 3.0, 2.0, 1.0])
633
sage: p.row_bounds(0) # optional - Nonexistent_LP_solver
634
(2.0, 2.0)
635
"""
636
raise NotImplementedError()
637
638
cpdef col_bounds(self, int index):
639
"""
640
Return the bounds of a specific variable.
641
642
INPUT:
643
644
- ``index`` (integer) -- the variable's id.
645
646
OUTPUT:
647
648
A pair ``(lower_bound, upper_bound)``. Each of them can be set
649
to ``None`` if the variable is not bounded in the
650
corresponding direction, and is a real value otherwise.
651
652
EXAMPLE::
653
654
sage: from sage.numerical.backends.generic_backend import get_solver
655
sage: p = get_solver(solver = "Nonexistent_LP_solver") # optional - Nonexistent_LP_solver
656
sage: p.add_variable() # optional - Nonexistent_LP_solver
657
1
658
sage: p.col_bounds(0) # optional - Nonexistent_LP_solver
659
(0.0, None)
660
sage: p.variable_upper_bound(0, 5) # optional - Nonexistent_LP_solver
661
sage: p.col_bounds(0) # optional - Nonexistent_LP_solver
662
(0.0, 5.0)
663
"""
664
raise NotImplementedError()
665
666
cpdef bint is_variable_binary(self, int index):
667
"""
668
Test whether the given variable is of binary type.
669
670
INPUT:
671
672
- ``index`` (integer) -- the variable's id
673
674
EXAMPLE::
675
676
sage: from sage.numerical.backends.generic_backend import get_solver
677
sage: p = get_solver(solver = "Nonexistent_LP_solver") # optional - Nonexistent_LP_solver
678
sage: p.ncols() # optional - Nonexistent_LP_solver
679
0
680
sage: p.add_variable() # optional - Nonexistent_LP_solver
681
1
682
sage: p.set_variable_type(0,0) # optional - Nonexistent_LP_solver
683
sage: p.is_variable_binary(0) # optional - Nonexistent_LP_solver
684
True
685
686
"""
687
raise NotImplementedError()
688
689
cpdef bint is_variable_integer(self, int index):
690
"""
691
Test whether the given variable is of integer type.
692
693
INPUT:
694
695
- ``index`` (integer) -- the variable's id
696
697
EXAMPLE::
698
699
sage: from sage.numerical.backends.generic_backend import get_solver
700
sage: p = get_solver(solver = "Nonexistent_LP_solver") # optional - Nonexistent_LP_solver
701
sage: p.ncols() # optional - Nonexistent_LP_solver
702
0
703
sage: p.add_variable() # optional - Nonexistent_LP_solver
704
1
705
sage: p.set_variable_type(0,1) # optional - Nonexistent_LP_solver
706
sage: p.is_variable_integer(0) # optional - Nonexistent_LP_solver
707
True
708
"""
709
raise NotImplementedError()
710
711
cpdef bint is_variable_continuous(self, int index):
712
"""
713
Test whether the given variable is of continuous/real type.
714
715
INPUT:
716
717
- ``index`` (integer) -- the variable's id
718
719
EXAMPLE::
720
721
sage: from sage.numerical.backends.generic_backend import get_solver
722
sage: p = get_solver(solver = "Nonexistent_LP_solver") # optional - Nonexistent_LP_solver
723
sage: p.ncols() # optional - Nonexistent_LP_solver
724
0
725
sage: p.add_variable() # optional - Nonexistent_LP_solver
726
1
727
sage: p.is_variable_continuous(0) # optional - Nonexistent_LP_solver
728
True
729
sage: p.set_variable_type(0,1) # optional - Nonexistent_LP_solver
730
sage: p.is_variable_continuous(0) # optional - Nonexistent_LP_solver
731
False
732
733
"""
734
raise NotImplementedError()
735
736
cpdef row_name(self, int index):
737
"""
738
Return the ``index`` th row name
739
740
INPUT:
741
742
- ``index`` (integer) -- the row's id
743
744
EXAMPLE::
745
746
sage: from sage.numerical.backends.generic_backend import get_solver
747
sage: p = get_solver(solver = "Nonexistent_LP_solver") # optional - Nonexistent_LP_solver
748
sage: p.add_linear_constraints(1, 2, None, name="Empty constraint 1") # optional - Nonexistent_LP_solver
749
sage: p.row_name(0) # optional - Nonexistent_LP_solver
750
'Empty constraint 1'
751
752
"""
753
raise NotImplementedError()
754
755
cpdef col_name(self, int index):
756
"""
757
Return the ``index`` th col name
758
759
INPUT:
760
761
- ``index`` (integer) -- the col's id
762
763
- ``name`` (``char *``) -- its name. When set to ``NULL``
764
(default), the method returns the current name.
765
766
EXAMPLE::
767
768
sage: from sage.numerical.backends.generic_backend import get_solver
769
sage: p = get_solver(solver = "Nonexistent_LP_solver") # optional - Nonexistent_LP_solver
770
sage: p.add_variable(name="I am a variable") # optional - Nonexistent_LP_solver
771
1
772
sage: p.col_name(0) # optional - Nonexistent_LP_solver
773
'I am a variable'
774
"""
775
raise NotImplementedError()
776
777
cpdef variable_upper_bound(self, int index, value = None):
778
"""
779
Return or define the upper bound on a variable
780
781
INPUT:
782
783
- ``index`` (integer) -- the variable's id
784
785
- ``value`` -- real value, or ``None`` to mean that the
786
variable has not upper bound. When set to ``None``
787
(default), the method returns the current value.
788
789
EXAMPLE::
790
791
sage: from sage.numerical.backends.generic_backend import get_solver
792
sage: p = get_solver(solver = "Nonexistent_LP_solver") # optional - Nonexistent_LP_solver
793
sage: p.add_variable() # optional - Nonexistent_LP_solver
794
1
795
sage: p.col_bounds(0) # optional - Nonexistent_LP_solver
796
(0.0, None)
797
sage: p.variable_upper_bound(0, 5) # optional - Nonexistent_LP_solver
798
sage: p.col_bounds(0) # optional - Nonexistent_LP_solver
799
(0.0, 5.0)
800
"""
801
raise NotImplementedError()
802
803
cpdef variable_lower_bound(self, int index, value = None):
804
"""
805
Return or define the lower bound on a variable
806
807
INPUT:
808
809
- ``index`` (integer) -- the variable's id
810
811
- ``value`` -- real value, or ``None`` to mean that the
812
variable has not lower bound. When set to ``None``
813
(default), the method returns the current value.
814
815
EXAMPLE::
816
817
sage: from sage.numerical.backends.generic_backend import get_solver
818
sage: p = get_solver(solver = "Nonexistent_LP_solver") # optional - Nonexistent_LP_solver
819
sage: p.add_variable() # optional - Nonexistent_LP_solver
820
1
821
sage: p.col_bounds(0) # optional - Nonexistent_LP_solver
822
(0.0, None)
823
sage: p.variable_lower_bound(0, 5) # optional - Nonexistent_LP_solver
824
sage: p.col_bounds(0) # optional - Nonexistent_LP_solver
825
(5.0, None)
826
"""
827
raise NotImplementedError()
828
829
cpdef solver_parameter(self, name, value = None):
830
"""
831
Return or define a solver parameter
832
833
INPUT:
834
835
- ``name`` (string) -- the parameter
836
837
- ``value`` -- the parameter's value if it is to be defined,
838
or ``None`` (default) to obtain its current value.
839
840
.. NOTE::
841
842
The list of available parameters is available at
843
:meth:`sage.numerical.mip.MixedIntegerlinearProgram.solver_parameter`
844
845
EXAMPLE::
846
847
sage: from sage.numerical.backends.generic_backend import get_solver
848
sage: p = get_solver(solver = "Nonexistent_LP_solver") # optional - Nonexistent_LP_solver
849
sage: p.solver_parameter("timelimit") # optional - Nonexistent_LP_solver
850
sage: p.solver_parameter("timelimit", 60) # optional - Nonexistent_LP_solver
851
sage: p.solver_parameter("timelimit") # optional - Nonexistent_LP_solver
852
"""
853
raise NotImplementedError()
854
855
856
default_solver = None
857
858
def default_mip_solver(solver = None):
859
"""
860
Returns/Sets the default MILP Solver used by Sage
861
862
INPUT:
863
864
- ``solver`` -- defines the solver to use:
865
866
- GLPK (``solver="GLPK"``). See the `GLPK
867
<http://www.gnu.org/software/glpk/>`_ web site.
868
869
- COIN Branch and Cut (``solver="Coin"``). See the `COIN-OR
870
<http://www.coin-or.org>`_ web site.
871
872
- CPLEX (``solver="CPLEX"``). See the
873
`CPLEX <http://www.ilog.com/products/cplex/>`_ web site.
874
875
- Gurobi (``solver="Gurobi"``). See the `Gurobi
876
<http://www.gurobi.com/>`_ web site.
877
878
``solver`` should then be equal to one of ``"GLPK"``,
879
``"Coin"``, ``"CPLEX"``, or ``"Gurobi"``.
880
881
- If ``solver=None`` (default), the current default solver's name is
882
returned.
883
884
OUTPUT:
885
886
This function returns the current default solver's name if ``solver = None``
887
(default). Otherwise, it sets the default solver to the one given. If this
888
solver does not exist, or is not available, a ``ValueError`` exception is
889
raised.
890
891
EXAMPLE::
892
893
sage: former_solver = default_mip_solver()
894
sage: default_mip_solver("GLPK")
895
sage: default_mip_solver()
896
'Glpk'
897
sage: default_mip_solver("Yeahhhhhhhhhhh")
898
Traceback (most recent call last):
899
...
900
ValueError: 'solver' should be set to 'GLPK', 'Coin', 'CPLEX', 'Gurobi' or None.
901
sage: default_mip_solver(former_solver)
902
"""
903
global default_solver
904
905
if solver is None:
906
907
if default_solver is not None:
908
return default_solver
909
910
else:
911
for s in ["Cplex", "Gurobi", "Coin", "Glpk"]:
912
try:
913
default_mip_solver(s)
914
return s
915
except ValueError:
916
pass
917
918
solver = solver.capitalize()
919
920
if solver == "Cplex":
921
try:
922
from sage.numerical.backends.cplex_backend import CPLEXBackend
923
default_solver = solver
924
except ImportError:
925
raise ValueError("CPLEX is not available. Please refer to the documentation to install it.")
926
927
elif solver == "Coin":
928
try:
929
from sage.numerical.backends.coin_backend import CoinBackend
930
default_solver = solver
931
except ImportError:
932
raise ValueError("COIN is not available. Please refer to the documentation to install it.")
933
934
elif solver == "Gurobi":
935
try:
936
from sage.numerical.backends.gurobi_backend import GurobiBackend
937
default_solver = solver
938
except ImportError:
939
raise ValueError("Gurobi is not available. Please refer to the documentation to install it.")
940
941
elif solver == "Glpk":
942
default_solver = solver
943
944
else:
945
raise ValueError("'solver' should be set to 'GLPK', 'Coin', 'CPLEX', 'Gurobi' or None.")
946
947
cpdef GenericBackend get_solver(constraint_generation = False, solver = None):
948
"""
949
Return a solver according to the given preferences
950
951
INPUT:
952
953
- ``solver`` -- 4 solvers should be available through this class:
954
955
- GLPK (``solver="GLPK"``). See the `GLPK
956
<http://www.gnu.org/software/glpk/>`_ web site.
957
958
- COIN Branch and Cut (``solver="Coin"``). See the `COIN-OR
959
<http://www.coin-or.org>`_ web site.
960
961
- CPLEX (``solver="CPLEX"``). See the
962
`CPLEX <http://www.ilog.com/products/cplex/>`_ web site.
963
964
- Gurobi (``solver="Gurobi"``). See the `Gurobi
965
<http://www.gurobi.com/>`_ web site.
966
967
``solver`` should then be equal to one of ``"GLPK"``, ``"Coin"``,
968
``"CPLEX"``, ``"Gurobi"``, or ``None``. If ``solver=None`` (default),
969
the default solver is used (see ``default_mip_solver`` method.
970
971
- ``constraint_generation`` (boolean) -- whether the solver
972
returned is to be used for constraint/variable generation. As
973
the interface with Coin does not support constraint/variable
974
generation, setting ``constraint_generation`` to ``False``
975
ensures that the backend to Coin is not returned when ``solver =
976
None``. This is set to ``False`` by default.
977
978
.. SEEALSO::
979
980
- :func:`default_mip_solver` -- Returns/Sets the default MIP solver.
981
982
EXAMPLE::
983
984
sage: from sage.numerical.backends.generic_backend import get_solver
985
sage: p = get_solver()
986
"""
987
988
if solver is None:
989
solver = default_mip_solver()
990
991
# We do not want to use Coin for constraint_generation. It just does not
992
# work
993
if solver == "Coin" and constraint_generation:
994
solver = "Glpk"
995
996
else:
997
solver = solver.capitalize()
998
999
if solver == "Coin":
1000
from sage.numerical.backends.coin_backend import CoinBackend
1001
return CoinBackend()
1002
1003
elif solver == "Glpk":
1004
from sage.numerical.backends.glpk_backend import GLPKBackend
1005
return GLPKBackend()
1006
1007
elif solver == "Cplex":
1008
from sage.numerical.backends.cplex_backend import CPLEXBackend
1009
return CPLEXBackend()
1010
1011
elif solver == "Gurobi":
1012
from sage.numerical.backends.gurobi_backend import GurobiBackend
1013
return GurobiBackend()
1014
1015
else:
1016
raise ValueError("'solver' should be set to 'GLPK', 'Coin', 'CPLEX', 'Gurobi' or None (in which case the default one is used).")
1017
1018
1019
1020