Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagesmc
Path: blob/master/src/sage/numerical/backends/ppl_backend.pyx
8817 views
1
"""
2
PPL Backend
3
4
AUTHORS:
5
6
- Risan (2012-02): initial implementation
7
"""
8
9
#*****************************************************************************
10
# Copyright (C) 2010 Risan <[email protected]>
11
#
12
# Distributed under the terms of the GNU General Public License (GPL)
13
# as published by the Free Software Foundation; either version 2 of
14
# the License, or (at your option) any later version.
15
# http://www.gnu.org/licenses/
16
#*****************************************************************************
17
18
from sage.numerical.mip import MIPSolverException
19
from sage.libs.ppl import MIP_Problem, Variable, Linear_Expression, Constraint, Generator
20
21
cdef class PPLBackend(GenericBackend):
22
cdef object mip
23
cdef list Matrix
24
cdef list row_lower_bound
25
cdef list row_upper_bound
26
cdef list col_lower_bound
27
cdef list col_upper_bound
28
cdef list objective_function
29
cdef list row_name_var
30
cdef list col_name_var
31
cdef int is_maximize
32
cdef str name
33
34
def __cinit__(self, maximization = True):
35
"""
36
Constructor
37
38
EXAMPLE::
39
40
sage: p = MixedIntegerLinearProgram(solver = "PPL")
41
"""
42
43
self.Matrix = []
44
self.row_lower_bound = []
45
self.row_upper_bound = []
46
self.col_lower_bound = []
47
self.col_upper_bound = []
48
self.objective_function = []
49
self.row_name_var = []
50
self.col_name_var = []
51
self.name = ''
52
self.obj_constant_term = 0;
53
54
if maximization:
55
self.set_sense(+1)
56
else:
57
self.set_sense(-1)
58
59
cpdef base_ring(self):
60
from sage.rings.all import QQ
61
return QQ
62
63
cpdef zero(self):
64
return self.base_ring()(0)
65
66
def init_mip(self):
67
"""
68
Converting the matrix form of the MIP Problem to PPL MIP_Problem.
69
70
EXAMPLE::
71
72
sage: from sage.numerical.backends.generic_backend import get_solver
73
sage: p = get_solver(solver = "PPL")
74
sage: p.base_ring()
75
Rational Field
76
sage: type(p.zero())
77
<type 'sage.rings.rational.Rational'>
78
sage: p.init_mip()
79
80
"""
81
82
self.mip = MIP_Problem()
83
mip_obj = Linear_Expression(0)
84
85
self.mip.add_space_dimensions_and_embed(len(self.objective_function))
86
for i in range(len(self.objective_function)):
87
mip_obj = mip_obj + Linear_Expression(self.objective_function[i] * Variable(i))
88
self.mip.set_objective_function(mip_obj)
89
for i in range(len(self.Matrix)):
90
l = Linear_Expression(0)
91
for j in range(len(self.Matrix[i])):
92
l = l + Linear_Expression(self.Matrix[i][j] * Variable(j))
93
if self.row_lower_bound[i] is not None:
94
self.mip.add_constraint(l >= self.row_lower_bound[i])
95
if self.row_upper_bound[i] is not None:
96
self.mip.add_constraint(l <= self.row_upper_bound[i])
97
98
for i in range(len(self.col_lower_bound)):
99
if self.col_lower_bound[i] is not None:
100
self.mip.add_constraint(Variable(i) >= self.col_lower_bound[i])
101
102
for i in range(len(self.col_upper_bound)):
103
if self.col_upper_bound[i] is not None:
104
self.mip.add_constraint(Variable(i) <= self.col_upper_bound[i])
105
106
if self.is_maximize == 1:
107
self.mip.set_optimization_mode('maximization')
108
else:
109
self.mip.set_optimization_mode('minimization')
110
111
cpdef int add_variable(self, lower_bound=0, upper_bound=None, binary=False, continuous=True, integer=False, obj=0, name=None) except -1:
112
"""
113
Add a variable.
114
115
This amounts to adding a new column to the matrix. By default,
116
the variable is both positive and real.
117
118
It has not been implemented for selecting the variable type yet.
119
120
INPUT:
121
122
- ``lower_bound`` -- the lower bound of the variable (default: 0)
123
124
- ``upper_bound`` -- the upper bound of the variable (default: ``None``)
125
126
- ``binary`` -- ``True`` if the variable is binary (default: ``False``).
127
128
- ``continuous`` -- ``True`` if the variable is binary (default: ``True``).
129
130
- ``integer`` -- ``True`` if the variable is binary (default: ``False``).
131
132
- ``obj`` -- (optional) coefficient of this variable in the objective function (default: 0)
133
134
- ``name`` -- an optional name for the newly added variable (default: ``None``).
135
136
OUTPUT: The index of the newly created variable
137
138
EXAMPLE::
139
140
sage: from sage.numerical.backends.generic_backend import get_solver
141
sage: p = get_solver(solver = "PPL")
142
sage: p.ncols()
143
0
144
sage: p.add_variable()
145
0
146
sage: p.ncols()
147
1
148
sage: p.add_variable(lower_bound=-2)
149
1
150
sage: p.add_variable(name='x',obj=2/3)
151
2
152
sage: p.col_name(2)
153
'x'
154
sage: p.objective_coefficient(2)
155
2/3
156
"""
157
for i in range(len(self.Matrix)):
158
self.Matrix[i].append(0)
159
self.col_lower_bound.append(lower_bound)
160
self.col_upper_bound.append(upper_bound)
161
self.objective_function.append(obj)
162
self.col_name_var.append(name)
163
return len(self.objective_function) - 1
164
165
cpdef int add_variables(self, int n, lower_bound=0, upper_bound=None, binary=False, continuous=True, integer=False, obj=0, names=None) except -1:
166
"""
167
Add ``n`` variables.
168
169
This amounts to adding new columns to the matrix. By default,
170
the variables are both positive and real.
171
172
It has not been implemented for selecting the variable type yet.
173
174
INPUT:
175
176
- ``n`` -- the number of new variables (must be > 0)
177
178
- ``lower_bound`` -- the lower bound of the variable (default: 0)
179
180
- ``upper_bound`` -- the upper bound of the variable (default: ``None``)
181
182
- ``binary`` -- ``True`` if the variable is binary (default: ``False``).
183
184
- ``continuous`` -- ``True`` if the variable is binary (default: ``True``).
185
186
- ``integer`` -- ``True`` if the variable is binary (default: ``False``).
187
188
- ``obj`` -- (optional) coefficient of all variables in the objective function (default: 0)
189
190
- ``names`` -- optional list of names (default: ``None``)
191
192
OUTPUT: The index of the variable created last.
193
194
EXAMPLE::
195
196
sage: from sage.numerical.backends.generic_backend import get_solver
197
sage: p = get_solver(solver = "PPL")
198
sage: p.ncols()
199
0
200
sage: p.add_variables(5)
201
4
202
sage: p.ncols()
203
5
204
sage: p.add_variables(2, lower_bound=-2.0, names=['a','b'])
205
6
206
"""
207
for k in range(n):
208
for i in range(len(self.Matrix)):
209
self.Matrix[i].append(0)
210
self.col_lower_bound.append(lower_bound)
211
self.col_upper_bound.append(upper_bound)
212
self.objective_function.append(obj)
213
if names is not None:
214
self.col_name_var.append(names[k])
215
else:
216
self.col_name_var.append(None)
217
return len(self.objective_function) - 1;
218
219
cpdef set_variable_type(self, int variable, int vtype):
220
"""
221
Set the type of a variable.
222
223
EXAMPLE::
224
225
sage: from sage.numerical.backends.generic_backend import get_solver
226
sage: p = get_solver(solver = "PPL")
227
sage: p.add_variables(5)
228
4
229
sage: p.set_variable_type(3, -1)
230
sage: p.set_variable_type(3, -2)
231
Traceback (most recent call last):
232
...
233
Exception: ...
234
"""
235
if vtype != -1:
236
raise Exception('This backend does not handle integer variables ! Read the doc !')
237
238
cpdef set_sense(self, int sense):
239
"""
240
Set the direction (maximization/minimization).
241
242
INPUT:
243
244
- ``sense`` (integer) :
245
246
* +1 => Maximization
247
* -1 => Minimization
248
249
EXAMPLE::
250
251
sage: from sage.numerical.backends.generic_backend import get_solver
252
sage: p = get_solver(solver = "PPL")
253
sage: p.is_maximization()
254
True
255
sage: p.set_sense(-1)
256
sage: p.is_maximization()
257
False
258
"""
259
if sense == 1:
260
self.is_maximize = 1
261
else:
262
self.is_maximize = 0
263
264
cpdef objective_coefficient(self, int variable, coeff=None):
265
"""
266
Set or get the coefficient of a variable in the objective
267
function
268
269
INPUT:
270
271
- ``variable`` (integer) -- the variable's id
272
273
- ``coeff`` (integer) -- its coefficient
274
275
EXAMPLE::
276
277
sage: from sage.numerical.backends.generic_backend import get_solver
278
sage: p = get_solver(solver = "PPL")
279
sage: p.add_variable()
280
0
281
sage: p.objective_coefficient(0)
282
0
283
sage: p.objective_coefficient(0,2)
284
sage: p.objective_coefficient(0)
285
2
286
"""
287
if coeff is not None:
288
self.objective_function[variable] = coeff;
289
else:
290
return self.objective_function[variable]
291
292
cpdef set_objective(self, list coeff, d = 0):
293
"""
294
Set the objective function.
295
296
INPUT:
297
298
- ``coeff`` -- a list of real values, whose ith element is the
299
coefficient of the ith variable in the objective function.
300
301
EXAMPLE::
302
303
sage: from sage.numerical.backends.generic_backend import get_solver
304
sage: p = get_solver(solver = "PPL")
305
sage: p.add_variables(5)
306
4
307
sage: p.set_objective([1, 1, 2, 1, 3])
308
sage: map(lambda x :p.objective_coefficient(x), range(5))
309
[1, 1, 2, 1, 3]
310
"""
311
for i in range(len(coeff)):
312
self.objective_function[i] = coeff[i];
313
obj_constant_term = d;
314
315
cpdef set_verbosity(self, int level):
316
"""
317
Set the log (verbosity) level. Not Implemented.
318
319
EXAMPLE::
320
321
sage: from sage.numerical.backends.generic_backend import get_solver
322
sage: p = get_solver(solver = "PPL")
323
sage: p.set_verbosity(0)
324
"""
325
326
cpdef add_linear_constraint(self, coefficients, lower_bound, upper_bound, name=None):
327
"""
328
Add a linear constraint.
329
330
INPUT:
331
332
- ``coefficients`` -- an iterable with ``(c,v)`` pairs where ``c``
333
is a variable index (integer) and ``v`` is a value (real
334
value).
335
336
- ``lower_bound`` -- a lower bound, either a real value or ``None``
337
338
- ``upper_bound`` -- an upper bound, either a real value or ``None``
339
340
- ``name`` -- an optional name for this row (default: ``None``)
341
342
EXAMPLE::
343
344
sage: from sage.numerical.backends.generic_backend import get_solver
345
sage: p = get_solver(solver = "PPL")
346
sage: p.add_variables(5)
347
4
348
sage: p.add_linear_constraint(zip(range(5), range(5)), 2.0, 2.0)
349
sage: p.row(0)
350
([1, 2, 3, 4], [1, 2, 3, 4])
351
sage: p.row_bounds(0)
352
(2.00000000000000, 2.00000000000000)
353
sage: p.add_linear_constraint( zip(range(5), range(5)), 1.0, 1.0, name='foo')
354
sage: p.row_name(-1)
355
'foo'
356
"""
357
last = len(self.Matrix)
358
self.Matrix.append([])
359
for i in range(len(self.objective_function)):
360
self.Matrix[last].append(0)
361
for a in coefficients:
362
self.Matrix[last][a[0]] = a[1]
363
364
self.row_lower_bound.append(lower_bound)
365
self.row_upper_bound.append(upper_bound)
366
self.row_name_var.append(name)
367
368
cpdef add_col(self, list indices, list coeffs):
369
"""
370
Add a column.
371
372
INPUT:
373
374
- ``indices`` (list of integers) -- this list constains the
375
indices of the constraints in which the variable's
376
coefficient is nonzero
377
378
- ``coeffs`` (list of real values) -- associates a coefficient
379
to the variable in each of the constraints in which it
380
appears. Namely, the ith entry of ``coeffs`` corresponds to
381
the coefficient of the variable in the constraint
382
represented by the ith entry in ``indices``.
383
384
.. NOTE::
385
386
``indices`` and ``coeffs`` are expected to be of the same
387
length.
388
389
EXAMPLE::
390
391
sage: from sage.numerical.backends.generic_backend import get_solver
392
sage: p = get_solver(solver = "PPL")
393
sage: p.ncols()
394
0
395
sage: p.nrows()
396
0
397
sage: p.add_linear_constraints(5, 0, None)
398
sage: p.add_col(range(5), range(5))
399
sage: p.nrows()
400
5
401
"""
402
for i in range(len(self.Matrix)):
403
self.Matrix[i].append(0)
404
for i in range(len(indices)):
405
self.Matrix[indices[i]][len(self.Matrix[indices[i]]) - 1] = coeffs[i]
406
407
self.col_lower_bound.append(None)
408
self.col_upper_bound.append(None)
409
self.objective_function.append(0)
410
self.col_name_var.append(None)
411
412
cpdef add_linear_constraints(self, int number, lower_bound, upper_bound, names=None):
413
"""
414
Add constraints.
415
416
INPUT:
417
418
- ``number`` (integer) -- the number of constraints to add.
419
420
- ``lower_bound`` -- a lower bound, either a real value or ``None``
421
422
- ``upper_bound`` -- an upper bound, either a real value or ``None``
423
424
- ``names`` -- an optional list of names (default: ``None``)
425
426
EXAMPLE::
427
428
sage: from sage.numerical.backends.generic_backend import get_solver
429
sage: p = get_solver(solver = "PPL")
430
sage: p.add_variables(5)
431
4
432
sage: p.add_linear_constraints(5, None, 2)
433
sage: p.row(4)
434
([], [])
435
sage: p.row_bounds(4)
436
(None, 2)
437
"""
438
for i in range(number):
439
self.Matrix.append([])
440
for j in range(len(self.objective_function)):
441
self.Matrix[i].append(0)
442
self.row_lower_bound.append(lower_bound)
443
self.row_upper_bound.append(upper_bound)
444
if names is not None:
445
self.row_name_var.append(names)
446
else:
447
self.row_name_var.append(None)
448
449
cpdef int solve(self) except -1:
450
"""
451
Solve the problem.
452
453
.. NOTE::
454
455
This method raises ``MIPSolverException`` exceptions when
456
the solution can not be computed for any reason (none
457
exists, or the LP solver was not able to find it, etc...)
458
459
EXAMPLE::
460
461
sage: from sage.numerical.backends.generic_backend import get_solver
462
sage: p = get_solver(solver = "PPL")
463
sage: p.add_linear_constraints(5, 0, None)
464
sage: p.add_col(range(5), range(5))
465
sage: p.solve()
466
0
467
sage: p.objective_coefficient(0,1)
468
sage: p.solve()
469
Traceback (most recent call last):
470
...
471
MIPSolverException: ...
472
"""
473
self.init_mip()
474
475
ans = self.mip.solve()
476
477
if ans['status'] == 'optimized':
478
pass
479
elif ans['status'] == 'unbounded':
480
raise MIPSolverException("PPL : Solution is unbounded")
481
elif ans['status'] == 'unfeasible':
482
raise MIPSolverException("PPL : There is no feasible solution")
483
484
return 0
485
486
cpdef get_objective_value(self):
487
"""
488
Return the exact value of the objective function.
489
490
.. NOTE::
491
492
Behaviour is undefined unless ``solve`` has been called before.
493
494
EXAMPLE::
495
496
sage: from sage.numerical.backends.generic_backend import get_solver
497
sage: p = get_solver(solver = "PPL")
498
sage: p.add_variables(2)
499
1
500
sage: p.add_linear_constraint([(0,1), (1,2)], None, 3)
501
sage: p.set_objective([2, 5])
502
sage: p.solve()
503
0
504
sage: p.get_objective_value()
505
15/2
506
sage: p.get_variable_value(0)
507
0
508
sage: p.get_variable_value(1)
509
3/2
510
"""
511
self.init_mip()
512
ans = self.mip.optimal_value()
513
return ans + self.obj_constant_term
514
515
cpdef get_variable_value(self, int variable):
516
"""
517
Return the value of a variable given by the solver.
518
519
.. NOTE::
520
521
Behaviour is undefined unless ``solve`` has been called before.
522
523
EXAMPLE::
524
525
sage: from sage.numerical.backends.generic_backend import get_solver
526
sage: p = get_solver(solver = "PPL")
527
sage: p.add_variables(2)
528
1
529
sage: p.add_linear_constraint([(0,1), (1, 2)], None, 3)
530
sage: p.set_objective([2, 5])
531
sage: p.solve()
532
0
533
sage: p.get_objective_value()
534
15/2
535
sage: p.get_variable_value(0)
536
0
537
sage: p.get_variable_value(1)
538
3/2
539
"""
540
self.init_mip()
541
g = self.mip.optimizing_point()
542
return g.coefficient(Variable(variable)) / g.divisor()
543
544
cpdef int ncols(self):
545
"""
546
Return the number of columns/variables.
547
548
EXAMPLE::
549
550
sage: from sage.numerical.backends.generic_backend import get_solver
551
sage: p = get_solver(solver = "PPL")
552
sage: p.ncols()
553
0
554
sage: p.add_variables(2)
555
1
556
sage: p.ncols()
557
2
558
"""
559
return len(self.objective_function)
560
561
cpdef int nrows(self):
562
"""
563
Return the number of rows/constraints.
564
565
EXAMPLE::
566
567
sage: from sage.numerical.backends.generic_backend import get_solver
568
sage: p = get_solver(solver = "PPL")
569
sage: p.nrows()
570
0
571
sage: p.add_linear_constraints(2, 2.0, None)
572
sage: p.nrows()
573
2
574
"""
575
return len(self.Matrix)
576
577
cpdef bint is_maximization(self):
578
"""
579
Test whether the problem is a maximization
580
581
EXAMPLE::
582
583
sage: from sage.numerical.backends.generic_backend import get_solver
584
sage: p = get_solver(solver = "PPL")
585
sage: p.is_maximization()
586
True
587
sage: p.set_sense(-1)
588
sage: p.is_maximization()
589
False
590
"""
591
if self.is_maximize == 1:
592
return 1
593
else:
594
return 0
595
596
cpdef problem_name(self, char * name = NULL):
597
"""
598
Return or define the problem's name
599
600
INPUT:
601
602
- ``name`` (``char *``) -- the problem's name. When set to
603
``NULL`` (default), the method returns the problem's name.
604
605
EXAMPLE::
606
607
sage: from sage.numerical.backends.generic_backend import get_solver
608
sage: p = get_solver(solver = "PPL")
609
sage: p.problem_name("There once was a french fry")
610
sage: print p.problem_name()
611
There once was a french fry
612
"""
613
if name == NULL:
614
return self.name
615
self.name = str(<bytes>name)
616
617
cpdef row(self, int i):
618
"""
619
Return a row
620
621
INPUT:
622
623
- ``index`` (integer) -- the constraint's id.
624
625
OUTPUT:
626
627
A pair ``(indices, coeffs)`` where ``indices`` lists the
628
entries whose coefficient is nonzero, and to which ``coeffs``
629
associates their coefficient on the model of the
630
``add_linear_constraint`` method.
631
632
EXAMPLE::
633
634
sage: from sage.numerical.backends.generic_backend import get_solver
635
sage: p = get_solver(solver = "PPL")
636
sage: p.add_variables(5)
637
4
638
sage: p.add_linear_constraint(zip(range(5), range(5)), 2, 2)
639
sage: p.row(0)
640
([1, 2, 3, 4], [1, 2, 3, 4])
641
sage: p.row_bounds(0)
642
(2, 2)
643
"""
644
idx = []
645
coef = []
646
for j in range(len(self.Matrix[i])):
647
if self.Matrix[i][j] != 0:
648
idx.append(j)
649
coef.append(self.Matrix[i][j])
650
return (idx, coef)
651
652
cpdef row_bounds(self, int index):
653
"""
654
Return the bounds of a specific constraint.
655
656
INPUT:
657
658
- ``index`` (integer) -- the constraint's id.
659
660
OUTPUT:
661
662
A pair ``(lower_bound, upper_bound)``. Each of them can be set
663
to ``None`` if the constraint is not bounded in the
664
corresponding direction, and is a real value otherwise.
665
666
EXAMPLE::
667
668
sage: from sage.numerical.backends.generic_backend import get_solver
669
sage: p = get_solver(solver = "PPL")
670
sage: p.add_variables(5)
671
4
672
sage: p.add_linear_constraint(zip(range(5), range(5)), 2, 2)
673
sage: p.row(0)
674
([1, 2, 3, 4], [1, 2, 3, 4])
675
sage: p.row_bounds(0)
676
(2, 2)
677
"""
678
return (self.row_lower_bound[index], self.row_upper_bound[index])
679
680
cpdef col_bounds(self, int index):
681
"""
682
Return the bounds of a specific variable.
683
684
INPUT:
685
686
- ``index`` (integer) -- the variable's id.
687
688
OUTPUT:
689
690
A pair ``(lower_bound, upper_bound)``. Each of them can be set
691
to ``None`` if the variable is not bounded in the
692
corresponding direction, and is a real value otherwise.
693
694
EXAMPLE::
695
696
sage: from sage.numerical.backends.generic_backend import get_solver
697
sage: p = get_solver(solver = "PPL")
698
sage: p.add_variable()
699
0
700
sage: p.col_bounds(0)
701
(0, None)
702
sage: p.variable_upper_bound(0, 5)
703
sage: p.col_bounds(0)
704
(0, 5)
705
"""
706
return (self.col_lower_bound[index], self.col_upper_bound[index])
707
708
709
cpdef bint is_variable_binary(self, int index):
710
"""
711
Test whether the given variable is of binary type.
712
713
INPUT:
714
715
- ``index`` (integer) -- the variable's id
716
717
EXAMPLE::
718
719
sage: from sage.numerical.backends.generic_backend import get_solver
720
sage: p = get_solver(solver = "PPL")
721
sage: p.ncols()
722
0
723
sage: p.add_variable()
724
0
725
sage: p.is_variable_binary(0)
726
False
727
"""
728
return False
729
730
cpdef bint is_variable_integer(self, int index):
731
"""
732
Test whether the given variable is of integer type.
733
734
INPUT:
735
736
- ``index`` (integer) -- the variable's id
737
738
EXAMPLE::
739
740
sage: from sage.numerical.backends.generic_backend import get_solver
741
sage: p = get_solver(solver = "PPL")
742
sage: p.ncols()
743
0
744
sage: p.add_variable()
745
0
746
sage: p.is_variable_integer(0)
747
False
748
"""
749
return False
750
751
cpdef bint is_variable_continuous(self, int index):
752
"""
753
Test whether the given variable is of continuous/real type.
754
755
INPUT:
756
757
- ``index`` (integer) -- the variable's id
758
759
EXAMPLE::
760
761
sage: from sage.numerical.backends.generic_backend import get_solver
762
sage: p = get_solver(solver = "PPL")
763
sage: p.ncols()
764
0
765
sage: p.add_variable()
766
0
767
sage: p.is_variable_continuous(0)
768
True
769
"""
770
return True
771
772
cpdef row_name(self, int index):
773
"""
774
Return the ``index`` th row name
775
776
INPUT:
777
778
- ``index`` (integer) -- the row's id
779
780
EXAMPLE::
781
782
sage: from sage.numerical.backends.generic_backend import get_solver
783
sage: p = get_solver(solver = "PPL")
784
sage: p.add_linear_constraints(1, 2, None, names="Empty constraint 1")
785
sage: p.row_name(0)
786
'Empty constraint 1'
787
"""
788
if self.row_name_var[index] is not None:
789
return self.row_name_var[index]
790
return "constraint_" + repr(index)
791
792
cpdef col_name(self, int index):
793
"""
794
Return the ``index`` th col name
795
796
INPUT:
797
798
- ``index`` (integer) -- the col's id
799
800
- ``name`` (``char *``) -- its name. When set to ``NULL``
801
(default), the method returns the current name.
802
803
EXAMPLE::
804
805
sage: from sage.numerical.backends.generic_backend import get_solver
806
sage: p = get_solver(solver = "PPL")
807
sage: p.add_variable(name="I am a variable")
808
0
809
sage: p.col_name(0)
810
'I am a variable'
811
"""
812
if self.col_name_var[index] is not None:
813
return self.col_name_var[index]
814
return "x_" + repr(index)
815
816
cpdef variable_upper_bound(self, int index, value = False):
817
"""
818
Return or define the upper bound on a variable
819
820
INPUT:
821
822
- ``index`` (integer) -- the variable's id
823
824
- ``value`` -- real value, or ``None`` to mean that the
825
variable has not upper bound. When set to ``None``
826
(default), the method returns the current value.
827
828
EXAMPLE::
829
830
sage: from sage.numerical.backends.generic_backend import get_solver
831
sage: p = get_solver(solver = "PPL")
832
sage: p.add_variable()
833
0
834
sage: p.col_bounds(0)
835
(0, None)
836
sage: p.variable_upper_bound(0, 5)
837
sage: p.col_bounds(0)
838
(0, 5)
839
sage: p.variable_upper_bound(0, None)
840
sage: p.col_bounds(0)
841
(0, None)
842
"""
843
if value is not False:
844
self.col_upper_bound[index] = value
845
else:
846
return self.col_upper_bound[index]
847
848
cpdef variable_lower_bound(self, int index, value = False):
849
"""
850
Return or define the lower bound on a variable
851
852
INPUT:
853
854
- ``index`` (integer) -- the variable's id
855
856
- ``value`` -- real value, or ``None`` to mean that the
857
variable has not lower bound. When set to ``None``
858
(default), the method returns the current value.
859
860
EXAMPLE::
861
862
sage: from sage.numerical.backends.generic_backend import get_solver
863
sage: p = get_solver(solver = "PPL")
864
sage: p.add_variable()
865
0
866
sage: p.col_bounds(0)
867
(0, None)
868
sage: p.variable_lower_bound(0, 5)
869
sage: p.col_bounds(0)
870
(5, None)
871
sage: p.variable_lower_bound(0, None)
872
sage: p.col_bounds(0)
873
(None, None)
874
"""
875
if value is not False:
876
self.col_lower_bound[index] = value
877
else:
878
return self.col_lower_bound[index]
879
880