# HG changeset patch
# User Nathann Cohen <nathann.cohen@gmail.com>
# Date 1254129856 25200
# Node ID 654a9e739eb27b7233b0230a597831d597f87c94
# Parent 50100c42b09396988e53fbc2ec0c48a36956c83e
Numerical.mip Class : functions renamed, typos, several docstring fixes, bugfixes...
diff -r 50100c42b093 -r 654a9e739eb2 sage/numerical/knapsack.py
a
|
b
|
|
641 | 641 | if reals: |
642 | 642 | seq=[(x,1) for x in seq] |
643 | 643 | |
644 | | from sage.numerical.mip import MIP |
645 | | p=MIP(sense=1) |
646 | | present=p.newvar() |
647 | | p.setobj(sum([present[i]*seq[i][1] for i in range(len(seq))])) |
648 | | p.addconstraint(sum([present[i]*seq[i][0] for i in range(len(seq))]),max=max) |
| 644 | from sage.numerical.mip import MixedIntegerLinearProgram |
| 645 | p=MixedIntegerLinearProgram(sense=1) |
| 646 | present=p.new_variable() |
| 647 | p.set_objective(sum([present[i]*seq[i][1] for i in range(len(seq))])) |
| 648 | p.add_constraint(sum([present[i]*seq[i][0] for i in range(len(seq))]),max=max) |
649 | 649 | |
650 | 650 | if binary: |
651 | | p.setbinary(present) |
| 651 | p.set_binary(present) |
652 | 652 | else: |
653 | | p.setinteger(present) |
| 653 | p.set_integer(present) |
654 | 654 | |
655 | 655 | if value_only: |
656 | 656 | return p.solve(objective_only=True) |
diff -r 50100c42b093 -r 654a9e739eb2 sage/numerical/mip.pyx
a
|
b
|
|
1 | 1 | include '../ext/stdsage.pxi' |
2 | 2 | |
3 | | class MIP: |
| 3 | class MixedIntegerLinearProgram: |
4 | 4 | r""" |
5 | | The MIP class is the link between SAGE and LP ( Linear Program ) and |
| 5 | The ``MixedIntegerLinearProgram`` class is the link between SAGE and LP ( Linear Program ) and |
6 | 6 | MIP ( Mixed Integer Program ) Solvers. Cf : http://en.wikipedia.org/wiki/Linear_programming |
7 | 7 | |
8 | 8 | It consists of variables, linear constraints on these variables, and an objective |
9 | 9 | function which is to be maximised or minimised under these constraints. |
10 | 10 | |
11 | | An instance of ``MIP`` also requires the information |
| 11 | An instance of ``MixedIntegerLinearProgram`` also requires the information |
12 | 12 | on the direction of the optimization : |
13 | 13 | |
14 | | A ``MIP`` ( or ``LP`` ) is defined as a maximization |
| 14 | A ``MixedIntegerLinearProgram`` ( or ``LP`` ) is defined as a maximization |
15 | 15 | if ``sense=1``, and is a minimization if ``sense=-1`` |
16 | 16 | |
17 | 17 | INPUT: |
18 | 18 | |
19 | | - ``sense'' : |
20 | | * When set to `1` (default), the ``MIP`` is defined as a Maximization |
21 | | * When set to `-1`, the ``MIP`` is defined as a Minimization |
| 19 | - ``sense`` : |
| 20 | * When set to `1` (default), the ``MixedIntegerLinearProgram`` is defined as a Maximization |
| 21 | * When set to `-1`, the ``MixedIntegerLinearProgram`` is defined as a Minimization |
22 | 22 | |
23 | 23 | EXAMPLES:: |
24 | 24 | |
25 | 25 | sage: ### Computation of a maximum stable set in Petersen's graph ### |
26 | 26 | sage: g=graphs.PetersenGraph() |
27 | | sage: p=MIP(sense=1) |
28 | | sage: b=p.newvar() |
29 | | sage: p.setobj(sum([b[v] for v in g])) |
| 27 | sage: p=MixedIntegerLinearProgram(sense=1) |
| 28 | sage: b=p.new_variable() |
| 29 | sage: p.set_objective(sum([b[v] for v in g])) |
30 | 30 | sage: for (u,v) in g.edges(labels=None): |
31 | | ... p.addconstraint(b[u]+b[v],max=1) |
32 | | sage: p.setbinary(b) |
| 31 | ... p.add_constraint(b[u]+b[v],max=1) |
| 32 | sage: p.set_binary(b) |
33 | 33 | sage: p.solve(objective_only=True) # optional - requires Glpk or COIN-OR/CBC |
34 | 34 | 4.0 |
35 | 35 | """ |
36 | 36 | |
37 | 37 | def __init__(self,sense=1): |
38 | 38 | r""" |
39 | | Constructor for the MIP class |
| 39 | Constructor for the ``MixedIntegerLinearProgram`` class |
40 | 40 | |
41 | 41 | INPUT: |
42 | 42 | |
43 | | - ``sense'' : |
44 | | When set to 1, the MIP is defined as a Maximization |
45 | | When set to -1, the MIP is defined as a Minimization |
| 43 | - ``sense`` : |
| 44 | When set to 1, the MixedIntegerLinearProgram is defined as a Maximization |
| 45 | When set to -1, the MixedIntegerLinearProgram is defined as a Minimization |
46 | 46 | |
47 | | EXAMPLE: |
| 47 | EXAMPLE:: |
48 | 48 | |
49 | | sage: p=MIP(sense=1) |
| 49 | sage: p=MixedIntegerLinearProgram(sense=1) |
50 | 50 | """ |
51 | 51 | |
52 | 52 | try: |
… |
… |
|
65 | 65 | P = InfinitePolynomialRing(RR(), names=('x',)); |
66 | 66 | (self.x,) = P._first_ngens(1) |
67 | 67 | |
68 | | self.count=[0] |
| 68 | # number of variables |
| 69 | self.count=0 |
69 | 70 | self.sense=sense |
70 | 71 | self.objective=None |
| 72 | |
71 | 73 | self.variables={} |
72 | 74 | self.constraints=[] |
| 75 | |
| 76 | #constains the min and max bounds on the variables |
73 | 77 | self.min={} |
74 | 78 | self.max={} |
| 79 | |
| 80 | # constains the variables types |
75 | 81 | self.types={} |
| 82 | |
| 83 | #constains the variables' values when solve(objective_only=False) is called |
76 | 84 | self.values={} |
| 85 | |
| 86 | # Several constants |
77 | 87 | self.__BINARY=1 |
78 | 88 | self.__REAL=-1 |
79 | 89 | self.__INTEGER=0 |
80 | 90 | |
81 | 91 | def __repr__(self): |
82 | 92 | r""" |
83 | | Returns a short description of the MIP |
| 93 | Returns a short description of the MixedIntegerLinearProgram |
84 | 94 | |
85 | | EXAMPLE: |
| 95 | EXAMPLE:: |
86 | 96 | |
87 | | sage: p=MIP() |
88 | | sage: v=p.newvar() |
89 | | sage: p.addconstraint(v[1]+v[2],max=2) |
| 97 | sage: p=MixedIntegerLinearProgram() |
| 98 | sage: v=p.new_variable() |
| 99 | sage: p.add_constraint(v[1]+v[2],max=2) |
90 | 100 | sage: print p |
91 | 101 | Mixed Integer Program ( maximization, 2 variables, 1 constraints ) |
92 | 102 | """ |
93 | 103 | return "Mixed Integer Program ( "+("maximization" if self.sense==1 else "minimization")+", "+str(len(self.variables))+" variables, "+str(len(self.constraints))+" constraints )" |
94 | 104 | |
95 | | def newvar(self,dim=1): |
| 105 | def new_variable(self,vtype=-1,dim=1): |
96 | 106 | r""" |
97 | 107 | Returns an instance of ``MIPVariable`` associated |
98 | | to the current instance of ``MIP``. |
| 108 | to the current instance of ``MixedIntegerLinearProgram``. |
99 | 109 | |
100 | | A new ``MIP`` variable ``x`` defined by ::: |
| 110 | A new variable ``x`` is defined by ::: |
101 | 111 | |
102 | | sage: p=MIP() |
103 | | sage: x=p.newvar() |
| 112 | sage: p=MixedIntegerLinearProgram() |
| 113 | sage: x=p.new_variable() |
104 | 114 | |
105 | | It behaves exactly as an usual dictionary would. It can use any key |
| 115 | It behaves exactly as a usual dictionary would. It can use any key |
106 | 116 | argument you may like, as ``x[5]`` or ``x["b"]``, and has methods |
107 | 117 | ``items()`` and ``keys()`` |
108 | 118 | |
… |
… |
|
113 | 123 | - ``dim`` ( integer ) : Defines the dimension of the dictionary |
114 | 124 | If ``x`` has dimension `2`, its fields will |
115 | 125 | be of the form ``x[key1][key2]`` |
| 126 | - ``vtype`` ( integer ) : Defines the type of the variables |
| 127 | ( default is Real ) |
| 128 | |
116 | 129 | |
117 | 130 | EXAMPLE:: |
118 | 131 | |
119 | | sage: p=MIP() |
120 | | sage: x=p.newvar() |
121 | | sage: y=p.newvar(dim=2) |
122 | | sage: p.addconstraint(x[2]+y[3][5],max=2) |
| 132 | sage: p=MixedIntegerLinearProgram() |
| 133 | sage: # available types are p.__REAL, p.__INTEGER and p.__BINARY |
| 134 | sage: x=p.new_variable(vtype=p.__REAL) |
| 135 | sage: y=p.new_variable(dim=2) |
| 136 | sage: p.add_constraint(x[2]+y[3][5],max=2) |
123 | 137 | """ |
124 | | return MIPVariable(self.x,self._addElementToRing,dim=dim) |
| 138 | return MIPVariable(self,vtype,dim=dim) |
125 | 139 | |
126 | 140 | |
127 | 141 | def export(self,format="text"): |
128 | 142 | r""" |
129 | | Exports the MIP to a string in different formats. |
| 143 | Exports the ``MixedIntegerLinearProgram`` to a string in different formats. |
130 | 144 | |
131 | 145 | INPUT: |
132 | 146 | |
133 | | - ``format'' : |
| 147 | - ``format`` : |
134 | 148 | "text" : human-readable format |
135 | 149 | |
136 | | sage: p=MIP() |
137 | | sage: x=p.newvar() |
138 | | sage: p.setobj(x[1]+x[2]) |
139 | | sage: p.addconstraint(-3*x[1]+2*x[2],max=2) |
| 150 | sage: p=MixedIntegerLinearProgram() |
| 151 | sage: x=p.new_variable() |
| 152 | sage: p.set_objective(x[1]+x[2]) |
| 153 | sage: p.add_constraint(-3*x[1]+2*x[2],max=2) |
140 | 154 | sage: print p.export(format="text") |
141 | 155 | Maximization : |
142 | 156 | x2 + x1 |
… |
… |
|
155 | 169 | value=value+"\nVariables :" |
156 | 170 | for v in self.variables.keys(): |
157 | 171 | value=value+"\n "+str(v)+" is" |
158 | | if self.isinteger(v): |
| 172 | if self.is_integer(v): |
159 | 173 | value=value+" an integer variable" |
160 | | elif self.isbinary(v): |
| 174 | elif self.is_binary(v): |
161 | 175 | value=value+" an boolean variable" |
162 | 176 | else: |
163 | 177 | value=value+" a real variable" |
164 | | value+=" (min="+(str(self.getmin(v)) if self.getmin(v)!= None else "-oo")+",max="+(str(self.getmax(v)) if self.getmax(v)!= None else "+oo")+")" |
| 178 | value+=" (min="+(str(self.get_min(v)) if self.get_min(v)!= None else "-oo")+",max="+(str(self.get_max(v)) if self.get_max(v)!= None else "+oo")+")" |
165 | 179 | return value |
166 | 180 | |
167 | 181 | def get_values(self,*lists): |
… |
… |
|
183 | 197 | |
184 | 198 | EXAMPLE:: |
185 | 199 | |
186 | | sage: p=MIP() |
187 | | sage: x=p.newvar() |
188 | | sage: y=p.newvar(dim=2) |
189 | | sage: p.setobj(x[3]+y[2][9]+x[5]) |
190 | | sage: p.addconstraint(x[3]+y[2][9]+2*x[5],max=2) |
| 200 | sage: p=MixedIntegerLinearProgram() |
| 201 | sage: x=p.new_variable() |
| 202 | sage: y=p.new_variable(dim=2) |
| 203 | sage: p.set_objective(x[3]+y[2][9]+x[5]) |
| 204 | sage: p.add_constraint(x[3]+y[2][9]+2*x[5],max=2) |
191 | 205 | sage: p.solve() # optional - requires Glpk or COIN-OR/CBC |
192 | 206 | 2.0 |
193 | 207 | sage: # |
194 | 208 | sage: # Returns the optimal value of x[3] |
195 | 209 | sage: p.get_values(x[3]) # optional - requires Glpk or COIN-OR/CBC |
196 | | 0.0 |
| 210 | 2.0 |
197 | 211 | sage: # |
198 | 212 | sage: # Returns a dictionary identical to x |
199 | 213 | sage: # containing values for the corresponding |
… |
… |
|
243 | 257 | |
244 | 258 | def show(self): |
245 | 259 | r""" |
246 | | Prints the MIP in a human-readable way |
| 260 | Prints the ``MixedIntegerLinearProgram`` in a human-readable way |
247 | 261 | |
248 | | EXAMPLE: |
| 262 | EXAMPLE:: |
249 | 263 | |
250 | | sage: p=MIP() |
251 | | sage: x=p.newvar() |
252 | | sage: p.setobj(x[1]+x[2]) |
253 | | sage: p.addconstraint(-3*x[1]+2*x[2],max=2) |
| 264 | sage: p=MixedIntegerLinearProgram() |
| 265 | sage: x=p.new_variable() |
| 266 | sage: p.set_objective(x[1]+x[2]) |
| 267 | sage: p.add_constraint(-3*x[1]+2*x[2],max=2) |
254 | 268 | sage: p.show() |
255 | 269 | Maximization : |
256 | 270 | x2 + x1 |
… |
… |
|
262 | 276 | """ |
263 | 277 | print self.export(format="text") |
264 | 278 | |
265 | | #Ok |
266 | | def setobj(self,obj): |
| 279 | def set_objective(self,obj): |
267 | 280 | r""" |
268 | | Sets the objective of the ``MIP``. |
| 281 | Sets the objective of the ``MixedIntegerLinearProgram``. |
269 | 282 | |
270 | 283 | INPUT: |
271 | 284 | |
… |
… |
|
284 | 297 | x is Real ( min = 0, max = None ) |
285 | 298 | y is Real ( min = 0, max = None ) |
286 | 299 | |
287 | | sage: p=MIP(sense=1) |
288 | | sage: x=p.newvar() |
289 | | sage: p.setobj(x[1]+5*x[2]) |
290 | | sage: p.addconstraint(x[1]+0.2*x[2],max=4) |
291 | | sage: p.addconstraint(1.5*x[1]+3*x[2],max=4) |
| 300 | sage: p=MixedIntegerLinearProgram(sense=1) |
| 301 | sage: x=p.new_variable() |
| 302 | sage: p.set_objective(x[1]+5*x[2]) |
| 303 | sage: p.add_constraint(x[1]+0.2*x[2],max=4) |
| 304 | sage: p.add_constraint(1.5*x[1]+3*x[2],max=4) |
292 | 305 | sage: p.solve() # optional - requires Glpk or COIN-OR/CBC |
293 | 306 | 6.6666666666666661 |
294 | 307 | |
295 | 308 | """ |
296 | 309 | self.objective=obj |
297 | 310 | |
298 | | def addconstraint(self,linear_function,max=None,min=None): |
| 311 | def add_constraint(self,linear_function,max=None,min=None): |
299 | 312 | r""" |
300 | | Adds a constraint to the MIP |
| 313 | Adds a constraint to the ``MixedIntegerLinearProgram`` |
301 | 314 | |
302 | 315 | INPUT : |
303 | 316 | |
… |
… |
|
318 | 331 | x is Real ( min = 0, max = None ) |
319 | 332 | y is Real ( min = 0, max = None ) |
320 | 333 | |
321 | | sage: p=MIP(sense=1) |
322 | | sage: x=p.newvar() |
323 | | sage: p.setobj(x[1]+5*x[2]) |
324 | | sage: p.addconstraint(x[1]+0.2*x[2],max=4) |
325 | | sage: p.addconstraint(1.5*x[1]+3*x[2],max=4) |
| 334 | sage: p=MixedIntegerLinearProgram(sense=1) |
| 335 | sage: x=p.new_variable() |
| 336 | sage: p.set_objective(x[1]+5*x[2]) |
| 337 | sage: p.add_constraint(x[1]+0.2*x[2],max=4) |
| 338 | sage: p.add_constraint(1.5*x[1]+3*x[2],max=4) |
326 | 339 | sage: p.solve() # optional - requires Glpk or COIN-OR/CBC |
327 | 340 | 6.6666666666666661 |
328 | 341 | """ |
… |
… |
|
331 | 344 | min=float(min) if min!=None else None |
332 | 345 | self.constraints.append({"function":linear_function,"min":min, "max":max,"card":len(linear_function.variables())}) |
333 | 346 | |
334 | | def setbinary(self,e): |
| 347 | def set_binary(self,e): |
335 | 348 | r""" |
336 | 349 | Sets a variable or a ``MIPVariable`` as binary |
337 | 350 | |
… |
… |
|
340 | 353 | - ``e`` : An instance of ``MIPVariable`` or one of |
341 | 354 | its elements |
342 | 355 | |
343 | | NOTE: |
| 356 | EXAMPLE:: |
344 | 357 | |
345 | | We recommend you to define the types of your variables after |
346 | | your problem has been completely defined ( see example ) |
347 | | |
348 | | EXAMPLE: |
349 | | |
350 | | sage: p=MIP() |
351 | | sage: x=p.newvar() |
| 358 | sage: p=MixedIntegerLinearProgram() |
| 359 | sage: x=p.new_variable() |
| 360 | sage: # With the following instruction, all the variables |
| 361 | sage: # from x will be binary |
| 362 | sage: p.set_binary(x) |
| 363 | sage: p.set_objective(x[0]+x[1]) |
| 364 | sage: p.add_constraint(-3*x[0]+2*x[1],max=2) |
352 | 365 | sage: # |
353 | | sage: # The following instruction does absolutely nothing |
354 | | sage: # as none of the variables of x have been used yet |
355 | | sage: p.setbinary(x) |
356 | | sage: p.setobj(x[0]+x[1]) |
357 | | sage: p.addconstraint(-3*x[0]+2*x[1],max=2) |
358 | | sage: # |
359 | | sage: # This instructions sets x[0] and x[1] |
360 | | sage: # as binary variables |
361 | | sage: p.setbinary(x) |
362 | | sage: p.addconstraint(x[3]+x[2],max=2) |
363 | | sage: # |
364 | | sage: # x[3] is not set as binary |
365 | | sage: # as no setbinary(x) has been called |
366 | | sage: # after its first definition |
367 | | sage: # |
368 | | sage: # Now it is done |
369 | | sage: p.setbinary(x[3]) |
| 366 | sage: # It is still possible, though, to set one of these |
| 367 | sage: # variable as real while keeping the others as they are |
| 368 | sage: p.set_real(x[3]) |
370 | 369 | """ |
371 | 370 | if isinstance(e,MIPVariable): |
| 371 | e.vtype=self.__BINARY |
372 | 372 | if e.depth()==1: |
373 | 373 | for v in e.values(): |
374 | 374 | self.types[v]=self.__BINARY |
375 | 375 | else: |
376 | 376 | for v in e.keys(): |
377 | | self.setbinary(e[v]) |
| 377 | self.set_binary(e[v]) |
378 | 378 | elif self.variables.has_key(e): |
379 | 379 | self.types[e]=self.__BINARY |
380 | 380 | else: |
381 | 381 | raise Exception("Wrong kind of variable..") |
382 | 382 | |
383 | | def isbinary(self,e): |
| 383 | def is_binary(self,e): |
384 | 384 | r""" |
385 | 385 | Tests whether the variable is binary. |
386 | 386 | |
… |
… |
|
394 | 394 | |
395 | 395 | ``True`` if the variable is binary, ``False`` otherwise |
396 | 396 | |
397 | | EXAMPLE: |
| 397 | EXAMPLE:: |
398 | 398 | |
399 | | sage: p=MIP() |
400 | | sage: v=p.newvar() |
401 | | sage: p.setobj(v[1]) |
402 | | sage: p.isbinary(v[1]) |
| 399 | sage: p=MixedIntegerLinearProgram() |
| 400 | sage: v=p.new_variable() |
| 401 | sage: p.set_objective(v[1]) |
| 402 | sage: p.is_binary(v[1]) |
403 | 403 | False |
404 | | sage: p.setbinary(v[1]) |
405 | | sage: p.isbinary(v[1]) |
| 404 | sage: p.set_binary(v[1]) |
| 405 | sage: p.is_binary(v[1]) |
406 | 406 | True |
407 | 407 | """ |
408 | 408 | # Returns an exception if the variable does not exist.. |
… |
… |
|
414 | 414 | return True |
415 | 415 | return False |
416 | 416 | |
417 | | def setinteger(self,e): |
| 417 | def set_integer(self,e): |
418 | 418 | r""" |
419 | 419 | Sets a variable or a ``MIPVariable`` as integer |
420 | 420 | |
… |
… |
|
423 | 423 | - ``e`` : An instance of ``MIPVariable`` or one of |
424 | 424 | its elements |
425 | 425 | |
426 | | NOTE: |
427 | 426 | |
428 | | We recommend you to define the types of your variables after |
429 | | your problem has been completely defined ( see example ) |
| 427 | EXAMPLE:: |
430 | 428 | |
431 | | EXAMPLE: |
| 429 | sage: p=MixedIntegerLinearProgram() |
| 430 | sage: x=p.new_variable() |
| 431 | sage: # With the following instruction, all the variables |
| 432 | sage: # from x will be integers |
| 433 | sage: p.set_integer(x) |
| 434 | sage: p.set_objective(x[0]+x[1]) |
| 435 | sage: p.add_constraint(-3*x[0]+2*x[1],max=2) |
| 436 | sage: # |
| 437 | sage: # It is still possible, though, to set one of these |
| 438 | sage: # variable as real while keeping the others as they are |
| 439 | sage: p.set_real(x[3]) |
432 | 440 | |
433 | | sage: p=MIP() |
434 | | sage: x=p.newvar() |
435 | | sage: # |
436 | | sage: # The following instruction does absolutely nothing |
437 | | sage: # as none of the variables of x have been used yet |
438 | | sage: p.setinteger(x) |
439 | | sage: p.setobj(x[0]+x[1]) |
440 | | sage: p.addconstraint(-3*x[0]+2*x[1],max=2) |
441 | | sage: # |
442 | | sage: # This instructions sets x[0] and x[1] |
443 | | sage: # as integer variables |
444 | | sage: p.setinteger(x) |
445 | | sage: p.addconstraint(x[3]+x[2],max=2) |
446 | | sage: # |
447 | | sage: # x[3] is not set as integer |
448 | | sage: # as no setinteger(x) has been called |
449 | | sage: # after its first definition |
450 | | sage: # |
451 | | sage: # Now it is done |
452 | | sage: p.setinteger(x[3]) |
453 | 441 | """ |
454 | 442 | if isinstance(e,MIPVariable): |
| 443 | e.vtype=self.__INTEGER |
455 | 444 | if e.depth()==1: |
456 | 445 | for v in e.values(): |
457 | 446 | self.types[v]=self.__INTEGER |
458 | 447 | else: |
459 | 448 | for v in e.keys(): |
460 | | self.setbinary(e[v]) |
| 449 | self.set_integer(e[v]) |
461 | 450 | elif self.variables.has_key(e): |
462 | 451 | self.types[e]=self.__INTEGER |
463 | 452 | else: |
464 | 453 | raise Exception("Wrong kind of variable..") |
465 | 454 | |
466 | | def isinteger(self,e): |
| 455 | def is_integer(self,e): |
467 | 456 | r""" |
468 | 457 | Tests whether the variable is integer. |
469 | 458 | |
… |
… |
|
477 | 466 | |
478 | 467 | ``True`` if the variable is integer, ``False`` otherwise |
479 | 468 | |
480 | | EXAMPLE: |
| 469 | EXAMPLE:: |
481 | 470 | |
482 | | sage: p=MIP() |
483 | | sage: v=p.newvar() |
484 | | sage: p.setobj(v[1]) |
485 | | sage: p.isinteger(v[1]) |
| 471 | sage: p=MixedIntegerLinearProgram() |
| 472 | sage: v=p.new_variable() |
| 473 | sage: p.set_objective(v[1]) |
| 474 | sage: p.is_integer(v[1]) |
486 | 475 | False |
487 | | sage: p.setinteger(v[1]) |
488 | | sage: p.isinteger(v[1]) |
| 476 | sage: p.set_integer(v[1]) |
| 477 | sage: p.is_integer(v[1]) |
489 | 478 | True |
490 | 479 | """ |
491 | 480 | # Returns an exception if the variable does not exist.. |
… |
… |
|
497 | 486 | return True |
498 | 487 | return False |
499 | 488 | |
500 | | def setreal(self,e): |
| 489 | def set_real(self,e): |
501 | 490 | r""" |
502 | 491 | Sets a variable or a ``MIPVariable`` as real |
503 | 492 | |
… |
… |
|
506 | 495 | - ``e`` : An instance of ``MIPVariable`` or one of |
507 | 496 | its elements |
508 | 497 | |
509 | | NOTE: |
| 498 | EXAMPLE:: |
510 | 499 | |
511 | | We recommend you to define the types of your variables after |
512 | | your problem has been completely defined ( see example ) |
513 | | |
514 | | EXAMPLE: |
515 | | |
516 | | sage: p=MIP() |
517 | | sage: x=p.newvar() |
| 500 | sage: p=MixedIntegerLinearProgram() |
| 501 | sage: x=p.new_variable() |
| 502 | sage: # With the following instruction, all the variables |
| 503 | sage: # from x will be real ( they are by default, though ) |
| 504 | sage: p.set_real(x) |
| 505 | sage: p.set_objective(x[0]+x[1]) |
| 506 | sage: p.add_constraint(-3*x[0]+2*x[1],max=2) |
518 | 507 | sage: # |
519 | | sage: # The following instruction does absolutely nothing |
520 | | sage: # as none of the variables of x have been used yet |
521 | | sage: p.setreal(x) |
522 | | sage: p.setobj(x[0]+x[1]) |
523 | | sage: p.addconstraint(-3*x[0]+2*x[1],max=2) |
524 | | sage: # |
525 | | sage: # This instructions sets x[0] and x[1] |
526 | | sage: # as real variables |
527 | | sage: p.setreal(x) |
528 | | sage: p.addconstraint(x[3]+x[2],max=2) |
529 | | sage: # |
530 | | sage: # x[3] is not set as real |
531 | | sage: # as no setreal(x) has been called |
532 | | sage: # after its first definition |
533 | | sage: # ( even if actually, it is as variables |
534 | | sage: # are real by default ... ) |
535 | | sage: # |
536 | | sage: # Now it is done |
537 | | sage: p.setreal(x[3]) |
| 508 | sage: # It is still possible, though, to set one of these |
| 509 | sage: # variable as binary while keeping the others as they are |
| 510 | sage: p.set_binary(x[3]) |
538 | 511 | """ |
539 | 512 | if isinstance(e,MIPVariable): |
| 513 | e.vtype=self.__REAL |
540 | 514 | if e.depth()==1: |
541 | 515 | for v in e.values(): |
542 | 516 | self.types[v]=self.__REAL |
543 | 517 | else: |
544 | 518 | for v in e.keys(): |
545 | | self.setbinary(e[v]) |
| 519 | self.set_real(e[v]) |
546 | 520 | elif self.variables.has_key(e): |
547 | 521 | self.types[e]=self.__REAL |
548 | 522 | else: |
549 | 523 | raise Exception("Wrong kind of variable..") |
550 | 524 | |
551 | 525 | |
552 | | def isreal(self,e): |
| 526 | def is_real(self,e): |
553 | 527 | r""" |
554 | 528 | Tests whether the variable is real. |
555 | 529 | |
… |
… |
|
563 | 537 | |
564 | 538 | ``True`` if the variable is real, ``False`` otherwise |
565 | 539 | |
566 | | EXAMPLE: |
| 540 | EXAMPLE:: |
567 | 541 | |
568 | | sage: p=MIP() |
569 | | sage: v=p.newvar() |
570 | | sage: p.setobj(v[1]) |
571 | | sage: p.isreal(v[1]) |
| 542 | sage: p=MixedIntegerLinearProgram() |
| 543 | sage: v=p.new_variable() |
| 544 | sage: p.set_objective(v[1]) |
| 545 | sage: p.is_real(v[1]) |
572 | 546 | True |
573 | | sage: p.setbinary(v[1]) |
574 | | sage: p.isreal(v[1]) |
| 547 | sage: p.set_binary(v[1]) |
| 548 | sage: p.is_real(v[1]) |
575 | 549 | False |
576 | | sage: p.setreal(v[1]) |
577 | | sage: p.isreal(v[1]) |
| 550 | sage: p.set_real(v[1]) |
| 551 | sage: p.is_real(v[1]) |
578 | 552 | True |
579 | 553 | """ |
580 | 554 | |
… |
… |
|
590 | 564 | |
591 | 565 | def solve(self,solver=None,log=False,objective_only=False): |
592 | 566 | r""" |
593 | | Solves the MIP. |
| 567 | Solves the MixedIntegerLinearProgram. |
594 | 568 | |
595 | 569 | INPUT : |
596 | | - ``solver'' : |
| 570 | - ``solver`` : |
597 | 571 | 3 solvers should be available through this class : |
598 | 572 | - GLPK ( ``solver="GLPK"`` ) |
599 | 573 | http://www.gnu.org/software/glpk/ |
… |
… |
|
636 | 610 | Variables: |
637 | 611 | x is Real ( min = 0, max = None ) |
638 | 612 | y is Real ( min = 0, max = None ) |
| 613 | |
| 614 | :: |
639 | 615 | |
640 | | |
641 | | sage: p=MIP(sense=1) |
642 | | sage: x=p.newvar() |
643 | | sage: p.setobj(x[1]+5*x[2]) |
644 | | sage: p.addconstraint(x[1]+0.2*x[2],max=4) |
645 | | sage: p.addconstraint(1.5*x[1]+3*x[2],max=4) |
| 616 | sage: p=MixedIntegerLinearProgram(sense=1) |
| 617 | sage: x=p.new_variable() |
| 618 | sage: p.set_objective(x[1]+5*x[2]) |
| 619 | sage: p.add_constraint(x[1]+0.2*x[2],max=4) |
| 620 | sage: p.add_constraint(1.5*x[1]+3*x[2],max=4) |
646 | 621 | sage: p.solve() # optional - requires Glpk or COIN-OR/CBC |
647 | 622 | 6.6666666666666661 |
648 | 623 | sage: p.get_values(x) # optional - requires Glpk or COIN-OR/CBC |
… |
… |
|
650 | 625 | |
651 | 626 | sage: ### Computation of a maximum stable set in Petersen's graph ### |
652 | 627 | sage: g=graphs.PetersenGraph() |
653 | | sage: p=MIP(sense=1) |
654 | | sage: b=p.newvar() |
655 | | sage: p.setobj(sum([b[v] for v in g])) |
| 628 | sage: p=MixedIntegerLinearProgram(sense=1) |
| 629 | sage: b=p.new_variable() |
| 630 | sage: p.set_objective(sum([b[v] for v in g])) |
656 | 631 | sage: for (u,v) in g.edges(labels=None): |
657 | | ... p.addconstraint(b[u]+b[v],max=1) |
658 | | sage: p.setbinary(b) |
| 632 | ... p.add_constraint(b[u]+b[v],max=1) |
| 633 | sage: p.set_binary(b) |
659 | 634 | sage: p.solve(objective_only=True) # optional - requires Glpk or COIN-OR/CBC |
660 | 635 | 4.0 |
661 | | |
662 | | |
663 | 636 | """ |
664 | 637 | |
665 | 638 | if self.objective==None: |
… |
… |
|
674 | 647 | try: |
675 | 648 | from sage.numerical.mipCoin import solveCoin |
676 | 649 | except: |
677 | | raise NotImplementedError("Coin/CBC is not installed and cannot be used to solve this MIP\n To install it, you can type in Sage : sage: install_package('cbc')") |
| 650 | raise NotImplementedError("Coin/CBC is not installed and cannot be used to solve this MixedIntegerLinearProgram\n To install it, you can type in Sage : sage: install_package('cbc')") |
678 | 651 | return solveCoin(self,log=log,objective_only=objective_only) |
679 | 652 | |
680 | 653 | elif solver=="GLPK": |
681 | 654 | try: |
682 | 655 | from sage.numerical.mipGlpk import solveGlpk |
683 | 656 | except: |
684 | | raise NotImplementedError("GLPK is not installed and cannot be used to solve this MIP\n To install it, you can type in Sage : sage: install_package('glpk')") |
| 657 | raise NotImplementedError("GLPK is not installed and cannot be used to solve this MixedIntegerLinearProgram\n To install it, you can type in Sage : sage: install_package('glpk')") |
685 | 658 | return solveGlpk(self,log=log,objective_only=objective_only) |
686 | 659 | elif solver=="CPLEX": |
687 | 660 | raise NotImplementedError("The support for CPLEX is not written yet... We're seriously thinking about it, though ;-)") |
… |
… |
|
703 | 676 | values are their coefficients. |
704 | 677 | The value corresponding to key `-1` is the constant coefficient |
705 | 678 | |
706 | | EXAMPLE: |
| 679 | EXAMPLE:: |
707 | 680 | |
708 | | sage: p=MIP() |
709 | | sage: v=p.newvar() |
| 681 | sage: p=MixedIntegerLinearProgram() |
| 682 | sage: v=p.new_variable() |
710 | 683 | sage: p._NormalForm(v[0]+v[1]) |
711 | 684 | {1: 1.0, 2: 1.0, -1: 0.0} |
712 | 685 | """ |
… |
… |
|
714 | 687 | d[-1]=exp.constant_coefficient() |
715 | 688 | return d |
716 | 689 | |
717 | | def _addElementToRing(self): |
| 690 | def _add_element_to_ring(self,vtype): |
718 | 691 | r""" |
719 | 692 | Creates a new variable from the main ``InfinitePolynomialRing`` |
720 | 693 | |
… |
… |
|
722 | 695 | |
723 | 696 | - The newly created variable |
724 | 697 | |
725 | | EXAMPLE: |
| 698 | EXAMPLE:: |
726 | 699 | |
727 | | sage: p=MIP() |
728 | | sage: v=p.newvar() |
729 | | sage: p.count[0] |
| 700 | sage: p=MixedIntegerLinearProgram() |
| 701 | sage: v=p.new_variable() |
| 702 | sage: p.count |
730 | 703 | 0 |
731 | | sage: p._addElementToRing() |
| 704 | sage: p._add_element_to_ring(p.__REAL) |
732 | 705 | x1 |
733 | | sage: p.count[0] |
| 706 | sage: p.count |
734 | 707 | 1 |
735 | 708 | """ |
736 | | self.count[0]+=1 |
737 | | v=self.x[self.count[0]] |
738 | | self.variables[v]=self.count[0] |
739 | | self.types[v]=self.__REAL |
| 709 | self.count+=1 |
| 710 | v=self.x[self.count] |
| 711 | self.variables[v]=self.count |
| 712 | self.types[v]=vtype |
740 | 713 | self.min[v]=0.0 |
741 | 714 | return v |
742 | 715 | |
743 | | def setmin(self,v,min): |
| 716 | def set_min(self,v,min): |
744 | 717 | r""" |
745 | 718 | Sets the minimum value of a variable |
746 | 719 | |
… |
… |
|
752 | 725 | |
753 | 726 | EXAMPLE:: |
754 | 727 | |
755 | | sage: p=MIP() |
756 | | sage: v=p.newvar() |
757 | | sage: p.setobj(v[1]) |
758 | | sage: p.getmin(v[1]) |
| 728 | sage: p=MixedIntegerLinearProgram() |
| 729 | sage: v=p.new_variable() |
| 730 | sage: p.set_objective(v[1]) |
| 731 | sage: p.get_min(v[1]) |
759 | 732 | 0.0 |
760 | | sage: p.setmin(v[1],6) |
761 | | sage: p.getmin(v[1]) |
| 733 | sage: p.set_min(v[1],6) |
| 734 | sage: p.get_min(v[1]) |
762 | 735 | 6.0 |
763 | 736 | """ |
764 | 737 | self.min[v]=min |
765 | 738 | |
766 | | def setmax(self,v,max): |
| 739 | def set_max(self,v,max): |
767 | 740 | r""" |
768 | 741 | Sets the maximum value of a variable |
769 | 742 | |
… |
… |
|
775 | 748 | |
776 | 749 | EXAMPLE:: |
777 | 750 | |
778 | | sage: p=MIP() |
779 | | sage: v=p.newvar() |
780 | | sage: p.setobj(v[1]) |
781 | | sage: p.getmax(v[1]) |
782 | | sage: p.setmax(v[1],6) |
783 | | sage: p.getmax(v[1]) |
| 751 | sage: p=MixedIntegerLinearProgram() |
| 752 | sage: v=p.new_variable() |
| 753 | sage: p.set_objective(v[1]) |
| 754 | sage: p.get_max(v[1]) |
| 755 | sage: p.set_max(v[1],6) |
| 756 | sage: p.get_max(v[1]) |
784 | 757 | 6.0 |
785 | 758 | """ |
786 | 759 | self.max[v]=max |
787 | 760 | |
788 | 761 | |
789 | | def getmin(self,v): |
| 762 | def get_min(self,v): |
790 | 763 | r""" |
791 | 764 | Returns the minimum value of a variable |
792 | 765 | |
… |
… |
|
801 | 774 | |
802 | 775 | EXAMPLE:: |
803 | 776 | |
804 | | sage: p=MIP() |
805 | | sage: v=p.newvar() |
806 | | sage: p.setobj(v[1]) |
807 | | sage: p.getmin(v[1]) |
| 777 | sage: p=MixedIntegerLinearProgram() |
| 778 | sage: v=p.new_variable() |
| 779 | sage: p.set_objective(v[1]) |
| 780 | sage: p.get_min(v[1]) |
808 | 781 | 0.0 |
809 | | sage: p.setmin(v[1],6) |
810 | | sage: p.getmin(v[1]) |
| 782 | sage: p.set_min(v[1],6) |
| 783 | sage: p.get_min(v[1]) |
811 | 784 | 6.0 |
812 | 785 | """ |
813 | | return float(self.min[v]) if self.min.has_key(v) else 0.0 |
814 | | def getmax(self,v): |
| 786 | return float(self.min[v]) if self.min.has_key(v) else None |
| 787 | |
| 788 | def get_max(self,v): |
815 | 789 | r""" |
816 | 790 | Returns the maximum value of a variable |
817 | 791 | |
… |
… |
|
826 | 800 | |
827 | 801 | EXAMPLE:: |
828 | 802 | |
829 | | sage: p=MIP() |
830 | | sage: v=p.newvar() |
831 | | sage: p.setobj(v[1]) |
832 | | sage: p.getmax(v[1]) |
833 | | sage: p.setmax(v[1],6) |
834 | | sage: p.getmax(v[1]) |
| 803 | sage: p=MixedIntegerLinearProgram() |
| 804 | sage: v=p.new_variable() |
| 805 | sage: p.set_objective(v[1]) |
| 806 | sage: p.get_max(v[1]) |
| 807 | sage: p.set_max(v[1],6) |
| 808 | sage: p.get_max(v[1]) |
835 | 809 | 6.0 |
836 | 810 | """ |
837 | 811 | return float(self.max[v]) if self.max.has_key(v) else None |
… |
… |
|
846 | 820 | |
847 | 821 | ``MIPSolverException`` is the exception raised when the solver fails |
848 | 822 | |
849 | | EXAMPLE: |
| 823 | EXAMPLE:: |
850 | 824 | |
851 | 825 | sage: MIPSolverException("Error") |
852 | 826 | MIPSolverException() |
… |
… |
|
857 | 831 | r""" |
858 | 832 | Returns the value of the instance of ``MIPSolverException` ` |
859 | 833 | |
860 | | EXAMPLE: |
| 834 | EXAMPLE:: |
861 | 835 | |
862 | 836 | sage: e=MIPSolverException("Error") |
863 | 837 | sage: print e |
… |
… |
|
867 | 841 | |
868 | 842 | class MIPVariable: |
869 | 843 | r""" |
870 | | ``MIPVariable`` is a variable used by the class ``MIP`` |
| 844 | ``MIPVariable`` is a variable used by the class ``MixedIntegerLinearProgram`` |
871 | 845 | """ |
872 | | def __init__(self,x,f,dim=1): |
| 846 | def __init__(self,p,vtype,dim=1): |
873 | 847 | r""" |
874 | 848 | Constructor for ``MIPVariable`` |
875 | 849 | |
876 | 850 | INPUT: |
877 | 851 | |
878 | | - ``x`` is the generator element of an ``InfinitePolynomialRing`` |
879 | | - ``f`` is a function returning a new variable from the parent class |
| 852 | - ``p`` is the instance of ``MixedIntegerLinearProgram`` to which the |
| 853 | variable is to be linked. |
880 | 854 | - ``dim`` is the integer defining the definition of the variable |
881 | 855 | |
882 | | For more informations, see method ``MIP.newvar`` |
| 856 | For more informations, see method ``MixedIntegerLinearProgram.new_variable`` |
883 | 857 | |
884 | | EXAMPLE: |
| 858 | EXAMPLE:: |
885 | 859 | |
886 | | sage: p=MIP() |
887 | | sage: v=p.newvar() |
| 860 | sage: p=MixedIntegerLinearProgram() |
| 861 | sage: v=p.new_variable() |
888 | 862 | |
889 | 863 | |
890 | 864 | """ |
891 | 865 | self.dim=dim |
892 | 866 | self.dict={} |
893 | | self.x=x |
894 | | self.f=f |
| 867 | self.p=p |
| 868 | self.vtype=vtype |
895 | 869 | |
896 | 870 | def __getitem__(self,i): |
897 | 871 | r""" |
… |
… |
|
900 | 874 | Returns the element asked, otherwise creates it. |
901 | 875 | ( When depth>1, recursively creates the variables ) |
902 | 876 | |
903 | | EXAMPLE: |
| 877 | EXAMPLE:: |
904 | 878 | |
905 | | sage: p=MIP() |
906 | | sage: v=p.newvar() |
907 | | sage: p.setobj(v[0]+v[1]) |
| 879 | sage: p=MixedIntegerLinearProgram() |
| 880 | sage: v=p.new_variable() |
| 881 | sage: p.set_objective(v[0]+v[1]) |
908 | 882 | sage: v[0] |
909 | 883 | x1 |
910 | 884 | """ |
911 | 885 | if self.dict.has_key(i): |
912 | 886 | return self.dict[i] |
913 | 887 | elif self.dim==1: |
914 | | self.dict[i]=self.f() |
| 888 | self.dict[i]=self.p._add_element_to_ring(self.vtype) |
915 | 889 | return self.dict[i] |
916 | 890 | else: |
917 | | self.dict[i]=MIPVariable(dim=self.dim-1,x=self.x, f=self.f) |
| 891 | self.dict[i]=MIPVariable(self.p,self.vtype,dim=self.dim-1) |
918 | 892 | return self.dict[i] |
919 | 893 | def keys(self): |
920 | 894 | r""" |
921 | 895 | Returns the keys already defined in the dictionary |
922 | 896 | |
923 | | EXAMPLE: |
| 897 | EXAMPLE:: |
924 | 898 | |
925 | | sage: p=MIP() |
926 | | sage: v=p.newvar() |
927 | | sage: p.setobj(v[0]+v[1]) |
| 899 | sage: p=MixedIntegerLinearProgram() |
| 900 | sage: v=p.new_variable() |
| 901 | sage: p.set_objective(v[0]+v[1]) |
928 | 902 | sage: v.keys() |
929 | 903 | [0, 1] |
930 | 904 | """ |
… |
… |
|
933 | 907 | r""" |
934 | 908 | Returns the pairs (keys,value) contained in the dictionary |
935 | 909 | |
936 | | EXAMPLE: |
| 910 | EXAMPLE:: |
937 | 911 | |
938 | | sage: p=MIP() |
939 | | sage: v=p.newvar() |
940 | | sage: p.setobj(v[0]+v[1]) |
| 912 | sage: p=MixedIntegerLinearProgram() |
| 913 | sage: v=p.new_variable() |
| 914 | sage: p.set_objective(v[0]+v[1]) |
941 | 915 | sage: v.items() |
942 | 916 | [(0, x1), (1, x2)] |
943 | 917 | """ |
… |
… |
|
946 | 920 | r""" |
947 | 921 | Returns the current variable's depth |
948 | 922 | |
949 | | EXAMPLE: |
| 923 | EXAMPLE:: |
950 | 924 | |
951 | | sage: p=MIP() |
952 | | sage: v=p.newvar() |
953 | | sage: p.setobj(v[0]+v[1]) |
| 925 | sage: p=MixedIntegerLinearProgram() |
| 926 | sage: v=p.new_variable() |
| 927 | sage: p.set_objective(v[0]+v[1]) |
954 | 928 | sage: v.depth() |
955 | 929 | 1 |
956 | 930 | """ |
… |
… |
|
959 | 933 | r""" |
960 | 934 | Returns the symbolic variables associated to the current dictionary |
961 | 935 | |
962 | | EXAMPLE: |
| 936 | EXAMPLE:: |
963 | 937 | |
964 | | sage: p=MIP() |
965 | | sage: v=p.newvar() |
966 | | sage: p.setobj(v[0]+v[1]) |
| 938 | sage: p=MixedIntegerLinearProgram() |
| 939 | sage: v=p.new_variable() |
| 940 | sage: p.set_objective(v[0]+v[1]) |
967 | 941 | sage: v.values() |
968 | 942 | [x1, x2] |
969 | 943 | """ |