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