# HG changeset patch
# User Nathann Cohen <nathann.cohen@gmail.com>
# Date 1330683028 3600
# Node ID 55d30918ba60644dff312590a99f3b64b5444cfb
# Parent 218094b2e56274dae1c8cf21bb191d2cc5ab7b44
The LP are not deallocated because of cyclic references !
diff git a/sage/numerical/mip.pyx b/sage/numerical/mip.pyx
a

b


1  1  r""" 
2  2  Mixed integer linear programming 
3  3  
4   A linear program (`LP <http://en.wikipedia.org/wiki/Linear_programming>`_) 
5   is an `optimization problem <http://en.wikipedia.org/wiki/Optimization_%28mathematics%29>`_ 
 4  A linear program (`LP <http://en.wikipedia.org/wiki/Linear_programming>`_) 
 5  is an `optimization problem <http://en.wikipedia.org/wiki/Optimization_%28mathematics%29>`_ 
6  6  in the following form 
7  7  
8  8  .. MATH:: 
9  9  \max \{ c^T x \;\; A x \leq b, x \geq 0 \} 
10  10  
11   with given `A \in \mathbb{R}^{m,n}`, `b \in \mathbb{R}^m`, 
 11  with given `A \in \mathbb{R}^{m,n}`, `b \in \mathbb{R}^m`, 
12  12  `c \in \mathbb{R}^n` and unknown `x \in \mathbb{R}^{n}`. 
13  13  If some or all variables in the vector `x` are restricted over 
14  14  the integers `\mathbb{Z}`, the problem is called mixed integer 
15   linear program (`MILP <http://en.wikipedia.org/wiki/Mixed_integer_linear_programming>`_). 
 15  linear program (`MILP <http://en.wikipedia.org/wiki/Mixed_integer_linear_programming>`_). 
16  16  A wide variety of problems in optimization 
17  17  can be formulated in this standard form. Then, solvers are 
18   able to calculate a solution. 
 18  able to calculate a solution. 
19  19  
20  20  Imagine you want to solve the following linear system of three equations: 
21  21  
… 
… 

34  34  A mixed integer linear program can give you an answer: 
35  35  
36  36  #. You have to create an instance of :class:`MixedIntegerLinearProgram` and 
37    in our case  specify that it is a minimization. 
 37   in our case  specify that it is a minimization. 
38  38  #. Create a variable vector ``w`` via ``w = p.new_variable(integer=True)`` and 
39  39  tell the system that it is over the integers. 
40   #. Add those three equations as equality constraints via 
 40  #. Add those three equations as equality constraints via 
41  41  :meth:`add_constraint <sage.numerical.mip.MixedIntegerLinearProgram.add_constraint>`. 
42  42  #. Also add the inequality constraint. 
43  43  #. Add an inequality constraint `w_3 \geq 1` to exclude the trivial solution. 
… 
… 

46  46  #. Specify the objective function via :meth:`set_objective <sage.numerical.mip.MixedIntegerLinearProgram.set_objective>`. 
47  47  In our case that is just `w_3`. If it 
48  48  is a pure constraint satisfaction problem, specify it as ``None``. 
49   #. To check if everything is set up correctly, you can print the problem via 
 49  #. To check if everything is set up correctly, you can print the problem via 
50  50  :meth:`show <sage.numerical.mip.MixedIntegerLinearProgram.show>`. 
51  51  #. :meth:`Solve <sage.numerical.mip.MixedIntegerLinearProgram.solve>` it and print the solution. 
52  52  
53  53  The following example shows all these steps:: 
54  54  
55   sage: p = MixedIntegerLinearProgram(maximization=False) 
56   sage: w = p.new_variable(integer=True) 
57   sage: p.add_constraint(w[0] + w[1] + w[2]  14*w[3] == 0) 
58   sage: p.add_constraint(w[1] + 2*w[2]  8*w[3] == 0) 
59   sage: p.add_constraint(2*w[2]  3*w[3] == 0) 
 55  sage: p = MixedIntegerLinearProgram(maximization=False) 
 56  sage: w = p.new_variable(integer=True) 
 57  sage: p.add_constraint(w[0] + w[1] + w[2]  14*w[3] == 0) 
 58  sage: p.add_constraint(w[1] + 2*w[2]  8*w[3] == 0) 
 59  sage: p.add_constraint(2*w[2]  3*w[3] == 0) 
60  60  sage: p.add_constraint(w[0]  w[1]  w[2] >= 0) 
61   sage: p.add_constraint(w[3] >= 1) 
62   sage: _ = [ p.set_min(w[i], None) for i in range(1,4) ] 
63   sage: p.set_objective(w[3]) 
64   sage: p.show() 
 61  sage: p.add_constraint(w[3] >= 1) 
 62  sage: _ = [ p.set_min(w[i], None) for i in range(1,4) ] 
 63  sage: p.set_objective(w[3]) 
 64  sage: p.show() 
65  65  Minimization: 
66  66  x_3 
67  67  Constraints: 
… 
… 

151  151  sage: p.solve(objective_only=True) 
152  152  4.0 
153  153  """ 
154   
 154  
