# HG changeset patch
# User Nathann Cohen <nathann.cohen@gmail.com>
# Date 1290872901 -3600
# Node ID 4825b49a4b2a955775c29046950b6f02444cc97b
# Parent cfaca337639bd3628804c0633d8074e04038dfa0
trac 10341 -- make MIP backend interface more Python-ic -- Coin and CPLEX
diff -r cfaca337639b -r 4825b49a4b2a sage/numerical/backends/coin_backend.pyx
a
|
b
|
|
35 | 35 | else: |
36 | 36 | self.set_sense(-1) |
37 | 37 | |
38 | | cpdef int add_variable(self): |
39 | | r""" |
40 | | Adds a variable. |
| 38 | cpdef int add_variable(self, lower_bound=0.0, upper_bound=None, binary=False, continuous=False, integer=False) except -1: |
| 39 | """ |
| 40 | Add a variable. |
41 | 41 | |
42 | 42 | This amounts to adding a new column to the matrix. By default, |
43 | 43 | the variable is both positive and real. |
44 | 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 | OUTPUT: The index of the newly created variable |
| 58 | |
45 | 59 | EXAMPLE:: |
46 | 60 | |
47 | 61 | sage: from sage.numerical.backends.generic_backend import get_solver |
48 | | sage: p = get_solver(solver = "Coin") # optional - Coin |
| 62 | sage: p = get_solver(solver = "Coin") # optional - Coin |
49 | 63 | sage: p.ncols() # optional - Coin |
50 | 64 | 0 |
51 | | sage: p.add_variable() # optional - Coin |
52 | | 1 |
| 65 | sage: p.add_variable() # optional - Coin |
| 66 | 0 |
53 | 67 | sage: p.ncols() # optional - Coin |
54 | 68 | 1 |
| 69 | sage: p.add_variable(binary=True) # optional - Coin |
| 70 | 1 |
| 71 | sage: p.add_variable(lower_bound=-2.0, integer=True) # optional - Coin |
| 72 | 2 |
| 73 | sage: p.add_variable(continuous=True, integer=True) # optional - Coin |
| 74 | Traceback (most recent call last): |
| 75 | ... |
| 76 | ValueError: ... |
55 | 77 | """ |
56 | 78 | |
| 79 | cdef int vtype = int(bool(binary)) + int(bool(continuous)) + int(bool(integer)) |
| 80 | if vtype == 0: |
| 81 | continuous = True |
| 82 | elif vtype != 1: |
| 83 | raise ValueError("Exactly one parameter of 'binary', 'integer' and 'continuous' must be 'True'.") |
| 84 | |
57 | 85 | self.si.addCol(0, NULL, NULL, 0, self.si.getInfinity(), 0) |
58 | | return self.si.getNumCols() |
59 | 86 | |
60 | | cpdef int add_variables(self, int number): |
61 | | r""" |
62 | | Adds ``number`` variables. |
| 87 | cdef int n |
| 88 | n = self.si.getNumCols() - 1 |
| 89 | |
| 90 | if lower_bound != 0.0: |
| 91 | self.variable_lower_bound(n, lower_bound) |
| 92 | if upper_bound is not None: |
| 93 | self.variable_upper_bound(n, upper_bound) |
| 94 | |
| 95 | if binary: |
| 96 | self.set_variable_type(n,0) |
| 97 | elif integer: |
| 98 | self.set_variable_type(n,1) |
| 99 | |
| 100 | return n |
| 101 | |
| 102 | cpdef int add_variables(self, int number, lower_bound=0.0, upper_bound=None, binary=False, continuous=False, integer=False) except -1: |
| 103 | """ |
| 104 | Add ``number`` new variables. |
63 | 105 | |
64 | 106 | This amounts to adding new columns to the matrix. By default, |
65 | 107 | the variables are both positive and real. |
66 | 108 | |
| 109 | INPUT: |
| 110 | |
| 111 | - ``n`` - the number of new variables (must be > 0) |
| 112 | |
| 113 | - ``lower_bound`` - the lower bound of the variable (default: 0) |
| 114 | |
| 115 | - ``upper_bound`` - the upper bound of the variable (default: ``None``) |
| 116 | |
| 117 | - ``binary`` - ``True`` if the variable is binary (default: ``False``). |
| 118 | |
| 119 | - ``continuous`` - ``True`` if the variable is binary (default: ``True``). |
| 120 | |
| 121 | - ``integer`` - ``True`` if the variable is binary (default: ``False``). |
| 122 | |
| 123 | OUTPUT: The index of the variable created last. |
| 124 | |
67 | 125 | EXAMPLE:: |
68 | 126 | |
69 | 127 | sage: from sage.numerical.backends.generic_backend import get_solver |
70 | | sage: p = get_solver(solver = "Coin") # optional - Coin |
71 | | sage: p.ncols() # optional - Coin |
| 128 | sage: p = get_solver(solver = "Coin") # optional - Coin |
| 129 | sage: p.ncols() # optional - Coin |
72 | 130 | 0 |
73 | | sage: p.add_variables(5) # optional - Coin |
| 131 | sage: p.add_variables(5) # optional - Coin |
| 132 | 4 |
| 133 | sage: p.ncols() # optional - Coin |
74 | 134 | 5 |
75 | | sage: p.ncols() # optional - Coin |
76 | | 5 |
| 135 | sage: p.add_variables(2, lower_bound=-2.0, integer=True) # optional - Coin |
| 136 | 6 |
77 | 137 | """ |
| 138 | cdef int vtype = int(bool(binary)) + int(bool(continuous)) + int(bool(integer)) |
| 139 | if vtype == 0: |
| 140 | continuous = True |
| 141 | elif vtype != 1: |
| 142 | raise ValueError("Exactly one parameter of 'binary', 'integer' and 'continuous' must be 'True'.") |
| 143 | |
| 144 | cdef int n |
| 145 | n = self.si.getNumCols() |
78 | 146 | |
79 | 147 | cdef int i |
80 | | for 0<= i< number: |
| 148 | |
| 149 | for 0<= i < number: |
| 150 | |
81 | 151 | self.si.addCol(0, NULL, NULL, 0, self.si.getInfinity(), 0) |
82 | | return self.si.getNumCols() |
| 152 | |
| 153 | if lower_bound != 0.0: |
| 154 | self.variable_lower_bound(n + i, lower_bound) |
| 155 | if upper_bound is not None: |
| 156 | self.variable_upper_bound(n + i, upper_bound) |
| 157 | |
| 158 | if binary: |
| 159 | self.set_variable_type(n + i,0) |
| 160 | elif integer: |
| 161 | self.set_variable_type(n + i,1) |
| 162 | |
| 163 | return n + number -1 |
83 | 164 | |
84 | 165 | cpdef set_variable_type(self, int variable, int vtype): |
85 | 166 | r""" |
… |
… |
|
102 | 183 | sage: p.ncols() # optional - Coin |
103 | 184 | 0 |
104 | 185 | sage: p.add_variable() # optional - Coin |
105 | | 1 |
| 186 | 0 |
106 | 187 | sage: p.set_variable_type(0,1) # optional - Coin |
107 | 188 | sage: p.is_variable_integer(0) # optional - Coin |
108 | 189 | True |
… |
… |
|
155 | 236 | sage: from sage.numerical.backends.generic_backend import get_solver |
156 | 237 | sage: p = get_solver(solver = "Coin") # optional - Coin |
157 | 238 | sage: p.add_variable() # optional - Coin |
158 | | 1 |
| 239 | 0 |
159 | 240 | sage: p.get_objective_coefficient(0) # optional - Coin |
160 | 241 | 0.0 |
161 | 242 | sage: p.set_objective_coefficient(0,2) # optional - Coin |
… |
… |
|
179 | 260 | sage: from sage.numerical.backends.generic_backend import get_solver |
180 | 261 | sage: p = get_solver(solver = "Coin") # optional - Coin |
181 | 262 | sage: p.add_variables(5) # optional - Coin |
182 | | 5 |
| 263 | 4 |
183 | 264 | sage: p.set_objective([1, 1, 2, 1, 3]) # optional - Coin |
184 | 265 | sage: map(lambda x :p.get_objective_coefficient(x), range(5)) # optional - Coin |
185 | 266 | [1.0, 1.0, 2.0, 1.0, 3.0] |
… |
… |
|
211 | 292 | msg = model.messageHandler() |
212 | 293 | msg.setLogLevel(level) |
213 | 294 | |
214 | | cpdef add_linear_constraints(self, int number, int direction, double bound): |
215 | | r""" |
216 | | Adds constraints. |
| 295 | cpdef add_linear_constraints(self, int number, lower_bound, upper_bound): |
| 296 | """ |
| 297 | Add ``'number`` linear constraints. |
217 | 298 | |
218 | 299 | INPUT: |
219 | 300 | |
220 | 301 | - ``number`` (integer) -- the number of constraints to add. |
221 | 302 | |
222 | | - ``direction`` (integer) -- the direction of the constraint, |
223 | | where : |
| 303 | - ``lower_bound`` - a lower bound, either a real value or ``None`` |
224 | 304 | |
225 | | * +1 indicates : function `\leq` ``bound`` |
226 | | * 0 indicates : function `=` ``bound`` |
227 | | * -1 indicates : function `\geq` ``bound`` |
228 | | |
229 | | - ``bound`` (double) -- value of the right-hand side (as |
230 | | illustrated immediately above). |
| 305 | - ``upper_bound`` - an upper bound, either a real value or ``None`` |
231 | 306 | |
232 | 307 | EXAMPLE:: |
233 | 308 | |
234 | 309 | sage: from sage.numerical.backends.generic_backend import get_solver |
235 | | sage: p = get_solver(solver = "Coin") # optional - Coin |
236 | | sage: p.add_variables(5) # optional - Coin |
237 | | 5 |
238 | | sage: p.add_linear_constraints(5, +1, 2) # optional - Coin |
239 | | sage: p.row(4) # optional - Coin |
| 310 | sage: p = get_solver(solver = "Coin") # optional - Coin |
| 311 | sage: p.add_variables(5) # optional - Coin |
| 312 | 4 |
| 313 | sage: p.add_linear_constraints(5, None, 2) # optional - Coin |
| 314 | sage: p.row(4) # optional - Coin |
240 | 315 | ([], []) |
241 | | sage: p.row_bounds(4) # optional - Coin |
| 316 | sage: p.row_bounds(4) # optional - Coin |
242 | 317 | (None, 2.0) |
243 | 318 | """ |
244 | 319 | |
245 | 320 | cdef int i |
246 | 321 | for 0<= i<number: |
247 | | self.add_linear_constraint([],[],direction, bound) |
| 322 | self.add_linear_constraint([],lower_bound, upper_bound) |
248 | 323 | |
249 | | cpdef add_linear_constraint(self, list indices, list coeffs, int direction, double bound): |
250 | | r""" |
251 | | Adds a linear constraint. |
| 324 | cpdef add_linear_constraint(self, coefficients, lower_bound, upper_bound): |
| 325 | """ |
| 326 | Add a linear constraint. |
252 | 327 | |
253 | 328 | INPUT: |
254 | 329 | |
255 | | - ``indices`` (list of integers) -- this list constains the |
256 | | indices of the variables whose coefficient is nonzero in the |
257 | | constraint. |
| 330 | - ``coefficients`` an iterable with ``(c,v)`` pairs where ``c`` |
| 331 | is a variable index (integer) and ``v`` is a value (real |
| 332 | value). |
258 | 333 | |
259 | | - ``coeffs`` (list of real values) -- associates a coefficient |
260 | | to the variables listed by ``indices``. Namely, the ith |
261 | | entry of ``coeffs`` corresponds to the coefficient of the |
262 | | variable represented by the ith entry in ``indices``. |
| 334 | - ``lower_bound`` - a lower bound, either a real value or ``None`` |
263 | 335 | |
264 | | - ``direction`` (integer) -- the direction of the constraint, |
265 | | where : |
266 | | |
267 | | * +1 indicates : function `\leq` ``bound`` |
268 | | * 0 indicates : function `=` ``bound`` |
269 | | * -1 indicates : function `\geq` ``bound`` |
270 | | |
271 | | - ``bound`` (double) -- value of the right-hand side (as |
272 | | illustrated immediately above). |
273 | | |
274 | | .. NOTE:: |
275 | | |
276 | | ``indices`` and ``coeffs`` are expected to be of the same |
277 | | length. |
278 | | |
| 336 | - ``upper_bound`` - an upper bound, either a real value or ``None`` |
| 337 | |
279 | 338 | EXAMPLE:: |
280 | 339 | |
281 | 340 | sage: from sage.numerical.backends.generic_backend import get_solver |
282 | | sage: p = get_solver(solver = "Coin") # optional - Coin |
283 | | sage: p.add_variables(5) # optional - Coin |
284 | | 5 |
285 | | sage: p.add_linear_constraint(range(5), range(5), 0, 2) # optional - Coin |
286 | | sage: p.row(0) # optional - Coin |
| 341 | sage: p = get_solver(solver = "Coin") # optional - Coin |
| 342 | sage: p.add_variables(5) # optional - Coin |
| 343 | 4 |
| 344 | sage: p.add_linear_constraint( zip(range(5), range(5)), 2.0, 2.0) # optional - Coin |
| 345 | sage: p.row(0) # optional - Coin |
287 | 346 | ([0, 1, 2, 3, 4], [0.0, 1.0, 2.0, 3.0, 4.0]) |
288 | | sage: p.row_bounds(0) # optional - Coin |
| 347 | sage: p.row_bounds(0) # optional - Coin |
289 | 348 | (2.0, 2.0) |
290 | 349 | """ |
| 350 | if lower_bound is None and upper_bound is None: |
| 351 | raise ValueError("At least one of 'upper_bound' or 'lower_bound' must be set.") |
291 | 352 | |
292 | 353 | cdef int i |
293 | | cdef int n = len(indices) |
| 354 | cdef double c |
294 | 355 | cdef c_CoinPackedVector* row |
295 | 356 | row = new_c_CoinPackedVector(); |
296 | 357 | |
297 | | for 0<= i<n: |
298 | | row.insert(indices[i], coeffs[i]) |
| 358 | for i,c in coefficients: |
| 359 | row.insert(i, c) |
299 | 360 | |
300 | 361 | self.si.addRow (row[0], |
301 | | bound if direction != +1 else -self.si.getInfinity(), |
302 | | bound if direction != -1 else +self.si.getInfinity()) |
| 362 | lower_bound if lower_bound != None else -self.si.getInfinity(), |
| 363 | upper_bound if upper_bound != None else +self.si.getInfinity()) |
303 | 364 | |
304 | 365 | |
305 | 366 | cpdef row(self, int index): |
… |
… |
|
322 | 383 | sage: from sage.numerical.backends.generic_backend import get_solver |
323 | 384 | sage: p = get_solver(solver = "Coin") # optional - Coin |
324 | 385 | sage: p.add_variables(5) # optional - Coin |
325 | | 5 |
326 | | sage: p.add_linear_constraint(range(5), range(5), 0, 2) # optional - Coin |
| 386 | 4 |
| 387 | sage: p.add_linear_constraint(zip(range(5), range(5)), 2, 2) # optional - Coin |
327 | 388 | sage: p.row(0) # optional - Coin |
328 | 389 | ([0, 1, 2, 3, 4], [0.0, 1.0, 2.0, 3.0, 4.0]) |
329 | 390 | sage: p.row_bounds(0) # optional - Coin |
… |
… |
|
367 | 428 | sage: from sage.numerical.backends.generic_backend import get_solver |
368 | 429 | sage: p = get_solver(solver = "Coin") # optional - Coin |
369 | 430 | sage: p.add_variables(5) # optional - Coin |
370 | | 5 |
371 | | sage: p.add_linear_constraint(range(5), range(5), 0, 2) # optional - Coin |
| 431 | 4 |
| 432 | sage: p.add_linear_constraint(zip(range(5), range(5)), 2, 2) # optional - Coin |
372 | 433 | sage: p.row(0) # optional - Coin |
373 | 434 | ([0, 1, 2, 3, 4], [0.0, 1.0, 2.0, 3.0, 4.0]) |
374 | 435 | sage: p.row_bounds(0) # optional - Coin |
… |
… |
|
403 | 464 | sage: from sage.numerical.backends.generic_backend import get_solver |
404 | 465 | sage: p = get_solver(solver = "Coin") # optional - Coin |
405 | 466 | sage: p.add_variable() # optional - Coin |
406 | | 1 |
| 467 | 0 |
407 | 468 | sage: p.col_bounds(0) # optional - Coin |
408 | 469 | (0.0, None) |
409 | | sage: p.variable_max(0, 5) # optional - Coin |
| 470 | sage: p.variable_upper_bound(0, 5) # optional - Coin |
410 | 471 | sage: p.col_bounds(0) # optional - Coin |
411 | 472 | (0.0, 5.0) |
412 | 473 | """ |
… |
… |
|
433 | 494 | sage: from sage.numerical.backends.generic_backend import get_solver |
434 | 495 | sage: p = get_solver(solver = "Coin") # optional - Coin |
435 | 496 | sage: p.add_variables(2) # optional - Coin |
436 | | 2 |
437 | | sage: p.add_linear_constraint([0, 1], [1, 2], +1, 3) # optional - Coin |
| 497 | 1 |
| 498 | sage: p.add_linear_constraint([(0, 1), (1, 2)], None, 3) # optional - Coin |
438 | 499 | sage: p.set_objective([2, 5]) # optional - Coin |
439 | 500 | sage: p.solve() # optional - Coin |
440 | 501 | 0 |
… |
… |
|
476 | 537 | 0 |
477 | 538 | sage: p.nrows() # optional - Coin |
478 | 539 | 0 |
479 | | sage: p.add_linear_constraints(5, -1, 0) # optional - Coin |
| 540 | sage: p.add_linear_constraints(5, 0, None) # optional - Coin |
480 | 541 | sage: p.add_col(range(5), range(5)) # optional - Coin |
481 | 542 | sage: p.nrows() # optional - Coin |
482 | 543 | 5 |
… |
… |
|
508 | 569 | |
509 | 570 | sage: from sage.numerical.backends.generic_backend import get_solver |
510 | 571 | sage: p = get_solver(solver = "Coin") # optional - Coin |
511 | | sage: p.add_linear_constraints(5, -1, 0) # optional - Coin |
| 572 | sage: p.add_linear_constraints(5, 0, None) # optional - Coin |
512 | 573 | sage: p.add_col(range(5), [1,2,3,4,5]) # optional - Coin |
513 | 574 | sage: p.solve() # optional - Coin |
514 | 575 | 0 |
… |
… |
|
518 | 579 | sage: from sage.numerical.backends.generic_backend import get_solver |
519 | 580 | sage: p = get_solver(solver = "Coin") # optional - Coin |
520 | 581 | sage: p.add_variable() # optional - Coin |
521 | | 1 |
522 | | sage: p.add_linear_constraint([0], [1], +1, 4) # optional - Coin |
523 | | sage: p.add_linear_constraint([0], [1], -1, 6) # optional - Coin |
| 582 | 0 |
| 583 | sage: p.add_linear_constraint([(0, 1)], None, 4) # optional - Coin |
| 584 | sage: p.add_linear_constraint([(0, 1)], 6, None) # optional - Coin |
524 | 585 | sage: p.set_objective_coefficient(0,1) # optional - Coin |
525 | 586 | sage: p.solve() # optional - Coin |
526 | 587 | Traceback (most recent call last): |
… |
… |
|
560 | 621 | sage: from sage.numerical.backends.generic_backend import get_solver |
561 | 622 | sage: p = get_solver(solver = "Coin") # optional - Coin |
562 | 623 | sage: p.add_variables(2) # optional - Coin |
563 | | 2 |
564 | | sage: p.add_linear_constraint([0, 1], [1, 2], +1, 3) # optional - Coin |
| 624 | 1 |
| 625 | sage: p.add_linear_constraint([(0, 1), (1, 2)], None, 3) # optional - Coin |
565 | 626 | sage: p.set_objective([2, 5]) # optional - Coin |
566 | 627 | sage: p.solve() # optional - Coin |
567 | 628 | 0 |
… |
… |
|
588 | 649 | sage: from sage.numerical.backends.generic_backend import get_solver |
589 | 650 | sage: p = get_solver(solver = "Coin") # optional - Coin |
590 | 651 | sage: p.add_variables(2) # optional - Coin |
591 | | 2 |
592 | | sage: p.add_linear_constraint([0, 1], [1, 2], +1, 3) # optional - Coin |
| 652 | 1 |
| 653 | sage: p.add_linear_constraint([(0, 1), (1, 2)], None, 3) # optional - Coin |
593 | 654 | sage: p.set_objective([2, 5]) # optional - Coin |
594 | 655 | sage: p.solve() # optional - Coin |
595 | 656 | 0 |
… |
… |
|
616 | 677 | sage: p.ncols() # optional - Coin |
617 | 678 | 0 |
618 | 679 | sage: p.add_variables(2) # optional - Coin |
619 | | 2 |
| 680 | 1 |
620 | 681 | sage: p.ncols() # optional - Coin |
621 | 682 | 2 |
622 | 683 | """ |
… |
… |
|
633 | 694 | sage: p = get_solver(solver = "Coin") # optional - Coin |
634 | 695 | sage: p.nrows() # optional - Coin |
635 | 696 | 0 |
636 | | sage: p.add_linear_constraints(2, -1, 2) # optional - Coin |
| 697 | sage: p.add_linear_constraints(2, 2, None) # optional - Coin |
637 | 698 | sage: p.nrows() # optional - Coin |
638 | 699 | 2 |
639 | 700 | """ |
… |
… |
|
655 | 716 | sage: p.ncols() # optional - Coin |
656 | 717 | 0 |
657 | 718 | sage: p.add_variable() # optional - Coin |
658 | | 1 |
| 719 | 0 |
659 | 720 | sage: p.set_variable_type(0,0) # optional - Coin |
660 | 721 | sage: p.is_variable_binary(0) # optional - Coin |
661 | 722 | True |
… |
… |
|
663 | 724 | """ |
664 | 725 | |
665 | 726 | return (0 == self.si.isContinuous(index) and |
666 | | self.variable_min(index) == 0 and |
667 | | self.variable_max(index) == 1) |
| 727 | self.variable_lower_bound(index) == 0 and |
| 728 | self.variable_upper_bound(index) == 1) |
668 | 729 | |
669 | 730 | cpdef bint is_variable_integer(self, int index): |
670 | 731 | r""" |
… |
… |
|
681 | 742 | sage: p.ncols() # optional - Coin |
682 | 743 | 0 |
683 | 744 | sage: p.add_variable() # optional - Coin |
684 | | 1 |
| 745 | 0 |
685 | 746 | sage: p.set_variable_type(0,1) # optional - Coin |
686 | 747 | sage: p.is_variable_integer(0) # optional - Coin |
687 | 748 | True |
688 | 749 | """ |
689 | 750 | return (0 == self.si.isContinuous(index) and |
690 | | (self.variable_min(index) != 0 or |
691 | | self.variable_max(index) != 1)) |
| 751 | (self.variable_lower_bound(index) != 0 or |
| 752 | self.variable_upper_bound(index) != 1)) |
692 | 753 | |
693 | 754 | cpdef bint is_variable_continuous(self, int index): |
694 | 755 | r""" |
… |
… |
|
705 | 766 | sage: p.ncols() # optional - Coin |
706 | 767 | 0 |
707 | 768 | sage: p.add_variable() # optional - Coin |
708 | | 1 |
| 769 | 0 |
709 | 770 | sage: p.is_variable_continuous(0) # optional - Coin |
710 | 771 | True |
711 | 772 | sage: p.set_variable_type(0,1) # optional - Coin |
… |
… |
|
733 | 794 | |
734 | 795 | return self.si.getObjSense() == -1 |
735 | 796 | |
736 | | cpdef variable_max(self, int index, value = False): |
| 797 | cpdef variable_upper_bound(self, int index, value = False): |
737 | 798 | r""" |
738 | 799 | Returns or defines the upper bound on a variable |
739 | 800 | |
… |
… |
|
750 | 811 | sage: from sage.numerical.backends.generic_backend import get_solver |
751 | 812 | sage: p = get_solver(solver = "Coin") # optional - Coin |
752 | 813 | sage: p.add_variable() # optional - Coin |
753 | | 1 |
| 814 | 0 |
754 | 815 | sage: p.col_bounds(0) # optional - Coin |
755 | 816 | (0.0, None) |
756 | | sage: p.variable_max(0, 5) # optional - Coin |
| 817 | sage: p.variable_upper_bound(0, 5) # optional - Coin |
757 | 818 | sage: p.col_bounds(0) # optional - Coin |
758 | 819 | (0.0, 5.0) |
759 | 820 | """ |
… |
… |
|
765 | 826 | else: |
766 | 827 | self.si.setColUpper(index, value if value is not None else +self.si.getInfinity()) |
767 | 828 | |
768 | | cpdef variable_min(self, int index, value = False): |
| 829 | cpdef variable_lower_bound(self, int index, value = False): |
769 | 830 | r""" |
770 | 831 | Returns or defines the lower bound on a variable |
771 | 832 | |
… |
… |
|
782 | 843 | sage: from sage.numerical.backends.generic_backend import get_solver |
783 | 844 | sage: p = get_solver(solver = "Coin") # optional - Coin |
784 | 845 | sage: p.add_variable() # optional - Coin |
785 | | 1 |
| 846 | 0 |
786 | 847 | sage: p.col_bounds(0) # optional - Coin |
787 | 848 | (0.0, None) |
788 | | sage: p.variable_min(0, 5) # optional - Coin |
| 849 | sage: p.variable_lower_bound(0, 5) # optional - Coin |
789 | 850 | sage: p.col_bounds(0) # optional - Coin |
790 | 851 | (5.0, None) |
791 | 852 | """ |
… |
… |
|
810 | 871 | sage: from sage.numerical.backends.generic_backend import get_solver |
811 | 872 | sage: p = get_solver(solver = "Coin") # optional - Coin |
812 | 873 | sage: p.add_variables(2) # optional - Coin |
813 | | 2 |
814 | | sage: p.add_linear_constraint([0, 1], [1, 2], +1, 3) # optional - Coin |
| 874 | 1 |
| 875 | sage: p.add_linear_constraint([(0, 1), (1, 2)], None, 3) # optional - Coin |
815 | 876 | sage: p.set_objective([2, 5]) # optional - Coin |
816 | 877 | sage: p.write_mps(SAGE_TMP+"/lp_problem.mps", 0) # optional - Coin |
817 | 878 | """ |
… |
… |
|
856 | 917 | |
857 | 918 | sage: from sage.numerical.backends.generic_backend import get_solver |
858 | 919 | sage: p = get_solver(solver = "Coin") # optional - Coin |
859 | | sage: p.add_linear_constraints(1, -1, 2) # optional - Coin |
| 920 | sage: p.add_linear_constraints(1, 2, None) # optional - Coin |
860 | 921 | sage: p.row_name(0, "Empty constraint 1") # optional - Coin |
861 | 922 | sage: print p.row_name(0) # optional - Coin |
862 | 923 | <BLANKLINE> |
… |
… |
|
880 | 941 | sage: from sage.numerical.backends.generic_backend import get_solver |
881 | 942 | sage: p = get_solver(solver = "Coin") # optional - Coin |
882 | 943 | sage: p.add_variable() # optional - Coin |
883 | | 1 |
| 944 | 0 |
884 | 945 | sage: p.col_name(0, "I am a variable") # optional - Coin |
885 | 946 | sage: print p.col_name(0) # optional - Coin |
886 | 947 | <BLANKLINE> |
diff -r cfaca337639b -r 4825b49a4b2a sage/numerical/backends/cplex_backend.pxd
a
|
b
|
|
157 | 157 | # Get the problem's type |
158 | 158 | int CPXgetprobtype(c_cpxlp * env, c_cpxlp * lp) |
159 | 159 | |
| 160 | # Change a row's range |
| 161 | int CPXchgrngval(c_cpxlp * env, c_cpxlp * lp, int cnt, int * indices, double * values) |
| 162 | |
| 163 | # Get a row's range |
| 164 | int CPXgetrngval(c_cpxlp * env, c_cpxlp * lp, double * rngval, int begin, int end) |
| 165 | |
160 | 166 | # CONSTANTS |
161 | 167 | int CPX_ON = 1 |
162 | 168 | int CPX_PARAM_SCRIND = 1035 |
diff -r cfaca337639b -r 4825b49a4b2a sage/numerical/backends/cplex_backend.pyx
a
|
b
|
|
34 | 34 | else: |
35 | 35 | self.set_sense(-1) |
36 | 36 | |
37 | | cpdef int add_variable(self): |
38 | | r""" |
39 | | Adds a variable. |
| 37 | cpdef int add_variable(self, lower_bound=0.0, upper_bound=None, binary=False, continuous=False, integer=False) except -1: |
| 38 | """ |
| 39 | Add a variable. |
40 | 40 | |
41 | 41 | This amounts to adding a new column to the matrix. By default, |
42 | 42 | the variable is both positive and real. |
43 | 43 | |
| 44 | INPUT: |
| 45 | |
| 46 | - ``lower_bound`` - the lower bound of the variable (default: 0) |
| 47 | |
| 48 | - ``upper_bound`` - the upper bound of the variable (default: ``None``) |
| 49 | |
| 50 | - ``binary`` - ``True`` if the variable is binary (default: ``False``). |
| 51 | |
| 52 | - ``continuous`` - ``True`` if the variable is binary (default: ``True``). |
| 53 | |
| 54 | - ``integer`` - ``True`` if the variable is binary (default: ``False``). |
| 55 | |
| 56 | OUTPUT: The index of the newly created variable |
| 57 | |
44 | 58 | EXAMPLE:: |
45 | 59 | |
46 | 60 | sage: from sage.numerical.backends.generic_backend import get_solver |
47 | | sage: p = get_solver(solver = "CPLEX") # optional - CPLEX |
| 61 | sage: p = get_solver(solver = "CPLEX") # optional - CPLEX |
48 | 62 | sage: p.ncols() # optional - CPLEX |
49 | 63 | 0 |
50 | | sage: p.add_variable() # optional - CPLEX |
51 | | 1 |
| 64 | sage: p.add_variable() # optional - CPLEX |
| 65 | 0 |
52 | 66 | sage: p.ncols() # optional - CPLEX |
53 | 67 | 1 |
| 68 | sage: p.add_variable(binary=True) # optional - CPLEX |
| 69 | 1 |
| 70 | sage: p.add_variable(lower_bound=-2.0, integer=True) # optional - CPLEX |
| 71 | 2 |
| 72 | sage: p.add_variable(continuous=True, integer=True) # optional - CPLEX |
| 73 | Traceback (most recent call last): |
| 74 | ... |
| 75 | ValueError: ... |
54 | 76 | """ |
55 | 77 | |
| 78 | cdef int vtype = int(bool(binary)) + int(bool(continuous)) + int(bool(integer)) |
| 79 | if vtype == 0: |
| 80 | continuous = True |
| 81 | elif vtype != 1: |
| 82 | raise ValueError("Exactly one parameter of 'binary', 'integer' and 'continuous' must be 'True'.") |
| 83 | |
56 | 84 | cdef int status |
57 | 85 | status = CPXnewcols(self.env, self.lp, 1, NULL, NULL, NULL, NULL, NULL) |
58 | 86 | check(status) |
59 | | return CPXgetnumcols(self.env, self.lp) |
60 | 87 | |
61 | | cpdef int add_variables(self, int number): |
62 | | r""" |
63 | | Adds ``number`` variables. |
| 88 | cdef int n |
| 89 | n = CPXgetnumcols(self.env, self.lp) - 1 |
| 90 | |
| 91 | if lower_bound != 0.0: |
| 92 | self.variable_lower_bound(n, lower_bound) |
| 93 | if upper_bound is not None: |
| 94 | self.variable_upper_bound(n, upper_bound) |
| 95 | |
| 96 | if binary: |
| 97 | self.set_variable_type(n,0) |
| 98 | elif integer: |
| 99 | self.set_variable_type(n,1) |
| 100 | |
| 101 | return n |
| 102 | |
| 103 | cpdef int add_variables(self, int number, lower_bound=0.0, upper_bound=None, binary=False, continuous=False, integer=False) except -1: |
| 104 | """ |
| 105 | Add ``number`` new variables. |
64 | 106 | |
65 | 107 | This amounts to adding new columns to the matrix. By default, |
66 | 108 | the variables are both positive and real. |
67 | 109 | |
| 110 | INPUT: |
| 111 | |
| 112 | - ``n`` - the number of new variables (must be > 0) |
| 113 | |
| 114 | - ``lower_bound`` - the lower bound of the variable (default: 0) |
| 115 | |
| 116 | - ``upper_bound`` - the upper bound of the variable (default: ``None``) |
| 117 | |
| 118 | - ``binary`` - ``True`` if the variable is binary (default: ``False``). |
| 119 | |
| 120 | - ``continuous`` - ``True`` if the variable is binary (default: ``True``). |
| 121 | |
| 122 | - ``integer`` - ``True`` if the variable is binary (default: ``False``). |
| 123 | |
| 124 | OUTPUT: The index of the variable created last. |
| 125 | |
68 | 126 | EXAMPLE:: |
69 | 127 | |
70 | 128 | sage: from sage.numerical.backends.generic_backend import get_solver |
71 | | sage: p = get_solver(solver = "CPLEX") # optional - CPLEX |
72 | | sage: p.ncols() # optional - CPLEX |
| 129 | sage: p = get_solver(solver = "CPLEX") # optional - CPLEX |
| 130 | sage: p.ncols() # optional - CPLEX |
73 | 131 | 0 |
74 | | sage: p.add_variables(5) # optional - CPLEX |
| 132 | sage: p.add_variables(5) # optional - CPLEX |
| 133 | 4 |
| 134 | sage: p.ncols() # optional - CPLEX |
75 | 135 | 5 |
76 | | sage: p.ncols() # optional - CPLEX |
77 | | 5 |
| 136 | sage: p.add_variables(2, lower_bound=-2.0, integer=True) # optional - CPLEX |
| 137 | 6 |
78 | 138 | """ |
| 139 | cdef int vtype = int(bool(binary)) + int(bool(continuous)) + int(bool(integer)) |
| 140 | if vtype == 0: |
| 141 | continuous = True |
| 142 | elif vtype != 1: |
| 143 | raise ValueError("Exactly one parameter of 'binary', 'integer' and 'continuous' must be 'True'.") |
79 | 144 | |
80 | 145 | cdef int status |
81 | 146 | status = CPXnewcols(self.env, self.lp, number, NULL, NULL, NULL, NULL, NULL) |
82 | 147 | check(status) |
83 | | return CPXgetnumcols(self.env, self.lp) |
| 148 | |
| 149 | cdef int n |
| 150 | n = CPXgetnumcols(self.env, self.lp) - 1 |
| 151 | |
| 152 | cdef int i |
| 153 | |
| 154 | for 0<= i < number: |
| 155 | if lower_bound != 0.0: |
| 156 | self.variable_lower_bound(n - i, lower_bound) |
| 157 | if upper_bound is not None: |
| 158 | self.variable_upper_bound(n - i, upper_bound) |
| 159 | |
| 160 | if binary: |
| 161 | self.set_variable_type(n - i,0) |
| 162 | elif integer: |
| 163 | self.set_variable_type(n - i,1) |
| 164 | |
| 165 | return n |
84 | 166 | |
85 | 167 | cpdef set_variable_type(self, int variable, int vtype): |
86 | 168 | r""" |
… |
… |
|
103 | 185 | sage: p.ncols() # optional - CPLEX |
104 | 186 | 0 |
105 | 187 | sage: p.add_variable() # optional - CPLEX |
106 | | 1 |
| 188 | 0 |
107 | 189 | sage: p.set_variable_type(0,1) # optional - CPLEX |
108 | 190 | sage: p.is_variable_integer(0) # optional - CPLEX |
109 | 191 | True |
… |
… |
|
161 | 243 | sage: from sage.numerical.backends.generic_backend import get_solver |
162 | 244 | sage: p = get_solver(solver = "CPLEX") # optional - CPLEX |
163 | 245 | sage: p.add_variable() # optional - CPLEX |
164 | | 1 |
| 246 | 0 |
165 | 247 | sage: p.get_objective_coefficient(0) # optional - CPLEX |
166 | 248 | 0.0 |
167 | 249 | sage: p.set_objective_coefficient(0,2) # optional - CPLEX |
… |
… |
|
223 | 305 | sage: from sage.numerical.backends.generic_backend import get_solver |
224 | 306 | sage: p = get_solver(solver = "CPLEX") # optional - CPLEX |
225 | 307 | sage: p.add_variables(5) # optional - CPLEX |
226 | | 5 |
| 308 | 4 |
227 | 309 | sage: p.set_objective([1, 1, 2, 1, 3]) # optional - CPLEX |
228 | 310 | sage: map(lambda x :p.get_objective_coefficient(x), range(5)) # optional - CPLEX |
229 | 311 | [1.0, 1.0, 2.0, 1.0, 3.0] |
… |
… |
|
266 | 348 | status = CPXsetintparam (self.env, CPX_PARAM_SCRIND, CPX_ON) |
267 | 349 | check(status) |
268 | 350 | |
269 | | cpdef add_linear_constraints(self, int number, int direction, double bound): |
270 | | r""" |
271 | | Adds constraints. |
| 351 | cpdef add_linear_constraints(self, int number, lower_bound, upper_bound): |
| 352 | """ |
| 353 | Add ``'number`` linear constraints. |
272 | 354 | |
273 | 355 | INPUT: |
274 | 356 | |
275 | 357 | - ``number`` (integer) -- the number of constraints to add. |
276 | 358 | |
277 | | - ``direction`` (integer) -- the direction of the constraint, |
278 | | where : |
| 359 | - ``lower_bound`` - a lower bound, either a real value or ``None`` |
279 | 360 | |
280 | | * +1 indicates : function `\leq` ``bound`` |
281 | | * 0 indicates : function `=` ``bound`` |
282 | | * -1 indicates : function `\geq` ``bound`` |
283 | | |
284 | | - ``bound`` (double) -- value of the right-hand side (as |
285 | | illustrated immediately above). |
| 361 | - ``upper_bound`` - an upper bound, either a real value or ``None`` |
286 | 362 | |
287 | 363 | EXAMPLE:: |
288 | 364 | |
289 | 365 | sage: from sage.numerical.backends.generic_backend import get_solver |
290 | | sage: p = get_solver(solver = "CPLEX") # optional - CPLEX |
291 | | sage: p.add_variables(5) # optional - CPLEX |
292 | | 5 |
293 | | sage: p.add_linear_constraints(5, +1, 2) # optional - CPLEX |
294 | | sage: p.row(4) # optional - CPLEX |
| 366 | sage: p = get_solver(solver = "CPLEX") # optional - CPLEX |
| 367 | sage: p.add_variables(5) # optional - CPLEX |
| 368 | 4 |
| 369 | sage: p.add_linear_constraints(5, None, 2) # optional - CPLEX |
| 370 | sage: p.row(4) # optional - CPLEX |
295 | 371 | ([], []) |
296 | | sage: p.row_bounds(4) # optional - CPLEX |
| 372 | sage: p.row_bounds(4) # optional - CPLEX |
297 | 373 | (None, 2.0) |
298 | 374 | """ |
| 375 | if lower_bound is None and upper_bound is None: |
| 376 | raise ValueError("At least one of 'upper_bound' or 'lower_bound' must be set.") |
299 | 377 | |
300 | | cdef char * c_types = <char *> sage_malloc(number * sizeof(char)) |
301 | | cdef double * c_bounds = <double *> sage_malloc(number * sizeof(double)) |
| 378 | cdef int status |
| 379 | cdef char * sense = <char *> sage_malloc(number * sizeof(char)) |
| 380 | cdef double * bound = <double *> sage_malloc(number * sizeof(double)) |
| 381 | cdef double * rng = NULL |
302 | 382 | cdef int i |
303 | | cdef int status |
304 | 383 | |
305 | | c_bounds[0] = bound |
306 | | |
307 | | if direction == +1: |
308 | | c_types[0] = 'L' |
309 | | elif direction == -1: |
310 | | c_types[0] = 'G' |
311 | | else: |
312 | | c_types[0] = 'E' |
| 384 | if upper_bound == lower_bound: |
| 385 | sense[0] = 'E' |
| 386 | bound[0] = lower_bound |
313 | 387 | |
314 | | for 1<= i < number: |
315 | | c_types[i] = c_types[0] |
316 | | c_bounds[i] = c_bounds[0] |
317 | | |
| 388 | elif upper_bound is not None and lower_bound is not None: |
| 389 | if upper_bound < lower_bound: |
| 390 | raise ValueError("The upper bound must be at least equal to the lower bound !") |
| 391 | |
| 392 | rng = <double *> sage_malloc(number * sizeof(double)) |
318 | 393 | |
319 | | status = CPXnewrows(self.env, self.lp, number, c_bounds, c_types, NULL, NULL) |
320 | | check(status) |
| 394 | sense[0] = 'R' |
| 395 | bound[0] = lower_bound |
| 396 | rng[0] = upper_bound - lower_bound |
321 | 397 | |
322 | | cpdef add_linear_constraint(self, list indices, list coeffs, int direction, double bound): |
323 | | r""" |
324 | | Adds a linear constraint. |
| 398 | |
| 399 | elif upper_bound is not None: |
| 400 | sense[0] = 'L' |
| 401 | bound[0] = upper_bound |
| 402 | |
| 403 | elif lower_bound is not None: |
| 404 | sense[0] = 'G' |
| 405 | bound[0] = lower_bound |
| 406 | |
| 407 | for 1<= i <number: |
| 408 | sense[i] = sense[0] |
| 409 | bound[i] = bound[0] |
| 410 | if rng != NULL: |
| 411 | rng[i] = rng[0] |
| 412 | |
| 413 | status = CPXnewrows(self.env, self.lp, number, bound, sense, rng, NULL) |
| 414 | check(status) |
| 415 | |
| 416 | cpdef add_linear_constraint(self, coefficients, lower_bound, upper_bound): |
| 417 | """ |
| 418 | Add a linear constraint. |
325 | 419 | |
326 | 420 | INPUT: |
327 | 421 | |
328 | | - ``indices`` (list of integers) -- this list constains the |
329 | | indices of the variables whose coefficient is nonzero in the |
330 | | constraint. |
| 422 | - ``coefficients`` an iterable with ``(c,v)`` pairs where ``c`` |
| 423 | is a variable index (integer) and ``v`` is a value (real |
| 424 | value). |
331 | 425 | |
332 | | - ``coeffs`` (list of real values) -- associates a coefficient |
333 | | to the variables listed by ``indices``. Namely, the ith |
334 | | entry of ``coeffs`` corresponds to the coefficient of the |
335 | | variable represented by the ith entry in ``indices``. |
| 426 | - ``lower_bound`` - a lower bound, either a real value or ``None`` |
336 | 427 | |
337 | | - ``direction`` (integer) -- the direction of the constraint, |
338 | | where : |
339 | | |
340 | | * +1 indicates : function `\leq` ``bound`` |
341 | | * 0 indicates : function `=` ``bound`` |
342 | | * -1 indicates : function `\geq` ``bound`` |
343 | | |
344 | | - ``bound`` (double) -- value of the right-hand side (as |
345 | | illustrated immediately above). |
346 | | |
347 | | .. NOTE:: |
348 | | |
349 | | ``indices`` and ``coeffs`` are expected to be of the same |
350 | | length. |
351 | | |
| 428 | - ``upper_bound`` - an upper bound, either a real value or ``None`` |
| 429 | |
352 | 430 | EXAMPLE:: |
353 | 431 | |
354 | 432 | sage: from sage.numerical.backends.generic_backend import get_solver |
355 | | sage: p = get_solver(solver = "CPLEX") # optional - CPLEX |
356 | | sage: p.add_variables(5) # optional - CPLEX |
357 | | 5 |
358 | | sage: p.add_linear_constraint(range(5), range(5), 0, 2) # optional - CPLEX |
359 | | sage: p.row(0) # optional - CPLEX |
| 433 | sage: p = get_solver(solver = "CPLEX") # optional - CPLEX |
| 434 | sage: p.add_variables(5) # optional - CPLEX |
| 435 | 4 |
| 436 | sage: p.add_linear_constraint( zip(range(5), range(5)), 2.0, 2.0) # optional - CPLEX |
| 437 | sage: p.row(0) # optional - CPLEX |
360 | 438 | ([1, 2, 3, 4], [1.0, 2.0, 3.0, 4.0]) |
361 | | sage: p.row_bounds(0) # optional - CPLEX |
| 439 | sage: p.row_bounds(0) # optional - CPLEX |
362 | 440 | (2.0, 2.0) |
363 | 441 | """ |
| 442 | if lower_bound is None and upper_bound is None: |
| 443 | raise ValueError("At least one of 'upper_bound' or 'lower_bound' must be set.") |
364 | 444 | |
365 | 445 | cdef int status |
366 | | cdef int i |
367 | | cdef int n = len(indices) |
| 446 | cdef int i, j |
| 447 | cdef int n = len(coefficients) |
368 | 448 | cdef int nrows = self.nrows() |
369 | 449 | cdef char sense |
370 | 450 | |
371 | | if direction == 1: |
372 | | sense = 'L' |
373 | | elif direction == -1: |
374 | | sense = 'G' |
375 | | else: |
376 | | sense = 'E' |
377 | | |
378 | | status = CPXnewrows(self.env, self.lp, 1, &bound, &sense, NULL, NULL) |
379 | | check(status) |
| 451 | cdef double * c_coeff |
| 452 | cdef int * c_indices |
| 453 | cdef int * c_row |
| 454 | cdef double bound |
| 455 | cdef double rng |
| 456 | cdef double c |
380 | 457 | |
381 | | cdef double * c_coeff = <double *> sage_malloc(n * sizeof(double)) |
382 | | cdef int * c_indices = <int *> sage_malloc(n * sizeof(int)) |
383 | | cdef int * c_row = <int *> sage_malloc(n * sizeof(int)) |
384 | | |
385 | | for 0<= i < n: |
386 | | c_coeff[i] = coeffs[i] |
387 | | c_indices[i] = indices[i] |
| 458 | c_coeff = <double *> sage_malloc(n * sizeof(double)) |
| 459 | c_indices = <int *> sage_malloc(n * sizeof(int)) |
| 460 | c_row = <int *> sage_malloc(n * sizeof(int)) |
| 461 | |
| 462 | for i, (j, c) in enumerate(coefficients): |
| 463 | c_coeff[i] = c |
| 464 | c_indices[i] = j |
388 | 465 | c_row[i] = nrows |
389 | 466 | |
| 467 | if upper_bound is None and lower_bound is None: |
| 468 | pass |
390 | 469 | |
| 470 | elif upper_bound == lower_bound: |
| 471 | sense = 'E' |
| 472 | bound = lower_bound |
| 473 | |
| 474 | elif upper_bound is not None and lower_bound is not None: |
| 475 | if upper_bound < lower_bound: |
| 476 | raise ValueError("The upper bound must be at least equal to the lower bound !") |
| 477 | |
| 478 | sense = 'R' |
| 479 | bound = lower_bound |
| 480 | |
| 481 | elif upper_bound is not None: |
| 482 | sense = 'L' |
| 483 | bound = upper_bound |
| 484 | |
| 485 | elif lower_bound is not None: |
| 486 | sense = 'G' |
| 487 | bound = lower_bound |
| 488 | |
| 489 | status = CPXnewrows(self.env, self.lp, 1, &bound, &sense, &rng, NULL) |
| 490 | check(status) |
391 | 491 | status = CPXchgcoeflist(self.env, self.lp, n, c_row, c_indices, c_coeff) |
392 | 492 | check(status) |
393 | 493 | |
… |
… |
|
411 | 511 | sage: from sage.numerical.backends.generic_backend import get_solver |
412 | 512 | sage: p = get_solver(solver = "CPLEX") # optional - CPLEX |
413 | 513 | sage: p.add_variables(5) # optional - CPLEX |
414 | | 5 |
415 | | sage: p.add_linear_constraint(range(5), range(5), 0, 2) # optional - CPLEX |
| 514 | 4 |
| 515 | sage: p.add_linear_constraint(zip(range(5), range(5)), 2, 2) # optional - CPLEX |
416 | 516 | sage: p.row(0) # optional - CPLEX |
417 | 517 | ([1, 2, 3, 4], [1.0, 2.0, 3.0, 4.0]) |
418 | 518 | sage: p.row_bounds(0) # optional - CPLEX |
… |
… |
|
460 | 560 | sage: from sage.numerical.backends.generic_backend import get_solver |
461 | 561 | sage: p = get_solver(solver = "CPLEX") # optional - CPLEX |
462 | 562 | sage: p.add_variables(5) # optional - CPLEX |
463 | | 5 |
464 | | sage: p.add_linear_constraint(range(5), range(5), 0, 2) # optional - CPLEX |
| 563 | 4 |
| 564 | sage: p.add_linear_constraint(zip(range(5), range(5)), 2, 2) # optional - CPLEX |
465 | 565 | sage: p.row(0) # optional - CPLEX |
466 | 566 | ([1, 2, 3, 4], [1.0, 2.0, 3.0, 4.0]) |
467 | 567 | sage: p.row_bounds(0) # optional - CPLEX |
… |
… |
|
469 | 569 | """ |
470 | 570 | |
471 | 571 | cdef int status |
| 572 | cdef double rng |
472 | 573 | cdef double value |
473 | 574 | status = CPXgetrhs(self.env, self.lp, &value, index, index) |
474 | 575 | check(status) |
… |
… |
|
481 | 582 | return (None, value) |
482 | 583 | elif direction == 'G': |
483 | 584 | return (value, None) |
484 | | else: |
| 585 | elif direction == 'E': |
485 | 586 | return (value, value) |
| 587 | elif direction == 'R': |
| 588 | status = CPXgetrngval(self.env, self.lp, &rng, index, index) |
| 589 | check(status) |
| 590 | return (value, value + rng) |
486 | 591 | |
487 | 592 | cpdef col_bounds(self, int index): |
488 | 593 | r""" |
… |
… |
|
503 | 608 | sage: from sage.numerical.backends.generic_backend import get_solver |
504 | 609 | sage: p = get_solver(solver = "CPLEX") # optional - CPLEX |
505 | 610 | sage: p.add_variable() # optional - CPLEX |
506 | | 1 |
| 611 | 0 |
507 | 612 | sage: p.col_bounds(0) # optional - CPLEX |
508 | 613 | (0.0, None) |
509 | | sage: p.variable_max(0, 5) # optional - CPLEX |
| 614 | sage: p.variable_upper_bound(0, 5) # optional - CPLEX |
510 | 615 | sage: p.col_bounds(0) # optional - CPLEX |
511 | 616 | (0.0, 5.0) |
512 | 617 | """ |
… |
… |
|
539 | 644 | sage: from sage.numerical.backends.generic_backend import get_solver |
540 | 645 | sage: p = get_solver(solver = "CPLEX") # optional - CPLEX |
541 | 646 | sage: p.add_variable() # optional - CPLEX |
542 | | 1 |
| 647 | 0 |
543 | 648 | sage: p.get_objective_coefficient(0) # optional - CPLEX |
544 | 649 | 0.0 |
545 | 650 | sage: p.set_objective_coefficient(0,2) # optional - CPLEX |
… |
… |
|
583 | 688 | 0 |
584 | 689 | sage: p.nrows() # optional - CPLEX |
585 | 690 | 0 |
586 | | sage: p.add_linear_constraints(5, -1, 0) # optional - CPLEX |
| 691 | sage: p.add_linear_constraints(5, 0, None) # optional - CPLEX |
587 | 692 | sage: p.add_col(range(5), range(5)) # optional - CPLEX |
588 | 693 | sage: p.nrows() # optional - CPLEX |
589 | 694 | 5 |
… |
… |
|
626 | 731 | |
627 | 732 | sage: from sage.numerical.backends.generic_backend import get_solver |
628 | 733 | sage: p = get_solver(solver = "CPLEX") # optional - CPLEX |
629 | | sage: p.add_linear_constraints(5, -1, 0) # optional - CPLEX |
| 734 | sage: p.add_linear_constraints(5, 0, None) # optional - CPLEX |
630 | 735 | sage: p.add_col(range(5), range(5)) # optional - CPLEX |
631 | 736 | sage: p.solve() # optional - CPLEX |
632 | 737 | 0 |
… |
… |
|
677 | 782 | sage: from sage.numerical.backends.generic_backend import get_solver |
678 | 783 | sage: p = get_solver(solver = "CPLEX") # optional - CPLEX |
679 | 784 | sage: p.add_variables(2) # optional - CPLEX |
680 | | 2 |
681 | | sage: p.add_linear_constraint([0, 1], [1, 2], +1, 3) # optional - CPLEX |
| 785 | 1 |
| 786 | sage: p.add_linear_constraint([(0,1), (1,2)], None, 3) # optional - CPLEX |
682 | 787 | sage: p.set_objective([2, 5]) # optional - CPLEX |
683 | 788 | sage: p.solve() # optional - CPLEX |
684 | 789 | 0 |
… |
… |
|
711 | 816 | sage: from sage.numerical.backends.generic_backend import get_solver |
712 | 817 | sage: p = get_solver(solver = "CPLEX") # optional - CPLEX |
713 | 818 | sage: p.add_variables(2) # optional - CPLEX |
714 | | 2 |
715 | | sage: p.add_linear_constraint([0, 1], [1, 2], +1, 3) # optional - CPLEX |
| 819 | 1 |
| 820 | sage: p.add_linear_constraint([(0,1), (1,2)], None, 3) # optional - CPLEX |
716 | 821 | sage: p.set_objective([2, 5]) # optional - CPLEX |
717 | 822 | sage: p.solve() # optional - CPLEX |
718 | 823 | 0 |
… |
… |
|
744 | 849 | sage: p.ncols() # optional - CPLEX |
745 | 850 | 0 |
746 | 851 | sage: p.add_variables(2) # optional - CPLEX |
747 | | 2 |
| 852 | 1 |
748 | 853 | sage: p.ncols() # optional - CPLEX |
749 | 854 | 2 |
750 | 855 | """ |
… |
… |
|
761 | 866 | sage: p = get_solver(solver = "CPLEX") # optional - CPLEX |
762 | 867 | sage: p.nrows() # optional - CPLEX |
763 | 868 | 0 |
764 | | sage: p.add_linear_constraints(2, -1, 2) # optional - CPLEX |
| 869 | sage: p.add_linear_constraints(2, 2, None) # optional - CPLEX |
765 | 870 | sage: p.nrows() # optional - CPLEX |
766 | 871 | 2 |
767 | 872 | """ |
… |
… |
|
783 | 888 | |
784 | 889 | sage: from sage.numerical.backends.generic_backend import get_solver |
785 | 890 | sage: p = get_solver(solver = "CPLEX") # optional - CPLEX |
786 | | sage: p.add_linear_constraints(1, -1, 2) # optional - CPLEX |
| 891 | sage: p.add_linear_constraints(1, 2, None) # optional - CPLEX |
787 | 892 | sage: p.row_name(0, "Empty constraint 1") # optional - CPLEX |
788 | 893 | sage: p.row_name(0) # optional - CPLEX |
789 | 894 | 'Empty constraint 1' |
… |
… |
|
828 | 933 | sage: from sage.numerical.backends.generic_backend import get_solver |
829 | 934 | sage: p = get_solver(solver = "CPLEX") # optional - CPLEX |
830 | 935 | sage: p.add_variable() # optional - CPLEX |
831 | | 1 |
| 936 | 0 |
832 | 937 | sage: p.col_name(0, "I am a variable") # optional - CPLEX |
833 | 938 | sage: p.col_name(0) # optional - CPLEX |
834 | 939 | 'I am a variable' |
… |
… |
|
872 | 977 | sage: p.ncols() # optional - CPLEX |
873 | 978 | 0 |
874 | 979 | sage: p.add_variable() # optional - CPLEX |
875 | | 1 |
| 980 | 0 |
876 | 981 | sage: p.set_variable_type(0,0) # optional - CPLEX |
877 | 982 | sage: p.is_variable_binary(0) # optional - CPLEX |
878 | 983 | True |
… |
… |
|
908 | 1013 | sage: p.ncols() # optional - CPLEX |
909 | 1014 | 0 |
910 | 1015 | sage: p.add_variable() # optional - CPLEX |
911 | | 1 |
| 1016 | 0 |
912 | 1017 | sage: p.set_variable_type(0,1) # optional - CPLEX |
913 | 1018 | sage: p.is_variable_integer(0) # optional - CPLEX |
914 | 1019 | True |
… |
… |
|
943 | 1048 | sage: p.ncols() # optional - CPLEX |
944 | 1049 | 0 |
945 | 1050 | sage: p.add_variable() # optional - CPLEX |
946 | | 1 |
| 1051 | 0 |
947 | 1052 | sage: p.is_variable_continuous(0) # optional - CPLEX |
948 | 1053 | True |
949 | 1054 | sage: p.set_variable_type(0,1) # optional - CPLEX |
… |
… |
|
983 | 1088 | |
984 | 1089 | return -1 == CPXgetobjsen(self.env, self.lp) |
985 | 1090 | |
986 | | cpdef variable_max(self, int index, value = False): |
| 1091 | cpdef variable_upper_bound(self, int index, value = False): |
987 | 1092 | r""" |
988 | 1093 | Returns or defines the upper bound on a variable |
989 | 1094 | |
… |
… |
|
1000 | 1105 | sage: from sage.numerical.backends.generic_backend import get_solver |
1001 | 1106 | sage: p = get_solver(solver = "CPLEX") # optional - CPLEX |
1002 | 1107 | sage: p.add_variable() # optional - CPLEX |
1003 | | 1 |
| 1108 | 0 |
1004 | 1109 | sage: p.col_bounds(0) # optional - CPLEX |
1005 | 1110 | (0.0, None) |
1006 | | sage: p.variable_max(0, 5) # optional - CPLEX |
| 1111 | sage: p.variable_upper_bound(0, 5) # optional - CPLEX |
1007 | 1112 | sage: p.col_bounds(0) # optional - CPLEX |
1008 | 1113 | (0.0, 5.0) |
1009 | 1114 | """ |
… |
… |
|
1026 | 1131 | status = CPXchgbds(self.env, self.lp, 1, &index, &x, &c_value) |
1027 | 1132 | check(status) |
1028 | 1133 | |
1029 | | cpdef variable_min(self, int index, value = False): |
| 1134 | cpdef variable_lower_bound(self, int index, value = False): |
1030 | 1135 | r""" |
1031 | 1136 | Returns or defines the lower bound on a variable |
1032 | 1137 | |
… |
… |
|
1043 | 1148 | sage: from sage.numerical.backends.generic_backend import get_solver |
1044 | 1149 | sage: p = get_solver(solver = "CPLEX") # optional - CPLEX |
1045 | 1150 | sage: p.add_variable() # optional - CPLEX |
1046 | | 1 |
| 1151 | 0 |
1047 | 1152 | sage: p.col_bounds(0) # optional - CPLEX |
1048 | 1153 | (0.0, None) |
1049 | | sage: p.variable_min(0, 5) # optional - CPLEX |
| 1154 | sage: p.variable_lower_bound(0, 5) # optional - CPLEX |
1050 | 1155 | sage: p.col_bounds(0) # optional - CPLEX |
1051 | 1156 | (5.0, None) |
1052 | 1157 | """ |
… |
… |
|
1079 | 1184 | sage: from sage.numerical.backends.generic_backend import get_solver |
1080 | 1185 | sage: p = get_solver(solver = "CPLEX") # optional - CPLEX |
1081 | 1186 | sage: p.add_variables(2) # optional - CPLEX |
1082 | | 2 |
1083 | | sage: p.add_linear_constraint([0, 1], [1, 2], +1, 3) # optional - CPLEX |
| 1187 | 1 |
| 1188 | sage: p.add_linear_constraint([(0, 1), (1, 2)], None, 3) # optional - CPLEX |
1084 | 1189 | sage: p.set_objective([2, 5]) # optional - CPLEX |
1085 | 1190 | sage: p.write_lp(SAGE_TMP+"/lp_problem.lp") # optional - CPLEX |
1086 | 1191 | """ |
… |
… |
|
1103 | 1208 | sage: from sage.numerical.backends.generic_backend import get_solver |
1104 | 1209 | sage: p = get_solver(solver = "CPLEX") # optional - CPLEX |
1105 | 1210 | sage: p.add_variables(2) # optional - CPLEX |
1106 | | 2 |
1107 | | sage: p.add_linear_constraint([0, 1], [1, 2], +1, 3) # optional - CPLEX |
| 1211 | 1 |
| 1212 | sage: p.add_linear_constraint([(0, 1), (1, 2)], None, 3) # optional - CPLEX |
1108 | 1213 | sage: p.set_objective([2, 5]) # optional - CPLEX |
1109 | 1214 | sage: p.write_lp(SAGE_TMP+"/lp_problem.lp") # optional - CPLEX |
1110 | 1215 | """ |
diff -r cfaca337639b -r 4825b49a4b2a sage/numerical/backends/generic_backend.pxd
a
|
b
|
|
19 | 19 | cpdef int solve(self) except -1 |
20 | 20 | cpdef double get_objective_value(self) |
21 | 21 | cpdef double get_variable_value(self, int variable) |
22 | | cpdef name(self) |
23 | 22 | cpdef bint is_maximization(self) |
24 | 23 | cpdef write_lp(self, char * name) |
25 | 24 | cpdef write_mps(self, char * name, int modern) |
diff -r cfaca337639b -r 4825b49a4b2a sage/numerical/backends/generic_backend.pyx
a
|
b
|
|
218 | 218 | """ |
219 | 219 | raise NotImplementedError() |
220 | 220 | |
221 | | cpdef add_linear_constraint(self, constraints, lower_bound, upper_bound): |
| 221 | cpdef add_linear_constraint(self, coefficients, lower_bound, upper_bound): |
222 | 222 | """ |
223 | 223 | Add a linear constraint. |
224 | 224 | |
225 | 225 | INPUT: |
226 | 226 | |
227 | | - ``contraints`` an iterable with ``(c,v)`` pairs where ``c`` |
| 227 | - ``coefficients`` an iterable with ``(c,v)`` pairs where ``c`` |
228 | 228 | is a variable index (integer) and ``v`` is a value (real |
229 | 229 | value). |
230 | 230 | |
diff -r cfaca337639b -r 4825b49a4b2a sage/numerical/backends/glpk_backend.pyx
a
|
b
|
|
319 | 319 | else: |
320 | 320 | self.iocp.msg_lev = GLP_MSG_ALL |
321 | 321 | |
322 | | cpdef add_linear_constraint(self, constraints, lower_bound, upper_bound): |
| 322 | cpdef add_linear_constraint(self, coefficients, lower_bound, upper_bound): |
323 | 323 | """ |
324 | 324 | Add a linear constraint. |
325 | 325 | |
326 | 326 | INPUT: |
327 | 327 | |
328 | | - ``contraints`` an iterable with ``(c,v)`` pairs where ``c`` |
| 328 | - ``coefficients`` an iterable with ``(c,v)`` pairs where ``c`` |
329 | 329 | is a variable index (integer) and ``v`` is a value (real |
330 | 330 | value). |
331 | 331 | |
… |
… |
|
354 | 354 | cdef int * row_i |
355 | 355 | cdef double * row_values |
356 | 356 | |
357 | | row_i = <int *> sage_malloc((len(constraints)+1) * sizeof(int)) |
358 | | row_values = <double *> sage_malloc((len(constraints)+1) * sizeof(double)) |
| 357 | row_i = <int *> sage_malloc((len(coefficients)+1) * sizeof(int)) |
| 358 | row_values = <double *> sage_malloc((len(coefficients)+1) * sizeof(double)) |
359 | 359 | |
360 | | for i,(c,v) in enumerate(constraints): |
| 360 | for i,(c,v) in enumerate(coefficients): |
361 | 361 | row_i[i+1] = c+1 |
362 | 362 | row_values[i+1] = v |
363 | 363 | |
364 | | glp_set_mat_row(self.lp, n, len(constraints), row_i, row_values) |
| 364 | glp_set_mat_row(self.lp, n, len(coefficients), row_i, row_values) |
365 | 365 | |
366 | 366 | if upper_bound is not None and lower_bound is None: |
367 | 367 | glp_set_row_bnds(self.lp, n, GLP_UP, upper_bound, upper_bound) |
diff -r cfaca337639b -r 4825b49a4b2a sage/numerical/mip.pyx
a
|
b
|
|
723 | 723 | |
724 | 724 | TESTS:: |
725 | 725 | |
| 726 | Complex constraints:: |
| 727 | |
| 728 | sage: p = MixedIntegerLinearProgram() |
| 729 | sage: b = p.new_variable() |
| 730 | sage: p.add_constraint( b[8] - b[15] <= 3*b[8] + 9) |
| 731 | sage: p.show() |
| 732 | |
| 733 | Empty constraint:: |
| 734 | |
726 | 735 | sage: p=MixedIntegerLinearProgram() |
727 | 736 | sage: p.add_constraint(sum([]),min=2) |
728 | 737 | |
… |
… |
|
773 | 782 | self._backend.row_name(self._backend.nrows()-1,name) |
774 | 783 | |
775 | 784 | elif isinstance(linear_function,LinearConstraint): |
776 | | ####### |
777 | | ####### IS THIS DEAD CODE??? |
778 | | ####### |
779 | 785 | functions = linear_function.constraints |
780 | 786 | |
781 | 787 | if linear_function.equality: |