simplex.py 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104
  1. """Tools for optimizing a linear function for a given simplex.
  2. For the linear objective function ``f`` with linear constraints
  3. expressed using `Le`, `Ge` or `Eq` can be found with ``lpmin`` or
  4. ``lpmax``. The symbols are **unbounded** unless specifically
  5. constrained.
  6. As an alternative, the matrices describing the objective and the
  7. constraints, and an optional list of bounds can be passed to
  8. ``linprog`` which will solve for the minimization of ``C*x``
  9. under constraints ``A*x <= b`` and/or ``Aeq*x = beq``, and
  10. individual bounds for variables given as ``(lo, hi)``. The values
  11. returned are **nonnegative** unless bounds are provided that
  12. indicate otherwise.
  13. Errors that might be raised are UnboundedLPError when there is no
  14. finite solution for the system or InfeasibleLPError when the
  15. constraints represent impossible conditions (i.e. a non-existent
  16. simplex).
  17. Here is a simple 1-D system: minimize `x` given that ``x >= 1``.
  18. >>> from sympy.solvers.simplex import lpmin, linprog
  19. >>> from sympy.abc import x
  20. The function and a list with the constraint is passed directly
  21. to `lpmin`:
  22. >>> lpmin(x, [x >= 1])
  23. (1, {x: 1})
  24. For `linprog` the matrix for the objective is `[1]` and the
  25. uivariate constraint can be passed as a bound with None acting
  26. as infinity:
  27. >>> linprog([1], bounds=(1, None))
  28. (1, [1])
  29. Or the matrices, corresponding to ``x >= 1`` expressed as
  30. ``-x <= -1`` as required by the routine, can be passed:
  31. >>> linprog([1], [-1], [-1])
  32. (1, [1])
  33. If there is no limit for the objective, an error is raised.
  34. In this case there is a valid region of interest (simplex)
  35. but no limit to how small ``x`` can be:
  36. >>> lpmin(x, [])
  37. Traceback (most recent call last):
  38. ...
  39. sympy.solvers.simplex.UnboundedLPError:
  40. Objective function can assume arbitrarily large values!
  41. An error is raised if there is no possible solution:
  42. >>> lpmin(x,[x<=1,x>=2])
  43. Traceback (most recent call last):
  44. ...
  45. sympy.solvers.simplex.InfeasibleLPError:
  46. Inconsistent/False constraint
  47. """
  48. from sympy.core import sympify
  49. from sympy.core.exprtools import factor_terms
  50. from sympy.core.relational import Le, Ge, Eq
  51. from sympy.core.singleton import S
  52. from sympy.core.symbol import Dummy
  53. from sympy.core.sorting import ordered
  54. from sympy.functions.elementary.complexes import sign
  55. from sympy.matrices.dense import Matrix, zeros
  56. from sympy.solvers.solveset import linear_eq_to_matrix
  57. from sympy.utilities.iterables import numbered_symbols
  58. from sympy.utilities.misc import filldedent
  59. class UnboundedLPError(Exception):
  60. """
  61. A linear programming problem is said to be unbounded if its objective
  62. function can assume arbitrarily large values.
  63. Example
  64. =======
  65. Suppose you want to maximize
  66. 2x
  67. subject to
  68. x >= 0
  69. There's no upper limit that 2x can take.
  70. """
  71. pass
  72. class InfeasibleLPError(Exception):
  73. """
  74. A linear programming problem is considered infeasible if its
  75. constraint set is empty. That is, if the set of all vectors
  76. satisfying the constraints is empty, then the problem is infeasible.
  77. Example
  78. =======
  79. Suppose you want to maximize
  80. x
  81. subject to
  82. x >= 10
  83. x <= 9
  84. No x can satisfy those constraints.
  85. """
  86. pass
  87. def _pivot(M, i, j):
  88. """
  89. The pivot element `M[i, j]` is inverted and the rest of the matrix
  90. modified and returned as a new matrix; original is left unmodified.
  91. Example
  92. =======
  93. >>> from sympy.matrices.dense import Matrix
  94. >>> from sympy.solvers.simplex import _pivot
  95. >>> from sympy import var
  96. >>> Matrix(3, 3, var('a:i'))
  97. Matrix([
  98. [a, b, c],
  99. [d, e, f],
  100. [g, h, i]])
  101. >>> _pivot(_, 1, 0)
  102. Matrix([
  103. [-a/d, -a*e/d + b, -a*f/d + c],
  104. [ 1/d, e/d, f/d],
  105. [-g/d, h - e*g/d, i - f*g/d]])
  106. """
  107. Mi, Mj, Mij = M[i, :], M[:, j], M[i, j]
  108. if Mij == 0:
  109. raise ZeroDivisionError(
  110. "Tried to pivot about zero-valued entry.")
  111. A = M - Mj * (Mi / Mij)
  112. A[i, :] = Mi / Mij
  113. A[:, j] = -Mj / Mij
  114. A[i, j] = 1 / Mij
  115. return A
  116. def _choose_pivot_row(A, B, candidate_rows, pivot_col, Y):
  117. # Choose row with smallest ratio
  118. # If there are ties, pick using Bland's rule
  119. return min(candidate_rows, key=lambda i: (B[i] / A[i, pivot_col], Y[i]))
  120. def _simplex(A, B, C, D=None, dual=False):
  121. """Return ``(o, x, y)`` obtained from the two-phase simplex method
  122. using Bland's rule: ``o`` is the minimum value of primal,
  123. ``Cx - D``, under constraints ``Ax <= B`` (with ``x >= 0``) and
  124. the maximum of the dual, ``y^{T}B - D``, under constraints
  125. ``A^{T}*y >= C^{T}`` (with ``y >= 0``). To compute the dual of
  126. the system, pass `dual=True` and ``(o, y, x)`` will be returned.
  127. Note: the nonnegative constraints for ``x`` and ``y`` supercede
  128. any values of ``A`` and ``B`` that are inconsistent with that
  129. assumption, so if a constraint of ``x >= -1`` is represented
  130. in ``A`` and ``B``, no value will be obtained that is negative; if
  131. a constraint of ``x <= -1`` is represented, an error will be
  132. raised since no solution is possible.
  133. This routine relies on the ability of determining whether an
  134. expression is 0 or not. This is guaranteed if the input contains
  135. only Float or Rational entries. It will raise a TypeError if
  136. a relationship does not evaluate to True or False.
  137. Examples
  138. ========
  139. >>> from sympy.solvers.simplex import _simplex
  140. >>> from sympy import Matrix
  141. Consider the simple minimization of ``f = x + y + 1`` under the
  142. constraint that ``y + 2*x >= 4``. This is the "standard form" of
  143. a minimization.
  144. In the nonnegative quadrant, this inequality describes a area above
  145. a triangle with vertices at (0, 4), (0, 0) and (2, 0). The minimum
  146. of ``f`` occurs at (2, 0). Define A, B, C, D for the standard
  147. minimization:
  148. >>> A = Matrix([[2, 1]])
  149. >>> B = Matrix([4])
  150. >>> C = Matrix([[1, 1]])
  151. >>> D = Matrix([-1])
  152. Confirm that this is the system of interest:
  153. >>> from sympy.abc import x, y
  154. >>> X = Matrix([x, y])
  155. >>> (C*X - D)[0]
  156. x + y + 1
  157. >>> [i >= j for i, j in zip(A*X, B)]
  158. [2*x + y >= 4]
  159. Since `_simplex` will do a minimization for constraints given as
  160. ``A*x <= B``, the signs of ``A`` and ``B`` must be negated since
  161. the currently correspond to a greater-than inequality:
  162. >>> _simplex(-A, -B, C, D)
  163. (3, [2, 0], [1/2])
  164. The dual of minimizing ``f`` is maximizing ``F = c*y - d`` for
  165. ``a*y <= b`` where ``a``, ``b``, ``c``, ``d`` are derived from the
  166. transpose of the matrix representation of the standard minimization:
  167. >>> tr = lambda a, b, c, d: [i.T for i in (a, c, b, d)]
  168. >>> a, b, c, d = tr(A, B, C, D)
  169. This time ``a*x <= b`` is the expected inequality for the `_simplex`
  170. method, but to maximize ``F``, the sign of ``c`` and ``d`` must be
  171. changed (so that minimizing the negative will give the negative of
  172. the maximum of ``F``):
  173. >>> _simplex(a, b, -c, -d)
  174. (-3, [1/2], [2, 0])
  175. The negative of ``F`` and the min of ``f`` are the same. The dual
  176. point `[1/2]` is the value of ``y`` that minimized ``F = c*y - d``
  177. under constraints a*x <= b``:
  178. >>> y = Matrix(['y'])
  179. >>> (c*y - d)[0]
  180. 4*y + 1
  181. >>> [i <= j for i, j in zip(a*y,b)]
  182. [2*y <= 1, y <= 1]
  183. In this 1-dimensional dual system, the more restrictive constraint is
  184. the first which limits ``y`` between 0 and 1/2 and the maximum of
  185. ``F`` is attained at the nonzero value, hence is ``4*(1/2) + 1 = 3``.
  186. In this case the values for ``x`` and ``y`` were the same when the
  187. dual representation was solved. This is not always the case (though
  188. the value of the function will be the same).
  189. >>> l = [[1, 1], [-1, 1], [0, 1], [-1, 0]], [5, 1, 2, -1], [[1, 1]], [-1]
  190. >>> A, B, C, D = [Matrix(i) for i in l]
  191. >>> _simplex(A, B, -C, -D)
  192. (-6, [3, 2], [1, 0, 0, 0])
  193. >>> _simplex(A, B, -C, -D, dual=True) # [5, 0] != [3, 2]
  194. (-6, [1, 0, 0, 0], [5, 0])
  195. In both cases the function has the same value:
  196. >>> Matrix(C)*Matrix([3, 2]) == Matrix(C)*Matrix([5, 0])
  197. True
  198. See Also
  199. ========
  200. _lp - poses min/max problem in form compatible with _simplex
  201. lpmin - minimization which calls _lp
  202. lpmax - maximimzation which calls _lp
  203. References
  204. ==========
  205. .. [1] Thomas S. Ferguson, LINEAR PROGRAMMING: A Concise Introduction
  206. web.tecnico.ulisboa.pt/mcasquilho/acad/or/ftp/FergusonUCLA_lp.pdf
  207. """
  208. A, B, C, D = [Matrix(i) for i in (A, B, C, D or [0])]
  209. if dual:
  210. _o, d, p = _simplex(-A.T, C.T, B.T, -D)
  211. return -_o, d, p
  212. if A and B:
  213. M = Matrix([[A, B], [C, D]])
  214. else:
  215. if A or B:
  216. raise ValueError("must give A and B")
  217. # no constraints given
  218. M = Matrix([[C, D]])
  219. n = M.cols - 1
  220. m = M.rows - 1
  221. if not all(i.is_Float or i.is_Rational for i in M):
  222. # with literal Float and Rational we are guaranteed the
  223. # ability of determining whether an expression is 0 or not
  224. raise TypeError(filldedent("""
  225. Only rationals and floats are allowed.
  226. """
  227. )
  228. )
  229. # x variables have priority over y variables during Bland's rule
  230. # since False < True
  231. X = [(False, j) for j in range(n)]
  232. Y = [(True, i) for i in range(m)]
  233. # Phase 1: find a feasible solution or determine none exist
  234. ## keep track of last pivot row and column
  235. last = None
  236. while True:
  237. B = M[:-1, -1]
  238. A = M[:-1, :-1]
  239. if all(B[i] >= 0 for i in range(B.rows)):
  240. # We have found a feasible solution
  241. break
  242. # Find k: first row with a negative rightmost entry
  243. for k in range(B.rows):
  244. if B[k] < 0:
  245. break # use current value of k below
  246. else:
  247. pass # error will raise below
  248. # Choose pivot column, c
  249. piv_cols = [_ for _ in range(A.cols) if A[k, _] < 0]
  250. if not piv_cols:
  251. raise InfeasibleLPError(filldedent("""
  252. The constraint set is empty!"""))
  253. _, c = min((X[i], i) for i in piv_cols) # Bland's rule
  254. # Choose pivot row, r
  255. piv_rows = [_ for _ in range(A.rows) if A[_, c] > 0 and B[_] > 0]
  256. piv_rows.append(k)
  257. r = _choose_pivot_row(A, B, piv_rows, c, Y)
  258. # check for oscillation
  259. if (r, c) == last:
  260. # Not sure what to do here; it looks like there will be
  261. # oscillations; see o1 test added at this commit to
  262. # see a system with no solution and the o2 for one
  263. # with a solution. In the case of o2, the solution
  264. # from linprog is the same as the one from lpmin, but
  265. # the matrices created in the lpmin case are different
  266. # than those created without replacements in linprog and
  267. # the matrices in the linprog case lead to oscillations.
  268. # If the matrices could be re-written in linprog like
  269. # lpmin does, this behavior could be avoided and then
  270. # perhaps the oscillating case would only occur when
  271. # there is no solution. For now, the output is checked
  272. # before exit if oscillations were detected and an
  273. # error is raised there if the solution was invalid.
  274. #
  275. # cf section 6 of Ferguson for a non-cycling modification
  276. last = True
  277. break
  278. last = r, c
  279. M = _pivot(M, r, c)
  280. X[c], Y[r] = Y[r], X[c]
  281. # Phase 2: from a feasible solution, pivot to optimal
  282. while True:
  283. B = M[:-1, -1]
  284. A = M[:-1, :-1]
  285. C = M[-1, :-1]
  286. # Choose a pivot column, c
  287. piv_cols = [_ for _ in range(n) if C[_] < 0]
  288. if not piv_cols:
  289. break
  290. _, c = min((X[i], i) for i in piv_cols) # Bland's rule
  291. # Choose a pivot row, r
  292. piv_rows = [_ for _ in range(m) if A[_, c] > 0]
  293. if not piv_rows:
  294. raise UnboundedLPError(filldedent("""
  295. Objective function can assume
  296. arbitrarily large values!"""))
  297. r = _choose_pivot_row(A, B, piv_rows, c, Y)
  298. M = _pivot(M, r, c)
  299. X[c], Y[r] = Y[r], X[c]
  300. argmax = [None] * n
  301. argmin_dual = [None] * m
  302. for i, (v, n) in enumerate(X):
  303. if v == False:
  304. argmax[n] = 0
  305. else:
  306. argmin_dual[n] = M[-1, i]
  307. for i, (v, n) in enumerate(Y):
  308. if v == True:
  309. argmin_dual[n] = 0
  310. else:
  311. argmax[n] = M[i, -1]
  312. if last and not all(i >= 0 for i in argmax + argmin_dual):
  313. raise InfeasibleLPError(filldedent("""
  314. Oscillating system led to invalid solution.
  315. If you believe there was a valid solution, please
  316. report this as a bug."""))
  317. return -M[-1, -1], argmax, argmin_dual
  318. ## routines that use _simplex or support those that do
  319. def _abcd(M, list=False):
  320. """return parts of M as matrices or lists
  321. Examples
  322. ========
  323. >>> from sympy import Matrix
  324. >>> from sympy.solvers.simplex import _abcd
  325. >>> m = Matrix(3, 3, range(9)); m
  326. Matrix([
  327. [0, 1, 2],
  328. [3, 4, 5],
  329. [6, 7, 8]])
  330. >>> a, b, c, d = _abcd(m)
  331. >>> a
  332. Matrix([
  333. [0, 1],
  334. [3, 4]])
  335. >>> b
  336. Matrix([
  337. [2],
  338. [5]])
  339. >>> c
  340. Matrix([[6, 7]])
  341. >>> d
  342. Matrix([[8]])
  343. The matrices can be returned as compact lists, too:
  344. >>> L = a, b, c, d = _abcd(m, list=True); L
  345. ([[0, 1], [3, 4]], [2, 5], [[6, 7]], [8])
  346. """
  347. def aslist(i):
  348. l = i.tolist()
  349. if len(l[0]) == 1: # col vector
  350. return [i[0] for i in l]
  351. return l
  352. m = M[:-1, :-1], M[:-1, -1], M[-1, :-1], M[-1:, -1:]
  353. if not list:
  354. return m
  355. return tuple([aslist(i) for i in m])
  356. def _m(a, b, c, d=None):
  357. """return Matrix([[a, b], [c, d]]) from matrices
  358. in Matrix or list form.
  359. Examples
  360. ========
  361. >>> from sympy import Matrix
  362. >>> from sympy.solvers.simplex import _abcd, _m
  363. >>> m = Matrix(3, 3, range(9))
  364. >>> L = _abcd(m, list=True); L
  365. ([[0, 1], [3, 4]], [2, 5], [[6, 7]], [8])
  366. >>> _abcd(m)
  367. (Matrix([
  368. [0, 1],
  369. [3, 4]]), Matrix([
  370. [2],
  371. [5]]), Matrix([[6, 7]]), Matrix([[8]]))
  372. >>> assert m == _m(*L) == _m(*_)
  373. """
  374. a, b, c, d = [Matrix(i) for i in (a, b, c, d or [0])]
  375. return Matrix([[a, b], [c, d]])
  376. def _primal_dual(M, factor=True):
  377. """return primal and dual function and constraints
  378. assuming that ``M = Matrix([[A, b], [c, d]])`` and the
  379. function ``c*x - d`` is being minimized with ``Ax >= b``
  380. for nonnegative values of ``x``. The dual and its
  381. constraints will be for maximizing `b.T*y - d` subject
  382. to ``A.T*y <= c.T``.
  383. Examples
  384. ========
  385. >>> from sympy.solvers.simplex import _primal_dual, lpmin, lpmax
  386. >>> from sympy import Matrix
  387. The following matrix represents the primal task of
  388. minimizing x + y + 7 for y >= x + 1 and y >= -2*x + 3.
  389. The dual task seeks to maximize x + 3*y + 7 with
  390. 2*y - x <= 1 and and x + y <= 1:
  391. >>> M = Matrix([
  392. ... [-1, 1, 1],
  393. ... [ 2, 1, 3],
  394. ... [ 1, 1, -7]])
  395. >>> p, d = _primal_dual(M)
  396. The minimum of the primal and maximum of the dual are the same
  397. (though they occur at different points):
  398. >>> lpmin(*p)
  399. (28/3, {x1: 2/3, x2: 5/3})
  400. >>> lpmax(*d)
  401. (28/3, {y1: 1/3, y2: 2/3})
  402. If the equivalent (but canonical) inequalities are
  403. desired, leave `factor=True`, otherwise the unmodified
  404. inequalities for M will be returned.
  405. >>> m = Matrix([
  406. ... [-3, -2, 4, -2],
  407. ... [ 2, 0, 0, -2],
  408. ... [ 0, 1, -3, 0]])
  409. >>> _primal_dual(m, False) # last condition is 2*x1 >= -2
  410. ((x2 - 3*x3,
  411. [-3*x1 - 2*x2 + 4*x3 >= -2, 2*x1 >= -2]),
  412. (-2*y1 - 2*y2,
  413. [-3*y1 + 2*y2 <= 0, -2*y1 <= 1, 4*y1 <= -3]))
  414. >>> _primal_dual(m) # condition now x1 >= -1
  415. ((x2 - 3*x3,
  416. [-3*x1 - 2*x2 + 4*x3 >= -2, x1 >= -1]),
  417. (-2*y1 - 2*y2,
  418. [-3*y1 + 2*y2 <= 0, -2*y1 <= 1, 4*y1 <= -3]))
  419. If you pass the transpose of the matrix, the primal will be
  420. identified as the standard minimization problem and the
  421. dual as the standard maximization:
  422. >>> _primal_dual(m.T)
  423. ((-2*x1 - 2*x2,
  424. [-3*x1 + 2*x2 >= 0, -2*x1 >= 1, 4*x1 >= -3]),
  425. (y2 - 3*y3,
  426. [-3*y1 - 2*y2 + 4*y3 <= -2, y1 <= -1]))
  427. A matrix must have some size or else None will be returned for
  428. the functions:
  429. >>> _primal_dual(Matrix([[1, 2]]))
  430. ((x1 - 2, []), (-2, []))
  431. >>> _primal_dual(Matrix([]))
  432. ((None, []), (None, []))
  433. References
  434. ==========
  435. .. [1] David Galvin, Relations between Primal and Dual
  436. www3.nd.edu/~dgalvin1/30210/30210_F07/presentations/dual_opt.pdf
  437. """
  438. if not M:
  439. return (None, []), (None, [])
  440. if not hasattr(M, "shape"):
  441. if len(M) not in (3, 4):
  442. raise ValueError("expecting Matrix or 3 or 4 lists")
  443. M = _m(*M)
  444. m, n = [i - 1 for i in M.shape]
  445. A, b, c, d = _abcd(M)
  446. d = d[0]
  447. _ = lambda x: numbered_symbols(x, start=1)
  448. x = Matrix([i for i, j in zip(_("x"), range(n))])
  449. yT = Matrix([i for i, j in zip(_("y"), range(m))]).T
  450. def ineq(L, r, op):
  451. rv = []
  452. for r in (op(i, j) for i, j in zip(L, r)):
  453. if r == True:
  454. continue
  455. elif r == False:
  456. return [False]
  457. if factor:
  458. f = factor_terms(r)
  459. if f.lhs.is_Mul and f.rhs % f.lhs.args[0] == 0:
  460. assert len(f.lhs.args) == 2, f.lhs
  461. k = f.lhs.args[0]
  462. r = r.func(sign(k) * f.lhs.args[1], f.rhs // abs(k))
  463. rv.append(r)
  464. return rv
  465. eq = lambda x, d: x[0] - d if x else -d
  466. F = eq(c * x, d)
  467. f = eq(yT * b, d)
  468. return (F, ineq(A * x, b, Ge)), (f, ineq(yT * A, c, Le))
  469. def _rel_as_nonpos(constr, syms):
  470. """return `(np, d, aux)` where `np` is a list of nonpositive
  471. expressions that represent the given constraints (possibly
  472. rewritten in terms of auxilliary variables) expressible with
  473. nonnegative symbols, and `d` is a dictionary mapping a given
  474. symbols to an expression with an auxilliary variable. In some
  475. cases a symbol will be used as part of the change of variables,
  476. e.g. x: x - z1 instead of x: z1 - z2.
  477. If any constraint is False/empty, return None. All variables in
  478. ``constr`` are assumed to be unbounded unless explicitly indicated
  479. otherwise with a univariate constraint, e.g. ``x >= 0`` will
  480. restrict ``x`` to nonnegative values.
  481. The ``syms`` must be included so all symbols can be given an
  482. unbounded assumption if they are not otherwise bound with
  483. univariate conditions like ``x <= 3``.
  484. Examples
  485. ========
  486. >>> from sympy.solvers.simplex import _rel_as_nonpos
  487. >>> from sympy.abc import x, y
  488. >>> _rel_as_nonpos([x >= y, x >= 0, y >= 0], (x, y))
  489. ([-x + y], {}, [])
  490. >>> _rel_as_nonpos([x >= 3, x <= 5], [x])
  491. ([_z1 - 2], {x: _z1 + 3}, [_z1])
  492. >>> _rel_as_nonpos([x <= 5], [x])
  493. ([], {x: 5 - _z1}, [_z1])
  494. >>> _rel_as_nonpos([x >= 1], [x])
  495. ([], {x: _z1 + 1}, [_z1])
  496. """
  497. r = {} # replacements to handle change of variables
  498. np = [] # nonpositive expressions
  499. aux = [] # auxilliary symbols added
  500. ui = numbered_symbols("z", start=1, cls=Dummy) # auxilliary symbols
  501. univariate = {} # {x: interval} for univariate constraints
  502. unbound = [] # symbols designated as unbound
  503. syms = set(syms) # the expected syms of the system
  504. # separate out univariates
  505. for i in constr:
  506. if i == True:
  507. continue # ignore
  508. if i == False:
  509. return # no solution
  510. if i.has(S.Infinity, S.NegativeInfinity):
  511. raise ValueError("only finite bounds are permitted")
  512. if isinstance(i, (Le, Ge)):
  513. i = i.lts - i.gts
  514. freei = i.free_symbols
  515. if freei - syms:
  516. raise ValueError(
  517. "unexpected symbol(s) in constraint: %s" % (freei - syms)
  518. )
  519. if len(freei) > 1:
  520. np.append(i)
  521. elif freei:
  522. x = freei.pop()
  523. if x in unbound:
  524. continue # will handle later
  525. ivl = Le(i, 0, evaluate=False).as_set()
  526. if x not in univariate:
  527. univariate[x] = ivl
  528. else:
  529. univariate[x] &= ivl
  530. elif i:
  531. return False
  532. else:
  533. raise TypeError(filldedent("""
  534. only equalities like Eq(x, y) or non-strict
  535. inequalities like x >= y are allowed in lp, not %s""" % i))
  536. # introduce auxilliary variables as needed for univariate
  537. # inequalities
  538. for x in syms:
  539. i = univariate.get(x, True)
  540. if not i:
  541. return None # no solution possible
  542. if i == True:
  543. unbound.append(x)
  544. continue
  545. a, b = i.inf, i.sup
  546. if a.is_infinite:
  547. u = next(ui)
  548. r[x] = b - u
  549. aux.append(u)
  550. elif b.is_infinite:
  551. if a:
  552. u = next(ui)
  553. r[x] = a + u
  554. aux.append(u)
  555. else:
  556. # standard nonnegative relationship
  557. pass
  558. else:
  559. u = next(ui)
  560. aux.append(u)
  561. # shift so u = x - a => x = u + a
  562. r[x] = u + a
  563. # add constraint for u <= b - a
  564. # since when u = b-a then x = u + a = b - a + a = b:
  565. # the upper limit for x
  566. np.append(u - (b - a))
  567. # make change of variables for unbound variables
  568. for x in unbound:
  569. u = next(ui)
  570. r[x] = u - x # reusing x
  571. aux.append(u)
  572. return np, r, aux
  573. def _lp_matrices(objective, constraints):
  574. """return A, B, C, D, r, x+X, X for maximizing
  575. objective = Cx - D with constraints Ax <= B, introducing
  576. introducing auxilliary variables, X, as necessary to make
  577. replacements of symbols as given in r, {xi: expression with Xj},
  578. so all variables in x+X will take on nonnegative values.
  579. Every univariate condition creates a semi-infinite
  580. condition, e.g. a single ``x <= 3`` creates the
  581. interval ``[-oo, 3]`` while ``x <= 3`` and ``x >= 2``
  582. create an interval ``[2, 3]``. Variables not in a univariate
  583. expression will take on nonnegative values.
  584. """
  585. # sympify input and collect free symbols
  586. F = sympify(objective)
  587. np = [sympify(i) for i in constraints]
  588. syms = set.union(*[i.free_symbols for i in [F] + np], set())
  589. # change Eq(x, y) to x - y <= 0 and y - x <= 0
  590. for i in range(len(np)):
  591. if isinstance(np[i], Eq):
  592. np[i] = np[i].lhs - np[i].rhs <= 0
  593. np.append(-np[i].lhs <= 0)
  594. # convert constraints to nonpositive expressions
  595. _ = _rel_as_nonpos(np, syms)
  596. if _ is None:
  597. raise InfeasibleLPError(filldedent("""
  598. Inconsistent/False constraint"""))
  599. np, r, aux = _
  600. # do change of variables
  601. F = F.xreplace(r)
  602. np = [i.xreplace(r) for i in np]
  603. # convert to matrices
  604. xx = list(ordered(syms)) + aux
  605. A, B = linear_eq_to_matrix(np, xx)
  606. C, D = linear_eq_to_matrix([F], xx)
  607. return A, B, C, D, r, xx, aux
  608. def _lp(min_max, f, constr):
  609. """Return the optimization (min or max) of ``f`` with the given
  610. constraints. All variables are unbounded unless constrained.
  611. If `min_max` is 'max' then the results corresponding to the
  612. maximization of ``f`` will be returned, else the minimization.
  613. The constraints can be given as Le, Ge or Eq expressions.
  614. Examples
  615. ========
  616. >>> from sympy.solvers.simplex import _lp as lp
  617. >>> from sympy import Eq
  618. >>> from sympy.abc import x, y, z
  619. >>> f = x + y - 2*z
  620. >>> c = [7*x + 4*y - 7*z <= 3, 3*x - y + 10*z <= 6]
  621. >>> c += [i >= 0 for i in (x, y, z)]
  622. >>> lp(min, f, c)
  623. (-6/5, {x: 0, y: 0, z: 3/5})
  624. By passing max, the maximum value for f under the constraints
  625. is returned (if possible):
  626. >>> lp(max, f, c)
  627. (3/4, {x: 0, y: 3/4, z: 0})
  628. Constraints that are equalities will require that the solution
  629. also satisfy them:
  630. >>> lp(max, f, c + [Eq(y - 9*x, 1)])
  631. (5/7, {x: 0, y: 1, z: 1/7})
  632. All symbols are reported, even if they are not in the objective
  633. function:
  634. >>> lp(min, x, [y + x >= 3, x >= 0])
  635. (0, {x: 0, y: 3})
  636. """
  637. # get the matrix components for the system expressed
  638. # in terms of only nonnegative variables
  639. A, B, C, D, r, xx, aux = _lp_matrices(f, constr)
  640. how = str(min_max).lower()
  641. if "max" in how:
  642. # _simplex minimizes for Ax <= B so we
  643. # have to change the sign of the function
  644. # and negate the optimal value returned
  645. _o, p, d = _simplex(A, B, -C, -D)
  646. o = -_o
  647. elif "min" in how:
  648. o, p, d = _simplex(A, B, C, D)
  649. else:
  650. raise ValueError("expecting min or max")
  651. # restore original variables and remove aux from p
  652. p = dict(zip(xx, p))
  653. if r: # p has original symbols and auxilliary symbols
  654. # if r has x: x - z1 use values from p to update
  655. r = {k: v.xreplace(p) for k, v in r.items()}
  656. # then use the actual value of x (= x - z1) in p
  657. p.update(r)
  658. # don't show aux
  659. p = {k: p[k] for k in ordered(p) if k not in aux}
  660. # not returning dual since there may be extra constraints
  661. # when a variable has finite bounds
  662. return o, p
  663. def lpmin(f, constr):
  664. """return minimum of linear equation ``f`` under
  665. linear constraints expressed using Ge, Le or Eq.
  666. All variables are unbounded unless constrained.
  667. Examples
  668. ========
  669. >>> from sympy.solvers.simplex import lpmin
  670. >>> from sympy import Eq
  671. >>> from sympy.abc import x, y
  672. >>> lpmin(x, [2*x - 3*y >= -1, Eq(x + 3*y, 2), x <= 2*y])
  673. (1/3, {x: 1/3, y: 5/9})
  674. Negative values for variables are permitted unless explicitly
  675. excluding, so minimizing ``x`` for ``x <= 3`` is an
  676. unbounded problem while the following has a bounded solution:
  677. >>> lpmin(x, [x >= 0, x <= 3])
  678. (0, {x: 0})
  679. Without indicating that ``x`` is nonnegative, there
  680. is no minimum for this objective:
  681. >>> lpmin(x, [x <= 3])
  682. Traceback (most recent call last):
  683. ...
  684. sympy.solvers.simplex.UnboundedLPError:
  685. Objective function can assume arbitrarily large values!
  686. See Also
  687. ========
  688. linprog, lpmax
  689. """
  690. return _lp(min, f, constr)
  691. def lpmax(f, constr):
  692. """return maximum of linear equation ``f`` under
  693. linear constraints expressed using Ge, Le or Eq.
  694. All variables are unbounded unless constrained.
  695. Examples
  696. ========
  697. >>> from sympy.solvers.simplex import lpmax
  698. >>> from sympy import Eq
  699. >>> from sympy.abc import x, y
  700. >>> lpmax(x, [2*x - 3*y >= -1, Eq(x+ 3*y,2), x <= 2*y])
  701. (4/5, {x: 4/5, y: 2/5})
  702. Negative values for variables are permitted unless explicitly
  703. excluding:
  704. >>> lpmax(x, [x <= -1])
  705. (-1, {x: -1})
  706. If a non-negative constraint is added for x, there is no
  707. possible solution:
  708. >>> lpmax(x, [x <= -1, x >= 0])
  709. Traceback (most recent call last):
  710. ...
  711. sympy.solvers.simplex.InfeasibleLPError: inconsistent/False constraint
  712. See Also
  713. ========
  714. linprog, lpmin
  715. """
  716. return _lp(max, f, constr)
  717. def _handle_bounds(bounds):
  718. # introduce auxiliary variables as needed for univariate
  719. # inequalities
  720. def _make_list(length: int, index_value_pairs):
  721. li = [0] * length
  722. for idx, val in index_value_pairs:
  723. li[idx] = val
  724. return li
  725. unbound = []
  726. row = []
  727. row2 = []
  728. b_len = len(bounds)
  729. for x, (a, b) in enumerate(bounds):
  730. if a is None and b is None:
  731. unbound.append(x)
  732. elif a is None:
  733. # r[x] = b - u
  734. b_len += 1
  735. row.append(_make_list(b_len, [(x, 1), (-1, 1)]))
  736. row.append(_make_list(b_len, [(x, -1), (-1, -1)]))
  737. row2.extend([[b], [-b]])
  738. elif b is None:
  739. if a:
  740. # r[x] = a + u
  741. b_len += 1
  742. row.append(_make_list(b_len, [(x, 1), (-1, -1)]))
  743. row.append(_make_list(b_len, [(x, -1), (-1, 1)]))
  744. row2.extend([[a], [-a]])
  745. else:
  746. # standard nonnegative relationship
  747. pass
  748. else:
  749. # r[x] = u + a
  750. b_len += 1
  751. row.append(_make_list(b_len, [(x, 1), (-1, -1)]))
  752. row.append(_make_list(b_len, [(x, -1), (-1, 1)]))
  753. # u <= b - a
  754. row.append(_make_list(b_len, [(-1, 1)]))
  755. row2.extend([[a], [-a], [b - a]])
  756. # make change of variables for unbound variables
  757. for x in unbound:
  758. # r[x] = u - v
  759. b_len += 2
  760. row.append(_make_list(b_len, [(x, 1), (-1, 1), (-2, -1)]))
  761. row.append(_make_list(b_len, [(x, -1), (-1, -1), (-2, 1)]))
  762. row2.extend([[0], [0]])
  763. return Matrix([r + [0]*(b_len - len(r)) for r in row]), Matrix(row2)
  764. def linprog(c, A=None, b=None, A_eq=None, b_eq=None, bounds=None):
  765. """Return the minimization of ``c*x`` with the given
  766. constraints ``A*x <= b`` and ``A_eq*x = b_eq``. Unless bounds
  767. are given, variables will have nonnegative values in the solution.
  768. If ``A`` is not given, then the dimension of the system will
  769. be determined by the length of ``C``.
  770. By default, all variables will be nonnegative. If ``bounds``
  771. is given as a single tuple, ``(lo, hi)``, then all variables
  772. will be constrained to be between ``lo`` and ``hi``. Use
  773. None for a ``lo`` or ``hi`` if it is unconstrained in the
  774. negative or positive direction, respectively, e.g.
  775. ``(None, 0)`` indicates nonpositive values. To set
  776. individual ranges, pass a list with length equal to the
  777. number of columns in ``A``, each element being a tuple; if
  778. only a few variables take on non-default values they can be
  779. passed as a dictionary with keys giving the corresponding
  780. column to which the variable is assigned, e.g. ``bounds={2:
  781. (1, 4)}`` would limit the 3rd variable to have a value in
  782. range ``[1, 4]``.
  783. Examples
  784. ========
  785. >>> from sympy.solvers.simplex import linprog
  786. >>> from sympy import symbols, Eq, linear_eq_to_matrix as M, Matrix
  787. >>> x = x1, x2, x3, x4 = symbols('x1:5')
  788. >>> X = Matrix(x)
  789. >>> c, d = M(5*x2 + x3 + 4*x4 - x1, x)
  790. >>> a, b = M([5*x2 + 2*x3 + 5*x4 - (x1 + 5)], x)
  791. >>> aeq, beq = M([Eq(3*x2 + x4, 2), Eq(-x1 + x3 + 2*x4, 1)], x)
  792. >>> constr = [i <= j for i,j in zip(a*X, b)]
  793. >>> constr += [Eq(i, j) for i,j in zip(aeq*X, beq)]
  794. >>> linprog(c, a, b, aeq, beq)
  795. (9/2, [0, 1/2, 0, 1/2])
  796. >>> assert all(i.subs(dict(zip(x, _[1]))) for i in constr)
  797. See Also
  798. ========
  799. lpmin, lpmax
  800. """
  801. ## the objective
  802. C = Matrix(c)
  803. if C.rows != 1 and C.cols == 1:
  804. C = C.T
  805. if C.rows != 1:
  806. raise ValueError("C must be a single row.")
  807. ## the inequalities
  808. if not A:
  809. if b:
  810. raise ValueError("A and b must both be given")
  811. # the governing equations will be simple constraints
  812. # on variables
  813. A, b = zeros(0, C.cols), zeros(C.cols, 1)
  814. else:
  815. A, b = [Matrix(i) for i in (A, b)]
  816. if A.cols != C.cols:
  817. raise ValueError("number of columns in A and C must match")
  818. ## the equalities
  819. if A_eq is None:
  820. if not b_eq is None:
  821. raise ValueError("A_eq and b_eq must both be given")
  822. else:
  823. A_eq, b_eq = [Matrix(i) for i in (A_eq, b_eq)]
  824. # if x == y then x <= y and x >= y (-x <= -y)
  825. A = A.col_join(A_eq)
  826. A = A.col_join(-A_eq)
  827. b = b.col_join(b_eq)
  828. b = b.col_join(-b_eq)
  829. if not (bounds is None or bounds == {} or bounds == (0, None)):
  830. ## the bounds are interpreted
  831. if type(bounds) is tuple and len(bounds) == 2:
  832. bounds = [bounds] * A.cols
  833. elif len(bounds) == A.cols and all(
  834. type(i) is tuple and len(i) == 2 for i in bounds):
  835. pass # individual bounds
  836. elif type(bounds) is dict and all(
  837. type(i) is tuple and len(i) == 2
  838. for i in bounds.values()):
  839. # sparse bounds
  840. db = bounds
  841. bounds = [(0, None)] * A.cols
  842. while db:
  843. i, j = db.popitem()
  844. bounds[i] = j # IndexError if out-of-bounds indices
  845. else:
  846. raise ValueError("unexpected bounds %s" % bounds)
  847. A_, b_ = _handle_bounds(bounds)
  848. aux = A_.cols - A.cols
  849. if A:
  850. A = Matrix([[A, zeros(A.rows, aux)], [A_]])
  851. b = b.col_join(b_)
  852. else:
  853. A = A_
  854. b = b_
  855. C = C.row_join(zeros(1, aux))
  856. else:
  857. aux = -A.cols # set so -aux will give all cols below
  858. o, p, d = _simplex(A, b, C)
  859. return o, p[:-aux] # don't include aux values
  860. def show_linprog(c, A=None, b=None, A_eq=None, b_eq=None, bounds=None):
  861. from sympy import symbols
  862. ## the objective
  863. C = Matrix(c)
  864. if C.rows != 1 and C.cols == 1:
  865. C = C.T
  866. if C.rows != 1:
  867. raise ValueError("C must be a single row.")
  868. ## the inequalities
  869. if not A:
  870. if b:
  871. raise ValueError("A and b must both be given")
  872. # the governing equations will be simple constraints
  873. # on variables
  874. A, b = zeros(0, C.cols), zeros(C.cols, 1)
  875. else:
  876. A, b = [Matrix(i) for i in (A, b)]
  877. if A.cols != C.cols:
  878. raise ValueError("number of columns in A and C must match")
  879. ## the equalities
  880. if A_eq is None:
  881. if not b_eq is None:
  882. raise ValueError("A_eq and b_eq must both be given")
  883. else:
  884. A_eq, b_eq = [Matrix(i) for i in (A_eq, b_eq)]
  885. if not (bounds is None or bounds == {} or bounds == (0, None)):
  886. ## the bounds are interpreted
  887. if type(bounds) is tuple and len(bounds) == 2:
  888. bounds = [bounds] * A.cols
  889. elif len(bounds) == A.cols and all(
  890. type(i) is tuple and len(i) == 2 for i in bounds):
  891. pass # individual bounds
  892. elif type(bounds) is dict and all(
  893. type(i) is tuple and len(i) == 2
  894. for i in bounds.values()):
  895. # sparse bounds
  896. db = bounds
  897. bounds = [(0, None)] * A.cols
  898. while db:
  899. i, j = db.popitem()
  900. bounds[i] = j # IndexError if out-of-bounds indices
  901. else:
  902. raise ValueError("unexpected bounds %s" % bounds)
  903. x = Matrix(symbols('x1:%s' % (A.cols+1)))
  904. f,c = (C*x)[0], [i<=j for i,j in zip(A*x, b)] + [Eq(i,j) for i,j in zip(A_eq*x,b_eq)]
  905. for i, (lo, hi) in enumerate(bounds):
  906. if lo is not None:
  907. c.append(x[i]>=lo)
  908. if hi is not None:
  909. c.append(x[i]<=hi)
  910. return f,c