155  155  def __init__(self, solver = None, maximization=True, constraint_generation = False, check_redundant = False): 
156  156  r""" 
157  157  Constructor for the ``MixedIntegerLinearProgram`` class. 
… 
… 

185  185  
186  186   ``constraint_generation``  whether to require the returned solver to 
187  187  support constraint generation (excludes Coin). ``False by default``. 
188   
 188  
189  189   ``check_redundant``  whether to check that constraints added to the 
190  190  program are redundant with constraints already in the program. 
191  191  Only obvious redundancies are checked: to be considered redundant, 
… 
… 

201  201  EXAMPLE:: 
202  202  
203  203  sage: p = MixedIntegerLinearProgram(maximization=True) 
 204  
 205  TESTS: 
 206  
 207  Checks the objects are deallocated (cf. :trac:`12616`):: 
 208  
 209  sage: del p 
 210  sage: def just_create_variables(): 
 211  ... p = MixedIntegerLinearProgram() 
 212  ... b = p.new_variable() 
 213  ... p.add_constraint(b[3]+b[6] <= 2) 
 214  ... p.solve() 
 215  sage: C = sage.numerical.mip.MixedIntegerLinearProgram 
 216  sage: import gc 
 217  sage: _ = gc.collect() # avoid side effects of other doc tests 
 218  sage: len([x for x in gc.get_objects() if isinstance(x,C)]) 
 219  0 
 220  sage: just_create_variables() 
 221  sage: len([x for x in gc.get_objects() if isinstance(x,C)]) 
 222  0 
204  223  """ 
205  224  
206  225  from sage.numerical.backends.generic_backend import get_solver 
207  226  
208   self._backend = get_solver(solver=solver, 
 227  self._backend = get_solver(solver=solver, 
209  228  constraint_generation=constraint_generation) 
210  229  
211  230  if not maximization: 
… 
… 

216  235  self.__INTEGER = 1 
217  236  
218  237  
219   # List of all the MIPVariables linked to this instance of 
220   # MixedIntegerLinearProgram 
221   self._mipvariables = [] 
222   
223  238  # Associates an index to the variables 
224  239  self._variables = {} 
225   
 240  
226  241  # Check for redundant constraints 
227  242  self._check_redundant = check_redundant 
228  243  if check_redundant: 
… 
… 

244  259  
245  260  return ("Mixed Integer Program "+ 
246  261  
247   ( "\"" +self._backend.problem_name()+ "\"" 
 262  ( "\"" +self._backend.problem_name()+ "\"" 
248  263  if (str(self._backend.problem_name()) != "") else "")+ 
249  264  
250  265  " ( " + ("maximization" if b.is_maximization() else "minimization" ) + 
… 
… 

257  272  Returns a copy of the current ``MixedIntegerLinearProgram`` instance. 
258  273  """ 
259  274  cdef MixedIntegerLinearProgram p = MixedIntegerLinearProgram(solver="GLPK") 
260   try: 
261   p._mipvariables = copy(self._mipvariables) 
262   except AttributeError: 
263   pass 
264  275  
265  276  try: 
266  277  p._variables = copy(self._variables) 
… 
… 

395  406  vtype = self.__REAL 
396  407  
397  408  v=MIPVariable(self, vtype, dim=dim,name=name) 
398   self._mipvariables.append(v) 
399  409  return v 
400  410  
401  411  cpdef int number_of_constraints(self): 