_linprog_simplex.py 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661
  1. """Simplex method for linear programming
  2. The *simplex* method uses a traditional, full-tableau implementation of
  3. Dantzig's simplex algorithm [1]_, [2]_ (*not* the Nelder-Mead simplex).
  4. This algorithm is included for backwards compatibility and educational
  5. purposes.
  6. .. versionadded:: 0.15.0
  7. Warnings
  8. --------
  9. The simplex method may encounter numerical difficulties when pivot
  10. values are close to the specified tolerance. If encountered try
  11. remove any redundant constraints, change the pivot strategy to Bland's
  12. rule or increase the tolerance value.
  13. Alternatively, more robust methods maybe be used. See
  14. :ref:`'interior-point' <optimize.linprog-interior-point>` and
  15. :ref:`'revised simplex' <optimize.linprog-revised_simplex>`.
  16. References
  17. ----------
  18. .. [1] Dantzig, George B., Linear programming and extensions. Rand
  19. Corporation Research Study Princeton Univ. Press, Princeton, NJ,
  20. 1963
  21. .. [2] Hillier, S.H. and Lieberman, G.J. (1995), "Introduction to
  22. Mathematical Programming", McGraw-Hill, Chapter 4.
  23. """
  24. import numpy as np
  25. from warnings import warn
  26. from ._optimize import OptimizeResult, OptimizeWarning, _check_unknown_options
  27. from ._linprog_util import _postsolve
  28. def _pivot_col(T, tol=1e-9, bland=False):
  29. """
  30. Given a linear programming simplex tableau, determine the column
  31. of the variable to enter the basis.
  32. Parameters
  33. ----------
  34. T : 2-D array
  35. A 2-D array representing the simplex tableau, T, corresponding to the
  36. linear programming problem. It should have the form:
  37. [[A[0, 0], A[0, 1], ..., A[0, n_total], b[0]],
  38. [A[1, 0], A[1, 1], ..., A[1, n_total], b[1]],
  39. .
  40. .
  41. .
  42. [A[m, 0], A[m, 1], ..., A[m, n_total], b[m]],
  43. [c[0], c[1], ..., c[n_total], 0]]
  44. for a Phase 2 problem, or the form:
  45. [[A[0, 0], A[0, 1], ..., A[0, n_total], b[0]],
  46. [A[1, 0], A[1, 1], ..., A[1, n_total], b[1]],
  47. .
  48. .
  49. .
  50. [A[m, 0], A[m, 1], ..., A[m, n_total], b[m]],
  51. [c[0], c[1], ..., c[n_total], 0],
  52. [c'[0], c'[1], ..., c'[n_total], 0]]
  53. for a Phase 1 problem (a problem in which a basic feasible solution is
  54. sought prior to maximizing the actual objective. ``T`` is modified in
  55. place by ``_solve_simplex``.
  56. tol : float
  57. Elements in the objective row larger than -tol will not be considered
  58. for pivoting. Nominally this value is zero, but numerical issues
  59. cause a tolerance about zero to be necessary.
  60. bland : bool
  61. If True, use Bland's rule for selection of the column (select the
  62. first column with a negative coefficient in the objective row,
  63. regardless of magnitude).
  64. Returns
  65. -------
  66. status: bool
  67. True if a suitable pivot column was found, otherwise False.
  68. A return of False indicates that the linear programming simplex
  69. algorithm is complete.
  70. col: int
  71. The index of the column of the pivot element.
  72. If status is False, col will be returned as nan.
  73. """
  74. ma = np.ma.masked_where(T[-1, :-1] >= -tol, T[-1, :-1], copy=False)
  75. if ma.count() == 0:
  76. return False, np.nan
  77. if bland:
  78. # ma.mask is sometimes 0d
  79. return True, np.nonzero(np.logical_not(np.atleast_1d(ma.mask)))[0][0]
  80. return True, np.ma.nonzero(ma == ma.min())[0][0]
  81. def _pivot_row(T, basis, pivcol, phase, tol=1e-9, bland=False):
  82. """
  83. Given a linear programming simplex tableau, determine the row for the
  84. pivot operation.
  85. Parameters
  86. ----------
  87. T : 2-D array
  88. A 2-D array representing the simplex tableau, T, corresponding to the
  89. linear programming problem. It should have the form:
  90. [[A[0, 0], A[0, 1], ..., A[0, n_total], b[0]],
  91. [A[1, 0], A[1, 1], ..., A[1, n_total], b[1]],
  92. .
  93. .
  94. .
  95. [A[m, 0], A[m, 1], ..., A[m, n_total], b[m]],
  96. [c[0], c[1], ..., c[n_total], 0]]
  97. for a Phase 2 problem, or the form:
  98. [[A[0, 0], A[0, 1], ..., A[0, n_total], b[0]],
  99. [A[1, 0], A[1, 1], ..., A[1, n_total], b[1]],
  100. .
  101. .
  102. .
  103. [A[m, 0], A[m, 1], ..., A[m, n_total], b[m]],
  104. [c[0], c[1], ..., c[n_total], 0],
  105. [c'[0], c'[1], ..., c'[n_total], 0]]
  106. for a Phase 1 problem (a Problem in which a basic feasible solution is
  107. sought prior to maximizing the actual objective. ``T`` is modified in
  108. place by ``_solve_simplex``.
  109. basis : array
  110. A list of the current basic variables.
  111. pivcol : int
  112. The index of the pivot column.
  113. phase : int
  114. The phase of the simplex algorithm (1 or 2).
  115. tol : float
  116. Elements in the pivot column smaller than tol will not be considered
  117. for pivoting. Nominally this value is zero, but numerical issues
  118. cause a tolerance about zero to be necessary.
  119. bland : bool
  120. If True, use Bland's rule for selection of the row (if more than one
  121. row can be used, choose the one with the lowest variable index).
  122. Returns
  123. -------
  124. status: bool
  125. True if a suitable pivot row was found, otherwise False. A return
  126. of False indicates that the linear programming problem is unbounded.
  127. row: int
  128. The index of the row of the pivot element. If status is False, row
  129. will be returned as nan.
  130. """
  131. if phase == 1:
  132. k = 2
  133. else:
  134. k = 1
  135. ma = np.ma.masked_where(T[:-k, pivcol] <= tol, T[:-k, pivcol], copy=False)
  136. if ma.count() == 0:
  137. return False, np.nan
  138. mb = np.ma.masked_where(T[:-k, pivcol] <= tol, T[:-k, -1], copy=False)
  139. q = mb / ma
  140. min_rows = np.ma.nonzero(q == q.min())[0]
  141. if bland:
  142. return True, min_rows[np.argmin(np.take(basis, min_rows))]
  143. return True, min_rows[0]
  144. def _apply_pivot(T, basis, pivrow, pivcol, tol=1e-9):
  145. """
  146. Pivot the simplex tableau inplace on the element given by (pivrow, pivol).
  147. The entering variable corresponds to the column given by pivcol forcing
  148. the variable basis[pivrow] to leave the basis.
  149. Parameters
  150. ----------
  151. T : 2-D array
  152. A 2-D array representing the simplex tableau, T, corresponding to the
  153. linear programming problem. It should have the form:
  154. [[A[0, 0], A[0, 1], ..., A[0, n_total], b[0]],
  155. [A[1, 0], A[1, 1], ..., A[1, n_total], b[1]],
  156. .
  157. .
  158. .
  159. [A[m, 0], A[m, 1], ..., A[m, n_total], b[m]],
  160. [c[0], c[1], ..., c[n_total], 0]]
  161. for a Phase 2 problem, or the form:
  162. [[A[0, 0], A[0, 1], ..., A[0, n_total], b[0]],
  163. [A[1, 0], A[1, 1], ..., A[1, n_total], b[1]],
  164. .
  165. .
  166. .
  167. [A[m, 0], A[m, 1], ..., A[m, n_total], b[m]],
  168. [c[0], c[1], ..., c[n_total], 0],
  169. [c'[0], c'[1], ..., c'[n_total], 0]]
  170. for a Phase 1 problem (a problem in which a basic feasible solution is
  171. sought prior to maximizing the actual objective. ``T`` is modified in
  172. place by ``_solve_simplex``.
  173. basis : 1-D array
  174. An array of the indices of the basic variables, such that basis[i]
  175. contains the column corresponding to the basic variable for row i.
  176. Basis is modified in place by _apply_pivot.
  177. pivrow : int
  178. Row index of the pivot.
  179. pivcol : int
  180. Column index of the pivot.
  181. """
  182. basis[pivrow] = pivcol
  183. pivval = T[pivrow, pivcol]
  184. T[pivrow] = T[pivrow] / pivval
  185. for irow in range(T.shape[0]):
  186. if irow != pivrow:
  187. T[irow] = T[irow] - T[pivrow] * T[irow, pivcol]
  188. # The selected pivot should never lead to a pivot value less than the tol.
  189. if np.isclose(pivval, tol, atol=0, rtol=1e4):
  190. message = (
  191. "The pivot operation produces a pivot value of:{0: .1e}, "
  192. "which is only slightly greater than the specified "
  193. "tolerance{1: .1e}. This may lead to issues regarding the "
  194. "numerical stability of the simplex method. "
  195. "Removing redundant constraints, changing the pivot strategy "
  196. "via Bland's rule or increasing the tolerance may "
  197. "help reduce the issue.".format(pivval, tol))
  198. warn(message, OptimizeWarning, stacklevel=5)
  199. def _solve_simplex(T, n, basis, callback, postsolve_args,
  200. maxiter=1000, tol=1e-9, phase=2, bland=False, nit0=0,
  201. ):
  202. """
  203. Solve a linear programming problem in "standard form" using the Simplex
  204. Method. Linear Programming is intended to solve the following problem form:
  205. Minimize::
  206. c @ x
  207. Subject to::
  208. A @ x == b
  209. x >= 0
  210. Parameters
  211. ----------
  212. T : 2-D array
  213. A 2-D array representing the simplex tableau, T, corresponding to the
  214. linear programming problem. It should have the form:
  215. [[A[0, 0], A[0, 1], ..., A[0, n_total], b[0]],
  216. [A[1, 0], A[1, 1], ..., A[1, n_total], b[1]],
  217. .
  218. .
  219. .
  220. [A[m, 0], A[m, 1], ..., A[m, n_total], b[m]],
  221. [c[0], c[1], ..., c[n_total], 0]]
  222. for a Phase 2 problem, or the form:
  223. [[A[0, 0], A[0, 1], ..., A[0, n_total], b[0]],
  224. [A[1, 0], A[1, 1], ..., A[1, n_total], b[1]],
  225. .
  226. .
  227. .
  228. [A[m, 0], A[m, 1], ..., A[m, n_total], b[m]],
  229. [c[0], c[1], ..., c[n_total], 0],
  230. [c'[0], c'[1], ..., c'[n_total], 0]]
  231. for a Phase 1 problem (a problem in which a basic feasible solution is
  232. sought prior to maximizing the actual objective. ``T`` is modified in
  233. place by ``_solve_simplex``.
  234. n : int
  235. The number of true variables in the problem.
  236. basis : 1-D array
  237. An array of the indices of the basic variables, such that basis[i]
  238. contains the column corresponding to the basic variable for row i.
  239. Basis is modified in place by _solve_simplex
  240. callback : callable, optional
  241. If a callback function is provided, it will be called within each
  242. iteration of the algorithm. The callback must accept a
  243. `scipy.optimize.OptimizeResult` consisting of the following fields:
  244. x : 1-D array
  245. Current solution vector
  246. fun : float
  247. Current value of the objective function
  248. success : bool
  249. True only when a phase has completed successfully. This
  250. will be False for most iterations.
  251. slack : 1-D array
  252. The values of the slack variables. Each slack variable
  253. corresponds to an inequality constraint. If the slack is zero,
  254. the corresponding constraint is active.
  255. con : 1-D array
  256. The (nominally zero) residuals of the equality constraints,
  257. that is, ``b - A_eq @ x``
  258. phase : int
  259. The phase of the optimization being executed. In phase 1 a basic
  260. feasible solution is sought and the T has an additional row
  261. representing an alternate objective function.
  262. status : int
  263. An integer representing the exit status of the optimization::
  264. 0 : Optimization terminated successfully
  265. 1 : Iteration limit reached
  266. 2 : Problem appears to be infeasible
  267. 3 : Problem appears to be unbounded
  268. 4 : Serious numerical difficulties encountered
  269. nit : int
  270. The number of iterations performed.
  271. message : str
  272. A string descriptor of the exit status of the optimization.
  273. postsolve_args : tuple
  274. Data needed by _postsolve to convert the solution to the standard-form
  275. problem into the solution to the original problem.
  276. maxiter : int
  277. The maximum number of iterations to perform before aborting the
  278. optimization.
  279. tol : float
  280. The tolerance which determines when a solution is "close enough" to
  281. zero in Phase 1 to be considered a basic feasible solution or close
  282. enough to positive to serve as an optimal solution.
  283. phase : int
  284. The phase of the optimization being executed. In phase 1 a basic
  285. feasible solution is sought and the T has an additional row
  286. representing an alternate objective function.
  287. bland : bool
  288. If True, choose pivots using Bland's rule [3]_. In problems which
  289. fail to converge due to cycling, using Bland's rule can provide
  290. convergence at the expense of a less optimal path about the simplex.
  291. nit0 : int
  292. The initial iteration number used to keep an accurate iteration total
  293. in a two-phase problem.
  294. Returns
  295. -------
  296. nit : int
  297. The number of iterations. Used to keep an accurate iteration total
  298. in the two-phase problem.
  299. status : int
  300. An integer representing the exit status of the optimization::
  301. 0 : Optimization terminated successfully
  302. 1 : Iteration limit reached
  303. 2 : Problem appears to be infeasible
  304. 3 : Problem appears to be unbounded
  305. 4 : Serious numerical difficulties encountered
  306. """
  307. nit = nit0
  308. status = 0
  309. message = ''
  310. complete = False
  311. if phase == 1:
  312. m = T.shape[1]-2
  313. elif phase == 2:
  314. m = T.shape[1]-1
  315. else:
  316. raise ValueError("Argument 'phase' to _solve_simplex must be 1 or 2")
  317. if phase == 2:
  318. # Check if any artificial variables are still in the basis.
  319. # If yes, check if any coefficients from this row and a column
  320. # corresponding to one of the non-artificial variable is non-zero.
  321. # If found, pivot at this term. If not, start phase 2.
  322. # Do this for all artificial variables in the basis.
  323. # Ref: "An Introduction to Linear Programming and Game Theory"
  324. # by Paul R. Thie, Gerard E. Keough, 3rd Ed,
  325. # Chapter 3.7 Redundant Systems (pag 102)
  326. for pivrow in [row for row in range(basis.size)
  327. if basis[row] > T.shape[1] - 2]:
  328. non_zero_row = [col for col in range(T.shape[1] - 1)
  329. if abs(T[pivrow, col]) > tol]
  330. if len(non_zero_row) > 0:
  331. pivcol = non_zero_row[0]
  332. _apply_pivot(T, basis, pivrow, pivcol, tol)
  333. nit += 1
  334. if len(basis[:m]) == 0:
  335. solution = np.empty(T.shape[1] - 1, dtype=np.float64)
  336. else:
  337. solution = np.empty(max(T.shape[1] - 1, max(basis[:m]) + 1),
  338. dtype=np.float64)
  339. while not complete:
  340. # Find the pivot column
  341. pivcol_found, pivcol = _pivot_col(T, tol, bland)
  342. if not pivcol_found:
  343. pivcol = np.nan
  344. pivrow = np.nan
  345. status = 0
  346. complete = True
  347. else:
  348. # Find the pivot row
  349. pivrow_found, pivrow = _pivot_row(T, basis, pivcol, phase, tol, bland)
  350. if not pivrow_found:
  351. status = 3
  352. complete = True
  353. if callback is not None:
  354. solution[:] = 0
  355. solution[basis[:n]] = T[:n, -1]
  356. x = solution[:m]
  357. x, fun, slack, con = _postsolve(
  358. x, postsolve_args
  359. )
  360. res = OptimizeResult({
  361. 'x': x,
  362. 'fun': fun,
  363. 'slack': slack,
  364. 'con': con,
  365. 'status': status,
  366. 'message': message,
  367. 'nit': nit,
  368. 'success': status == 0 and complete,
  369. 'phase': phase,
  370. 'complete': complete,
  371. })
  372. callback(res)
  373. if not complete:
  374. if nit >= maxiter:
  375. # Iteration limit exceeded
  376. status = 1
  377. complete = True
  378. else:
  379. _apply_pivot(T, basis, pivrow, pivcol, tol)
  380. nit += 1
  381. return nit, status
  382. def _linprog_simplex(c, c0, A, b, callback, postsolve_args,
  383. maxiter=1000, tol=1e-9, disp=False, bland=False,
  384. **unknown_options):
  385. """
  386. Minimize a linear objective function subject to linear equality and
  387. non-negativity constraints using the two phase simplex method.
  388. Linear programming is intended to solve problems of the following form:
  389. Minimize::
  390. c @ x
  391. Subject to::
  392. A @ x == b
  393. x >= 0
  394. User-facing documentation is in _linprog_doc.py.
  395. Parameters
  396. ----------
  397. c : 1-D array
  398. Coefficients of the linear objective function to be minimized.
  399. c0 : float
  400. Constant term in objective function due to fixed (and eliminated)
  401. variables. (Purely for display.)
  402. A : 2-D array
  403. 2-D array such that ``A @ x``, gives the values of the equality
  404. constraints at ``x``.
  405. b : 1-D array
  406. 1-D array of values representing the right hand side of each equality
  407. constraint (row) in ``A``.
  408. callback : callable, optional
  409. If a callback function is provided, it will be called within each
  410. iteration of the algorithm. The callback function must accept a single
  411. `scipy.optimize.OptimizeResult` consisting of the following fields:
  412. x : 1-D array
  413. Current solution vector
  414. fun : float
  415. Current value of the objective function
  416. success : bool
  417. True when an algorithm has completed successfully.
  418. slack : 1-D array
  419. The values of the slack variables. Each slack variable
  420. corresponds to an inequality constraint. If the slack is zero,
  421. the corresponding constraint is active.
  422. con : 1-D array
  423. The (nominally zero) residuals of the equality constraints,
  424. that is, ``b - A_eq @ x``
  425. phase : int
  426. The phase of the algorithm being executed.
  427. status : int
  428. An integer representing the status of the optimization::
  429. 0 : Algorithm proceeding nominally
  430. 1 : Iteration limit reached
  431. 2 : Problem appears to be infeasible
  432. 3 : Problem appears to be unbounded
  433. 4 : Serious numerical difficulties encountered
  434. nit : int
  435. The number of iterations performed.
  436. message : str
  437. A string descriptor of the exit status of the optimization.
  438. postsolve_args : tuple
  439. Data needed by _postsolve to convert the solution to the standard-form
  440. problem into the solution to the original problem.
  441. Options
  442. -------
  443. maxiter : int
  444. The maximum number of iterations to perform.
  445. disp : bool
  446. If True, print exit status message to sys.stdout
  447. tol : float
  448. The tolerance which determines when a solution is "close enough" to
  449. zero in Phase 1 to be considered a basic feasible solution or close
  450. enough to positive to serve as an optimal solution.
  451. bland : bool
  452. If True, use Bland's anti-cycling rule [3]_ to choose pivots to
  453. prevent cycling. If False, choose pivots which should lead to a
  454. converged solution more quickly. The latter method is subject to
  455. cycling (non-convergence) in rare instances.
  456. unknown_options : dict
  457. Optional arguments not used by this particular solver. If
  458. `unknown_options` is non-empty a warning is issued listing all
  459. unused options.
  460. Returns
  461. -------
  462. x : 1-D array
  463. Solution vector.
  464. status : int
  465. An integer representing the exit status of the optimization::
  466. 0 : Optimization terminated successfully
  467. 1 : Iteration limit reached
  468. 2 : Problem appears to be infeasible
  469. 3 : Problem appears to be unbounded
  470. 4 : Serious numerical difficulties encountered
  471. message : str
  472. A string descriptor of the exit status of the optimization.
  473. iteration : int
  474. The number of iterations taken to solve the problem.
  475. References
  476. ----------
  477. .. [1] Dantzig, George B., Linear programming and extensions. Rand
  478. Corporation Research Study Princeton Univ. Press, Princeton, NJ,
  479. 1963
  480. .. [2] Hillier, S.H. and Lieberman, G.J. (1995), "Introduction to
  481. Mathematical Programming", McGraw-Hill, Chapter 4.
  482. .. [3] Bland, Robert G. New finite pivoting rules for the simplex method.
  483. Mathematics of Operations Research (2), 1977: pp. 103-107.
  484. Notes
  485. -----
  486. The expected problem formulation differs between the top level ``linprog``
  487. module and the method specific solvers. The method specific solvers expect a
  488. problem in standard form:
  489. Minimize::
  490. c @ x
  491. Subject to::
  492. A @ x == b
  493. x >= 0
  494. Whereas the top level ``linprog`` module expects a problem of form:
  495. Minimize::
  496. c @ x
  497. Subject to::
  498. A_ub @ x <= b_ub
  499. A_eq @ x == b_eq
  500. lb <= x <= ub
  501. where ``lb = 0`` and ``ub = None`` unless set in ``bounds``.
  502. The original problem contains equality, upper-bound and variable constraints
  503. whereas the method specific solver requires equality constraints and
  504. variable non-negativity.
  505. ``linprog`` module converts the original problem to standard form by
  506. converting the simple bounds to upper bound constraints, introducing
  507. non-negative slack variables for inequality constraints, and expressing
  508. unbounded variables as the difference between two non-negative variables.
  509. """
  510. _check_unknown_options(unknown_options)
  511. status = 0
  512. messages = {0: "Optimization terminated successfully.",
  513. 1: "Iteration limit reached.",
  514. 2: "Optimization failed. Unable to find a feasible"
  515. " starting point.",
  516. 3: "Optimization failed. The problem appears to be unbounded.",
  517. 4: "Optimization failed. Singular matrix encountered."}
  518. n, m = A.shape
  519. # All constraints must have b >= 0.
  520. is_negative_constraint = np.less(b, 0)
  521. A[is_negative_constraint] *= -1
  522. b[is_negative_constraint] *= -1
  523. # As all constraints are equality constraints the artificial variables
  524. # will also be basic variables.
  525. av = np.arange(n) + m
  526. basis = av.copy()
  527. # Format the phase one tableau by adding artificial variables and stacking
  528. # the constraints, the objective row and pseudo-objective row.
  529. row_constraints = np.hstack((A, np.eye(n), b[:, np.newaxis]))
  530. row_objective = np.hstack((c, np.zeros(n), c0))
  531. row_pseudo_objective = -row_constraints.sum(axis=0)
  532. row_pseudo_objective[av] = 0
  533. T = np.vstack((row_constraints, row_objective, row_pseudo_objective))
  534. nit1, status = _solve_simplex(T, n, basis, callback=callback,
  535. postsolve_args=postsolve_args,
  536. maxiter=maxiter, tol=tol, phase=1,
  537. bland=bland
  538. )
  539. # if pseudo objective is zero, remove the last row from the tableau and
  540. # proceed to phase 2
  541. nit2 = nit1
  542. if abs(T[-1, -1]) < tol:
  543. # Remove the pseudo-objective row from the tableau
  544. T = T[:-1, :]
  545. # Remove the artificial variable columns from the tableau
  546. T = np.delete(T, av, 1)
  547. else:
  548. # Failure to find a feasible starting point
  549. status = 2
  550. messages[status] = (
  551. "Phase 1 of the simplex method failed to find a feasible "
  552. "solution. The pseudo-objective function evaluates to {0:.1e} "
  553. "which exceeds the required tolerance of {1} for a solution to be "
  554. "considered 'close enough' to zero to be a basic solution. "
  555. "Consider increasing the tolerance to be greater than {0:.1e}. "
  556. "If this tolerance is unacceptably large the problem may be "
  557. "infeasible.".format(abs(T[-1, -1]), tol)
  558. )
  559. if status == 0:
  560. # Phase 2
  561. nit2, status = _solve_simplex(T, n, basis, callback=callback,
  562. postsolve_args=postsolve_args,
  563. maxiter=maxiter, tol=tol, phase=2,
  564. bland=bland, nit0=nit1
  565. )
  566. solution = np.zeros(n + m)
  567. solution[basis[:n]] = T[:n, -1]
  568. x = solution[:m]
  569. return x, status, messages[status], int(nit2)