Ticket #7012: trac_7012-flattened.patch
File trac_7012-flattened.patch, 59.3 KB (added by , 11 years ago) |
---|
-
doc/en/reference/numerical.rst
# HG changeset patch # User Nathann Cohen <nathann.cohen@gmail.com> # Date 1254129856 25200 # Node ID 98c624cabaf9c396055c57688d658de97661b850 # Parent e334f15125a3faecdecfefc6079a7ba4536955e8 trac 7012: Numerical.mip Class : functions renamed, typos, several docstring fixes, bugfixes; reviewer patch Minh Van Nguyen <nguyenminh2@gmail.com> diff -r e334f15125a3 -r 98c624cabaf9 doc/en/reference/numerical.rst
a b 5 5 :maxdepth: 2 6 6 7 7 sage/numerical/knapsack 8 sage/numerical/mip 8 9 sage/numerical/optimize -
sage/numerical/knapsack.py
diff -r e334f15125a3 -r 98c624cabaf9 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 M IP645 p = M IP(sense=1)646 present = p.new var()647 p.set obj(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)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.set binary(present)651 p.set_binary(present) 652 652 else: 653 p.set integer(present)653 p.set_integer(present) 654 654 655 655 if value_only: 656 656 return p.solve(objective_only=True) -
sage/numerical/mip.pyx
diff -r e334f15125a3 -r 98c624cabaf9 sage/numerical/mip.pyx
a b 1 include '../ext/stdsage.pxi' 1 r""" 2 Mixed integer linear programming 3 """ 2 4 3 class MIP: 5 include "../ext/stdsage.pxi" 6 7 class MixedIntegerLinearProgram: 4 8 r""" 5 The MIP class is the link between SAGE and LP ( Linear Program ) and 6 MIP ( Mixed Integer Program ) Solvers. Cf : http://en.wikipedia.org/wiki/Linear_programming 9 The ``MixedIntegerLinearProgram`` class is the link between Sage, linear 10 programming (LP) and mixed integer programming (MIP) solvers. See the 11 Wikipedia article on 12 `linear programming <http://en.wikipedia.org/wiki/Linear_programming>`_ 13 for further information. A mixed integer program consists of variables, 14 linear constraints on these variables, and an objective function which is 15 to be maximised or minimised under these constraints. An instance of 16 ``MixedIntegerLinearProgram`` also requires the information on the 17 direction of the optimization. 7 18 8 It consists of variables, linear constraints on these variables, and an objective 9 function which is to be maximised or minimised under these constraints. 10 11 An instance of ``MIP`` also requires the information 12 on the direction of the optimization : 13 14 A ``MIP`` ( or ``LP`` ) is defined as a maximization 15 if ``sense=1``, and is a minimization if ``sense=-1`` 19 A ``MixedIntegerLinearProgram`` (or ``LP``) is defined as a maximization 20 if ``maximization=True`` and is a minimization if ``maximization=False``. 16 21 17 22 INPUT: 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 22 23 24 - ``maximization`` 25 26 - When set to ``True`` (default), the ``MixedIntegerLinearProgram`` is 27 defined as a maximization. 28 - When set to ``False``, the ``MixedIntegerLinearProgram`` is defined as 29 a minimization. 30 23 31 EXAMPLES:: 24 32 25 sage: ### Computation of a maximum stable set in Petersen's graph ###26 sage: g =graphs.PetersenGraph()27 sage: p =MIP(sense=1)28 sage: b =p.newvar()29 sage: p.set obj(sum([b[v] for v in g]))33 sage: ### Computation of a maximum stable set in Petersen's graph 34 sage: g = graphs.PetersenGraph() 35 sage: p = MixedIntegerLinearProgram(maximization=True) 36 sage: b = p.new_variable() 37 sage: p.set_objective(sum([b[v] for v in g])) 30 38 sage: for (u,v) in g.edges(labels=None): 31 ... p.add constraint(b[u]+b[v],max=1)32 sage: p.set binary(b)39 ... p.add_constraint(b[u] + b[v], max=1) 40 sage: p.set_binary(b) 33 41 sage: p.solve(objective_only=True) # optional - requires Glpk or COIN-OR/CBC 34 42 4.0 35 """ 43 """ 36 44 37 def __init__(self, sense=1):45 def __init__(self, maximization=True): 38 46 r""" 39 Constructor for the MIP class47 Constructor for the ``MixedIntegerLinearProgram`` class. 40 48 41 49 INPUT: 42 43 - ``sense'' :44 When set to 1, the MIP is defined as a Maximization45 When set to -1, the MIP is defined as a Minimization46 50 47 EXAMPLE:51 - ``maximization`` 48 52 49 sage: p=MIP(sense=1) 53 - When set to ``True`` (default), the ``MixedIntegerLinearProgram`` 54 is defined as a maximization. 55 - When set to ``False``, the ``MixedIntegerLinearProgram`` is 56 defined as a minimization. 57 58 EXAMPLE:: 59 60 sage: p = MixedIntegerLinearProgram(maximization=True) 50 61 """ 51 52 62 try: 53 54 self.default_solver="Coin"63 from sage.numerical.mipCoin import solveCoin 64 self.default_solver = "Coin" 55 65 except: 56 try: 57 from sage.numerical.mipGlpk import solveGlpk 58 self.default_solver="GLPK" 59 except: 60 self.default_solver=None 61 66 try: 67 from sage.numerical.mipGlpk import solveGlpk 68 self.default_solver = "GLPK" 69 except: 70 self.default_solver = None 62 71 63 72 from sage.rings.polynomial.infinite_polynomial_ring import InfinitePolynomialRing 64 73 from sage.rings.real_double import RealDoubleField as RR 65 P = InfinitePolynomialRing(RR(), names=('x',)) ;74 P = InfinitePolynomialRing(RR(), names=('x',)) 66 75 (self.x,) = P._first_ngens(1) 67 76 68 self.count=[0] 69 self.sense=sense 70 self.objective=None 71 self.variables={} 72 self.constraints=[] 73 self.min={} 74 self.max={} 75 self.types={} 76 self.values={} 77 self.__BINARY=1 78 self.__REAL=-1 79 self.__INTEGER=0 77 # number of variables 78 self.count = 0 79 self.maximization = maximization 80 self.objective = None 81 82 self.variables = {} 83 self.constraints = [] 84 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 93 # solve(objective_only=False) is called 94 self.values = {} 95 96 # Several constants 97 self.__BINARY = 1 98 self.__REAL = -1 99 self.__INTEGER = 0 80 100 81 101 def __repr__(self): 82 102 r""" 83 Returns a short description of the MIP84 85 EXAMPLE: 86 87 sage: p=MIP()88 sage: v=p.newvar()89 sage: p.addconstraint(v[1]+v[2],max=2)90 sage: print p91 Mixed Integer Program ( maximization, 2 variables, 1 constraints )103 Returns a short description of the ``MixedIntegerLinearProgram``. 104 105 EXAMPLE:: 106 107 sage: p = MixedIntegerLinearProgram() 108 sage: v = p.new_variable() 109 sage: p.add_constraint(v[1] + v[2], max=2) 110 sage: print p 111 Mixed Integer Program ( maximization, 2 variables, 1 constraints ) 92 112 """ 93 return "Mixed Integer Program ( "+("maximization" if self.sense==1 else "minimization")+", "+str(len(self.variables))+" variables, "+str(len(self.constraints))+" constraints )" 113 return "Mixed Integer Program ( " + \ 114 ( "maximization" if self.maximization else "minimization" ) + \ 115 ", " + str(len(self.variables)) + " variables, " + \ 116 str(len(self.constraints)) + " constraints )" 94 117 95 def new var(self,dim=1):118 def new_variable(self, vtype=-1, dim=1): 96 119 r""" 97 120 Returns an instance of ``MIPVariable`` associated 98 to the current instance of ``MIP``. 99 100 A new ``MIP`` variable ``x`` defined by ::: 121 to the current instance of ``MixedIntegerLinearProgram``. 101 122 102 sage: p=MIP() 103 sage: x=p.newvar() 123 A new variable ``x`` is defined by:: 104 124 105 It behaves exactly as an usual dictionary would. It can use any key 106 argument you may like, as ``x[5]`` or ``x["b"]``, and has methods 107 ``items()`` and ``keys()`` 108 125 sage: p = MixedIntegerLinearProgram() 126 sage: x = p.new_variable() 127 128 It behaves exactly as a usual dictionary would. It can use any key 129 argument you may like, as ``x[5]`` or ``x["b"]``, and has methods 130 ``items()`` and ``keys()``. 131 109 132 Any of its fields exists, and is uniquely defined. 110 133 111 134 INPUT: 112 135 113 - ``dim`` ( integer ) : Defines the dimension of the dictionary 114 If ``x`` has dimension `2`, its fields will 115 be of the form ``x[key1][key2]`` 136 - ``dim`` (integer) -- Defines the dimension of the dictionary. 137 If ``x`` has dimension `2`, its fields will be of the form 138 ``x[key1][key2]``. 139 - ``vtype`` (integer) -- Defines the type of the variables 140 (default is ``REAL``). 116 141 117 142 EXAMPLE:: 118 143 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) 144 sage: p = MixedIntegerLinearProgram() 145 sage: # available types are p.__REAL, p.__INTEGER and p.__BINARY 146 sage: x = p.new_variable(vtype=p.__REAL) 147 sage: y = p.new_variable(dim=2) 148 sage: p.add_constraint(x[2] + y[3][5], max=2) 123 149 """ 124 return MIPVariable(self.x,self._addElementToRing,dim=dim) 125 150 return MIPVariable(self, vtype, dim=dim) 126 151 127 def export(self,format="text"): 128 r""" 129 Exports the MIP to a string in different formats. 130 131 INPUT: 132 133 - ``format'' : 134 "text" : human-readable format 135 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) 140 sage: print p.export(format="text") 141 Maximization : 142 x2 + x1 143 Constraints : 144 2.0*x2 - 3.0*x1 145 Variables : 146 x2 is a real variable (min=0.0,max=+oo) 147 x1 is a real variable (min=0.0,max=+oo) 148 """ 149 if format=="text": 150 value=("Maximization :\n" if self.sense==1 else "Minimization :\n") 151 value=value+" "+(str(self.objective) if self.objective!=None else "Undefined") 152 value=value+"\nConstraints :" 153 for c in self.constraints: 154 value=value+"\n "+str(c["function"]) 155 value=value+"\nVariables :" 156 for v in self.variables.keys(): 157 value=value+"\n "+str(v)+" is" 158 if self.isinteger(v): 159 value=value+" an integer variable" 160 elif self.isbinary(v): 161 value=value+" an boolean variable" 162 else: 163 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")+")" 165 return value 166 167 def get_values(self,*lists): 152 def export(self, format="text"): 168 153 r""" 169 Return values found by the previous call to ``solve()`` 154 Exports the ``MixedIntegerLinearProgram`` to a string in 155 different formats. 170 156 171 157 INPUT: 172 173 - Any instance of ``MIPVariable`` ( or one of its elements ), 158 159 - ``format`` 160 161 - ``"text"`` -- (default) human-readable format 162 163 EXAMPLES:: 164 165 sage: p = MixedIntegerLinearProgram() 166 sage: x = p.new_variable() 167 sage: p.set_objective(x[1] + x[2]) 168 sage: p.add_constraint(-3*x[1] + 2*x[2], max=2) 169 sage: print p.export(format="text") 170 Maximization: 171 x2 + x1 172 Constraints: 173 2.0*x2 - 3.0*x1 174 Variables: 175 x2 is a real variable (min=0.0, max=+oo) 176 x1 is a real variable (min=0.0, max=+oo) 177 """ 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 207 else: 208 raise ValueError("Only human-readable format is currently defined.") 209 210 def get_values(self, *lists): 211 r""" 212 Return values found by the previous call to ``solve()``. 213 214 INPUT: 215 216 - Any instance of ``MIPVariable`` (or one of its elements), 174 217 or lists of them. 175 218 176 219 OUTPUT: 177 220 178 221 - Each instance of ``MIPVariable`` is replaced by a dictionary 179 containing the numerical values found for each180 corresponding variable in the instance222 containing the numerical values found for each 223 corresponding variable in the instance. 181 224 - Each element of an instance of a ``MIPVariable`` is replaced 182 225 by its corresponding numerical value. 183 226 184 227 EXAMPLE:: 185 228 186 sage: p =MIP()187 sage: x =p.newvar()188 sage: y =p.newvar(dim=2)189 sage: p.set obj(x[3]+y[2][9]+x[5])190 sage: p.add constraint(x[3]+y[2][9]+2*x[5],max=2)229 sage: p = MixedIntegerLinearProgram() 230 sage: x = p.new_variable() 231 sage: y = p.new_variable(dim=2) 232 sage: p.set_objective(x[3] + y[2][9] + x[5]) 233 sage: p.add_constraint(x[3] + y[2][9] + 2*x[5], max=2) 191 234 sage: p.solve() # optional - requires Glpk or COIN-OR/CBC 192 235 2.0 193 236 sage: # 194 237 sage: # Returns the optimal value of x[3] 195 238 sage: p.get_values(x[3]) # optional - requires Glpk or COIN-OR/CBC 196 0.0239 2.0 197 240 sage: # 198 241 sage: # Returns a dictionary identical to x 199 242 sage: # containing values for the corresponding 200 243 sage: # variables 201 sage: x_sol =p.get_values(x)244 sage: x_sol = p.get_values(x) 202 245 sage: x_sol.keys() 203 246 [3, 5] 204 247 sage: # 205 248 sage: # Obviously, it also works with 206 249 sage: # variables of higher dimension 207 sage: y_sol =p.get_values(y)208 sage: # 250 sage: y_sol = p.get_values(y) 251 sage: # 209 252 sage: # We could also have tried : 210 sage: [x_sol, y_sol]=p.get_values(x,y)253 sage: [x_sol, y_sol] = p.get_values(x, y) 211 254 sage: # Or 212 sage: [x_sol, y_sol]=p.get_values([x,y])255 sage: [x_sol, y_sol] = p.get_values([x, y]) 213 256 """ 214 215 val=[] 257 val = [] 216 258 for l in lists: 217 if isinstance(l, MIPVariable):218 if l.depth() ==1:219 c ={}259 if isinstance(l, MIPVariable): 260 if l.depth() == 1: 261 c = {} 220 262 for (k,v) in l.items(): 221 c[k] =self.values[v] if self.values.has_key(v) else None263 c[k] = self.values[v] if self.values.has_key(v) else None 222 264 val.append(c) 223 265 else: 224 c ={}266 c = {} 225 267 for (k,v) in l.items(): 226 c[k] =self.get_values(v)227 val.append(c) 228 elif isinstance(l, list):229 if len(l) ==1:268 c[k] = self.get_values(v) 269 val.append(c) 270 elif isinstance(l, list): 271 if len(l) == 1: 230 272 val.append([self.get_values(l[0])]) 231 273 else: 232 c =[]274 c = [] 233 275 [c.append(self.get_values(ll)) for ll in l] 234 276 val.append(c) 235 277 elif self.variables.has_key(l): 236 278 val.append(self.values[l]) 237 if len(lists) ==1:279 if len(lists) == 1: 238 280 return val[0] 239 281 else: 240 282 return val 241 242 243 283 244 284 def show(self): 245 285 r""" 246 Prints the MIP in a human-readable way 286 Prints the ``MixedIntegerLinearProgram`` in a human-readable 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 + x1 297 Constraints: 298 2.0*x2 - 3.0*x1 299 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 def set_objective(self,obj): 306 r""" 307 Sets the objective of the ``MixedIntegerLinearProgram``. 308 309 INPUT: 310 311 - ``obj`` -- A linear function to be optimized. 247 312 248 313 EXAMPLE: 249 314 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) 254 sage: p.show() 255 Maximization : 256 x2 + x1 257 Constraints : 258 2.0*x2 - 3.0*x1 259 Variables : 260 x2 is a real variable (min=0.0,max=+oo) 261 x1 is a real variable (min=0.0,max=+oo) 262 """ 263 print self.export(format="text") 264 265 #Ok 266 def setobj(self,obj): 267 r""" 268 Sets the objective of the ``MIP``. 315 Let's solve the following linear program:: 269 316 270 INPUT: 271 272 - ``obj`` : A linear function to be optimized 317 Maximize: 318 x + 5 * y 319 Constraints: 320 x + 0.2 y <= 4 321 1.5 * x + 3 * y <= 4 322 Variables: 323 x is Real (min = 0, max = None) 324 y is Real (min = 0, max = None) 273 325 274 EXAMPLE:: 275 276 This code solves the following Linear Program : 277 278 Maximize: 279 x + 5 * y 280 Constraints: 281 x + 0.2 y <= 4 282 1.5 * x + 3 * y <=4 283 Variables: 284 x is Real ( min = 0, max = None ) 285 y is Real ( min = 0, max = None ) 326 This linear program can be solved as follows:: 286 327 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) 292 sage: p.solve() # optional - requires Glpk or COIN-OR/CBC 293 6.6666666666666661 294 328 sage: p = MixedIntegerLinearProgram(maximization=True) 329 sage: x = p.new_variable() 330 sage: p.set_objective(x[1] + 5*x[2]) 331 sage: p.add_constraint(x[1] + 0.2*x[2], max=4) 332 sage: p.add_constraint(1.5*x[1]+3*x[2], max=4) 333 sage: p.solve() # optional - requires Glpk or COIN-OR/CBC 334 6.6666666666666661 295 335 """ 296 336 self.objective=obj 297 337 298 def add constraint(self,linear_function,max=None,min=None):338 def add_constraint(self, linear_function, max=None, min=None): 299 339 r""" 300 Adds a constraint to the MIP 301 302 INPUT : 303 304 - ``consraint`` : : A linear function 305 - ``max`` : An upper bound on the constraint ( set to ``None`` by default ) 306 - ``min`` : A lower bound on the constraint 307 308 EXAMPLE:: 309 310 This code solves the following Linear Program : 311 312 Maximize: 313 x + 5 * y 314 Constraints: 315 x + 0.2 y <= 4 316 1.5 * x + 3 * y <=4 317 Variables: 318 x is Real ( min = 0, max = None ) 319 y is Real ( min = 0, max = None ) 320 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) 326 sage: p.solve() # optional - requires Glpk or COIN-OR/CBC 327 6.6666666666666661 328 """ 329 330 max=float(max) if max!=None else None 331 min=float(min) if min!=None else None 332 self.constraints.append({"function":linear_function,"min":min, "max":max,"card":len(linear_function.variables())}) 333 334 def setbinary(self,e): 335 r""" 336 Sets a variable or a ``MIPVariable`` as binary 340 Adds a constraint to the ``MixedIntegerLinearProgram``. 337 341 338 342 INPUT: 339 343 340 - ``e`` : An instance of ``MIPVariable`` or one of 341 its elements 342 343 NOTE: 344 345 We recommend you to define the types of your variables after 346 your problem has been completely defined ( see example ) 344 - ``consraint`` -- A linear function. 345 - ``max`` -- An upper bound on the constraint (set to ``None`` 346 by default). 347 - ``min`` -- A lower bound on the constraint. 347 348 348 349 EXAMPLE: 349 350 350 sage: p=MIP()351 sage: x=p.newvar() 352 sage: #353 sage: # The following instruction does absolutely nothing354 sage: # as none of the variables of x have been used yet355 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 binary365 sage: # as no setbinary(x) has been called366 sage: # after its first definition367 sage: #368 sage: # Now it is done369 sage: p.setbinary(x[3])351 Consider the following linear program:: 352 353 Maximize: 354 x + 5 * y 355 Constraints: 356 x + 0.2 y <= 4 357 1.5 * x + 3 * y <= 4 358 Variables: 359 x is Real (min = 0, max = None) 360 y is Real (min = 0, max = None) 361 362 This linear program can be solved as follows:: 363 364 sage: p = MixedIntegerLinearProgram(maximization=True) 365 sage: x = p.new_variable() 366 sage: p.set_objective(x[1] + 5*x[2]) 367 sage: p.add_constraint(x[1] + 0.2*x[2], max=4) 368 sage: p.add_constraint(1.5*x[1] + 3*x[2], max=4) 369 sage: p.solve() # optional - requires Glpk or COIN-OR/CBC 370 6.6666666666666661 370 371 """ 371 if isinstance(e,MIPVariable): 372 if e.depth()==1: 373 for v in e.values(): 374 self.types[v]=self.__BINARY 375 else: 376 for v in e.keys(): 377 self.setbinary(e[v]) 378 elif self.variables.has_key(e): 379 self.types[e]=self.__BINARY 380 else: 381 raise Exception("Wrong kind of variable..") 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()) }) 382 379 383 def isbinary(self,e):380 def set_binary(self, e): 384 381 r""" 385 Tests whether the variable is binary. 386 387 ( Variables are real by default ) 382 Sets a variable or a ``MIPVariable`` as binary. 388 383 389 384 INPUT: 390 385 391 - ``e`` : a variable ( not a ``MIPVariable``, but one of its elements ! ) 386 - ``e`` -- An instance of ``MIPVariable`` or one of 387 its elements. 388 389 EXAMPLE:: 390 391 sage: p = MixedIntegerLinearProgram() 392 sage: x = p.new_variable() 393 sage: # With the following instruction, all the variables 394 sage: # from x will be binary. 395 sage: p.set_binary(x) 396 sage: p.set_objective(x[0] + x[1]) 397 sage: p.add_constraint(-3*x[0] + 2*x[1], max=2) 398 sage: # 399 sage: # It is still possible, though, to set one of these 400 sage: # variables as real while keeping the others as they are. 401 sage: p.set_real(x[3]) 402 """ 403 if isinstance(e, MIPVariable): 404 e.vtype = self.__BINARY 405 if e.depth() == 1: 406 for v in e.values(): 407 self.types[v] = self.__BINARY 408 else: 409 for v in e.keys(): 410 self.set_binary(e[v]) 411 elif self.variables.has_key(e): 412 self.types[e] = self.__BINARY 413 else: 414 raise ValueError("e must be an instance of MIPVariable or one of its elements.") 415 416 def is_binary(self, e): 417 r""" 418 Tests whether the variable ``e`` is binary. Variables are real by 419 default. 420 421 INPUT: 422 423 - ``e`` -- A variable (not a ``MIPVariable``, but one of its elements.) 392 424 393 425 OUTPUT: 394 426 395 ``True`` if the variable is binary, ``False`` otherwise427 ``True`` if the variable ``e`` is binary; ``False`` otherwise. 396 428 397 EXAMPLE: 429 EXAMPLE:: 398 430 399 sage: p =MIP()400 sage: v =p.newvar()401 sage: p.set obj(v[1])402 sage: p.is binary(v[1])431 sage: p = MixedIntegerLinearProgram() 432 sage: v = p.new_variable() 433 sage: p.set_objective(v[1]) 434 sage: p.is_binary(v[1]) 403 435 False 404 sage: p.set binary(v[1])405 sage: p.is binary(v[1])436 sage: p.set_binary(v[1]) 437 sage: p.is_binary(v[1]) 406 438 True 407 439 """ 408 # Returns an exception if the variable does not exist. .409 # For ex emple if the userstries to find out the type of410 # a MIPVariable or anything else 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. 411 443 self.variables[e] 412 413 if self.types.has_key(e) and self.types[e]==self.__BINARY: 444 if self.types.has_key(e) and self.types[e] == self.__BINARY: 414 445 return True 415 446 return False 416 447 417 def set integer(self,e):448 def set_integer(self, e): 418 449 r""" 419 Sets a variable or a ``MIPVariable`` as integer 450 Sets a variable or a ``MIPVariable`` as integer. 420 451 421 452 INPUT: 422 453 423 - ``e`` :An instance of ``MIPVariable`` or one of424 its elements454 - ``e`` -- An instance of ``MIPVariable`` or one of 455 its elements. 425 456 426 NOTE:457 EXAMPLE:: 427 458 428 We recommend you to define the types of your variables after 429 your problem has been completely defined ( see example ) 430 431 EXAMPLE: 432 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]) 459 sage: p = MixedIntegerLinearProgram() 460 sage: x = p.new_variable() 461 sage: # With the following instruction, all the variables 462 sage: # from x will be integers 463 sage: p.set_integer(x) 464 sage: p.set_objective(x[0] + x[1]) 465 sage: p.add_constraint(-3*x[0] + 2*x[1], max=2) 466 sage: # 467 sage: # It is still possible, though, to set one of these 468 sage: # variables as real while keeping the others as they are. 469 sage: p.set_real(x[3]) 453 470 """ 454 if isinstance(e,MIPVariable): 455 if e.depth()==1: 471 if isinstance(e, MIPVariable): 472 e.vtype = self.__INTEGER 473 if e.depth() == 1: 456 474 for v in e.values(): 457 self.types[v] =self.__INTEGER475 self.types[v] = self.__INTEGER 458 476 else: 459 477 for v in e.keys(): 460 self.set binary(e[v])461 elif self.variables.has_key(e): 462 self.types[e] =self.__INTEGER478 self.set_integer(e[v]) 479 elif self.variables.has_key(e): 480 self.types[e] = self.__INTEGER 463 481 else: 464 raise Exception("Wrong kind of variable..")482 raise ValueError("e must be an instance of MIPVariable or one of its elements.") 465 483 466 def is integer(self,e):484 def is_integer(self, e): 467 485 r""" 468 Tests whether the variable is integer. 469 470 ( Variables are real by default ) 486 Tests whether the variable is an integer. Variables are real by 487 default. 471 488 472 489 INPUT: 473 490 474 - ``e`` : a variable ( not a ``MIPVariable``, but one of its elements !)491 - ``e`` -- A variable (not a ``MIPVariable``, but one of its elements.) 475 492 476 493 OUTPUT: 477 494 478 ``True`` if the variable is integer, ``False`` otherwise495 ``True`` if the variable ``e`` is an integer; ``False`` otherwise. 479 496 480 EXAMPLE: 497 EXAMPLE:: 481 498 482 sage: p =MIP()483 sage: v =p.newvar()484 sage: p.set obj(v[1])485 sage: p.is integer(v[1])499 sage: p = MixedIntegerLinearProgram() 500 sage: v = p.new_variable() 501 sage: p.set_objective(v[1]) 502 sage: p.is_integer(v[1]) 486 503 False 487 sage: p.set integer(v[1])488 sage: p.is integer(v[1])504 sage: p.set_integer(v[1]) 505 sage: p.is_integer(v[1]) 489 506 True 490 507 """ 491 # Returns an exception if the variable does not exist. .492 # For ex emple if the userstries to find out the type of493 # a MIPVariable or anything else 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. 494 511 self.variables[e] 495 496 if self.types.has_key(e) and self.types[e]==self.__INTEGER: 512 if self.types.has_key(e) and self.types[e] == self.__INTEGER: 497 513 return True 498 514 return False 499 515 500 def set real(self,e):516 def set_real(self,e): 501 517 r""" 502 Sets a variable or a ``MIPVariable`` as real 518 Sets a variable or a ``MIPVariable`` as real. 503 519 504 520 INPUT: 505 521 506 - ``e`` :An instance of ``MIPVariable`` or one of507 its elements522 - ``e`` -- An instance of ``MIPVariable`` or one of 523 its elements. 508 524 509 NOTE:525 EXAMPLE:: 510 526 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() 518 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]) 527 sage: p = MixedIntegerLinearProgram() 528 sage: x = p.new_variable() 529 sage: # With the following instruction, all the variables 530 sage: # from x will be real (they are by default, though). 531 sage: p.set_real(x) 532 sage: p.set_objective(x[0] + x[1]) 533 sage: p.add_constraint(-3*x[0] + 2*x[1], max=2) 534 sage: # 535 sage: # It is still possible, though, to set one of these 536 sage: # variables as binary while keeping the others as they are. 537 sage: p.set_binary(x[3]) 538 538 """ 539 if isinstance(e,MIPVariable): 540 if e.depth()==1: 539 if isinstance(e, MIPVariable): 540 e.vtype = self.__REAL 541 if e.depth() == 1: 541 542 for v in e.values(): 542 self.types[v] =self.__REAL543 self.types[v] = self.__REAL 543 544 else: 544 545 for v in e.keys(): 545 self.set binary(e[v])546 elif self.variables.has_key(e): 547 self.types[e] =self.__REAL546 self.set_real(e[v]) 547 elif self.variables.has_key(e): 548 self.types[e] = self.__REAL 548 549 else: 549 raise Exception("Wrong kind of variable..")550 raise ValueError("e must be an instance of MIPVariable or one of its elements.") 550 551 551 552 def isreal(self,e): 552 def is_real(self, e): 553 553 r""" 554 Tests whether the variable is real. 555 556 ( Variables are real by default ) 554 Tests whether the variable is real. Variables are real by default. 557 555 558 556 INPUT: 559 557 560 - ``e`` : a variable ( not a ``MIPVariable``, but one of its elements !)558 - ``e`` -- A variable (not a ``MIPVariable``, but one of its elements.) 561 559 562 560 OUTPUT: 563 561 564 ``True`` if the variable is real , ``False`` otherwise562 ``True`` if the variable is real; ``False`` otherwise. 565 563 566 EXAMPLE: 564 EXAMPLE:: 567 565 568 sage: p =MIP()569 sage: v =p.newvar()570 sage: p.set obj(v[1])571 sage: p.is real(v[1])566 sage: p = MixedIntegerLinearProgram() 567 sage: v = p.new_variable() 568 sage: p.set_objective(v[1]) 569 sage: p.is_real(v[1]) 572 570 True 573 sage: p.set binary(v[1])574 sage: p.is real(v[1])571 sage: p.set_binary(v[1]) 572 sage: p.is_real(v[1]) 575 573 False 576 sage: p.set real(v[1])577 sage: p.is real(v[1])574 sage: p.set_real(v[1]) 575 sage: p.is_real(v[1]) 578 576 True 579 577 """ 580 581 # Returns an exception if the variable does not exist.. 582 # For exemple if the users tries to find out the type of 583 # a MIPVariable or anything else 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. 584 581 self.variables[e] 585 586 if (not self.types.has_key(e)) or self.types[e]==self.__REAL: 582 if (not self.types.has_key(e)) or self.types[e] == self.__REAL: 587 583 return True 588 584 return False 589 585 590 591 def solve(self,solver=None,log=False,objective_only=False): 586 def solve(self, solver=None, log=False, objective_only=False): 592 587 r""" 593 Solves the MIP. 594 595 INPUT : 596 - ``solver'' : 597 3 solvers should be available through this class : 598 - GLPK ( ``solver="GLPK"`` ) 599 http://www.gnu.org/software/glpk/ 600 601 - COIN Branch and Cut ( ``solver="Coin"`` ) 602 COIN-OR http://www.coin-or.org/ 603 If the spkg is installed 604 605 - CPLEX ( ``solver="CPLEX"`` ) 606 http://www.ilog.com/products/cplex/ 607 Not Implemented Yet 608 609 ``solver`` should then be equal to one of ``"GLPK"``, 610 ``"Coin"``, ``"CPLEX"``, or ``None``. 611 If ``solver=None`` ( default ), the default solver is used 612 ( Coin if available, GLPK otherwise ) 613 614 - ``log`` : This boolean variable indicates whether progress should be printed 615 during the computations. 616 617 - ``objective_only`` : Boolean variable 618 * When set to ``True``, only the objective function is returned 619 * When set to ``False`` (default), the optimal 620 numerical values are stored ( takes computational 621 time ) 622 623 OUTPUT : 624 625 The optimal value taken by the objective function 626 627 EXAMPLE : 628 629 This code solves the following Linear Program : 630 631 Maximize: 632 x + 5 * y 633 Constraints: 634 x + 0.2 y <= 4 635 1.5 * x + 3 * y <=4 636 Variables: 637 x is Real ( min = 0, max = None ) 638 y is Real ( min = 0, max = None ) 639 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) 646 sage: p.solve() # optional - requires Glpk or COIN-OR/CBC 647 6.6666666666666661 648 sage: p.get_values(x) # optional - requires Glpk or COIN-OR/CBC 649 {1: 0.0, 2: 1.3333333333333333} 650 651 sage: ### Computation of a maximum stable set in Petersen's graph ### 652 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])) 656 sage: for (u,v) in g.edges(labels=None): 657 ... p.addconstraint(b[u]+b[v],max=1) 658 sage: p.setbinary(b) 659 sage: p.solve(objective_only=True) # optional - requires Glpk or COIN-OR/CBC 660 4.0 661 662 663 """ 664 665 if self.objective==None: 666 raise Exception("No objective function has been defined !") 667 668 if solver==None: 669 solver=self.default_solver 670 671 if solver==None: 672 raise Exception("There does not seem to be any solver installed...\n Please visit http://www.sagemath.org/doc/tutorial/tour_LP.html for more informations") 673 elif solver=="Coin": 674 try: 675 from sage.numerical.mipCoin import solveCoin 676 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')") 678 return solveCoin(self,log=log,objective_only=objective_only) 679 680 elif solver=="GLPK": 681 try: 682 from sage.numerical.mipGlpk import solveGlpk 683 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')") 685 return solveGlpk(self,log=log,objective_only=objective_only) 686 elif solver=="CPLEX": 687 raise NotImplementedError("The support for CPLEX is not written yet... We're seriously thinking about it, though ;-)") 688 else: 689 raise NotImplementedError("solver should be set to 'GLPK', 'Coin', 'CPLEX' or None (in which case the default one is used).") 690 691 692 def _NormalForm(self,exp): 693 r""" 694 Returns a dictionary built from the linear function 588 Solves the ``MixedIntegerLinearProgram``. 695 589 696 590 INPUT: 697 591 698 - ``exp`` : The expression representing a linear function 592 - ``solver`` -- 3 solvers should be available through this class: 593 594 - GLPK (``solver="GLPK"``). See the 595 `GLPK <http://www.gnu.org/software/glpk/>`_ web site. 596 597 - COIN Branch and Cut (``solver="Coin"``). See the 598 `COIN-OR <http://www.coin-or.org>`_ web site. 599 600 - CPLEX (``solver="CPLEX"``). See the 601 `CPLEX <http://www.ilog.com/products/cplex/>`_ web site. 602 An interface to CPLEX is not yet implemented. 603 604 ``solver`` should then be equal to one of ``"GLPK"``, ``"Coin"``, 605 ``"CPLEX"``, or ``None``. If ``solver=None`` (default), the default 606 solver is used (COIN if available, GLPK otherwise). 607 608 - ``log`` -- This boolean variable indicates whether progress should 609 be printed during the computations. 610 611 - ``objective_only`` -- Boolean variable. 612 613 - When set to ``True``, only the objective function is returned. 614 - When set to ``False`` (default), the optimal numerical values 615 are stored (takes computational time). 699 616 700 617 OUTPUT: 701 618 702 A dictionary whose keys are the id of the variables, and whose 703 values are their coefficients. 704 The value corresponding to key `-1` is the constant coefficient 619 The optimal value taken by the objective function. 705 620 706 EXAMPLE :621 EXAMPLES: 707 622 708 sage: p=MIP() 709 sage: v=p.newvar() 710 sage: p._NormalForm(v[0]+v[1]) 711 {1: 1.0, 2: 1.0, -1: 0.0} 623 Consider the following linear program:: 624 625 Maximize: 626 x + 5 * y 627 Constraints: 628 x + 0.2 y <= 4 629 1.5 * x + 3 * y <= 4 630 Variables: 631 x is Real (min = 0, max = None) 632 y is Real (min = 0, max = None) 633 634 This linear program can be solved as follows:: 635 636 sage: p = MixedIntegerLinearProgram(maximization=True) 637 sage: x = p.new_variable() 638 sage: p.set_objective(x[1] + 5*x[2]) 639 sage: p.add_constraint(x[1] + 0.2*x[2], max=4) 640 sage: p.add_constraint(1.5*x[1] + 3*x[2], max=4) 641 sage: p.solve() # optional - requires Glpk or COIN-OR/CBC 642 6.6666666666666661 643 sage: p.get_values(x) # optional - requires Glpk or COIN-OR/CBC 644 {1: 0.0, 2: 1.3333333333333333} 645 646 sage: ### Computation of a maximum stable set in Petersen's graph 647 sage: g = graphs.PetersenGraph() 648 sage: p = MixedIntegerLinearProgram(maximization=True) 649 sage: b = p.new_variable() 650 sage: p.set_objective(sum([b[v] for v in g])) 651 sage: for (u,v) in g.edges(labels=None): 652 ... p.add_constraint(b[u] + b[v], max=1) 653 sage: p.set_binary(b) 654 sage: p.solve(objective_only=True) # optional - requires Glpk or COIN-OR/CBC 655 4.0 712 656 """ 713 d=dict(zip([self.variables[v] for v in exp.variables()],exp.coefficients())) 714 d[-1]=exp.constant_coefficient() 715 return d 657 if self.objective == None: 658 raise ValueError("No objective function has been defined.") 716 659 717 def _addElementToRing(self): 660 if solver == None: 661 solver = self.default_solver 662 663 if solver == None: 664 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.") 665 elif solver == "Coin": 666 try: 667 from sage.numerical.mipCoin import solveCoin 668 except: 669 raise NotImplementedError("Coin/CBC is not installed and cannot be used to solve this MixedIntegerLinearProgram. To install it, you can type in Sage: install_package('cbc')") 670 return solveCoin(self, log=log, objective_only=objective_only) 671 elif solver == "GLPK": 672 try: 673 from sage.numerical.mipGlpk import solveGlpk 674 except: 675 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 solveGlpk(self, log=log, objective_only=objective_only) 677 elif solver == "CPLEX": 678 raise NotImplementedError("The support for CPLEX is not implemented yet.") 679 else: 680 raise NotImplementedError("'solver' should be set to 'GLPK', 'Coin', 'CPLEX' or None (in which case the default one is used).") 681 682 def _NormalForm(self, exp): 718 683 r""" 719 Creates a new variable from the main ``InfinitePolynomialRing`` 684 Returns a dictionary built from the linear function. 685 686 INPUT: 687 688 - ``exp`` -- The expression representing a linear function. 720 689 721 690 OUTPUT: 722 691 723 - The newly created variable 692 A dictionary whose keys are the IDs of the variables and whose 693 values are their coefficients. The value corresponding to key 694 `-1` is the constant coefficient. 724 695 725 EXAMPLE: 696 EXAMPLE:: 726 697 727 sage: p=MIP() 728 sage: v=p.newvar() 729 sage: p.count[0] 698 sage: p = MixedIntegerLinearProgram() 699 sage: v = p.new_variable() 700 sage: p._NormalForm(v[0] + v[1]) 701 {1: 1.0, 2: 1.0, -1: 0.0} 702 """ 703 d = dict( zip([self.variables[v] for v in exp.variables()], 704 exp.coefficients()) ) 705 d[-1] = exp.constant_coefficient() 706 return d 707 708 def _add_element_to_ring(self, vtype): 709 r""" 710 Creates a new variable from the main ``InfinitePolynomialRing``. 711 712 INPUT: 713 714 - ``vtype`` (integer) -- Defines the type of the variables 715 (default is ``REAL``). 716 717 OUTPUT: 718 719 - The newly created variable. 720 721 EXAMPLE:: 722 723 sage: p = MixedIntegerLinearProgram() 724 sage: v = p.new_variable() 725 sage: p.count 730 726 0 731 sage: p._add ElementToRing()727 sage: p._add_element_to_ring(p.__REAL) 732 728 x1 733 sage: p.count [0]729 sage: p.count 734 730 1 735 731 """ 736 self.count [0]+=1737 v =self.x[self.count[0]]738 self.variables[v] =self.count[0]739 self.types[v] =self.__REAL740 self.min[v] =0.0732 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 741 737 return v 742 738 743 def set min(self,v,min):739 def set_min(self, v, min): 744 740 r""" 745 Sets the minimum value of a variable 741 Sets the minimum value of a variable. 742 743 INPUT: 744 745 - ``v`` -- a variable (not a ``MIPVariable``, but one of its 746 elements). 747 - ``min`` -- the minimum value the variable can take. 748 When ``min=None``, the variable has no lower bound. 749 750 EXAMPLE:: 751 752 sage: p = MixedIntegerLinearProgram() 753 sage: v = p.new_variable() 754 sage: p.set_objective(v[1]) 755 sage: p.get_min(v[1]) 756 0.0 757 sage: p.set_min(v[1],6) 758 sage: p.get_min(v[1]) 759 6.0 760 """ 761 self.min[v] = min 762 763 def set_max(self, v, max): 764 r""" 765 Sets the maximum value of a variable. 746 766 747 767 INPUT 748 768 749 - ``v`` : a variable ( not a ``MIPVariable``, but one of its elements ! ) 750 - ``min`` : the minimum value the variable can take 751 when ``min=None``, the variable has no lower bound 769 - ``v`` -- a variable (not a ``MIPVariable``, but one of its 770 elements). 771 - ``max`` -- the maximum value the variable can take. 772 When ``max=None``, the variable has no upper bound. 752 773 753 774 EXAMPLE:: 754 775 755 sage: p=MIP() 756 sage: v=p.newvar() 757 sage: p.setobj(v[1]) 758 sage: p.getmin(v[1]) 759 0.0 760 sage: p.setmin(v[1],6) 761 sage: p.getmin(v[1]) 776 sage: p = MixedIntegerLinearProgram() 777 sage: v = p.new_variable() 778 sage: p.set_objective(v[1]) 779 sage: p.get_max(v[1]) 780 sage: p.set_max(v[1],6) 781 sage: p.get_max(v[1]) 762 782 6.0 763 783 """ 764 self.m in[v]=min784 self.max[v] = max 765 785 766 def setmax(self,v,max):786 def get_min(self, v): 767 787 r""" 768 Sets the maximum value of a variable788 Returns the minimum value of a variable. 769 789 770 INPUT 790 INPUT: 771 791 772 - ``v`` : a variable ( not a ``MIPVariable``, but one of its elements ! ) 773 - ``max`` : the maximum value the variable can take 774 when ``max=None``, the variable has no upper bound 792 - ``v`` -- a variable (not a ``MIPVariable``, but one of its elements). 793 794 OUTPUT: 795 796 Minimum value of the variable, or ``None`` if 797 the variable has no lower bound. 775 798 776 799 EXAMPLE:: 777 800 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]) 801 sage: p = MixedIntegerLinearProgram() 802 sage: v = p.new_variable() 803 sage: p.set_objective(v[1]) 804 sage: p.get_min(v[1]) 805 0.0 806 sage: p.set_min(v[1],6) 807 sage: p.get_min(v[1]) 784 808 6.0 785 809 """ 786 self.max[v]=max810 return float(self.min[v]) if self.min.has_key(v) else None 787 811 812 def get_max(self, v): 813 r""" 814 Returns the maximum value of a variable. 788 815 789 def getmin(self,v): 790 r""" 791 Returns the minimum value of a variable 816 INPUT: 792 817 793 INPUT818 - ``v`` -- a variable (not a ``MIPVariable``, but one of its elements). 794 819 795 - ``v`` a variable ( not a ``MIPVariable``, but one of its elements ! )820 OUTPUT: 796 821 797 OUTPUT 798 799 Minimum value of the variable, or ``None`` is 800 the variable has no lower bound 822 Maximum value of the variable, or ``None`` if 823 the variable has no upper bound. 801 824 802 825 EXAMPLE:: 803 826 804 sage: p=MIP() 805 sage: v=p.newvar() 806 sage: p.setobj(v[1]) 807 sage: p.getmin(v[1]) 808 0.0 809 sage: p.setmin(v[1],6) 810 sage: p.getmin(v[1]) 811 6.0 812 """ 813 return float(self.min[v]) if self.min.has_key(v) else 0.0 814 def getmax(self,v): 815 r""" 816 Returns the maximum value of a variable 817 818 INPUT 819 820 - ``v`` a variable ( not a ``MIPVariable``, but one of its elements ! ) 821 822 OUTPUT 823 824 Maximum value of the variable, or ``None`` is 825 the variable has no upper bound 826 827 EXAMPLE:: 828 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]) 827 sage: p = MixedIntegerLinearProgram() 828 sage: v = p.new_variable() 829 sage: p.set_objective(v[1]) 830 sage: p.get_max(v[1]) 831 sage: p.set_max(v[1],6) 832 sage: p.get_max(v[1]) 835 833 6.0 836 834 """ 837 835 return float(self.max[v]) if self.max.has_key(v) else None 838 836 839 837 class MIPSolverException(Exception): 840 838 r""" 841 Exception raised when the solver fails 839 Exception raised when the solver fails. 842 840 """ 841 843 842 def __init__(self, value): 844 843 r""" 845 Constructor for ``MIPSolverException`` 844 Constructor for ``MIPSolverException``. 846 845 847 ``MIPSolverException`` is the exception raised when the solver fails 846 ``MIPSolverException`` is the exception raised when the solver fails. 848 847 849 EXAMPLE: 848 EXAMPLE:: 850 849 851 850 sage: MIPSolverException("Error") 852 851 MIPSolverException() 853 854 852 """ 855 853 self.value = value 854 856 855 def __str__(self): 857 856 r""" 858 Returns the value of the instance of ``MIPSolverException` `857 Returns the value of the instance of ``MIPSolverException``. 859 858 860 EXAMPLE: 859 EXAMPLE:: 861 860 862 sage: e =MIPSolverException("Error")861 sage: e = MIPSolverException("Error") 863 862 sage: print e 864 863 'Error' 865 864 """ 866 865 return repr(self.value) 867 866 868 867 class MIPVariable: 869 r""" 870 ``MIPVariable`` is a variable used by the class ``MIP`` 871 """ 872 def __init__(self,x,f,dim=1): 873 r""" 874 Constructor for ``MIPVariable`` 868 r""" 869 ``MIPVariable`` is a variable used by the class 870 ``MixedIntegerLinearProgram``. 871 """ 875 872 876 INPUT: 873 def __init__(self, p, vtype, dim=1): 874 r""" 875 Constructor for ``MIPVariable``. 877 876 878 - ``x`` is the generator element of an ``InfinitePolynomialRing`` 879 - ``f`` is a function returning a new variable from the parent class 880 - ``dim`` is the integer defining the definition of the variable 877 INPUT: 881 878 882 For more informations, see method ``MIP.newvar`` 879 - ``p`` -- the instance of ``MixedIntegerLinearProgram`` to which the 880 variable is to be linked. 881 - ``vtype`` (integer) -- Defines the type of the variables 882 (default is ``REAL``). 883 - ``dim`` -- the integer defining the definition of the variable. 883 884 884 EXAMPLE: 885 For more informations, see the method 886 ``MixedIntegerLinearProgram.new_variable``. 885 887 886 sage: p=MIP() 887 sage: v=p.newvar() 888 889 890 """ 891 self.dim=dim 892 self.dict={} 893 self.x=x 894 self.f=f 888 EXAMPLE:: 895 889 896 def __getitem__(self,i): 897 r""" 898 Returns the symbolic variable corresponding to the key 890 sage: p=MixedIntegerLinearProgram() 891 sage: v=p.new_variable() 892 """ 893 self.dim = dim 894 self.dict = {} 895 self.p = p 896 self.vtype = vtype 899 897 900 Returns the element asked, otherwise creates it. 901 ( When depth>1, recursively creates the variables ) 898 def __getitem__(self, i): 899 r""" 900 Returns the symbolic variable corresponding to the key. 902 901 903 EXAMPLE: 902 Returns the element asked, otherwise creates it. 903 (When depth>1, recursively creates the variables). 904 904 905 sage: p=MIP() 906 sage: v=p.newvar() 907 sage: p.setobj(v[0]+v[1]) 908 sage: v[0] 909 x1 910 """ 911 if self.dict.has_key(i): 912 return self.dict[i] 913 elif self.dim==1: 914 self.dict[i]=self.f() 915 return self.dict[i] 916 else: 917 self.dict[i]=MIPVariable(dim=self.dim-1,x=self.x, f=self.f) 918 return self.dict[i] 919 def keys(self): 920 r""" 921 Returns the keys already defined in the dictionary 905 EXAMPLE:: 922 906 923 EXAMPLE: 907 sage: p = MixedIntegerLinearProgram() 908 sage: v = p.new_variable() 909 sage: p.set_objective(v[0] + v[1]) 910 sage: v[0] 911 x1 912 """ 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] 918 else: 919 self.dict[i] = MIPVariable(self.p, self.vtype, dim=self.dim-1) 920 return self.dict[i] 924 921 925 sage: p=MIP() 926 sage: v=p.newvar() 927 sage: p.setobj(v[0]+v[1]) 928 sage: v.keys() 929 [0, 1] 930 """ 931 return self.dict.keys() 932 def items(self): 933 r""" 934 Returns the pairs (keys,value) contained in the dictionary 922 def keys(self): 923 r""" 924 Returns the keys already defined in the dictionary. 935 925 936 EXAMPLE:926 EXAMPLE:: 937 927 938 sage: p=MIP() 939 sage: v=p.newvar() 940 sage: p.setobj(v[0]+v[1]) 941 sage: v.items() 942 [(0, x1), (1, x2)] 943 """ 944 return self.dict.items() 945 def depth(self): 946 r""" 947 Returns the current variable's depth 928 sage: p = MixedIntegerLinearProgram() 929 sage: v = p.new_variable() 930 sage: p.set_objective(v[0] + v[1]) 931 sage: v.keys() 932 [0, 1] 933 """ 934 return self.dict.keys() 948 935 949 EXAMPLE: 936 def items(self): 937 r""" 938 Returns the pairs (keys,value) contained in the dictionary. 950 939 951 sage: p=MIP() 952 sage: v=p.newvar() 953 sage: p.setobj(v[0]+v[1]) 954 sage: v.depth() 955 1 956 """ 957 return self.dim 958 def values(self): 959 r""" 960 Returns the symbolic variables associated to the current dictionary 940 EXAMPLE:: 961 941 962 EXAMPLE: 942 sage: p = MixedIntegerLinearProgram() 943 sage: v = p.new_variable() 944 sage: p.set_objective(v[0] + v[1]) 945 sage: v.items() 946 [(0, x1), (1, x2)] 947 """ 948 return self.dict.items() 963 949 964 sage: p=MIP() 965 sage: v=p.newvar() 966 sage: p.setobj(v[0]+v[1]) 967 sage: v.values() 968 [x1, x2] 969 """ 970 return self.dict.values() 950 def depth(self): 951 r""" 952 Returns the current variable's depth. 971 953 954 EXAMPLE:: 972 955 956 sage: p = MixedIntegerLinearProgram() 957 sage: v = p.new_variable() 958 sage: p.set_objective(v[0] + v[1]) 959 sage: v.depth() 960 1 961 """ 962 return self.dim 963 964 def values(self): 965 r""" 966 Returns the symbolic variables associated to the current dictionary. 967 968 EXAMPLE:: 969 970 sage: p = MixedIntegerLinearProgram() 971 sage: v = p.new_variable() 972 sage: p.set_objective(v[0] + v[1]) 973 sage: v.values() 974 [x1, x2] 975 """ 976 return self.dict.values()