Ticket #7270: trac_7270.patch
File trac_7270.patch, 34.2 KB (added by , 11 years ago) 


sage/numerical/all.py
# HG changeset patch # User Nathann Cohen <nathann.cohen@gmail.com> # Date 1255776303 7200 # Node ID 494f8a8c14f24bedd964f1ecf19e7f0fa9595dc0 # Parent 14516cf5b0ccefed648d0043a7c9beb7121a5598 Last "core" modifications of numerical.mip. diff r 14516cf5b0cc r 494f8a8c14f2 sage/numerical/all.py
a b 1 1 from optimize import (find_root, find_maximum_on_interval, 2 2 find_minimum_on_interval,minimize,minimize_constrained, 3 3 linear_program, find_fit) 4 from sage.numerical.mip import *4 from sage.numerical.mip import MixedIntegerLinearProgram 
sage/numerical/mip.pyx
diff r 14516cf5b0cc r 494f8a8c14f2 sage/numerical/mip.pyx
a b 61 61 """ 62 62 try: 63 63 from sage.numerical.mipCoin import solveCoin 64 self. default_solver = "Coin"64 self._default_solver = "Coin" 65 65 except: 66 66 try: 67 from sage.numerical.mipGlpk import solve Glpk68 self. default_solver = "GLPK"67 from sage.numerical.mipGlpk import solve_glpk 68 self._default_solver = "GLPK" 69 69 except: 70 self. default_solver = None70 self._default_solver = None 71 71 72 72 from sage.rings.polynomial.infinite_polynomial_ring import InfinitePolynomialRing 73 73 from sage.rings.real_double import RealDoubleField as RR 74 74 P = InfinitePolynomialRing(RR(), names=('x',)) 75 (self. x,) = P._first_ngens(1)75 (self._x,) = P._first_ngens(1) 76 76 77 # number of variables 78 self.count = 0 79 self.maximization = maximization 80 self.objective = None 77 # List of all the MIPVariables linked to this instance of 78 # MixedIntegerLinearProgram 79 self._mipvariables = [] 81 80 82 self.variables = {}83 self. constraints = []81 # Associates an index to the variables from self._x 82 self._variables = {} 84 83 85 #constains the min and max bounds on the variables 86 self.min = {} 87 self.max = {} 88 89 # constains the variables types 90 self.types = {} 91 92 #constains the variables' values when 84 # contains the variables' values when 93 85 # solve(objective_only=False) is called 94 self. values = {}86 self._values = {} 95 87 96 88 # Several constants 97 89 self.__BINARY = 1 98 90 self.__REAL = 1 99 91 self.__INTEGER = 0 100 92 93 # ###################################################### 94 # The informations of a Linear Program 95 # 96 #  name 97 #  maximization 98 #  objective 99 # > name 100 # > i 101 # > values 102 #  variables 103 # > names 104 # > type 105 # > bounds 106 # > min 107 # > max 108 #  constraints 109 # > names 110 # > matrix 111 # > i 112 # > j 113 # > values 114 # > bounds 115 # > min 116 # > max 117 # 118 # The Constraint matrix being almost always sparse, it is stored 119 # as a list of positions (i,j) in the matrix with an associated value. 120 # 121 # This is how matrices are exchanged in GLPK's or Cbc's libraries 122 # By storing the data this way, we do no have to convert them 123 # ( too often ) and this process is a bit faster. 124 # 125 # ###################################################### 126 127 128 self._name = None 129 self._maximization = maximization 130 self._objective_i = None 131 self._objective_values = None 132 self._objective_name = None 133 self._variables_name = [] 134 self._variables_type = [] 135 self._variables_bounds_min = [] 136 self._variables_bounds_max = [] 137 self._constraints_name = [] 138 self._constraints_matrix_i = [] 139 self._constraints_matrix_j = [] 140 self._constraints_matrix_values = [] 141 self._constraints_bounds_max = [] 142 self._constraints_bounds_min = [] 143 144 101 145 def __repr__(self): 102 146 r""" 103 147 Returns a short description of the ``MixedIntegerLinearProgram``. … … 110 154 sage: print p 111 155 Mixed Integer Program ( maximization, 2 variables, 1 constraints ) 112 156 """ 113 return "Mixed Integer Program ( " + \ 114 ( "maximization" if self.maximization else "minimization" ) + \ 115 ", " + str(len(self.variables)) + " variables, " + \ 116 str(len(self.constraints)) + " constraints )" 157 return "Mixed Integer Program "+("\""+self._name+"\"" if self._name!=None else "")+" ( " + \ 158 ( "maximization" if self._maximization else "minimization" ) + \ 159 ", " + str(len(self._variables)) + " variables, " + \ 160 str(len(self._constraints_bounds_min)) + " constraints )" 161 162 def __eq__(self,p): 163 r""" 164 Test of equality. 117 165 118 def new_variable(self, vtype=1, dim=1): 166 INPUT: 167 168  ``p``  an instance of ``MixedIntegerLinearProgram`` to be tested 169 against ``self``. 170 171 EXAMPLE:: 172 173 sage: p = MixedIntegerLinearProgram() 174 sage: v = p.new_variable() 175 sage: p.add_constraint(v[1] + v[2], max=2) 176 sage: p == loads(dumps(p)) 177 True 178 sage: p2 = loads(dumps(p)) 179 sage: p2.add_constraint(2*v[1] + 3*v[2], max=1) 180 sage: p == p2 181 False 182 """ 183 184 return ( 185 self._name == p._name and 186 self._maximization == p._maximization and 187 self._objective_i == p._objective_i and 188 self._objective_values == p._objective_values and 189 self._objective_name == p._objective_name and 190 self._variables_name == p._variables_name and 191 self._variables_type == p._variables_type and 192 self._variables_bounds_min == p._variables_bounds_min and 193 self._variables_bounds_max == p._variables_bounds_max and 194 self._constraints_name == p._constraints_name and 195 self._constraints_matrix_i == p._constraints_matrix_i and 196 self._constraints_matrix_j == p._constraints_matrix_j and 197 self._constraints_matrix_values == p._constraints_matrix_values and 198 self._constraints_bounds_max == p._constraints_bounds_max 199 ) 200 201 def set_problem_name(self,name): 202 r""" 203 Sets the name of the ``MixedIntegerLinearProgram``. 204 205 INPUT: 206 207  ``name``  A string representing the name of the 208 ``MixedIntegerLinearProgram``. 209 210 EXAMPLE:: 211 212 sage: p=MixedIntegerLinearProgram() 213 sage: p.set_problem_name("Test program") 214 sage: p 215 Mixed Integer Program "Test program" ( maximization, 0 variables, 0 constraints ) 216 """ 217 218 self._name=name 219 220 def set_objective_name(self,name): 221 r""" 222 Sets the name of the objective function. 223 224 INPUT: 225 226  ``name``  A string representing the name of the 227 objective function. 228 229 EXAMPLE:: 230 231 sage: p=MixedIntegerLinearProgram() 232 sage: p.set_objective_name("Objective function") 233 """ 234 235 self._objective_name=name 236 237 def _update_variables_name(self): 238 r""" 239 Updates the names of the variables. 240 241 Only called before writing the Problem to a MPS or LP file. 242 243 EXAMPLE:: 244 245 sage: p=MixedIntegerLinearProgram() 246 sage: v=p.new_variable(name="Test") 247 sage: v[5]+v[99] 248 x1 + x0 249 sage: p._update_variables_name() 250 """ 251 252 self._variables_name=['']*len(self._variables) 253 for v in self._mipvariables: 254 v._update_variables_name() 255 256 257 def new_variable(self, vtype=1, dim=1,name=None): 119 258 r""" 120 259 Returns an instance of ``MIPVariable`` associated 121 260 to the current instance of ``MixedIntegerLinearProgram``. … … 138 277 ``x[key1][key2]``. 139 278  ``vtype`` (integer)  Defines the type of the variables 140 279 (default is ``REAL``). 280  ``name`` (string)  A name for the variable 281 ( default is V+number ) 141 282 142 283 EXAMPLE:: 143 284 … … 147 288 sage: y = p.new_variable(dim=2) 148 289 sage: p.add_constraint(x[2] + y[3][5], max=2) 149 290 """ 150 return MIPVariable(self, vtype, dim=dim) 291 if name==None: 292 name="V"+str(len(self._mipvariables)) 293 v=MIPVariable(self, vtype, dim=dim,name=name) 294 self._mipvariables.append(v) 295 return v 151 296 152 def export(self, format="text"):297 def constraints(self): 153 298 r""" 154 Exports the ``MixedIntegerLinearProgram`` to a string in 155 different formats. 299 Returns the list of constraints. 156 300 157 INPUT: 301 This functions returns the constraints as a list 302 of tuples ``(linear_function,min_bound,max_bound)``, representing 303 the constraint : 304 305 `\mbox{min_bound} \leq \mbox{linear_function} \leq \mbox{max_bound}` 306 307 Variables ``min_bound`` (respectively ``max_bound``) is set 308 to ``None`` when the function has no lower ( respectively upper ) 309 bound. 310 311 EXAMPLE:: 312 sage: p = MixedIntegerLinearProgram(maximization=True) 313 sage: x = p.new_variable() 314 sage: p.set_objective(x[1] + 5*x[2]) 315 sage: p.add_constraint(x[1] + 0.2*x[2], max=4) 316 sage: p.add_constraint(1.5*x[1]+3*x[2], max=4) 317 sage: p.constraints() 318 [(3.0*x1 + 1.5*x0, None, 4.0), (0.2*x1 + x0, None, 4.0)] 319 """ 320 321 constraints=[0]*len(self._constraints_bounds_min) 322 for (i,j,value) in zip(self._constraints_matrix_i,self._constraints_matrix_j,self._constraints_matrix_values): 323 constraints[i1]+=value*self._x[j] 324 return zip(constraints,self._constraints_bounds_min,self._constraints_bounds_max) 158 325 159  ``format``160 326 161  ``"text"``  (default) humanreadable format 327 def show(self): 328 r""" 329 Displays the ``MixedIntegerLinearProgram`` in a humanreadable 330 way. 162 331 163 332 EXAMPLES:: 164 333 … … 166 335 sage: x = p.new_variable() 167 336 sage: p.set_objective(x[1] + x[2]) 168 337 sage: p.add_constraint(3*x[1] + 2*x[2], max=2) 169 sage: p rint p.export(format="text")338 sage: p.show() 170 339 Maximization: 171 x2 + x1340 +1.0 x_0 +1.0 x_1 172 341 Constraints: 173 2.0*x 2  3.0*x1342 2.0*x1  3.0*x0 <= 2.0 174 343 Variables: 175 x2 is a real variable (min=0.0, max=+oo)176 344 x1 is a real variable (min=0.0, max=+oo) 345 x0 is a real variable (min=0.0, max=+oo) 177 346 """ 178 if format == "text": 179 value = ( "Maximization:\n" 180 if self.maximization 181 else "Minimization:\n" ) 182 value += " " + ( str(self.objective) 183 if self.objective != None 184 else "Undefined" ) 185 value += "\nConstraints:" 186 for c in self.constraints: 187 value += "\n " + str(c["function"]) 188 value += "\nVariables:" 189 for v in self.variables.keys(): 190 value += "\n " + str(v) + " is" 191 if self.is_integer(v): 192 value += " an integer variable" 193 elif self.is_binary(v): 194 value += " an boolean variable" 195 else: 196 value += " a real variable" 197 value += " (min=" + \ 198 ( str(self.get_min(v)) 199 if self.get_min(v) != None 200 else "oo" ) + \ 201 ", max=" + \ 202 ( str(self.get_max(v)) 203 if self.get_max(v) != None 204 else "+oo" ) + \ 205 ")" 206 return value 347 value = ( "Maximization:\n" 348 if self._maximization 349 else "Minimization:\n" ) 350 value+=" " 351 if self._objective_i==None: 352 value+="Undefined" 207 353 else: 208 raise ValueError("Only humanreadable format is currently defined.") 354 for (i,c) in zip(self._objective_i, self._objective_values): 355 value+=("+"+str(c) if c>0 else str(c))+" x_"+str(i)+" " 209 356 357 value += "\nConstraints:" 358 for (c,min,max) in self.constraints(): 359 value += "\n " + (str(min)+" <= " if min!=None else "")+str(c)+(" <= "+str(max) if max!=None else "") 360 value += "\nVariables:" 361 for v in self._variables.keys(): 362 value += "\n " + str(v) + " is" 363 if self.is_integer(v): 364 value += " an integer variable" 365 elif self.is_binary(v): 366 value += " an boolean variable" 367 else: 368 value += " a real variable" 369 value += " (min=" + \ 370 ( str(self.get_min(v)) 371 if self.get_min(v) != None 372 else "oo" ) + \ 373 ", max=" + \ 374 ( str(self.get_max(v)) 375 if self.get_max(v) != None 376 else "+oo" ) + \ 377 ")" 378 print value 379 380 def write_mps(self,filename,modern=True): 381 r""" 382 Write the linear program as a MPS file. 383 384 This function export the problem as a MPS file. 385 386 INPUT: 387 388  ``filename``  The file in which you want the problem 389 to be written. 390 391  ``modern``  Lets you choose between Fixed MPS and Free MPS 392 393  ``True``  Outputs the problem in Free MPS 394  ``False``  Outputs the problem in Fixed MPS 395 396 EXAMPLE:: 397 398 sage: p = MixedIntegerLinearProgram() 399 sage: x = p.new_variable() 400 sage: p.set_objective(x[1] + x[2]) 401 sage: p.add_constraint(3*x[1] + 2*x[2], max=2,name="OneConstraint") 402 sage: p.write_mps(SAGE_TMP+"/lp_problem.mps") # optional  requires GLPK 403 404 For information about the MPS file format : 405 http://en.wikipedia.org/wiki/MPS_%28format%29 406 """ 407 408 try: 409 from sage.numerical.mipGlpk import write_mps 410 except: 411 raise NotImplementedError("You need GLPK installed to use this function. To install it, you can type in Sage: install_package('glpk')") 412 413 self._update_variables_name() 414 write_mps(self, filename, modern) 415 416 417 def write_lp(self,filename): 418 r""" 419 Write the linear program as a LP file. 420 421 This function export the problem as a LP file. 422 423 INPUT: 424 425  ``filename``  The file in which you want the problem 426 to be written. 427 428 EXAMPLE:: 429 430 sage: p = MixedIntegerLinearProgram() 431 sage: x = p.new_variable() 432 sage: p.set_objective(x[1] + x[2]) 433 sage: p.add_constraint(3*x[1] + 2*x[2], max=2) 434 sage: p.write_lp(SAGE_TMP+"/lp_problem.lp") # optional  requires GLPK 435 436 For more information about the LP file format : 437 http://lpsolve.sourceforge.net/5.5/lpformat.htm 438 """ 439 try: 440 from sage.numerical.mipGlpk import write_lp 441 except: 442 raise NotImplementedError("You need GLPK installed to use this function. To install it, you can type in Sage: install_package('glpk')") 443 444 self._update_variables_name() 445 write_lp(self, filename) 446 447 210 448 def get_values(self, *lists): 211 449 r""" 212 450 Return values found by the previous call to ``solve()``. … … 260 498 if l.depth() == 1: 261 499 c = {} 262 500 for (k,v) in l.items(): 263 c[k] = self. values[v] if self.values.has_key(v) else None501 c[k] = self._values[v] if self._values.has_key(v) else None 264 502 val.append(c) 265 503 else: 266 504 c = {} … … 274 512 c = [] 275 513 [c.append(self.get_values(ll)) for ll in l] 276 514 val.append(c) 277 elif self. variables.has_key(l):278 val.append(self. values[l])515 elif self._variables.has_key(l): 516 val.append(self._values[l]) 279 517 if len(lists) == 1: 280 518 return val[0] 281 519 else: 282 520 return val 283 521 284 def show(self):285 r"""286 Prints the ``MixedIntegerLinearProgram`` in a humanreadable format.287 288 EXAMPLE::289 290 sage: p = MixedIntegerLinearProgram()291 sage: x = p.new_variable()292 sage: p.set_objective(x[1] + x[2])293 sage: p.add_constraint(3*x[1] + 2*x[2], max=2)294 sage: p.show()295 Maximization:296 x2 + x1297 Constraints:298 2.0*x2  3.0*x1299 Variables:300 x2 is a real variable (min=0.0, max=+oo)301 x1 is a real variable (min=0.0, max=+oo)302 """303 print self.export(format="text")304 305 522 def set_objective(self,obj): 306 523 r""" 307 524 Sets the objective of the ``MixedIntegerLinearProgram``. 308 525 309 526 INPUT: 310 527 311  ``obj``  A linear function to be optimized. 528  ``obj``  A linear function to be optimized. 529 ( can also be set to ``None`` or ``0`` when just 530 looking for a feasible solution ) 312 531 313 532 EXAMPLE: 314 533 … … 331 550 sage: p.add_constraint(x[1] + 0.2*x[2], max=4) 332 551 sage: p.add_constraint(1.5*x[1]+3*x[2], max=4) 333 552 sage: p.solve() # optional  requires Glpk or COINOR/CBC 334 6.6666666666666661 553 6.6666666666666661 554 sage: p.set_objective(None) 555 sage: p.solve() 556 0.0 335 557 """ 336 self.objective=obj337 558 338 def add_constraint(self, linear_function, max=None, min=None): 559 560 self._objective_i = [] 561 self._objective_values = [] 562 563 564 # If the objective is None, or a constant, we want to remember 565 # that the objective function has been defined ( the user did not 566 # forget it ). In some LP problems, you just want a feasible solution 567 # and do not care about any function being optimal. 568 try: 569 obj.constant_coefficient() 570 except: 571 return None 572 573 for (id, coeff) in [(id, coeff) for (id, coeff) in self._NormalForm(obj).items() if id != 1]: 574 self._objective_i.append(id) 575 self._objective_values.append(coeff) 576 577 def add_constraint(self, linear_function, max=None, min=None, name=None): 339 578 r""" 340 579 Adds a constraint to the ``MixedIntegerLinearProgram``. 341 580 … … 345 584  ``max``  An upper bound on the constraint (set to ``None`` 346 585 by default). 347 586  ``min``  A lower bound on the constraint. 587  ``name``  A name for the constraint. 348 588 349 589 EXAMPLE: 350 590 … … 368 608 sage: p.add_constraint(1.5*x[1] + 3*x[2], max=4) 369 609 sage: p.solve() # optional  requires Glpk or COINOR/CBC 370 610 6.6666666666666661 611 612 TESTS:: 613 614 sage: p=MixedIntegerLinearProgram() 615 sage: p.add_constraint(sum([]),min=2) 371 616 """ 372 max = float(max) if max != None else None 373 min = float(min) if min != None else None 374 self.constraints.append({ 375 "function": linear_function, 376 "min": min, 377 "max": max, 378 "card": len(linear_function.variables()) }) 617 618 619 # In case a null constraint is given ( see tests ) 620 try: 621 linear_function.constant_coefficient() 622 except: 623 return None 624 625 if linear_function==0: 626 return None 627 628 self._constraints_name.append(name) 629 630 # We do not want to ignore the constant coefficient 631 max = float(maxlinear_function.constant_coefficient()) if max != None else None 632 min = float(minlinear_function.constant_coefficient()) if min != None else None 633 634 linear_function=linear_function.constant_coefficient() 635 c=len(self._constraints_bounds_min) 636 637 self._constraints_bounds_max.append(max) 638 self._constraints_bounds_min.append(min) 639 640 641 for (id,value) in zip([self._variables[var] for var in linear_function.variables()], linear_function.coefficients()): 642 self._constraints_matrix_i.append(c) 643 self._constraints_matrix_j.append(id) 644 self._constraints_matrix_values.append(value) 379 645 380 646 def set_binary(self, e): 381 647 r""" … … 404 670 e.vtype = self.__BINARY 405 671 if e.depth() == 1: 406 672 for v in e.values(): 407 self. types[v] = self.__BINARY673 self._variables_type[self._variables[v]] = self.__BINARY 408 674 else: 409 675 for v in e.keys(): 410 676 self.set_binary(e[v]) 411 elif self. variables.has_key(e):412 self. types[e] = self.__BINARY677 elif self._variables.has_key(e): 678 self._variables_type[self._variables[e]] = self.__BINARY 413 679 else: 414 680 raise ValueError("e must be an instance of MIPVariable or one of its elements.") 415 681 … … 437 703 sage: p.is_binary(v[1]) 438 704 True 439 705 """ 440 # Returns an exception if the variable does not exist. 441 # For example if the user tries to find out the type of 442 # a MIPVariable or anything else. 443 self.variables[e] 444 if self.types.has_key(e) and self.types[e] == self.__BINARY: 706 707 if self._variables_type[self._variables[e]] == self.__BINARY: 445 708 return True 446 709 return False 447 710 … … 472 735 e.vtype = self.__INTEGER 473 736 if e.depth() == 1: 474 737 for v in e.values(): 475 self. types[v] = self.__INTEGER738 self._variables_type[self._variables[v]] = self.__INTEGER 476 739 else: 477 740 for v in e.keys(): 478 741 self.set_integer(e[v]) 479 elif self. variables.has_key(e):480 self. types[e] = self.__INTEGER742 elif self._variables.has_key(e): 743 self._variables_type[self._variables[e]] = self.__INTEGER 481 744 else: 482 745 raise ValueError("e must be an instance of MIPVariable or one of its elements.") 483 746 … … 505 768 sage: p.is_integer(v[1]) 506 769 True 507 770 """ 508 # Returns an exception if the variable does not exist. 509 # For example if the user tries to find out the type of 510 # a MIPVariable or anything else. 511 self.variables[e] 512 if self.types.has_key(e) and self.types[e] == self.__INTEGER: 771 772 if self._variables_type[self._variables[e]] == self.__INTEGER: 513 773 return True 514 774 return False 515 775 … … 540 800 e.vtype = self.__REAL 541 801 if e.depth() == 1: 542 802 for v in e.values(): 543 self. types[v] = self.__REAL803 self._variables_type[self._variables[v]] = self.__REAL 544 804 else: 545 805 for v in e.keys(): 546 806 self.set_real(e[v]) 547 elif self. variables.has_key(e):548 self. types[e] = self.__REAL807 elif self._variables.has_key(e): 808 self._variables_type[self._variables[e]] = self.__REAL 549 809 else: 550 810 raise ValueError("e must be an instance of MIPVariable or one of its elements.") 551 811 … … 575 835 sage: p.is_real(v[1]) 576 836 True 577 837 """ 578 # Returns an exception if the variable does not exist. 579 # For example if the user tries to find out the type of 580 # a MIPVariable or anything else. 581 self.variables[e] 582 if (not self.types.has_key(e)) or self.types[e] == self.__REAL: 838 839 if self._variables_type[self._variables[e]] == self.__REAL: 583 840 return True 584 841 return False 585 842 … … 641 898 sage: p.solve() # optional  requires Glpk or COINOR/CBC 642 899 6.6666666666666661 643 900 sage: p.get_values(x) # optional random  requires Glpk or COINOR/CBC 644 { 1: 0.0, 2: 1.3333333333333333}901 {0: 0.0, 1: 1.3333333333333333} 645 902 646 903 sage: ### Computation of a maximum stable set in Petersen's graph 647 904 sage: g = graphs.PetersenGraph() … … 654 911 sage: p.solve(objective_only=True) # optional  requires Glpk or COINOR/CBC 655 912 4.0 656 913 """ 657 if self. objective== None:914 if self._objective_i == None: 658 915 raise ValueError("No objective function has been defined.") 659 916 660 917 if solver == None: 661 solver = self. default_solver918 solver = self._default_solver 662 919 663 920 if solver == None: 664 921 raise ValueError("There does not seem to be any solver installed. Please visit http://www.sagemath.org/doc/tutorial/tour_LP.html for more informations.") … … 670 927 return solveCoin(self, log=log, objective_only=objective_only) 671 928 elif solver == "GLPK": 672 929 try: 673 from sage.numerical.mipGlpk import solve Glpk930 from sage.numerical.mipGlpk import solve_glpk 674 931 except: 675 932 raise NotImplementedError("GLPK is not installed and cannot be used to solve this MixedIntegerLinearProgram. To install it, you can type in Sage: install_package('glpk')") 676 return solve Glpk(self, log=log, objective_only=objective_only)933 return solve_glpk(self, log=log, objective_only=objective_only) 677 934 elif solver == "CPLEX": 678 935 raise NotImplementedError("The support for CPLEX is not implemented yet.") 679 936 else: … … 698 955 sage: p = MixedIntegerLinearProgram() 699 956 sage: v = p.new_variable() 700 957 sage: p._NormalForm(v[0] + v[1]) 701 { 1: 1.0, 2: 1.0, 1: 0.0}958 {0: 1.0, 1: 1.0, 1: 0.0} 702 959 """ 703 d = dict( zip([self. variables[v] for v in exp.variables()],960 d = dict( zip([self._variables[v] for v in exp.variables()], 704 961 exp.coefficients()) ) 705 962 d[1] = exp.constant_coefficient() 706 963 return d … … 722 979 723 980 sage: p = MixedIntegerLinearProgram() 724 981 sage: v = p.new_variable() 725 sage: p.count982 sage: len(p._variables_type) 726 983 0 727 984 sage: p._add_element_to_ring(p.__REAL) 728 x 1729 sage: p.count985 x0 986 sage: len(p._variables_type) 730 987 1 731 988 """ 732 self.count += 1 733 v = self.x[self.count] 734 self.variables[v] = self.count 735 self.types[v] = vtype 736 self.min[v] = 0.0 989 990 v = self._x[len(self._variables_type)] 991 self._variables[v] = len(self._variables_type) 992 self._variables_type.append(vtype) 993 self._variables_bounds_min.append(0) 994 self._variables_bounds_max.append(None) 737 995 return v 738 996 739 997 def set_min(self, v, min): … … 758 1016 sage: p.get_min(v[1]) 759 1017 6.0 760 1018 """ 761 self. min[v] = min1019 self._variables_bounds_min[self._variables[v]] = min 762 1020 763 1021 def set_max(self, v, max): 764 1022 r""" … … 781 1039 sage: p.get_max(v[1]) 782 1040 6.0 783 1041 """ 784 self.max[v] = max 1042 1043 self._variables_bounds_max[self._variables[v]] = max 785 1044 786 1045 def get_min(self, v): 787 1046 r""" … … 807 1066 sage: p.get_min(v[1]) 808 1067 6.0 809 1068 """ 810 return float(self. min[v]) if self.min.has_key(v)else None1069 return float(self._variables_bounds_min[self._variables[v]]) if self._variables_bounds_min[self._variables[v]] != None else None 811 1070 812 1071 def get_max(self, v): 813 1072 r""" … … 832 1091 sage: p.get_max(v[1]) 833 1092 6.0 834 1093 """ 835 return float(self. max[v]) if self.max.has_key(v)else None1094 return float(self._variables_bounds_max[self._variables[v]]) if self._variables_bounds_max[self._variables[v]] != None else None 836 1095 837 1096 class MIPSolverException(Exception): 838 1097 r""" … … 847 1106 848 1107 EXAMPLE:: 849 1108 1109 sage: from sage.numerical.mip import MIPSolverException 850 1110 sage: MIPSolverException("Error") 851 1111 MIPSolverException() 1112 1113 TESTS:: 1114 1115 sage: # No continuous solution 1116 sage: # 1117 sage: p=MixedIntegerLinearProgram() 1118 sage: v=p.new_variable() 1119 sage: p.add_constraint(v[0],max=5.5) 1120 sage: p.add_constraint(v[0],min=7.6) 1121 sage: p.set_objective(v[0]) 1122 sage: # 1123 sage: # Tests of GLPK's Exceptions 1124 sage: # 1125 sage: p.solve(solver="GLPK") # optional  requires GLPK 1126 Traceback (most recent call last): 1127 ... 1128 MIPSolverException: 'GLPK : Solution is undefined' 1129 sage: # 1130 sage: # 1131 sage: # No integer solution 1132 sage: # 1133 sage: p=MixedIntegerLinearProgram() 1134 sage: v=p.new_variable() 1135 sage: p.add_constraint(v[0],max=5.6) 1136 sage: p.add_constraint(v[0],min=5.2) 1137 sage: p.set_objective(v[0]) 1138 sage: p.set_integer(v) 1139 sage: # 1140 sage: # Tests of GLPK's Exceptions 1141 sage: # 1142 sage: p.solve(solver="GLPK") # optional  requires GLPK 1143 Traceback (most recent call last): 1144 ... 1145 MIPSolverException: 'GLPK : Solution is undefined' 1146 1147 852 1148 """ 853 1149 self.value = value 854 1150 … … 858 1154 859 1155 EXAMPLE:: 860 1156 1157 sage: from sage.numerical.mip import MIPSolverException 861 1158 sage: e = MIPSolverException("Error") 862 1159 sage: print e 863 1160 'Error' … … 870 1167 ``MixedIntegerLinearProgram``. 871 1168 """ 872 1169 873 def __init__(self, p, vtype, dim=1 ):1170 def __init__(self, p, vtype, dim=1, name=None): 874 1171 r""" 875 1172 Constructor for ``MIPVariable``. 876 1173 … … 881 1178  ``vtype`` (integer)  Defines the type of the variables 882 1179 (default is ``REAL``). 883 1180  ``dim``  the integer defining the definition of the variable. 1181  ``name``  A name for the ``MIPVariable``. 884 1182 885 1183 For more informations, see the method 886 1184 ``MixedIntegerLinearProgram.new_variable``. … … 890 1188 sage: p=MixedIntegerLinearProgram() 891 1189 sage: v=p.new_variable() 892 1190 """ 893 self.dim = dim 894 self.dict = {} 895 self.p = p 896 self.vtype = vtype 1191 self._dim = dim 1192 self._dict = {} 1193 self._p = p 1194 self._vtype = vtype 1195 self._name=name 1196 897 1197 898 1198 def __getitem__(self, i): 899 1199 r""" … … 908 1208 sage: v = p.new_variable() 909 1209 sage: p.set_objective(v[0] + v[1]) 910 1210 sage: v[0] 911 x 11211 x0 912 1212 """ 913 if self. dict.has_key(i):914 return self. dict[i]915 elif self. dim == 1:916 self. dict[i] = self.p._add_element_to_ring(self.vtype)917 return self. dict[i]1213 if self._dict.has_key(i): 1214 return self._dict[i] 1215 elif self._dim == 1: 1216 self._dict[i] = self._p._add_element_to_ring(self._vtype) 1217 return self._dict[i] 918 1218 else: 919 self.dict[i] = MIPVariable(self.p, self.vtype, dim=self.dim1) 920 return self.dict[i] 1219 self._dict[i] = MIPVariable(self._p, self._vtype, dim=self._dim1) 1220 return self._dict[i] 1221 1222 def _update_variables_name(self, prefix=None): 1223 r""" 1224 Updates the names of the variables in the parent instant of ``MixedIntegerLinearProgram``. 1225 1226 Only called before writing the Problem to a MPS or LP file. 1227 1228 EXAMPLE:: 1229 1230 sage: p=MixedIntegerLinearProgram() 1231 sage: v=p.new_variable(name="Test") 1232 sage: v[5]+v[99] 1233 x1 + x0 1234 sage: p._variables_name=['']*2 1235 sage: v._update_variables_name() 1236 """ 1237 1238 if prefix==None: 1239 prefix=self._name 1240 1241 if self._dim==1: 1242 for (k,v) in self._dict.iteritems(): 1243 self._p._variables_name[int(str(v)[1:])]=prefix+"["+str(k)+"]" 1244 else: 1245 for v in self._dict.itervalues(): 1246 v._update_variables_name(prefix=prefix+"["+str(k)+"]") 1247 1248 1249 1250 def __repr__(self): 1251 r""" 1252 Returns a representation of self. 1253 1254 EXAMPLE:: 1255 1256 sage: p=MixedIntegerLinearProgram() 1257 sage: v=p.new_variable(dim=3) 1258 sage: v 1259 MIPVariable of dimension 3. 1260 sage: v[2][5][9] 1261 x0 1262 sage: v 1263 MIPVariable of dimension 3. 1264 """ 1265 return "MIPVariable of dimension "+str(self._dim)+"." 921 1266 922 1267 def keys(self): 923 1268 r""" … … 931 1276 sage: v.keys() 932 1277 [0, 1] 933 1278 """ 934 return self. dict.keys()1279 return self._dict.keys() 935 1280 936 1281 def items(self): 937 1282 r""" … … 943 1288 sage: v = p.new_variable() 944 1289 sage: p.set_objective(v[0] + v[1]) 945 1290 sage: v.items() 946 [(0, x 1), (1, x2)]1291 [(0, x0), (1, x1)] 947 1292 """ 948 return self. dict.items()1293 return self._dict.items() 949 1294 950 1295 def depth(self): 951 1296 r""" … … 959 1304 sage: v.depth() 960 1305 1 961 1306 """ 962 return self. dim1307 return self._dim 963 1308 964 1309 def values(self): 965 1310 r""" … … 971 1316 sage: v = p.new_variable() 972 1317 sage: p.set_objective(v[0] + v[1]) 973 1318 sage: v.values() 974 [x 1, x2]1319 [x0, x1] 975 1320 """ 976 return self. dict.values()1321 return self._dict.values()