# 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): |