123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708 |
- """
- A top-level linear programming interface.
- .. versionadded:: 0.15.0
- Functions
- ---------
- .. autosummary::
- :toctree: generated/
- linprog
- linprog_verbose_callback
- linprog_terse_callback
- """
- import numpy as np
- from ._optimize import OptimizeResult, OptimizeWarning
- from warnings import warn
- from ._linprog_highs import _linprog_highs
- from ._linprog_ip import _linprog_ip
- from ._linprog_simplex import _linprog_simplex
- from ._linprog_rs import _linprog_rs
- from ._linprog_doc import (_linprog_highs_doc, _linprog_ip_doc,
- _linprog_rs_doc, _linprog_simplex_doc,
- _linprog_highs_ipm_doc, _linprog_highs_ds_doc)
- from ._linprog_util import (
- _parse_linprog, _presolve, _get_Abc, _LPProblem, _autoscale,
- _postsolve, _check_result, _display_summary)
- from copy import deepcopy
- __all__ = ['linprog', 'linprog_verbose_callback', 'linprog_terse_callback']
- __docformat__ = "restructuredtext en"
- LINPROG_METHODS = ['simplex', 'revised simplex', 'interior-point', 'highs', 'highs-ds', 'highs-ipm']
- def linprog_verbose_callback(res):
- """
- A sample callback function demonstrating the linprog callback interface.
- This callback produces detailed output to sys.stdout before each iteration
- and after the final iteration of the simplex algorithm.
- Parameters
- ----------
- res : A `scipy.optimize.OptimizeResult` consisting of the following fields:
- x : 1-D array
- The independent variable vector which optimizes the linear
- programming problem.
- fun : float
- Value of the objective function.
- success : bool
- True if the algorithm succeeded in finding an optimal solution.
- slack : 1-D array
- The values of the slack variables. Each slack variable corresponds
- to an inequality constraint. If the slack is zero, then the
- corresponding constraint is active.
- con : 1-D array
- The (nominally zero) residuals of the equality constraints, that is,
- ``b - A_eq @ x``
- phase : int
- The phase of the optimization being executed. In phase 1 a basic
- feasible solution is sought and the T has an additional row
- representing an alternate objective function.
- status : int
- An integer representing the exit status of the optimization::
- 0 : Optimization terminated successfully
- 1 : Iteration limit reached
- 2 : Problem appears to be infeasible
- 3 : Problem appears to be unbounded
- 4 : Serious numerical difficulties encountered
- nit : int
- The number of iterations performed.
- message : str
- A string descriptor of the exit status of the optimization.
- """
- x = res['x']
- fun = res['fun']
- phase = res['phase']
- status = res['status']
- nit = res['nit']
- message = res['message']
- complete = res['complete']
- saved_printoptions = np.get_printoptions()
- np.set_printoptions(linewidth=500,
- formatter={'float': lambda x: "{0: 12.4f}".format(x)})
- if status:
- print('--------- Simplex Early Exit -------\n')
- print('The simplex method exited early with status {0:d}'.format(status))
- print(message)
- elif complete:
- print('--------- Simplex Complete --------\n')
- print('Iterations required: {}'.format(nit))
- else:
- print('--------- Iteration {0:d} ---------\n'.format(nit))
- if nit > 0:
- if phase == 1:
- print('Current Pseudo-Objective Value:')
- else:
- print('Current Objective Value:')
- print('f = ', fun)
- print()
- print('Current Solution Vector:')
- print('x = ', x)
- print()
- np.set_printoptions(**saved_printoptions)
- def linprog_terse_callback(res):
- """
- A sample callback function demonstrating the linprog callback interface.
- This callback produces brief output to sys.stdout before each iteration
- and after the final iteration of the simplex algorithm.
- Parameters
- ----------
- res : A `scipy.optimize.OptimizeResult` consisting of the following fields:
- x : 1-D array
- The independent variable vector which optimizes the linear
- programming problem.
- fun : float
- Value of the objective function.
- success : bool
- True if the algorithm succeeded in finding an optimal solution.
- slack : 1-D array
- The values of the slack variables. Each slack variable corresponds
- to an inequality constraint. If the slack is zero, then the
- corresponding constraint is active.
- con : 1-D array
- The (nominally zero) residuals of the equality constraints, that is,
- ``b - A_eq @ x``.
- phase : int
- The phase of the optimization being executed. In phase 1 a basic
- feasible solution is sought and the T has an additional row
- representing an alternate objective function.
- status : int
- An integer representing the exit status of the optimization::
- 0 : Optimization terminated successfully
- 1 : Iteration limit reached
- 2 : Problem appears to be infeasible
- 3 : Problem appears to be unbounded
- 4 : Serious numerical difficulties encountered
- nit : int
- The number of iterations performed.
- message : str
- A string descriptor of the exit status of the optimization.
- """
- nit = res['nit']
- x = res['x']
- if nit == 0:
- print("Iter: X:")
- print("{0: <5d} ".format(nit), end="")
- print(x)
- def linprog(c, A_ub=None, b_ub=None, A_eq=None, b_eq=None,
- bounds=None, method='highs', callback=None,
- options=None, x0=None, integrality=None):
- r"""
- Linear programming: minimize a linear objective function subject to linear
- equality and inequality constraints.
- Linear programming solves problems of the following form:
- .. math::
- \min_x \ & c^T x \\
- \mbox{such that} \ & A_{ub} x \leq b_{ub},\\
- & A_{eq} x = b_{eq},\\
- & l \leq x \leq u ,
- where :math:`x` is a vector of decision variables; :math:`c`,
- :math:`b_{ub}`, :math:`b_{eq}`, :math:`l`, and :math:`u` are vectors; and
- :math:`A_{ub}` and :math:`A_{eq}` are matrices.
- Alternatively, that's:
- minimize::
- c @ x
- such that::
- A_ub @ x <= b_ub
- A_eq @ x == b_eq
- lb <= x <= ub
- Note that by default ``lb = 0`` and ``ub = None`` unless specified with
- ``bounds``.
- Parameters
- ----------
- c : 1-D array
- The coefficients of the linear objective function to be minimized.
- A_ub : 2-D array, optional
- The inequality constraint matrix. Each row of ``A_ub`` specifies the
- coefficients of a linear inequality constraint on ``x``.
- b_ub : 1-D array, optional
- The inequality constraint vector. Each element represents an
- upper bound on the corresponding value of ``A_ub @ x``.
- A_eq : 2-D array, optional
- The equality constraint matrix. Each row of ``A_eq`` specifies the
- coefficients of a linear equality constraint on ``x``.
- b_eq : 1-D array, optional
- The equality constraint vector. Each element of ``A_eq @ x`` must equal
- the corresponding element of ``b_eq``.
- bounds : sequence, optional
- A sequence of ``(min, max)`` pairs for each element in ``x``, defining
- the minimum and maximum values of that decision variable. Use ``None``
- to indicate that there is no bound. By default, bounds are
- ``(0, None)`` (all decision variables are non-negative).
- If a single tuple ``(min, max)`` is provided, then ``min`` and
- ``max`` will serve as bounds for all decision variables.
- method : str, optional
- The algorithm used to solve the standard form problem.
- :ref:`'highs' <optimize.linprog-highs>` (default),
- :ref:`'highs-ds' <optimize.linprog-highs-ds>`,
- :ref:`'highs-ipm' <optimize.linprog-highs-ipm>`,
- :ref:`'interior-point' <optimize.linprog-interior-point>` (legacy),
- :ref:`'revised simplex' <optimize.linprog-revised_simplex>` (legacy),
- and
- :ref:`'simplex' <optimize.linprog-simplex>` (legacy) are supported.
- The legacy methods are deprecated and will be removed in SciPy 1.11.0.
- callback : callable, optional
- If a callback function is provided, it will be called at least once per
- iteration of the algorithm. The callback function must accept a single
- `scipy.optimize.OptimizeResult` consisting of the following fields:
- x : 1-D array
- The current solution vector.
- fun : float
- The current value of the objective function ``c @ x``.
- success : bool
- ``True`` when the algorithm has completed successfully.
- slack : 1-D array
- The (nominally positive) values of the slack,
- ``b_ub - A_ub @ x``.
- con : 1-D array
- The (nominally zero) residuals of the equality constraints,
- ``b_eq - A_eq @ x``.
- phase : int
- The phase of the algorithm being executed.
- status : int
- An integer representing the status of the algorithm.
- ``0`` : Optimization proceeding nominally.
- ``1`` : Iteration limit reached.
- ``2`` : Problem appears to be infeasible.
- ``3`` : Problem appears to be unbounded.
- ``4`` : Numerical difficulties encountered.
- nit : int
- The current iteration number.
- message : str
- A string descriptor of the algorithm status.
- Callback functions are not currently supported by the HiGHS methods.
- options : dict, optional
- A dictionary of solver options. All methods accept the following
- options:
- maxiter : int
- Maximum number of iterations to perform.
- Default: see method-specific documentation.
- disp : bool
- Set to ``True`` to print convergence messages.
- Default: ``False``.
- presolve : bool
- Set to ``False`` to disable automatic presolve.
- Default: ``True``.
- All methods except the HiGHS solvers also accept:
- tol : float
- A tolerance which determines when a residual is "close enough" to
- zero to be considered exactly zero.
- autoscale : bool
- Set to ``True`` to automatically perform equilibration.
- Consider using this option if the numerical values in the
- constraints are separated by several orders of magnitude.
- Default: ``False``.
- rr : bool
- Set to ``False`` to disable automatic redundancy removal.
- Default: ``True``.
- rr_method : string
- Method used to identify and remove redundant rows from the
- equality constraint matrix after presolve. For problems with
- dense input, the available methods for redundancy removal are:
- "SVD":
- Repeatedly performs singular value decomposition on
- the matrix, detecting redundant rows based on nonzeros
- in the left singular vectors that correspond with
- zero singular values. May be fast when the matrix is
- nearly full rank.
- "pivot":
- Uses the algorithm presented in [5]_ to identify
- redundant rows.
- "ID":
- Uses a randomized interpolative decomposition.
- Identifies columns of the matrix transpose not used in
- a full-rank interpolative decomposition of the matrix.
- None:
- Uses "svd" if the matrix is nearly full rank, that is,
- the difference between the matrix rank and the number
- of rows is less than five. If not, uses "pivot". The
- behavior of this default is subject to change without
- prior notice.
- Default: None.
- For problems with sparse input, this option is ignored, and the
- pivot-based algorithm presented in [5]_ is used.
- For method-specific options, see
- :func:`show_options('linprog') <show_options>`.
- x0 : 1-D array, optional
- Guess values of the decision variables, which will be refined by
- the optimization algorithm. This argument is currently used only by the
- 'revised simplex' method, and can only be used if `x0` represents a
- basic feasible solution.
- integrality : 1-D array or int, optional
- Indicates the type of integrality constraint on each decision variable.
- ``0`` : Continuous variable; no integrality constraint.
- ``1`` : Integer variable; decision variable must be an integer
- within `bounds`.
- ``2`` : Semi-continuous variable; decision variable must be within
- `bounds` or take value ``0``.
- ``3`` : Semi-integer variable; decision variable must be an integer
- within `bounds` or take value ``0``.
- By default, all variables are continuous.
- For mixed integrality constraints, supply an array of shape `c.shape`.
- To infer a constraint on each decision variable from shorter inputs,
- the argument will be broadcasted to `c.shape` using `np.broadcast_to`.
- This argument is currently used only by the ``'highs'`` method and
- ignored otherwise.
- Returns
- -------
- res : OptimizeResult
- A :class:`scipy.optimize.OptimizeResult` consisting of the fields
- below. Note that the return types of the fields may depend on whether
- the optimization was successful, therefore it is recommended to check
- `OptimizeResult.status` before relying on the other fields:
- x : 1-D array
- The values of the decision variables that minimizes the
- objective function while satisfying the constraints.
- fun : float
- The optimal value of the objective function ``c @ x``.
- slack : 1-D array
- The (nominally positive) values of the slack variables,
- ``b_ub - A_ub @ x``.
- con : 1-D array
- The (nominally zero) residuals of the equality constraints,
- ``b_eq - A_eq @ x``.
- success : bool
- ``True`` when the algorithm succeeds in finding an optimal
- solution.
- status : int
- An integer representing the exit status of the algorithm.
- ``0`` : Optimization terminated successfully.
- ``1`` : Iteration limit reached.
- ``2`` : Problem appears to be infeasible.
- ``3`` : Problem appears to be unbounded.
- ``4`` : Numerical difficulties encountered.
- nit : int
- The total number of iterations performed in all phases.
- message : str
- A string descriptor of the exit status of the algorithm.
- See Also
- --------
- show_options : Additional options accepted by the solvers.
- Notes
- -----
- This section describes the available solvers that can be selected by the
- 'method' parameter.
- `'highs-ds'` and
- `'highs-ipm'` are interfaces to the
- HiGHS simplex and interior-point method solvers [13]_, respectively.
- `'highs'` (default) chooses between
- the two automatically. These are the fastest linear
- programming solvers in SciPy, especially for large, sparse problems;
- which of these two is faster is problem-dependent.
- The other solvers (`'interior-point'`, `'revised simplex'`, and
- `'simplex'`) are legacy methods and will be removed in SciPy 1.11.0.
- Method *highs-ds* is a wrapper of the C++ high performance dual
- revised simplex implementation (HSOL) [13]_, [14]_. Method *highs-ipm*
- is a wrapper of a C++ implementation of an **i**\ nterior-\ **p**\ oint
- **m**\ ethod [13]_; it features a crossover routine, so it is as accurate
- as a simplex solver. Method *highs* chooses between the two automatically.
- For new code involving `linprog`, we recommend explicitly choosing one of
- these three method values.
- .. versionadded:: 1.6.0
- Method *interior-point* uses the primal-dual path following algorithm
- as outlined in [4]_. This algorithm supports sparse constraint matrices and
- is typically faster than the simplex methods, especially for large, sparse
- problems. Note, however, that the solution returned may be slightly less
- accurate than those of the simplex methods and will not, in general,
- correspond with a vertex of the polytope defined by the constraints.
- .. versionadded:: 1.0.0
- Method *revised simplex* uses the revised simplex method as described in
- [9]_, except that a factorization [11]_ of the basis matrix, rather than
- its inverse, is efficiently maintained and used to solve the linear systems
- at each iteration of the algorithm.
- .. versionadded:: 1.3.0
- Method *simplex* uses a traditional, full-tableau implementation of
- Dantzig's simplex algorithm [1]_, [2]_ (*not* the
- Nelder-Mead simplex). This algorithm is included for backwards
- compatibility and educational purposes.
- .. versionadded:: 0.15.0
- Before applying *interior-point*, *revised simplex*, or *simplex*,
- a presolve procedure based on [8]_ attempts
- to identify trivial infeasibilities, trivial unboundedness, and potential
- problem simplifications. Specifically, it checks for:
- - rows of zeros in ``A_eq`` or ``A_ub``, representing trivial constraints;
- - columns of zeros in ``A_eq`` `and` ``A_ub``, representing unconstrained
- variables;
- - column singletons in ``A_eq``, representing fixed variables; and
- - column singletons in ``A_ub``, representing simple bounds.
- If presolve reveals that the problem is unbounded (e.g. an unconstrained
- and unbounded variable has negative cost) or infeasible (e.g., a row of
- zeros in ``A_eq`` corresponds with a nonzero in ``b_eq``), the solver
- terminates with the appropriate status code. Note that presolve terminates
- as soon as any sign of unboundedness is detected; consequently, a problem
- may be reported as unbounded when in reality the problem is infeasible
- (but infeasibility has not been detected yet). Therefore, if it is
- important to know whether the problem is actually infeasible, solve the
- problem again with option ``presolve=False``.
- If neither infeasibility nor unboundedness are detected in a single pass
- of the presolve, bounds are tightened where possible and fixed
- variables are removed from the problem. Then, linearly dependent rows
- of the ``A_eq`` matrix are removed, (unless they represent an
- infeasibility) to avoid numerical difficulties in the primary solve
- routine. Note that rows that are nearly linearly dependent (within a
- prescribed tolerance) may also be removed, which can change the optimal
- solution in rare cases. If this is a concern, eliminate redundancy from
- your problem formulation and run with option ``rr=False`` or
- ``presolve=False``.
- Several potential improvements can be made here: additional presolve
- checks outlined in [8]_ should be implemented, the presolve routine should
- be run multiple times (until no further simplifications can be made), and
- more of the efficiency improvements from [5]_ should be implemented in the
- redundancy removal routines.
- After presolve, the problem is transformed to standard form by converting
- the (tightened) simple bounds to upper bound constraints, introducing
- non-negative slack variables for inequality constraints, and expressing
- unbounded variables as the difference between two non-negative variables.
- Optionally, the problem is automatically scaled via equilibration [12]_.
- The selected algorithm solves the standard form problem, and a
- postprocessing routine converts the result to a solution to the original
- problem.
- References
- ----------
- .. [1] Dantzig, George B., Linear programming and extensions. Rand
- Corporation Research Study Princeton Univ. Press, Princeton, NJ,
- 1963
- .. [2] Hillier, S.H. and Lieberman, G.J. (1995), "Introduction to
- Mathematical Programming", McGraw-Hill, Chapter 4.
- .. [3] Bland, Robert G. New finite pivoting rules for the simplex method.
- Mathematics of Operations Research (2), 1977: pp. 103-107.
- .. [4] Andersen, Erling D., and Knud D. Andersen. "The MOSEK interior point
- optimizer for linear programming: an implementation of the
- homogeneous algorithm." High performance optimization. Springer US,
- 2000. 197-232.
- .. [5] Andersen, Erling D. "Finding all linearly dependent rows in
- large-scale linear programming." Optimization Methods and Software
- 6.3 (1995): 219-227.
- .. [6] Freund, Robert M. "Primal-Dual Interior-Point Methods for Linear
- Programming based on Newton's Method." Unpublished Course Notes,
- March 2004. Available 2/25/2017 at
- https://ocw.mit.edu/courses/sloan-school-of-management/15-084j-nonlinear-programming-spring-2004/lecture-notes/lec14_int_pt_mthd.pdf
- .. [7] Fourer, Robert. "Solving Linear Programs by Interior-Point Methods."
- Unpublished Course Notes, August 26, 2005. Available 2/25/2017 at
- http://www.4er.org/CourseNotes/Book%20B/B-III.pdf
- .. [8] Andersen, Erling D., and Knud D. Andersen. "Presolving in linear
- programming." Mathematical Programming 71.2 (1995): 221-245.
- .. [9] Bertsimas, Dimitris, and J. Tsitsiklis. "Introduction to linear
- programming." Athena Scientific 1 (1997): 997.
- .. [10] Andersen, Erling D., et al. Implementation of interior point
- methods for large scale linear programming. HEC/Universite de
- Geneve, 1996.
- .. [11] Bartels, Richard H. "A stabilization of the simplex method."
- Journal in Numerische Mathematik 16.5 (1971): 414-434.
- .. [12] Tomlin, J. A. "On scaling linear programming problems."
- Mathematical Programming Study 4 (1975): 146-166.
- .. [13] Huangfu, Q., Galabova, I., Feldmeier, M., and Hall, J. A. J.
- "HiGHS - high performance software for linear optimization."
- https://highs.dev/
- .. [14] Huangfu, Q. and Hall, J. A. J. "Parallelizing the dual revised
- simplex method." Mathematical Programming Computation, 10 (1),
- 119-142, 2018. DOI: 10.1007/s12532-017-0130-5
- Examples
- --------
- Consider the following problem:
- .. math::
- \min_{x_0, x_1} \ -x_0 + 4x_1 & \\
- \mbox{such that} \ -3x_0 + x_1 & \leq 6,\\
- -x_0 - 2x_1 & \geq -4,\\
- x_1 & \geq -3.
- The problem is not presented in the form accepted by `linprog`. This is
- easily remedied by converting the "greater than" inequality
- constraint to a "less than" inequality constraint by
- multiplying both sides by a factor of :math:`-1`. Note also that the last
- constraint is really the simple bound :math:`-3 \leq x_1 \leq \infty`.
- Finally, since there are no bounds on :math:`x_0`, we must explicitly
- specify the bounds :math:`-\infty \leq x_0 \leq \infty`, as the
- default is for variables to be non-negative. After collecting coeffecients
- into arrays and tuples, the input for this problem is:
- >>> from scipy.optimize import linprog
- >>> c = [-1, 4]
- >>> A = [[-3, 1], [1, 2]]
- >>> b = [6, 4]
- >>> x0_bounds = (None, None)
- >>> x1_bounds = (-3, None)
- >>> res = linprog(c, A_ub=A, b_ub=b, bounds=[x0_bounds, x1_bounds])
- >>> res.fun
- -22.0
- >>> res.x
- array([10., -3.])
- >>> res.message
- 'Optimization terminated successfully. (HiGHS Status 7: Optimal)'
- The marginals (AKA dual values / shadow prices / Lagrange multipliers)
- and residuals (slacks) are also available.
- >>> res.ineqlin
- residual: [ 3.900e+01 0.000e+00]
- marginals: [-0.000e+00 -1.000e+00]
- For example, because the marginal associated with the second inequality
- constraint is -1, we expect the optimal value of the objective function
- to decrease by ``eps`` if we add a small amount ``eps`` to the right hand
- side of the second inequality constraint:
- >>> eps = 0.05
- >>> b[1] += eps
- >>> linprog(c, A_ub=A, b_ub=b, bounds=[x0_bounds, x1_bounds]).fun
- -22.05
- Also, because the residual on the first inequality constraint is 39, we
- can decrease the right hand side of the first constraint by 39 without
- affecting the optimal solution.
- >>> b = [6, 4] # reset to original values
- >>> b[0] -= 39
- >>> linprog(c, A_ub=A, b_ub=b, bounds=[x0_bounds, x1_bounds]).fun
- -22.0
- """
- meth = method.lower()
- methods = {"highs", "highs-ds", "highs-ipm",
- "simplex", "revised simplex", "interior-point"}
- if meth not in methods:
- raise ValueError(f"Unknown solver '{method}'")
- if x0 is not None and meth != "revised simplex":
- warning_message = "x0 is used only when method is 'revised simplex'. "
- warn(warning_message, OptimizeWarning)
- if np.any(integrality) and not meth == "highs":
- integrality = None
- warning_message = ("Only `method='highs'` supports integer "
- "constraints. Ignoring `integrality`.")
- warn(warning_message, OptimizeWarning)
- elif np.any(integrality):
- integrality = np.broadcast_to(integrality, np.shape(c))
- lp = _LPProblem(c, A_ub, b_ub, A_eq, b_eq, bounds, x0, integrality)
- lp, solver_options = _parse_linprog(lp, options, meth)
- tol = solver_options.get('tol', 1e-9)
- # Give unmodified problem to HiGHS
- if meth.startswith('highs'):
- if callback is not None:
- raise NotImplementedError("HiGHS solvers do not support the "
- "callback interface.")
- highs_solvers = {'highs-ipm': 'ipm', 'highs-ds': 'simplex',
- 'highs': None}
- sol = _linprog_highs(lp, solver=highs_solvers[meth],
- **solver_options)
- sol['status'], sol['message'] = (
- _check_result(sol['x'], sol['fun'], sol['status'], sol['slack'],
- sol['con'], lp.bounds, tol, sol['message']))
- sol['success'] = sol['status'] == 0
- return OptimizeResult(sol)
- warn(f"`method='{meth}'` is deprecated and will be removed in SciPy "
- "1.11.0. Please use one of the HiGHS solvers (e.g. "
- "`method='highs'`) in new code.", DeprecationWarning, stacklevel=2)
- iteration = 0
- complete = False # will become True if solved in presolve
- undo = []
- # Keep the original arrays to calculate slack/residuals for original
- # problem.
- lp_o = deepcopy(lp)
- # Solve trivial problem, eliminate variables, tighten bounds, etc.
- rr_method = solver_options.pop('rr_method', None) # need to pop these;
- rr = solver_options.pop('rr', True) # they're not passed to methods
- c0 = 0 # we might get a constant term in the objective
- if solver_options.pop('presolve', True):
- (lp, c0, x, undo, complete, status, message) = _presolve(lp, rr,
- rr_method,
- tol)
- C, b_scale = 1, 1 # for trivial unscaling if autoscale is not used
- postsolve_args = (lp_o._replace(bounds=lp.bounds), undo, C, b_scale)
- if not complete:
- A, b, c, c0, x0 = _get_Abc(lp, c0)
- if solver_options.pop('autoscale', False):
- A, b, c, x0, C, b_scale = _autoscale(A, b, c, x0)
- postsolve_args = postsolve_args[:-2] + (C, b_scale)
- if meth == 'simplex':
- x, status, message, iteration = _linprog_simplex(
- c, c0=c0, A=A, b=b, callback=callback,
- postsolve_args=postsolve_args, **solver_options)
- elif meth == 'interior-point':
- x, status, message, iteration = _linprog_ip(
- c, c0=c0, A=A, b=b, callback=callback,
- postsolve_args=postsolve_args, **solver_options)
- elif meth == 'revised simplex':
- x, status, message, iteration = _linprog_rs(
- c, c0=c0, A=A, b=b, x0=x0, callback=callback,
- postsolve_args=postsolve_args, **solver_options)
- # Eliminate artificial variables, re-introduce presolved variables, etc.
- disp = solver_options.get('disp', False)
- x, fun, slack, con = _postsolve(x, postsolve_args, complete)
- status, message = _check_result(x, fun, status, slack, con, lp_o.bounds, tol, message)
- if disp:
- _display_summary(message, status, fun, iteration)
- sol = {
- 'x': x,
- 'fun': fun,
- 'slack': slack,
- 'con': con,
- 'status': status,
- 'message': message,
- 'nit': iteration,
- 'success': status == 0}
- return OptimizeResult(sol)
|