From aa1fdf0341c089c183e8a0fb8ee4eea22c35f393 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Fri, 20 Jun 2014 12:31:41 -0700 Subject: [PATCH] First pass: documentation formatting. --- .../numerical/interactive_simplex_method.py | 1607 ++++++++--------- 1 file changed, 802 insertions(+), 805 deletions(-) diff --git a/src/sage/numerical/interactive_simplex_method.py b/src/sage/numerical/interactive_simplex_method.py index 54a8b842e0b..338b3dfeeac 100644 --- a/src/sage/numerical/interactive_simplex_method.py +++ b/src/sage/numerical/interactive_simplex_method.py @@ -2,7 +2,7 @@ Interactive Simplex Method The purpose of this module is to support learning and exploring of the simplex -method. While it does allow solving Linear Programming Problems (LPPs) in a +method. While it does allow solving Linear Programming Problems (LPPs) in a number of ways, it may require explicit (and correct!) description of steps and is likely to be much slower than "regular" LP solvers. Therefore, do not use this module if all you want is the result. If, however, you want to @@ -10,7 +10,7 @@ using different strategies, but don't want to deal with tedious arithmetic, this module is for you! -Historically it was created to complement Math 373 course on Mathematical +Historically it was created to complement the Math 373 course on Mathematical Programming and Optimization at the University of Alberta, Edmonton, Canada. AUTHORS: @@ -24,14 +24,14 @@ .. admonition:: Corn & Barley A farmer has 1000 acres available to grow corn and barley. - Corn has a net profit of 10 dollars per acre while barley has a net profit - of 5 dollars per acre. - The farmer has 1500 kg of fertilizer available with 3 kg per acre needed for - corn and 1 kg per acre needed for barley. + Corn has a net profit of 10 dollars per acre while barley has a net + profit of 5 dollars per acre. + The farmer has 1500 kg of fertilizer available with 3 kg per acre + needed for corn and 1 kg per acre needed for barley. The farmer wants to maximize profit. (Sometimes we also add one more constraint to make the initial dictionary infeasible: the farmer has to use at least 40% of the available land.) - + Using variables `C` and `B` for land used to grow corn and barley respectively, in acres, we can construct the following LP problem:: @@ -45,7 +45,7 @@ It is recommended to copy-paste such examples into your own worksheet, so that you can run these commands with typeset mode on and get -.. math:: +.. MATH:: \begin{array}{l} \begin{array}{lcrcrcl} @@ -59,14 +59,14 @@ Since it has only two variables, we can solve it graphically:: sage: P.plot() - - + + The simplex method can be applied only to :class:`problems in standard form `, which can be created either directly :: sage: LPProblemStandardForm(A, b, c, ["C", "B"]) LP problem (use typeset mode to see details) - + or from an already constructed problem of "general type" :: sage: P = P.standard_form() @@ -87,10 +87,10 @@ sage: D = P.initial_dictionary() sage: D LP problem dictionary (use typeset mode to see details) - + Using typeset mode as recommended, you'll see -.. math:: +.. MATH:: \renewcommand{\arraystretch}{1.5} \begin{array}{|rcrcrcr|} @@ -108,7 +108,7 @@ True sage: D.is_optimal() False - + You can look at many of its pieces and associated data:: sage: D.basic_variables() @@ -124,7 +124,7 @@ sage: D.enter("C") sage: D.leave(4) sage: D.update() - + If everything was done correctly, the new dictionary is still feasible and the objective value did not decrease:: @@ -132,7 +132,7 @@ True sage: D.objective_value() 5000 - + If you are unsure about picking entering and leaving variables, you can use helper methods that will try their best to tell you what are your next options:: @@ -142,9 +142,9 @@ Traceback (most recent call last): ... ValueError: leaving variables can be determined - for feasible dictionaries with a set entering variable - or for dual feasible dictionaries - + for feasible dictionaries with a set entering variable + or for dual feasible dictionaries + It is also possible to obtain :meth:`feasible sets ` and :meth:`final dictionaries ` of problems, work with :class:`revised dictionaries `, and use the dual @@ -156,8 +156,8 @@ # Copyright (C) 2013 Andrey Novoseltsev # # Distributed under the terms of the GNU General Public License (GPL) -# as published by the Free Software Foundation; either version 2 of -# the License, or (at your option) any later version. +# as published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. # http://www.gnu.org/licenses/ #***************************************************************************** @@ -199,20 +199,20 @@ def _assemble_arrayl(lines, stretch=None): r""" Return ``lines`` assembled in a left-justified array. - + INPUT: - + - ``lines`` -- a list of strings suitable for math mode typesetting; - + - ``stretch`` -- (default: None) if given, a command setting ``\arraystretch`` to this value will be added before the array. - + OUTPUT: - + - a :class:`LatexExpr`. - + EXAMPLES:: - + sage: from sage.numerical.interactive_simplex_method \ ....: import _assemble_arrayl sage: lines = ["1 + 1", "2"] @@ -243,41 +243,41 @@ def _latex_product(coefficients, variables, drop_plus=True, allow_empty=False): r""" Generate LaTeX code for a linear function. - + This function is intended for internal use by LaTeX methods of LP problems and their dictionaries. - + INPUT: - - - ``coefficients`` -- a list of coefficients; - - - ``variables`` -- a list of variables; - - - ``separator`` -- (default: "&" with some extra space adjustment) a string - to be inserted between elements of the generated expression; - - - ``head`` -- either ``None`` (default) or a list of entries to be added to - the beginning of the output; - - - ``tail`` -- either ``None`` (default) or a list of entries to be added to - the end of the output; - + + - ``coefficients`` -- a list of coefficients + + - ``variables`` -- a list of variables + + - ``separator`` -- (default: ``"&"`` with some extra space adjustment) a + string to be inserted between elements of the generated expression + + - ``head`` -- either ``None`` (default) or a list of entries to be + added to the beginning of the output + + - ``tail`` -- either ``None`` (default) or a list of entries to be + added to the end of the output + - ``drop_plus`` -- (default: ``True``) whether to drop the leading plus - sign or not; - + sign or not + - ``allow_empty`` -- (default: ``False``) whether to allow empty output or - produce at least "0". - + produce at least "0" + OUTPUT: - - - a strings joining ``head``, each sign and coefficient-variable product, + + - A string joining ``head``, each sign and coefficient-variable product, and ``tail`` using ``separator``. Strings in ``head`` and ``tail`` are used as is except for "<=", "==", and ">=", which are replaced by LaTeX commands. Other elements in ``head`` in ``tail`` are processed by :func:`latex`. - + TESTS:: - + sage: from sage.numerical.interactive_simplex_method import \ ....: _latex_product sage: var("x, y") @@ -331,27 +331,26 @@ def _latex_product(coefficients, variables, else: separator = r" \mspace{-6mu}&\mspace{-6mu} " return separator.join(entries) - + @cached_function def variable(R, v): r""" Interpret ``v`` as a variable of ``R``. - + INPUT: - - - ``R`` -- a polynomial ring; - + + - ``R`` -- a polynomial ring + - ``v`` -- a variable of ``R`` or convertible into ``R``, a string - with the name of a variable of ``R`` or an index of a variable in - ``R``. - + with the name of a variable of ``R`` or an index of a variable in ``R`` + OUTPUT: - - - a variable of ``R``. - + + - a variable of ``R`` + EXAMPLES:: - + sage: from sage.numerical.interactive_simplex_method \ ....: import variable sage: R = PolynomialRing(QQ, "x3, y5, x5, y") @@ -406,48 +405,44 @@ def variable(R, v): class LPProblem(SageObject): r""" Construct an LP (Linear Programming) problem. - + This class supports LP problems with "variables on the left" constraints. - + INPUT: - - ``A`` -- a matrix of constraint coefficients; - - - ``b`` -- a vector of constraint constant terms; - - - ``c`` -- a vector of objective coefficients; - - - ``x`` -- (default: "x") a vector of decision variables or a string giving - the base name; - - - ``constraint_type`` -- (default: "<=") a string specifying constraint - type(s): either "<=", or ">=", or "==", or a list of them; - - - ``variable_type`` -- (default: "") a string specifying variable type(s): - either ">=", or "<=", or "" (empty string), or a list of them, - corresponding, respectively, to non-negative, non-positive, and free - variables; - - - ``problem_type`` -- (default: "max") a string specifying the problem type: - "max", "min", "-max", or "-min"; - + - ``A`` -- a matrix of constraint coefficients + + - ``b`` -- a vector of constraint constant terms + + - ``c`` -- a vector of objective coefficients + + - ``x`` -- (default: ``"x"``) a vector of decision variables or a + string giving the base name + + - ``constraint_type`` -- (default: ``"<="``) a string specifying constraint + type(s): either ``"<="``, ``">="``, ``"=="``, or a list of them + + - ``variable_type`` -- (default: ``""``) a string specifying variable + type(s): either ``">="``, ``"<="``, ``""`` (the empty string), or a + list of them, corresponding, respectively, to non-negative, + non-positive, and free variables + + - ``problem_type`` -- (default: ``"max"``) a string specifying the + problem type: ``"max"``, ``"min"``, ``"-max"``, or ``"-min"`` + - ``prefix`` -- (default: parameter ``x`` if it was given as a string, - string "x" otherwise) a string giving the base name of automatically - created variables in :meth:`standard_form`; - + string ``"x"`` otherwise) a string giving the base name of automatically + created variables in :meth:`standard_form` + - ``base_ring`` -- (default: the fraction field of a common ring for all input coefficients) a field to which all input coefficients will be - converted. - - OUTPUT: - - - an :class:`LPProblem`. + converted EXAMPLES: We will construct the following problem: - - .. math:: + + .. MATH:: \begin{array}{l} \begin{array}{lcrcrcl} @@ -456,25 +451,25 @@ class LPProblem(SageObject): \!\!\!&\!\!\! \!\!\!&\!\!\! 3 C \!\!\!&\!\!\! + \!\!\!&\!\!\! B \!\!\!&\!\!\! \leq \!\!\!&\!\!\! 1500 \\ \end{array} \\ C, B \geq 0 - \end{array} - + \end{array} + :: - + sage: A = ([1, 1], [3, 1]) sage: b = (1000, 1500) sage: c = (10, 5) sage: P = LPProblem(A, b, c, ["C", "B"], variable_type=">=") Same problem, but more explicitly:: - + sage: P = LPProblem(A, b, c, ["C", "B"], ....: constraint_type="<=", variable_type=">=") - + Even more explicitly:: - + sage: P = LPProblem(A, b, c, ["C", "B"], problem_type="max", ....: constraint_type=["<=", "<="], variable_type=[">=", ">="]) - + Using the last form you should be able to represent any LP problem, as long as all like terms are collected and in constraints variables and constants are on different sides. @@ -520,9 +515,9 @@ def __init__(self, A, b, c, x="x", if len(x) != n: raise ValueError("A and x have incompatible dimensions") R = PolynomialRing(base_ring, x, order="neglex") - x = vector(R, R.gens()) # All variables as a vector + x = vector(R, R.gens()) # All variables as a vector self._Abcx = A, b, c, x - + if constraint_type in ["<=", ">=", "=="]: constraint_type = (constraint_type, ) * m else: @@ -530,9 +525,9 @@ def __init__(self, A, b, c, x="x", if any(ct not in ["<=", ">=", "=="] for ct in constraint_type): raise ValueError("unknown constraint type") if len(constraint_type) != m: - raise ValueError("wrong number of constraint types") + raise ValueError("wrong number of constraint types") self._constraint_types = constraint_type - + if variable_type in ["<=", ">=", ""]: variable_type = (variable_type, ) * n else: @@ -540,9 +535,9 @@ def __init__(self, A, b, c, x="x", if any(vt not in ["<=", ">=", ""] for vt in variable_type): raise ValueError("unknown variable type") if len(variable_type) != n: - raise ValueError("wrong number of variable types") + raise ValueError("wrong number of variable types") self._variable_types = variable_type - + if problem_type.startswith("-"): self._is_negative = True problem_type = problem_type[1:] @@ -551,22 +546,22 @@ def __init__(self, A, b, c, x="x", if problem_type not in ["max", "min"]: raise ValueError("unknown problem type") self._problem_type = problem_type - + self._prefix = prefix def __eq__(self, other): r""" Check if two LP problems are equal. - + INPUT: - + - ``other`` -- anything. - + OUTPUT: - + - ``True`` if ``other`` is an :class:`LPProblem` with all details the same as ``self``, ``False`` otherwise. - + TESTS:: sage: A = ([1, 1], [3, 1]) @@ -580,14 +575,14 @@ def __eq__(self, other): sage: P == P3 False """ - return (isinstance(other, LPProblem) and + return (isinstance(other, LPProblem) and self.Abcx() == other.Abcx() and self._problem_type == other._problem_type and self._is_negative == other._is_negative and self._constraint_types == other._constraint_types and self._variable_types == other._variable_types and self._prefix == other._prefix) - + def _latex_(self): r""" Return a LaTeX representation of ``self``. @@ -611,7 +606,7 @@ def _latex_(self): \end{array} \\ C, B \geq 0 \end{array} - """ + """ A, b, c, x = self.Abcx() lines = [] lines.append(r"\begin{array}{l}") @@ -633,7 +628,7 @@ def _latex_(self): latex(xj), r"\geq" if vt == ">=" else r"\leq") for xj, vt in zip(x, self._variable_types) if vt)) lines.append(r"\end{array}") - return "\n".join(lines) + return "\n".join(lines) def _repr_(self): r""" @@ -658,17 +653,17 @@ def _repr_(self): def _solve(self): r""" Return an optimal solution and the optimal value of ``self``. - + OUTPUT: - + - a pair consisting of a vector and a number. If the problem is infeasible, both components are ``None``. If the problem is unbounded, the first component is ``None`` and the second is `\pm \infty`. - + This function uses "brute force" solution technique of evaluating the objective at all vertices of the feasible set and taking into account its rays and lines. - + EXAMPLES:: sage: A = ([1, 1], [3, 1]) @@ -703,15 +698,15 @@ def _solve(self): S = vector(R, S) S.set_immutable() return S, M - + def Abcx(self): r""" Return `A`, `b`, `c`, and `x` of ``self`` as a tuple. - + OUTPUT: - + - a tuple. - + EXAMPLES:: sage: A = ([1, 1], [3, 1]) @@ -720,24 +715,24 @@ def Abcx(self): sage: P = LPProblem(A, b, c, ["C", "B"], variable_type=">=") sage: P.Abcx() ( - [1 1] + [1 1] [3 1], (1000, 1500), (10, 5), (C, B) ) """ return self._Abcx - + def base_ring(self): r""" Return the base ring of ``self``. - + .. note:: - + The base ring of LP problems is always a field. - + OUTPUT: - + - a ring. - + EXAMPLES:: sage: A = ([1, 1], [3, 1]) @@ -746,22 +741,22 @@ def base_ring(self): sage: P = LPProblem(A, b, c, ["C", "B"], variable_type=">=") sage: P.base_ring() Rational Field - + sage: c = (10, 5.) sage: P = LPProblem(A, b, c, ["C", "B"], variable_type=">=") sage: P.base_ring() Real Field with 53 bits of precision """ return self._Abcx[0].base_ring() - + def constant_terms(self): r""" Return constant terms of constraints of ``self``, i.e. `b`. - + OUTPUT: - + - a vector. - + EXAMPLES:: sage: A = ([1, 1], [3, 1]) @@ -774,15 +769,15 @@ def constant_terms(self): (1000, 1500) """ return self._Abcx[1] - + def constraint_coefficients(self): r""" Return coefficients of constraints of ``self``, i.e. `A`. - + OUTPUT: - + - a matrix. - + EXAMPLES:: sage: A = ([1, 1], [3, 1]) @@ -801,11 +796,11 @@ def constraint_coefficients(self): def decision_variables(self): r""" Return decision variables of ``self``, i.e. `x`. - + OUTPUT: - + - a vector. - + EXAMPLES:: sage: A = ([1, 1], [3, 1]) @@ -822,19 +817,19 @@ def decision_variables(self): def dual(self, y=None): r""" Construct the dual LP problem for ``self``. - + INPUT: - + - ``y`` -- (default: "x" if the prefix of ``self`` is "y", "y" otherwise) a vector of dual decision variables or a string giving the base name. - + OUTPUT: - an :class:`LPProblem`. EXAMPLES:: - + sage: A = ([1, 1], [3, 1]) sage: b = (1000, 1500) sage: c = (10, 5) @@ -849,7 +844,7 @@ def dual(self, y=None): A = A.transpose() if y is None: y = "x" if self._prefix == "y" else "y" - problem_type = "min" if self._problem_type == "max" else "max" + problem_type = "min" if self._problem_type == "max" else "max" constraint_type = [] for vt in self._variable_types: if (vt == ">=" and problem_type == "min" or @@ -874,16 +869,16 @@ def dual(self, y=None): problem_type = "-" + problem_type return LPProblem(A, b, c, y, constraint_type, variable_type, problem_type) - + @cached_method def feasible_set(self): r""" Return the feasible set of ``self``. - + OUTPUT: - + - a :mod:`Polyhedron `. - + EXAMPLES:: sage: A = ([1, 1], [3, 1]) @@ -915,15 +910,15 @@ def feasible_set(self): ieqs = [map(R, ieq) for ieq in ieqs] eqns = [map(R, eqn) for eqn in eqns] return Polyhedron(ieqs=ieqs, eqns=eqns, base_ring=R) - + def is_bounded(self): r""" Check if ``self`` is bounded. - + OUTPUT: - + - ``True`` is ``self`` is bounded, ``False`` otherwise. - + EXAMPLES:: sage: A = ([1, 1], [3, 1]) @@ -938,11 +933,11 @@ def is_bounded(self): def is_feasible(self): r""" Check if ``self`` is feasible. - + OUTPUT: - + - ``True`` is ``self`` is feasible, ``False`` otherwise. - + EXAMPLES:: sage: A = ([1, 1], [3, 1]) @@ -957,11 +952,11 @@ def is_feasible(self): def n_constraints(self): r""" Return the number of constraints of ``self``, i.e. `m`. - + OUTPUT: - + - an integer. - + EXAMPLES:: sage: A = ([1, 1], [3, 1]) @@ -978,11 +973,11 @@ def n_constraints(self): def n_variables(self): r""" Return the number of decision variables of ``self``, i.e. `n`. - + OUTPUT: - + - an integer. - + EXAMPLES:: sage: A = ([1, 1], [3, 1]) @@ -995,15 +990,15 @@ def n_variables(self): 2 """ return self._Abcx[0].ncols() - + def objective_coefficients(self): r""" Return coefficients of the objective of ``self``, i.e. `c`. - + OUTPUT: - + - a vector. - + EXAMPLES:: sage: A = ([1, 1], [3, 1]) @@ -1016,15 +1011,15 @@ def objective_coefficients(self): (10, 5) """ return self._Abcx[2] - + def optimal_solution(self): r""" Return **an** optimal solution of ``self``. - + OUTPUT: - + - a vector or ``None`` if there are no optimal solutions. - + EXAMPLES:: sage: A = ([1, 1], [3, 1]) @@ -1039,12 +1034,12 @@ def optimal_solution(self): def optimal_value(self): r""" Return the optimal value for ``self``. - + OUTPUT: - + - a number if the problem is bounded, `\pm \infty` if it is unbounded, or ``None`` if it is infeasible. - + EXAMPLES:: sage: A = ([1, 1], [3, 1]) @@ -1059,15 +1054,15 @@ def optimal_value(self): def plot(self, *args, **kwds): r""" Return a plot for solving ``self`` graphically. - + INPUT: - + - same as for :meth:`plot_feasible_set`. - + OUTPUT: - + - a plot. - + This only works for problems with two decision variables. On the plot the black arrow indicates the direction of growth of the objective. The lines perpendicular to it are level curves of the objective. If there @@ -1076,7 +1071,7 @@ def plot(self, *args, **kwds): are optimal solutions. Otherwise the arrow is placed in the center. If the problem is infeasible or the objective is zero, a plot of the feasible set only is returned. - + EXAMPLES:: sage: A = ([1, 1], [3, 1]) @@ -1085,16 +1080,16 @@ def plot(self, *args, **kwds): sage: P = LPProblem(A, b, c, ["C", "B"], variable_type=">=") sage: p = P.plot() sage: p.show() - + In this case the plot works better with the following axes ranges:: - + sage: p = P.plot(0, 1000, 0, 1500) sage: p.show() - + TESTS: - + We check that zero objective can be dealt with:: - + sage: LPProblem(A, b, (0, 0), ["C", "B"], variable_type=">=").plot() """ FP = self.plot_feasible_set(*args, **kwds) @@ -1110,7 +1105,7 @@ def plot(self, *args, **kwds): start = vector(QQ, start.n() if start is not None else [xmin + (xmax-xmin)/2, ymin + (ymax-ymin)/2]) length = min(xmax - xmin, ymax - ymin) / 5 - end = start + (c * length / c.norm()).n().change_ring(QQ) + end = start + (c * length / c.norm()).n().change_ring(QQ) result = FP + point(start, color="black", size=50, zorder=10) result += arrow(start, end, color="black", zorder=10) ieqs = [(xmax, -1, 0), (- xmin, 1, 0), @@ -1130,29 +1125,29 @@ def plot(self, *args, **kwds): result.set_axes_range(xmin, xmax, ymin, ymax) result.axes_labels(FP.axes_labels()) #FIXME: should be preserved! return result - + def plot_feasible_set(self, xmin=None, xmax=None, ymin=None, ymax=None, alpha=0.2): r""" Return a plot of the feasible set of ``self``. - + INPUT: - + - ``xmin``, ``xmax``, ``ymin``, ``ymax`` -- bounds for the axes, if not given, an attempt will be made to pick reasonable values; - + - ``alpha`` -- (default: 0.2) determines how opaque are shadows. - + OUTPUT: - + - a plot. - + This only works for a problem with two decision variables. The plot shows boundaries of constraints with a shadow on one side for inequalities. If the :meth:`feasible_set` is not empty and at least part of it is in the given boundaries, it will be shaded gray and `F` will be placed in its middle. - + EXAMPLES:: sage: A = ([1, 1], [3, 1]) @@ -1161,9 +1156,9 @@ def plot_feasible_set(self, xmin=None, xmax=None, ymin=None, ymax=None, sage: P = LPProblem(A, b, c, ["C", "B"], variable_type=">=") sage: p = P.plot_feasible_set() sage: p.show() - + In this case the plot works better with the following axes ranges:: - + sage: p = P.plot_feasible_set(0, 1000, 0, 1500) sage: p.show() """ @@ -1234,18 +1229,18 @@ def plot_feasible_set(self, xmin=None, xmax=None, ymin=None, ymax=None, shadow=True) result._extra_kwds["aspect_ratio"] = 1 result.set_aspect_ratio(1) - return result + return result def standard_form(self): r""" Construct the LP problem in standard form equivalent to ``self``. - + OUTPUT: - an :class:`LPProblemStandardForm`. EXAMPLES:: - + sage: A = ([1, 1], [3, 1]) sage: b = (1000, 1500) sage: c = (10, 5) @@ -1295,7 +1290,7 @@ def standard_form(self): problem_type = "-max" if is_negative else "max" return LPProblemStandardForm(A, b, c, x, problem_type, self._prefix, self._prefix + "0") - + # Aliases for the standard notation A = constraint_coefficients b = constant_terms @@ -1308,63 +1303,60 @@ def standard_form(self): class LPProblemStandardForm(LPProblem): r""" Construct an LP (Linear Programming) problem in standard form. - + The used standard form is: - - .. math:: - + + .. MATH:: + \begin{array}{l} \pm \max cx \\ Ax \leq b \\ x \geq 0 \end{array} - + INPUT: - - ``A`` -- a matrix of constraint coefficients; + - ``A`` -- a matrix of constraint coefficients + + - ``b`` -- a vector of constraint constant terms - - ``b`` -- a vector of constraint constant terms; + - ``c`` -- a vector of objective coefficients - - ``c`` -- a vector of objective coefficients; + - ``x`` -- (default: ``"x"``) a vector of decision variables or a string + the base name giving + + - ``problem_type`` -- (default: ``"max"``) a string specifying the + problem type: either ``"max"`` or ``"-max"`` - - ``x`` -- (default: "x") a vector of decision variables or a string giving - the base name; - - - ``problem_type`` -- (default: "max") a string specifying the problem type: - either "max" or "-max"; - - ``slack_variables`` -- (default: same as ``x`` parameter, if it was given - as a string, otherwise string "x") a vector of slack variables or a sting - giving the base name; - + as a string, otherwise string ``"x"``) a vector of slack variables or + a sting giving the base name + - ``auxiliary_variable`` -- (default: same as ``x`` parameter with adjoined - "0" if it was given as a string, otherwise "x0") the auxiliary variable - name, expected to be the same as the first decision variable for auxiliary - problems; - - - ``objective`` -- (default: "z") the objective variable (used for the - initial dictionary); - + ``"0"`` if it was given as a string, otherwise ``"x0"``) the auxiliary + name, expected to be the same as the first decision variable for + auxiliary problems + + - ``objective`` -- (default: ``"z"``) the objective variable (used for the + initial dictionary) + - ``base_ring`` -- (default: the fraction field of a common ring for all input coefficients) a field to which all input coefficients will be - converted. - - OUTPUT: - - - an :class:`LPProblemStandardForm`. + converted EXAMPLES:: - + sage: A = ([1, 1], [3, 1]) sage: b = (1000, 1500) sage: c = (10, 5) sage: P = LPProblemStandardForm(A, b, c) - Unlike :class:`LPProblem`, this class does not allow you to adjust types of - constraints (they are always "<=") and variables (they are always ">="), and - the problem type may only be "max" or "-max". You may give custom names to - slack and auxiliary variables, but in most cases defaults should work:: - + Unlike :class:`LPProblem`, this class does not allow you to adjust types of + constraints (they are always ``"<="``) and variables (they are always + ``">="``), and the problem type may only be ``"max"`` or ``"-max"``. + You may give custom names to slack and auxiliary variables, but in + most cases defaults should work:: + sage: P.decision_variables() (x1, x2) sage: P.slack_variables() @@ -1378,7 +1370,7 @@ def __init__(self, A, b, c, x="x", problem_type="max", See :class:`StandardFormLPP` for documentation. TESTS:: - + sage: A = ([1, 1], [3, 1]) sage: b = (1000, 1500) sage: c = (10, 5) @@ -1418,26 +1410,26 @@ def __init__(self, A, b, c, x="x", problem_type="max", def auxiliary_problem(self): r""" Construct the auxiliary problem for ``self``. - + OUTPUT: - - - an :class:`LP problem in standard form `. - + + - an :class:`LP problem in standard form ` + The auxiliary problem with the auxiliary variable `x_0` is - - .. math:: - + + .. MATH:: + \begin{array}{l} \max - x_0 \\ - x_0 + A_i x \leq b_i \text{ for all } i \\ x \geq 0 - \end{array} - + \end{array}\ . + Such problems are used when the :meth:`initial_dictionary` is infeasible. - + EXAMPLES:: - + sage: A = ([1, 1], [3, 1], [-1, -1]) sage: b = (1000, 1500, -400) sage: c = (10, 5) @@ -1456,18 +1448,18 @@ def auxiliary_problem(self): slack_variables=X[-m:], auxiliary_variable=X[0], objective="w") - + def auxiliary_variable(self): r""" Return the auxiliary variable of ``self``. - + Note that the auxiliary variable may or may not be among :meth:`~LPProblem.decision_variables`. - + OUTPUT: - - - a variable of the :meth:`coordinate_ring` of ``self``. - + + - a variable of the :meth:`coordinate_ring` of ``self`` + EXAMPLES:: sage: A = ([1, 1], [3, 1], [-1, -1]) @@ -1485,17 +1477,17 @@ def auxiliary_variable(self): (x0, x1, x2) """ return self._R.gen(0) - + def coordinate_ring(self): r""" Return the coordinate ring of ``self``. - + OUTPUT: - + - a polynomial ring over the :meth:`~LPProblem.base_ring` of ``self`` in the :meth:`auxiliary_variable`, :meth:`~LPProblem.decision_variables`, - and :meth:`slack_variables` with "neglex" order. - + and :meth:`slack_variables` with "neglex" order + EXAMPLES:: sage: A = ([1, 1], [3, 1], [-1, -1]) @@ -1515,26 +1507,26 @@ def coordinate_ring(self): (x3, x4, x5) """ return self._R - + def dictionary(self, *x_B): r""" Construct a dictionary for ``self`` with given basic variables. - + INPUT: - - - basic variables for the dictionary to be constructed. - + + - basic variables for the dictionary to be constructed + OUTPUT: - - - a :class:`dictionary `. - + + - a :class:`dictionary ` + .. NOTE:: - + This is a synonym for ``self.revised_dictionary(x_B).dictionary()``, but basic variables are mandatory. - + EXAMPLES:: - + sage: A = ([1, 1], [3, 1]) sage: b = (1000, 1500) sage: c = (10, 5) @@ -1546,23 +1538,23 @@ def dictionary(self, *x_B): if not x_B: raise ValueError("basic variables must be given explicitly") return self.revised_dictionary(*x_B).dictionary() - + def feasible_dictionary(self, auxiliary_dictionary): r""" Construct a feasible dictionary for ``self``. - + INPUT: - + - ``auxiliary_dictionary`` -- an optimal dictionary for the :meth:`auxiliary_problem` of ``self`` with the optimal value `0` and - a non-basic auxiliary variable. - + a non-basic auxiliary variable + OUTPUT: - - - a feasible :class:`dictionary ` for ``self``. - + + - a feasible :class:`dictionary ` for ``self`` + EXAMPLES:: - + sage: A = ([1, 1], [3, 1], [-1, -1]) sage: b = (1000, 1500, -400) sage: c = (10, 5) @@ -1617,19 +1609,19 @@ def feasible_dictionary(self, auxiliary_dictionary): B = map(self._R, B) N = map(self._R, N) return LPDictionary(A, b, c, v, B, N, self._objective) - + def final_dictionary(self): r""" Return the final dictionary of the simplex method applied to ``self``. - + See :meth:`run_simplex_method` for the description of possibilities. - + OUTPUT: - - - a :class:`dictionary `. - + + - a :class:`dictionary ` + EXAMPLES:: - + sage: A = ([1, 1], [3, 1]) sage: b = (1000, 1500) sage: c = (10, 5) @@ -1637,9 +1629,9 @@ def final_dictionary(self): sage: D = P.final_dictionary() sage: D.is_optimal() True - + TESTS:: - + sage: P.final_dictionary() is P.final_dictionary() False """ @@ -1651,20 +1643,21 @@ def final_dictionary(self): except AttributeError: self.run_simplex_method() return self.final_dictionary() - + def final_revised_dictionary(self): r""" - Return the final dictionary of the revised simplex method applied to ``self``. - + Return the final dictionary of the revised simplex method applied + to ``self``. + See :meth:`run_revised_simplex_method` for the description of possibilities. - + OUTPUT: - - - a :class:`revised dictionary `. - + + - a :class:`revised dictionary ` + EXAMPLES:: - + sage: A = ([1, 1], [3, 1]) sage: b = (1000, 1500) sage: c = (10, 5) @@ -1672,9 +1665,9 @@ def final_revised_dictionary(self): sage: D = P.final_revised_dictionary() sage: D.is_optimal() True - + TESTS:: - + sage: P.final_revised_dictionary() is P.final_revised_dictionary() False """ @@ -1686,21 +1679,21 @@ def final_revised_dictionary(self): except AttributeError: self.run_revised_simplex_method() return self.final_revised_dictionary() - + def initial_dictionary(self): r""" Construct the initial dictionary of ``self``. - - The initial dictionary "defines" :meth:`slack_variables` in terms of the - :meth:`~LPProblem.decision_variables`, i.e. it has slack variables as - basic ones. - + + The initial dictionary "defines" :meth:`slack_variables` in terms + of the :meth:`~LPProblem.decision_variables`, i.e. it has slack + variables as basic ones. + OUTPUT: - - - a :class:`dictionary `. - + + - a :class:`dictionary ` + EXAMPLES:: - + sage: A = ([1, 1], [3, 1]) sage: b = (1000, 1500) sage: c = (10, 5) @@ -1711,21 +1704,21 @@ def initial_dictionary(self): x = self._R.gens() m, n = self.m(), self.n() return LPDictionary(A, b, c, 0, x[-m:], x[-m-n:-m], self._objective) - + def inject_variables(self, scope=None, verbose=True): r""" Inject variables of ``self`` into ``scope``. INPUT: - - ``scope`` -- namespace (default: global); + - ``scope`` -- namespace (default: global) - ``verbose`` -- if ``True`` (default), names of injected variables - will be printed. + will be printed OUTPUT: - - none. + - none EXAMPLES:: @@ -1744,24 +1737,23 @@ def inject_variables(self, scope=None, verbose=True): self._R.inject_variables(scope, verbose) except AttributeError: pass - + def revised_dictionary(self, *x_B): r""" Construct a revised dictionary for ``self``. - + INPUT: - - - basic variables for the dictionary to be constructed. If not given, + + - basic variables for the dictionary to be constructed; if not given, :meth:`slack_variables` will be used, perhaps with the - :meth:`auxiliary_variable` to - give a feasible dictionary. - + :meth:`auxiliary_variable` to give a feasible dictionary + OUTPUT: - - - a :class:`revised dictionary `. - + + - a :class:`revised dictionary ` + EXAMPLES:: - + sage: A = ([1, 1], [3, 1]) sage: b = (1000, 1500) sage: c = (10, 5) @@ -1769,17 +1761,18 @@ def revised_dictionary(self, *x_B): sage: D = P.revised_dictionary("x1", "x2") sage: D.basic_variables() (x1, x2) - - If basic variables are not given the initial dictionary is constructed:: - + + If basic variables are not given the initial dictionary is + constructed:: + sage: P.revised_dictionary().basic_variables() (x3, x4) sage: P.initial_dictionary().basic_variables() (x3, x4) - + Unless it is infeasible, in which case a feasible dictionary for the auxiliary problem is constructed:: - + sage: A = ([1, 1], [3, 1], [-1,-1]) sage: b = (1000, 1500, -400) sage: P = LPProblemStandardForm(A, b, c) @@ -1794,29 +1787,29 @@ def revised_dictionary(self, *x_B): if bm < 0: x_B[self.b().list().index(bm)] = self.auxiliary_variable() return LPRevisedDictionary(self, x_B) - + def run_revised_simplex_method(self): r""" Apply the revised simplex method to solve ``self`` and show the steps. - + OUTPUT: - - - a string with `\LaTeX` code of intermediate dictionaries. - - .. note:: - + + - a string with `\LaTeX` code of intermediate dictionaries + + .. NOTE:: + You can access the :meth:`final_revised_dictionary`, which can be one of the following: - + - an optimal dictionary with the :meth:`auxiliary_variable` among :meth:`~LPRevisedDictionary.basic_variables` and a non-zero optimal value indicating that ``self`` is infeasible; - + - a non-optimal dictionary that has marked entering variable for which there is no choice of the leaving variable, indicating that ``self`` is unbounded; - + - an optimal dictionary. EXAMPLES:: @@ -1873,27 +1866,27 @@ def run_revised_simplex_method(self): latex(v), latex(d.basic_solution()))) self._final_revised_dictionary = d return _assemble_arrayl(result, 1.5) - - def run_simplex_method(self): + + def run_simplex_method(self): r""" Apply the simplex method to solve ``self`` and show the steps. - + OUTPUT: - - - a string with `\LaTeX` code of intermediate dictionaries. - - .. note:: - - You can access the :meth:`final_dictionary`, which can be one of the - following: - + + - a string with `\LaTeX` code of intermediate dictionaries + + .. NOTE:: + + You can access the :meth:`final_dictionary`, which can be one + of the following: + - an optimal dictionary for the :meth:`auxiliary_problem` with a non-zero optimal value indicating that ``self`` is infeasible; - + - a non-optimal dictionary for ``self`` that has marked entering variable for which there is no choice of the leaving variable, indicating that ``self`` is unbounded; - + - an optimal dictionary for ``self``. EXAMPLES:: @@ -1903,10 +1896,10 @@ def run_simplex_method(self): sage: c = (10, 5) sage: P = LPProblemStandardForm(A, b, c) sage: P.run_simplex_method() # not tested - + You should use the typeset mode as the command above generates long `\LaTeX` code:: - + sage: print P.run_simplex_method() \begin{gather*} ... @@ -1929,7 +1922,7 @@ def step(entering, leaving): result.append(r"\text{{Entering: ${}$. Leaving: ${}$.}}" .format(latex(entering), latex(leaving))) result.append(d.ELLUL(entering, leaving)) - + result = [] d = self.initial_dictionary() result.append(latex(d)) @@ -1943,7 +1936,7 @@ def step(entering, leaving): x0 = self.auxiliary_variable() _, leaving = min(zip(d.constant_terms(), d.basic_variables())) step(x0, leaving) - # while not d.is_optimal(): + # while not d.is_optimal(): # either optimality check should handle rounding errors or while not (d.is_optimal() or x0 in d.nonbasic_variables()): entering, leaving = min(d.possible_simplex_method_steps()) @@ -1981,23 +1974,23 @@ def step(entering, leaving): "\\displaybreak[0]\\\\\n".join(result) + "\n\\end{gather*}") return _assemble_arrayl(result, 1.5) - + def slack_variables(self): r""" Return slack variables of ``self``. - - Slack variables are differences between the constant terms and left hand - sides of the constraints. - + + Slack variables are differences between the constant terms and + left hand sides of the constraints. + If you want to give custom names to slack variables, you have to do so during construction of the problem. - + OUTPUT: - - - a tuple. - + + - a tuple + EXAMPLES:: - + sage: A = ([1, 1], [3, 1]) sage: b = (1000, 1500) sage: c = (10, 5) @@ -2015,17 +2008,17 @@ def slack_variables(self): class LPAbstractDictionary(SageObject): r""" Abstract base class for dictionaries for LP problems. - + Instantiating this class directly is meaningless, see :class:`LPDictionary` and :class:`LPRevisedDictionary` for useful extensions. """ - + def __init__(self): r""" Initialize internal fields for entering and leaving variables. - + TESTS:: - + sage: A = ([1, 1], [3, 1]) sage: b = (1000, 1500) sage: c = (10, 5) @@ -2042,7 +2035,7 @@ def _repr_(self): OUTPUT: - - a string. + - a string TESTS:: @@ -2061,12 +2054,12 @@ def _repr_(self): def base_ring(self): r""" - Return the base ring of ``self``, i.e. the ring of coefficients. - + Return the base ring of ``self``, i.e. the ring of coefficients. + OUTPUT: - - - a ring. - + + - a ring + EXAMPLES:: sage: A = ([1, 1], [3, 1]) @@ -2081,29 +2074,29 @@ def base_ring(self): Rational Field """ return self.coordinate_ring().base_ring() - + def basic_solution(self, include_slack_variables=False): r""" Return the basic solution of ``self``. - + The basic solution associated to a dictionary is obtained by setting to zero all :meth:`~LPDictionary.nonbasic_variables`, in which case :meth:`~LPDictionary.basic_variables` have to be equal to :meth:`~LPDictionary.constant_terms` in equations. It may refer to values of :meth:`~LPProblem.decision_variables` only or include :meth:`~LPProblemStandardForm.slack_variables` as well. - + INPUT: - + - ``include_slack_variables`` -- (default: ``False``) if ``True``, - values of slack variables will be appended at the end. - + values of slack variables will be appended at the end + OUTPUT: - - - a vector. - + + - a vector + EXAMPLES:: - + sage: A = ([1, 1], [3, 1]) sage: b = (1000, 1500) sage: c = (10, 5) @@ -2123,22 +2116,22 @@ def basic_solution(self, include_slack_variables=False): N = self.nonbasic_variables() vv += [(v, 0) for v in N] vv.sort() # We use neglex order - v = [value for _, value in vv] + v = [value for _, value in vv] return vector(self.base_ring(), v if include_slack_variables else v[:len(N)]) - + def coordinate_ring(self): r""" Return the coordinate ring of ``self``. - + OUTPUT: - + - a polynomial ring in :meth:`~LPProblemStandardForm.auxiliary_variable`, :meth:`~LPProblem.decision_variables`, and :meth:`~LPProblemStandardForm.slack_variables` of ``self`` over the - :meth:`base_ring`. - + :meth:`base_ring` + EXAMPLES:: sage: A = ([1, 1], [3, 1]) @@ -2155,37 +2148,37 @@ def coordinate_ring(self): over Rational Field """ return self.basic_variables()[0].parent() - + def dual_ratios(self): r""" Return ratios used to determine the entering variable based on leaving. - + OUTPUT: - - - a list of pairs `(r_j, x_j)` where `x_j` is a non-basic variable and + + - A list of pairs `(r_j, x_j)` where `x_j` is a non-basic variable and `r_j = c_j / a_{ij}` is the ratio of the objective coefficient `c_j` to the coefficient `a_{ij}` of `x_j` in the relation for the leaving variable `x_i`: - - .. math:: - - x_i = b_i - \dots - a_{ij} x_j - \dots. - + + .. MATH:: + + x_i = b_i - \cdots - a_{ij} x_j - \cdots. + The order of pairs matches the order of :meth:`~LPDictionary.nonbasic_variables`, but only `x_j` with negative `a_{ij}` are considered. - + EXAMPLES:: - + sage: A = ([1, 1], [3, 1], [-1, -1]) sage: b = (1000, 1500, -400) sage: c = (10, 5) sage: P = LPProblemStandardForm(A, b, c) - sage: D = P.dictionary(2, 3, 5) + sage: D = P.dictionary(2, 3, 5) sage: D.leave(3) sage: D.dual_ratios() [(5/2, x1), (5, x4)] - sage: D = P.revised_dictionary(2, 3, 5) + sage: D = P.revised_dictionary(2, 3, 5) sage: D.leave(3) sage: D.dual_ratios() [(5/2, x1), (5, x4)] @@ -2197,42 +2190,42 @@ def dual_ratios(self): def enter(self, v): r""" Set ``v`` as the entering variable of ``self``. - + INPUT: - + - ``v`` -- a non-basic variable of ``self``, can be given as a string, an actual variable, or an integer interpreted as the index of a - variable. - + variable + OUTPUT: - + - none, but the selected variable will be used as entering by methods that require an entering variable and the corresponding column will be - typeset in green. - + typeset in green + EXAMPLES:: - + sage: A = ([1, 1], [3, 1]) sage: b = (1000, 1500) sage: c = (10, 5) sage: P = LPProblemStandardForm(A, b, c) sage: D = P.initial_dictionary() sage: D.enter("x1") - + We can also use indices of variables:: - + sage: D.enter(1) - + Or variable names without quotes after injecting them:: - + sage: P.inject_variables() Defining x0, x1, x2, x3, x4 sage: D.enter(x1) - + The same works for revised dictionaries as well:: - + sage: D = P.revised_dictionary() - sage: D.enter(x1) + sage: D.enter(x1) """ v = variable(self.coordinate_ring(), v) if v not in self.nonbasic_variables(): @@ -2242,14 +2235,14 @@ def enter(self, v): def is_dual_feasible(self): r""" Check if ``self`` is dual feasible. - + OUTPUT: - + - ``True`` if all :meth:`~LPDictionary.objective_coefficients` are - non-positive, ``False`` otherwise. - + non-positive, ``False`` otherwise + EXAMPLES:: - + sage: A = ([1, 1], [3, 1]) sage: b = (1000, 1500) sage: c = (10, 5) @@ -2262,18 +2255,18 @@ def is_dual_feasible(self): False """ return all(ci <= 0 for ci in self.objective_coefficients()) - + def is_feasible(self): r""" Check if ``self`` is feasible. - + OUTPUT: - - - ``True`` if all :meth:`~LPDictionary.constant_terms` are non-negative, - ``False`` otherwise. - + + - ``True`` if all :meth:`~LPDictionary.constant_terms` are + non-negative,``False`` otherwise + EXAMPLES:: - + sage: A = ([1, 1], [3, 1]) sage: b = (1000, 1500) sage: c = (10, 5) @@ -2286,20 +2279,20 @@ def is_feasible(self): True """ return all(bi >= 0 for bi in self.constant_terms()) - + def is_optimal(self): r""" Check if ``self`` is optimal. - + OUTPUT: - + - ``True`` if ``self`` :meth:`is_feasible` and :meth:`is_dual_feasible` (i.e. all :meth:`~LPDictionary.constant_terms` are non-negative and all :meth:`~LPDictionary.objective_coefficients` are non-positive), - ``False`` otherwise. - + ``False`` otherwise. + EXAMPLES:: - + sage: A = ([1, 1], [3, 1]) sage: b = (1000, 1500) sage: c = (10, 5) @@ -2319,61 +2312,61 @@ def is_optimal(self): def leave(self, v): r""" Set ``v`` as the leaving variable of ``self``. - + INPUT: - + - ``v`` -- a basic variable of ``self``, can be given as a string, an - actual variable, or an integer interpreted as the index of a variable. - + actual variable, or an integer interpreted as the index of a variable + OUTPUT: - + - none, but the selected variable will be used as leaving by methods that require a leaving variable and the corresponding row will be - typeset in red. - + typeset in red + EXAMPLES:: - + sage: A = ([1, 1], [3, 1]) sage: b = (1000, 1500) sage: c = (10, 5) sage: P = LPProblemStandardForm(A, b, c) sage: D = P.initial_dictionary() sage: D.leave("x4") - + We can also use indices of variables:: - + sage: D.leave(4) - + Or variable names without quotes after injecting them:: - + sage: P.inject_variables() Defining x0, x1, x2, x3, x4 sage: D.leave(x4) - + The same works for revised dictionaries as well:: - + sage: D = P.revised_dictionary() - sage: D.leave(x4) + sage: D.leave(x4) """ v = variable(self.coordinate_ring(), v) if v not in self.basic_variables(): raise ValueError("leaving variable must be basic") self._leaving = v - + def possible_dual_simplex_method_steps(self): r""" Return possible dual simplex method steps for ``self``. - + OUTPUT: - - - a list of pairs ``(leaving, entering)``, where ``leaving`` is a + + - A list of pairs ``(leaving, entering)``, where ``leaving`` is a basic variable that may :meth:`leave` and ``entering`` is a list of non-basic variables that may :meth:`enter` when ``leaving`` leaves. Note that ``entering`` may be empty, indicating that the problem is infeasible (since the dual one is unbounded). - + EXAMPLES:: - + sage: A = ([1, 1], [3, 1]) sage: b = (1000, 1500) sage: c = (10, 5) @@ -2398,23 +2391,23 @@ def possible_dual_simplex_method_steps(self): self._entering = old_entering self._leaving = old_leaving return steps - + def possible_entering(self): r""" Return possible entering variables for ``self``. - + OUTPUT: - + - a list of non-basic variables of ``self`` that can :meth:`enter` on - the next step of the (dual) simplex method. - + the next step of the (dual) simplex method + EXAMPLES:: - + sage: A = ([1, 1], [3, 1]) sage: b = (1000, 1500) sage: c = (10, 5) sage: P = LPProblemStandardForm(A, b, c) - sage: D = P.initial_dictionary() + sage: D = P.initial_dictionary() sage: D.possible_entering() [x1, x2] sage: D = P.revised_dictionary() @@ -2433,23 +2426,23 @@ def possible_entering(self): raise ValueError("entering variables can be determined for feasible " "dictionaries or for dual feasible dictionaries " "with a set leaving variable") - + def possible_leaving(self): r""" Return possible leaving variables for ``self``. - + OUTPUT: - + - a list of basic variables of ``self`` that can :meth:`leave` on - the next step of the (dual) simplex method. - + the next step of the (dual) simplex method + EXAMPLES:: - + sage: A = ([1, 1], [3, 1]) sage: b = (1000, 1500) sage: c = (10, 5) sage: P = LPProblemStandardForm(A, b, c) - sage: D = P.initial_dictionary() + sage: D = P.initial_dictionary() sage: D.enter(1) sage: D.possible_leaving() [x4] @@ -2470,26 +2463,26 @@ def possible_leaving(self): raise ValueError("leaving variables can be determined for feasible " "dictionaries with a set entering variable " "or for dual feasible dictionaries") - + def possible_simplex_method_steps(self): r""" Return possible simplex method steps for ``self``. - + OUTPUT: - - - a list of pairs ``(entering, leaving)``, where ``entering`` is a - non-basic variable that may :meth:`enter` and ``leaving`` is a list of - basic variables that may :meth:`leave` when ``entering`` enters. Note - that ``leaving`` may be empty, indicating that the problem is + + - A list of pairs ``(entering, leaving)``, where ``entering`` is a + non-basic variable that may :meth:`enter` and ``leaving`` is a list + of basic variables that may :meth:`leave` when ``entering`` enters. + Note that ``leaving`` may be empty, indicating that the problem is unbounded. - + EXAMPLES:: - + sage: A = ([1, 1], [3, 1]) sage: b = (1000, 1500) sage: c = (10, 5) sage: P = LPProblemStandardForm(A, b, c) - sage: D = P.initial_dictionary() + sage: D = P.initial_dictionary() sage: D.possible_simplex_method_steps() [(x1, [x4]), (x2, [x3])] sage: D = P.revised_dictionary() @@ -2509,37 +2502,37 @@ def possible_simplex_method_steps(self): self._entering = old_entering self._leaving = old_leaving return steps - + def ratios(self): r""" Return ratios used to determine the leaving variable based on entering. - + OUTPUT: - - - a list of pairs `(r_i, x_i)` where `x_i` is a basic variable and + + - A list of pairs `(r_i, x_i)` where `x_i` is a basic variable and `r_i = b_i / a_{ik}` is the ratio of the constant term `b_i` to the coefficient `a_{ik}` of the entering variable `x_k` in the relation for `x_i`: - - .. math:: - - x_i = b_i - \dots - a_{ik} x_k - \dots. - + + .. MATH:: + + x_i = b_i - \cdots - a_{ik} x_k - \cdots. + The order of pairs matches the order of :meth:`~LPDictionary.basic_variables`, but only `x_i` with positive `a_{ik}` are considered. - + EXAMPLES:: - + sage: A = ([1, 1], [3, 1]) sage: b = (1000, 1500) sage: c = (10, 5) sage: P = LPProblemStandardForm(A, b, c) - sage: D = P.initial_dictionary() + sage: D = P.initial_dictionary() sage: D.enter(1) sage: D.ratios() [(1000, x3), (500, x4)] - sage: D = P.revised_dictionary() + sage: D = P.revised_dictionary() sage: D.enter(1) sage: D.ratios() [(1000, x3), (500, x4)] @@ -2552,48 +2545,48 @@ def ratios(self): class LPDictionary(LPAbstractDictionary): r""" Construct a dictionary for an LP problem. - + A dictionary consists of the following data: - - .. math:: - + + .. MATH:: + \begin{array}{|l|} \hline x_B = b - A x_N\\ \hline z = z^* + c x_N\\ \hline - \end{array} - + \end{array} + INPUT: - - ``A`` -- a matrix of relation coefficients; + - ``A`` -- a matrix of relation coefficients + + - ``b`` -- a vector of relation constant terms - - ``b`` -- a vector of relation constant terms; - - - ``c`` -- a vector of objective coefficients; - - - ``objective_value`` -- current value of the objective `z^*`; + - ``c`` -- a vector of objective coefficients - - ``basic_variables`` -- a list of basic variables `x_B`; + - ``objective_value`` -- current value of the objective `z^*` - - ``nonbasic_variables`` -- a list of non-basic variables `x_N`; - - - ``objective_variable`` -- an objective variable `z`. + - ``basic_variables`` -- a list of basic variables `x_B` + + - ``nonbasic_variables`` -- a list of non-basic variables `x_N` + + - ``objective_variable`` -- an objective variable `z` OUTPUT: - - a :class:`dictionary for an LP problem `. - - .. note:: - - This constructor does not check correctness of input, as it is intended - to be used internally by :class:`LPProblemStandardForm`. + - a :class:`dictionary for an LP problem ` + + .. NOTE:: + + This constructor does not check correctness of input, as it is + intended to be used internally by :class:`LPProblemStandardForm`. EXAMPLES: - + The intended way to use this class is indirect:: - + sage: A = ([1, 1], [3, 1]) sage: b = (1000, 1500) sage: c = (10, 5) @@ -2601,10 +2594,10 @@ class LPDictionary(LPAbstractDictionary): sage: D = P.initial_dictionary() sage: D LP problem dictionary (use typeset mode to see details) - + But if you want you can create a dictionary without starting with an LP problem, here is construction of the same dictionary as above:: - + sage: A = matrix(QQ, ([1, 1], [3, 1])) sage: b = vector(QQ, (1000, 1500)) sage: c = vector(QQ, (10, 5)) @@ -2622,7 +2615,7 @@ def __init__(self, A, b, c, objective_value, See :class:`LPDictionary` for documentation. TESTS::: - + sage: A = matrix(QQ, ([1, 1], [3, 1])) sage: b = vector(QQ, (1000, 1500)) sage: c = vector(QQ, (10, 5)) @@ -2644,16 +2637,16 @@ def __init__(self, A, b, c, objective_value, def __eq__(self, other): r""" Check if two LP problem dictionaries are equal. - + INPUT: - - - ``other`` -- anything. - + + - ``other`` -- anything + OUTPUT: - - - ``True`` if ``other`` is an :class:`LPDictionary` with all details the - same as ``self``, ``False`` otherwise. - + + - ``True`` if ``other`` is an :class:`LPDictionary` with all + details the same as ``self``, ``False`` otherwise. + TESTS:: sage: A = ([1, 1], [3, 1]) @@ -2661,7 +2654,7 @@ def __eq__(self, other): sage: c = (10, 5) sage: P = LPProblemStandardForm(A, b, c) sage: D = P.initial_dictionary() - + sage: A = matrix(QQ, ([1, 1], [3, 1])) sage: b = vector(QQ, (1000, 1500)) sage: c = vector(QQ, (10, 5)) @@ -2671,21 +2664,21 @@ def __eq__(self, other): sage: D2 = LPDictionary(A, b, c, 0, R.gens()[2:], R.gens()[:2], "z") sage: D2 == D True - + sage: D3 = LPDictionary(A, b, c, 0, R.gens()[2:], R.gens()[:2], "w") sage: D2 == D3 False """ - return (isinstance(other, LPDictionary) and + return (isinstance(other, LPDictionary) and self._AbcvBNz == other._AbcvBNz) - + def _latex_(self): r""" Return a LaTeX representation of ``self``. OUTPUT: - - a string. + - a string TESTS:: @@ -2704,7 +2697,7 @@ def _latex_(self): z & = & 0 & + & 10 x_{1} & + & 5 x_{2}\\ \hline \end{array} - """ + """ A, b, c, v, B, N, z = self._AbcvBNz lines = [] lines.append(r"\renewcommand{\arraystretch}{1.5}") @@ -2720,7 +2713,7 @@ def _latex_(self): lines.append(r"\hline") lines.append(_latex_product(c, N, head=[z, "=", v], drop_plus=False, allow_empty=True) + r"\\") - lines.append(r"\hline") + lines.append(r"\hline") lines.append(r"\end{array}") latex.add_package_to_preamble_if_available("color") if self._entering is not None: @@ -2732,7 +2725,7 @@ def _latex_(self): if not generate_real_LaTeX: line[e] = ("{" + line[e] + "}").replace(r"\\}", r"}\\") line[e] = r"\color{green}" + line[e] - lines[i] = "&".join(line) + lines[i] = "&".join(line) if self._leaving is not None: # Highlight the leaving variable row l = tuple(B).index(self._leaving) + 3 @@ -2754,19 +2747,19 @@ def _latex_(self): def ELLUL(self, entering, leaving): r""" Perform the Enter-Leave-LaTeX-Update-LaTeX step sequence on ``self``. - + INPUT: - - - ``entering`` -- the entering variable; - - - ``leaving`` -- the leaving variable. - + + - ``entering`` -- the entering variable + + - ``leaving`` -- the leaving variable + OUTPUT: - - - a string with LaTeX code for ``self`` before and after update. - + + - a string with LaTeX code for ``self`` before and after update + EXAMPLES:: - + sage: A = ([1, 1], [3, 1]) sage: b = (1000, 1500) sage: c = (10, 5) @@ -2789,11 +2782,11 @@ def ELLUL(self, entering, leaving): z & = & 5000 & - & \frac{10}{3} x_{4} & + & \frac{5}{3} x_{2}\\ \hline \end{array} - + This is how the above output looks when rendered: - - .. math:: - + + .. MATH:: + \renewcommand{\arraystretch}{1.5} \begin{array}{|rcrcrcr|} \hline @@ -2810,33 +2803,33 @@ def ELLUL(self, entering, leaving): z \!\!\!&\!\!\! = \!\!\!&\!\!\! 5000 \!\!\!&\!\!\! - \!\!\!&\!\!\! \frac{10}{3} x_{4} \!\!\!&\!\!\! + \!\!\!&\!\!\! \frac{5}{3} x_{2}\\ \hline \end{array} - + The column of the entering variable is green, while the row of the - leaving variable is red in the original dictionary state on the top. The - new state after the update step is shown on the bottom. + leaving variable is red in the original dictionary state on the top. + The new state after the update step is shown on the bottom. """ self.enter(entering) - self.leave(leaving) + self.leave(leaving) result = latex(self).rsplit("\n", 1)[0] # Remove \end{array} # Make an empty line in the array if generate_real_LaTeX: - result += "\n" r"\multicolumn{2}{c}{}\\[-3ex]" "\n" + result += "\n" r"\multicolumn{2}{c}{}\\[-3ex]" "\n" else: result += "\n\\\\\n" - self.update() + self.update() result += latex(self).split("\n", 2)[2] # Remove array header return LatexExpr(result) def basic_variables(self): r""" Return the basic variables of ``self``. - + OUTPUT: - - - a vector. - + + - a vector + EXAMPLES:: - + sage: A = ([1, 1], [3, 1]) sage: b = (1000, 1500) sage: c = (10, 5) @@ -2846,17 +2839,17 @@ def basic_variables(self): (x3, x4) """ return self._AbcvBNz[4] - + def constant_terms(self): r""" Return the constant terms of relations of ``self``. - + OUTPUT: - + - a vector. - + EXAMPLES:: - + sage: A = ([1, 1], [3, 1]) sage: b = (1000, 1500) sage: c = (10, 5) @@ -2866,17 +2859,17 @@ def constant_terms(self): (1000, 1500) """ return self._AbcvBNz[1] - + def entering_coefficients(self): r""" Return coefficients of the entering variable. - + OUTPUT: - - - a vector. - + + - a vector + EXAMPLES:: - + sage: A = ([1, 1], [3, 1]) sage: b = (1000, 1500) sage: c = (10, 5) @@ -2891,17 +2884,17 @@ def entering_coefficients(self): "its coefficients") k = tuple(self.nonbasic_variables()).index(self._entering) return self._AbcvBNz[0].column(k) - + def leaving_coefficients(self): r""" Return coefficients of the leaving variable. - + OUTPUT: - - - a vector. - + + - a vector + EXAMPLES:: - + sage: A = ([1, 1], [3, 1]) sage: b = (1000, 1500) sage: c = (10, 5) @@ -2916,17 +2909,17 @@ def leaving_coefficients(self): "its coefficients") i = tuple(self.basic_variables()).index(self._leaving) return self._AbcvBNz[0][i] - + def nonbasic_variables(self): r""" Return non-basic variables of ``self``. - + OUTPUT: - - - a vector. - + + - a vector + EXAMPLES:: - + sage: A = ([1, 1], [3, 1]) sage: b = (1000, 1500) sage: c = (10, 5) @@ -2936,17 +2929,17 @@ def nonbasic_variables(self): (x1, x2) """ return self._AbcvBNz[5] - + def objective_coefficients(self): r""" Return coefficients of the objective of ``self``. - + OUTPUT: - - - a vector. - + + - a vector + EXAMPLES:: - + sage: A = ([1, 1], [3, 1]) sage: b = (1000, 1500) sage: c = (10, 5) @@ -2956,18 +2949,18 @@ def objective_coefficients(self): (10, 5) """ return self._AbcvBNz[2] - + def objective_value(self): r""" Return the value of the objective at the :meth:`~LPAbstractDictionary.basic_solution` of ``self``. - + OUTPUT: - - - a number. - + + - a number + EXAMPLES:: - + sage: A = ([1, 1], [3, 1]) sage: b = (1000, 1500) sage: c = (10, 5) @@ -2977,18 +2970,18 @@ def objective_value(self): 0 """ return self._AbcvBNz[3] - + def update(self): r""" Update ``self`` using previously set entering and leaving variables. - + EXAMPLES:: - + sage: A = ([1, 1], [3, 1]) sage: b = (1000, 1500) sage: c = (10, 5) sage: P = LPProblemStandardForm(A, b, c) - sage: D = P.initial_dictionary() + sage: D = P.initial_dictionary() sage: D.objective_value() 0 sage: D.enter("x1") @@ -3010,7 +3003,7 @@ def update(self): if Ale == 0: raise ValueError("incompatible choice of entering and leaving " "variables") - # Variables + # Variables B[l] = entering N[e] = leaving # "The Changing Relation" @@ -3026,34 +3019,34 @@ def update(self): A[i] -= Aie * A[l] # Objective ce = c[e] - c[e] = 0 + c[e] = 0 self._AbcvBNz[2] = c - ce * A[l] self._AbcvBNz[3] += ce * b[l] self._entering = None self._leaving = None - + def random_dictionary(m, n, bound=5, special_probability=0.2): r""" Construct a random dictionary. - + INPUT: - - - ``m`` -- the number of constraints/basic variables; - - - ``n`` -- the number of decision/non-basic variables; - - - ``bound`` -- (default: 5) a bound on dictionary entries; - + + - ``m`` -- the number of constraints/basic variables + + - ``n`` -- the number of decision/non-basic variables + + - ``bound`` -- (default: 5) a bound on dictionary entries + - ``special_probability`` -- (default: 0.2) probability of constructing a - potentially infeasible or potentially optimal dictionary. - + potentially infeasible or potentially optimal dictionary + OUTPUT: - - - an :class:`LP problem dictionary `. - + + - an :class:`LP problem dictionary ` + EXAMPLES:: - + sage: from sage.numerical.interactive_simplex_method \ ....: import random_dictionary sage: random_dictionary(3, 4) @@ -3063,7 +3056,7 @@ def random_dictionary(m, n, bound=5, special_probability=0.2): if special_probability < random(): b = random_vector(ZZ, m, x=0, y=bound).change_ring(QQ) else: # Allow infeasible dictionary - b = random_vector(ZZ, m, x=-bound, y=bound).change_ring(QQ) + b = random_vector(ZZ, m, x=-bound, y=bound).change_ring(QQ) if special_probability < random(): c = random_vector(ZZ, n, x=-bound, y=bound).change_ring(QQ) else: # Make dual feasible dictionary @@ -3079,32 +3072,32 @@ def random_dictionary(m, n, bound=5, special_probability=0.2): class LPRevisedDictionary(LPAbstractDictionary): r""" Construct a revised dictionary for an LP problem. - + INPUT: - ``problem`` -- an :class:`LP problem in standard form - `; + ` - - ``basic_variables`` -- a list of basic variables or their indices. + - ``basic_variables`` -- a list of basic variables or their indices OUTPUT: - - a :class:`revised dictionary for an LP problem `. - + - a :class:`revised dictionary for an LP problem ` + A revised dictionary encodes the same relations as a :class:`regular dictionary `, but stores only what is "necessary to efficiently compute data for the simplex method". - + Let the original problem be - - .. math:: - + + .. MATH:: + \begin{array}{l} \pm \max cx \\ Ax \leq b \\ x \geq 0 \end{array} - + Let `\bar{x}` be the vector of :meth:`~LPProblem.decision_variables` `x` followed by the :meth:`~LPProblemStandardForm.slack_variables`. Let `\bar{c}` be the vector of :meth:`~LPProblem.objective_coefficients` `c` @@ -3112,16 +3105,16 @@ class LPRevisedDictionary(LPAbstractDictionary): Let `\bar{A} = (A | I)` be the matrix of :meth:`~LPProblem.constraint_coefficients` `A` augmented by the identity matrix as columns corresponding to the slack variables. Then the problem - above can be written as - - .. math:: - + above can be written as + + .. MATH:: + \begin{array}{l} \pm \max \bar{c} \bar{x} \\ \bar{A} \bar{x} = b \\ \bar{x} \geq 0 \end{array} - + and any dictionary is a system of equations equivalent to `\bar{A} \bar{x} = b`, but resolved for :meth:`basic_variables` `x_B` in terms of :meth:`nonbasic_variables` `x_N` together with the expression for @@ -3129,24 +3122,24 @@ class LPRevisedDictionary(LPAbstractDictionary): "splitting `\bar{c}` into basic and non-basic parts". Let :meth:`B` and :meth:`A_N` be the splitting of `\bar{A}`. Then the corresponding dictionary is - - .. math:: - + + .. MATH:: + \begin{array}{|l|} \hline x_B = B^{-1} b - B^{-1} A_N x_N\\ \hline z = y b + \left(c_N - y^T A_N\right) x_N\\ \hline - \end{array} - + \end{array} + where `y = c_B^T B^{-1}`. To proceed with the simplex method, it is not necessary to compute all entries of this dictionary. On the other hand, any entry is easy to compute, if you know `B^{-1}`, so we keep track of it through the update steps. - + EXAMPLES:: - + sage: A = ([1, 1], [3, 1]) sage: b = (1000, 1500) sage: c = (10, 5) @@ -3158,16 +3151,16 @@ class LPRevisedDictionary(LPAbstractDictionary): (x1, x2) sage: D LP problem dictionary (use typeset mode to see details) - + The same dictionary can be constructed through the problem:: - + sage: P.revised_dictionary(1, 2) == D True - + When this dictionary is typeset, you will see two tables like these ones: - - .. math:: - + + .. MATH:: + \renewcommand{\arraystretch}{1.500000} \begin{array}{l} \begin{array}{l|r|rr||r||r} @@ -3186,7 +3179,7 @@ class LPRevisedDictionary(LPAbstractDictionary): c_N^T - y^T A_N & -\frac{5}{2} & -\frac{5}{2} \\ \end{array} \end{array} - + More details will be shown if entering and leaving variables are set, but in any case the top table shows `B^{-1}` and a few extra columns, while the bottom one shows several rows: these are related to columns and rows of @@ -3198,7 +3191,7 @@ def __init__(self, problem, basic_variables): See :class:`LPRevisedDictionary` for documentation. TESTS::: - + sage: A = ([1, 1], [3, 1]) sage: b = (1000, 1500) sage: c = (10, 5) @@ -3219,17 +3212,17 @@ def __init__(self, problem, basic_variables): def __eq__(self, other): r""" Check if two revised LP problem dictionaries are equal. - + INPUT: - - - ``other`` -- anything. - + + - ``other`` -- anything + OUTPUT: - + - ``True`` if ``other`` is an :class:`LPRevisedDictionary` for the same :class:`LPProblemStandardForm` with the same :meth:`basic_variables`, - ``False`` otherwise. - + ``False`` otherwise + TESTS:: sage: A = ([1, 1], [3, 1]) @@ -3248,17 +3241,17 @@ def __eq__(self, other): sage: D1 == D3 False """ - return (isinstance(other, LPRevisedDictionary) and + return (isinstance(other, LPRevisedDictionary) and self._problem == other._problem and self._x_B == other._x_B) - + def _latex_(self): r""" Return a LaTeX representation of ``self``. OUTPUT: - - a string. + - a string TESTS:: @@ -3282,14 +3275,14 @@ def _latex_(self): \begin{array}{r|rr} x_N & \color{green} x_{1} & x_{2} \\ \hline - c_N^T & \color{green} 10 & 5 \\ + c_N^T & \color{green} 10 & 5 \\ \hline y^T A_N & \color{green} 0 & 0 \\ \hline c_N^T - y^T A_N & \color{green} 10 & 5 \\ \end{array} \end{array} - """ + """ latex.add_package_to_preamble_if_available("color") x_B = self._x_B m = len(x_B) @@ -3317,7 +3310,7 @@ def _latex_(self): lines.append(r"\hline") Bi = self.B_inverse() c_B = self.c_B() - y = self.y() + y = self.y() Bib = self.constant_terms() if entering is not None: Biae = self.entering_coefficients() @@ -3343,16 +3336,16 @@ def _latex_(self): lines.append(" & ".join(terms) + r" \\") lines.append(r"\end{array}") top = "\n".join(lines) - + def make_line(header, terms): terms = map(latex, terms) if entering is not None: t = terms[k] if not generate_real_LaTeX: t = "{" + t + "}" - terms[k] = r"\color{green} " + t + terms[k] = r"\color{green} " + t lines.append(" & ".join([header] + terms) + r" \\") - + lines = [] x_N = self.x_N() if entering is not None: @@ -3381,17 +3374,17 @@ def make_line(header, terms): def A(self, v): r""" Return the column of constraint coefficients corresponding to ``v``. - + INPUT: - - - ``v`` -- a variable, its name, or its index. - + + - ``v`` -- a variable, its name, or its index + OUTPUT: - - - a vector. - + + - a vector + EXAMPLES:: - + sage: A = ([1, 1], [3, 1]) sage: b = (1000, 1500) sage: c = (10, 5) @@ -3419,14 +3412,15 @@ def A(self, v): def A_N(self): r""" - Return the `A_N` matrix, constraint coefficients of non-basic variables. - + Return the `A_N` matrix, constraint coefficients of + non-basic variables. + OUTPUT: - - - a matrix. - + + - a matrix + EXAMPLES:: - + sage: A = ([1, 1], [3, 1]) sage: b = (1000, 1500) sage: c = (10, 5) @@ -3438,17 +3432,18 @@ def A_N(self): """ return column_matrix(self.problem().base_ring(), [self.A(x) for x in self.x_N()]) - + def B(self): r""" - Return the `B` matrix, i.e. constraint coefficients of basic variables. - + Return the `B` matrix, i.e. constraint coefficients of + basic variables. + OUTPUT: - - - a matrix. - + + - a matrix + EXAMPLES:: - + sage: A = ([1, 1], [3, 1]) sage: b = (1000, 1500) sage: c = (10, 5) @@ -3464,16 +3459,16 @@ def B(self): def B_inverse(self): r""" Return the inverse of the :meth:`B` matrix. - + This inverse matrix is stored and computed during dictionary update in a more efficient way than generic inversion. - + OUTPUT: - - - a matrix. - + + - a matrix + EXAMPLES:: - + sage: A = ([1, 1], [3, 1]) sage: b = (1000, 1500) sage: c = (10, 5) @@ -3492,17 +3487,17 @@ def B_inverse(self): def E(self): r""" Return the eta matrix between ``self`` and the next dictionary. - + OUTPUT: - - - a matrix. - - If `B_\mathrm{old}` is the current matrix `B` and `B_\mathrm{new}` is - the `B` matrix of the next dictionary (after the update step), then - `B_\mathrm{new} = B_\mathrm{old} E`. - + + - a matrix + + If `B_{\mathrm{old}}` is the current matrix `B` and `B_{\mathrm{new}}` + is the `B` matrix of the next dictionary (after the update step), then + `B_{\mathrm{new}} = B_{\mathrm{old}} E`. + EXAMPLES:: - + sage: A = ([1, 1], [3, 1]) sage: b = (1000, 1500) sage: c = (10, 5) @@ -3525,20 +3520,20 @@ def E(self): E = identity_matrix(self.base_ring(), self.problem().m()) E.set_column(l, self.entering_coefficients()) return E - + def E_inverse(self): r""" Return the inverse of the matrix :meth:`E`. - + This inverse matrix is computed in a more efficient way than generic inversion. - + OUTPUT: - - - a matrix. - + + - a matrix + EXAMPLES:: - + sage: A = ([1, 1], [3, 1]) sage: b = (1000, 1500) sage: c = (10, 5) @@ -3563,21 +3558,21 @@ def E_inverse(self): def basic_indices(self): r""" Return the basic indices of ``self``. - - .. note:: - + + .. NOTE:: + Basic indices are indices of :meth:`basic_variables` in the list of generators of the :meth:`~LPProblemStandardForm.coordinate_ring` of the :meth:`problem` of ``self``, they may not coincide with the indices of variables which are parts of their names. (They will for the default indexed names.) - + OUTPUT: - + - a list. - + EXAMPLES:: - + sage: A = ([1, 1], [3, 1]) sage: b = (1000, 1500) sage: c = (10, 5) @@ -3586,19 +3581,19 @@ def basic_indices(self): sage: D.basic_indices() [3, 4] """ - gens = self.coordinate_ring().gens() + gens = self.coordinate_ring().gens() return [gens.index(x) for x in self._x_B] def basic_variables(self): r""" Return the basic variables of ``self``. - + OUTPUT: - - - a vector. - + + - a vector + EXAMPLES:: - + sage: A = ([1, 1], [3, 1]) sage: b = (1000, 1500) sage: c = (10, 5) @@ -3612,13 +3607,13 @@ def basic_variables(self): def c_B(self): r""" Return the `c_B` vector, objective coefficients of basic variables. - + OUTPUT: - - - a vector. - + + - a vector + EXAMPLES:: - + sage: A = ([1, 1], [3, 1]) sage: b = (1000, 1500) sage: c = (10, 5) @@ -3638,17 +3633,17 @@ def c_B(self): c_D = P.c() n = P.n() return vector(R, [c_D[k - 1] if k <= n else 0 for k in BB]) - + def c_N(self): r""" Return the `c_N` vector, objective coefficients of non-basic variables. - + OUTPUT: - - - a vector. - + + - a vector + EXAMPLES:: - + sage: A = ([1, 1], [3, 1]) sage: b = (1000, 1500) sage: c = (10, 5) @@ -3666,17 +3661,17 @@ def c_N(self): c_D = P.c() return vector(R, (c_D[k - 1] if k <= n else 0 for k in self.nonbasic_indices())) - + def constant_terms(self): r""" Return constant terms in the relations of ``self``. - + OUTPUT: - - - a vector. - + + - a vector + EXAMPLES:: - + sage: A = ([1, 1], [3, 1]) sage: b = (1000, 1500) sage: c = (10, 5) @@ -3686,17 +3681,17 @@ def constant_terms(self): (1000, 1500) """ return self.B_inverse() * self.problem().b() - + def dictionary(self): r""" Return a regular LP dictionary matching ``self``. - + OUTPUT: - - - an :class:`LP dictionary `. - + + - an :class:`LP dictionary ` + EXAMPLES:: - + sage: A = ([1, 1], [3, 1], [-1, -1]) sage: b = (1000, 1500, -400) sage: c = (10, 5) @@ -3715,17 +3710,17 @@ def dictionary(self): D._entering = self._entering D._leaving = self._leaving return D - + def entering_coefficients(self): r""" Return coefficients of the entering variable. - + OUTPUT: - - - a vector. - + + - a vector + EXAMPLES:: - + sage: A = ([1, 1], [3, 1]) sage: b = (1000, 1500) sage: c = (10, 5) @@ -3739,17 +3734,17 @@ def entering_coefficients(self): raise ValueError("entering variable must be chosen to compute " "its coefficients") return self.B_inverse() * self.A(self._entering) - + def leaving_coefficients(self): r""" Return coefficients of the leaving variable. - + OUTPUT: - - - a vector. - + + - a vector + EXAMPLES:: - + sage: A = ([1, 1], [3, 1]) sage: b = (1000, 1500) sage: c = (10, 5) @@ -3764,26 +3759,26 @@ def leaving_coefficients(self): "its coefficients") i = self.basic_variables().list().index(self._leaving) return self.B_inverse()[i] * self.A_N() - + def nonbasic_indices(self): r""" Return the non-basic indices of ``self``. - - .. note:: - + + .. NOTE:: + Non-basic indices are indices of :meth:`nonbasic_variables` in the list of generators of the :meth:`~LPProblemStandardForm.coordinate_ring` of the :meth:`problem` of ``self``, they may not coincide with the indices of variables which are parts of their names. (They will for the default indexed names.) - + OUTPUT: - - - a list. - + + - a list + EXAMPLES:: - + sage: A = ([1, 1], [3, 1]) sage: b = (1000, 1500) sage: c = (10, 5) @@ -3792,19 +3787,19 @@ def nonbasic_indices(self): sage: D.nonbasic_indices() [1, 2] """ - gens = self.coordinate_ring().gens() + gens = self.coordinate_ring().gens() return [gens.index(x) for x in self.x_N()] def nonbasic_variables(self): r""" Return non-basic variables of ``self``. - + OUTPUT: - - - a vector. - + + - a vector + EXAMPLES:: - + sage: A = ([1, 1], [3, 1]) sage: b = (1000, 1500) sage: c = (10, 5) @@ -3813,22 +3808,22 @@ def nonbasic_variables(self): sage: D.nonbasic_variables() (x1, x2) """ - R = self.coordinate_ring() + R = self.coordinate_ring() return vector(R, [xi for xi in R.gens()[1:] if xi not in self._x_B]) - + def objective_coefficients(self): r""" Return coefficients of the objective of ``self``. - + OUTPUT: - - - a vector. - + + - a vector + These are coefficients of non-basic variables when basic variables are eliminated. - + EXAMPLES:: - + sage: A = ([1, 1], [3, 1]) sage: b = (1000, 1500) sage: c = (10, 5) @@ -3838,17 +3833,17 @@ def objective_coefficients(self): (10, 5) """ return self.c_N() - self.y() * self.A_N() - + def objective_value(self): r""" Return the value of the objective at the basic solution of ``self``. - + OUTPUT: - - - a number. - + + - a number + EXAMPLES:: - + sage: A = ([1, 1], [3, 1]) sage: b = (1000, 1500) sage: c = (10, 5) @@ -3858,15 +3853,15 @@ def objective_value(self): 0 """ return self.y() * self.problem().b() - + def problem(self): r""" Return the original problem. - + OUTPUT: - - - an :class:`LP problem in standard form `. - + + - an :class:`LP problem in standard form ` + EXAMPLES:: sage: A = ([1, 1], [3, 1]) @@ -3878,13 +3873,13 @@ def problem(self): True """ return self._problem - + def update(self): r""" Update ``self`` using previously set entering and leaving variables. - + EXAMPLES:: - + sage: A = ([1, 1], [3, 1]) sage: b = (1000, 1500) sage: c = (10, 5) @@ -3904,15 +3899,16 @@ def update(self): self._x_B[self._x_B.list().index(self._leaving)] = self._entering self._entering = None self._leaving = None - + def y(self): r""" - Return the `y` vector, the product of :meth:`c_B` and :meth:`B_inverse`. - + Return the `y` vector, the product of :meth:`c_B` and + :meth:`B_inverse`. + OUTPUT: - - - a vector. - + + - a vector + EXAMPLES:: sage: A = ([1, 1], [3, 1]) @@ -3924,7 +3920,8 @@ def y(self): (0, 0) """ return self.c_B() * self.B_inverse() - + # Aliases for the standard notation x_B = basic_variables x_N = nonbasic_variables +