passagemath-polyhedra 10.6.31rc3__cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of passagemath-polyhedra might be problematic. Click here for more details.

Files changed (206) hide show
  1. passagemath_polyhedra-10.6.31rc3.dist-info/METADATA +367 -0
  2. passagemath_polyhedra-10.6.31rc3.dist-info/METADATA.bak +369 -0
  3. passagemath_polyhedra-10.6.31rc3.dist-info/RECORD +206 -0
  4. passagemath_polyhedra-10.6.31rc3.dist-info/WHEEL +6 -0
  5. passagemath_polyhedra-10.6.31rc3.dist-info/top_level.txt +2 -0
  6. passagemath_polyhedra.libs/libgmp-6e109695.so.10.5.0 +0 -0
  7. passagemath_polyhedra.libs/libgomp-e985bcbb.so.1.0.0 +0 -0
  8. sage/all__sagemath_polyhedra.py +50 -0
  9. sage/game_theory/all.py +8 -0
  10. sage/game_theory/catalog.py +6 -0
  11. sage/game_theory/catalog_normal_form_games.py +923 -0
  12. sage/game_theory/cooperative_game.py +844 -0
  13. sage/game_theory/matching_game.py +1181 -0
  14. sage/game_theory/normal_form_game.py +2697 -0
  15. sage/game_theory/parser.py +275 -0
  16. sage/geometry/all__sagemath_polyhedra.py +22 -0
  17. sage/geometry/cone.py +6940 -0
  18. sage/geometry/cone_catalog.py +847 -0
  19. sage/geometry/cone_critical_angles.py +1027 -0
  20. sage/geometry/convex_set.py +1119 -0
  21. sage/geometry/fan.py +3743 -0
  22. sage/geometry/fan_isomorphism.py +389 -0
  23. sage/geometry/fan_morphism.py +1884 -0
  24. sage/geometry/hasse_diagram.py +202 -0
  25. sage/geometry/hyperplane_arrangement/affine_subspace.py +390 -0
  26. sage/geometry/hyperplane_arrangement/all.py +1 -0
  27. sage/geometry/hyperplane_arrangement/arrangement.py +3895 -0
  28. sage/geometry/hyperplane_arrangement/check_freeness.py +145 -0
  29. sage/geometry/hyperplane_arrangement/hyperplane.py +773 -0
  30. sage/geometry/hyperplane_arrangement/library.py +825 -0
  31. sage/geometry/hyperplane_arrangement/ordered_arrangement.py +642 -0
  32. sage/geometry/hyperplane_arrangement/plot.py +520 -0
  33. sage/geometry/integral_points.py +35 -0
  34. sage/geometry/integral_points_generic_dense.cpython-314-x86_64-linux-gnu.so +0 -0
  35. sage/geometry/integral_points_generic_dense.pyx +7 -0
  36. sage/geometry/lattice_polytope.py +5894 -0
  37. sage/geometry/linear_expression.py +773 -0
  38. sage/geometry/newton_polygon.py +767 -0
  39. sage/geometry/point_collection.cpython-314-x86_64-linux-gnu.so +0 -0
  40. sage/geometry/point_collection.pyx +1008 -0
  41. sage/geometry/polyhedral_complex.py +2616 -0
  42. sage/geometry/polyhedron/all.py +8 -0
  43. sage/geometry/polyhedron/backend_cdd.py +460 -0
  44. sage/geometry/polyhedron/backend_cdd_rdf.py +231 -0
  45. sage/geometry/polyhedron/backend_field.py +347 -0
  46. sage/geometry/polyhedron/backend_normaliz.py +2503 -0
  47. sage/geometry/polyhedron/backend_number_field.py +168 -0
  48. sage/geometry/polyhedron/backend_polymake.py +765 -0
  49. sage/geometry/polyhedron/backend_ppl.py +582 -0
  50. sage/geometry/polyhedron/base.py +1206 -0
  51. sage/geometry/polyhedron/base0.py +1444 -0
  52. sage/geometry/polyhedron/base1.py +886 -0
  53. sage/geometry/polyhedron/base2.py +812 -0
  54. sage/geometry/polyhedron/base3.py +1845 -0
  55. sage/geometry/polyhedron/base4.py +1262 -0
  56. sage/geometry/polyhedron/base5.py +2700 -0
  57. sage/geometry/polyhedron/base6.py +1741 -0
  58. sage/geometry/polyhedron/base7.py +997 -0
  59. sage/geometry/polyhedron/base_QQ.py +1258 -0
  60. sage/geometry/polyhedron/base_RDF.py +98 -0
  61. sage/geometry/polyhedron/base_ZZ.py +934 -0
  62. sage/geometry/polyhedron/base_mutable.py +215 -0
  63. sage/geometry/polyhedron/base_number_field.py +122 -0
  64. sage/geometry/polyhedron/cdd_file_format.py +155 -0
  65. sage/geometry/polyhedron/combinatorial_polyhedron/all.py +1 -0
  66. sage/geometry/polyhedron/combinatorial_polyhedron/base.cpython-314-x86_64-linux-gnu.so +0 -0
  67. sage/geometry/polyhedron/combinatorial_polyhedron/base.pxd +76 -0
  68. sage/geometry/polyhedron/combinatorial_polyhedron/base.pyx +3859 -0
  69. sage/geometry/polyhedron/combinatorial_polyhedron/combinatorial_face.cpython-314-x86_64-linux-gnu.so +0 -0
  70. sage/geometry/polyhedron/combinatorial_polyhedron/combinatorial_face.pxd +39 -0
  71. sage/geometry/polyhedron/combinatorial_polyhedron/combinatorial_face.pyx +1038 -0
  72. sage/geometry/polyhedron/combinatorial_polyhedron/conversions.cpython-314-x86_64-linux-gnu.so +0 -0
  73. sage/geometry/polyhedron/combinatorial_polyhedron/conversions.pxd +9 -0
  74. sage/geometry/polyhedron/combinatorial_polyhedron/conversions.pyx +501 -0
  75. sage/geometry/polyhedron/combinatorial_polyhedron/face_data_structure.pxd +207 -0
  76. sage/geometry/polyhedron/combinatorial_polyhedron/face_iterator.cpython-314-x86_64-linux-gnu.so +0 -0
  77. sage/geometry/polyhedron/combinatorial_polyhedron/face_iterator.pxd +102 -0
  78. sage/geometry/polyhedron/combinatorial_polyhedron/face_iterator.pyx +2274 -0
  79. sage/geometry/polyhedron/combinatorial_polyhedron/face_list_data_structure.cpython-314-x86_64-linux-gnu.so +0 -0
  80. sage/geometry/polyhedron/combinatorial_polyhedron/face_list_data_structure.pxd +370 -0
  81. sage/geometry/polyhedron/combinatorial_polyhedron/face_list_data_structure.pyx +84 -0
  82. sage/geometry/polyhedron/combinatorial_polyhedron/list_of_faces.cpython-314-x86_64-linux-gnu.so +0 -0
  83. sage/geometry/polyhedron/combinatorial_polyhedron/list_of_faces.pxd +31 -0
  84. sage/geometry/polyhedron/combinatorial_polyhedron/list_of_faces.pyx +587 -0
  85. sage/geometry/polyhedron/combinatorial_polyhedron/polyhedron_face_lattice.cpython-314-x86_64-linux-gnu.so +0 -0
  86. sage/geometry/polyhedron/combinatorial_polyhedron/polyhedron_face_lattice.pxd +52 -0
  87. sage/geometry/polyhedron/combinatorial_polyhedron/polyhedron_face_lattice.pyx +560 -0
  88. sage/geometry/polyhedron/constructor.py +773 -0
  89. sage/geometry/polyhedron/double_description.py +753 -0
  90. sage/geometry/polyhedron/double_description_inhomogeneous.py +564 -0
  91. sage/geometry/polyhedron/face.py +1060 -0
  92. sage/geometry/polyhedron/generating_function.py +1810 -0
  93. sage/geometry/polyhedron/lattice_euclidean_group_element.py +178 -0
  94. sage/geometry/polyhedron/library.py +3502 -0
  95. sage/geometry/polyhedron/misc.py +121 -0
  96. sage/geometry/polyhedron/modules/all.py +1 -0
  97. sage/geometry/polyhedron/modules/formal_polyhedra_module.py +155 -0
  98. sage/geometry/polyhedron/palp_database.py +447 -0
  99. sage/geometry/polyhedron/parent.py +1279 -0
  100. sage/geometry/polyhedron/plot.py +1986 -0
  101. sage/geometry/polyhedron/ppl_lattice_polygon.py +556 -0
  102. sage/geometry/polyhedron/ppl_lattice_polytope.py +1257 -0
  103. sage/geometry/polyhedron/representation.py +1723 -0
  104. sage/geometry/pseudolines.py +515 -0
  105. sage/geometry/relative_interior.py +445 -0
  106. sage/geometry/toric_plotter.py +1103 -0
  107. sage/geometry/triangulation/all.py +2 -0
  108. sage/geometry/triangulation/base.cpython-314-x86_64-linux-gnu.so +0 -0
  109. sage/geometry/triangulation/base.pyx +963 -0
  110. sage/geometry/triangulation/data.h +147 -0
  111. sage/geometry/triangulation/data.pxd +4 -0
  112. sage/geometry/triangulation/element.py +914 -0
  113. sage/geometry/triangulation/functions.h +10 -0
  114. sage/geometry/triangulation/functions.pxd +4 -0
  115. sage/geometry/triangulation/point_configuration.py +2256 -0
  116. sage/geometry/triangulation/triangulations.h +49 -0
  117. sage/geometry/triangulation/triangulations.pxd +7 -0
  118. sage/geometry/voronoi_diagram.py +319 -0
  119. sage/interfaces/all__sagemath_polyhedra.py +1 -0
  120. sage/interfaces/polymake.py +2028 -0
  121. sage/numerical/all.py +13 -0
  122. sage/numerical/all__sagemath_polyhedra.py +11 -0
  123. sage/numerical/backends/all.py +1 -0
  124. sage/numerical/backends/all__sagemath_polyhedra.py +1 -0
  125. sage/numerical/backends/cvxopt_backend.cpython-314-x86_64-linux-gnu.so +0 -0
  126. sage/numerical/backends/cvxopt_backend.pyx +1006 -0
  127. sage/numerical/backends/cvxopt_backend_test.py +19 -0
  128. sage/numerical/backends/cvxopt_sdp_backend.cpython-314-x86_64-linux-gnu.so +0 -0
  129. sage/numerical/backends/cvxopt_sdp_backend.pyx +382 -0
  130. sage/numerical/backends/cvxpy_backend.cpython-314-x86_64-linux-gnu.so +0 -0
  131. sage/numerical/backends/cvxpy_backend.pxd +41 -0
  132. sage/numerical/backends/cvxpy_backend.pyx +934 -0
  133. sage/numerical/backends/cvxpy_backend_test.py +13 -0
  134. sage/numerical/backends/generic_backend_test.py +24 -0
  135. sage/numerical/backends/interactivelp_backend.cpython-314-x86_64-linux-gnu.so +0 -0
  136. sage/numerical/backends/interactivelp_backend.pxd +36 -0
  137. sage/numerical/backends/interactivelp_backend.pyx +1231 -0
  138. sage/numerical/backends/interactivelp_backend_test.py +12 -0
  139. sage/numerical/backends/logging_backend.py +391 -0
  140. sage/numerical/backends/matrix_sdp_backend.cpython-314-x86_64-linux-gnu.so +0 -0
  141. sage/numerical/backends/matrix_sdp_backend.pxd +15 -0
  142. sage/numerical/backends/matrix_sdp_backend.pyx +478 -0
  143. sage/numerical/backends/ppl_backend.cpython-314-x86_64-linux-gnu.so +0 -0
  144. sage/numerical/backends/ppl_backend.pyx +1126 -0
  145. sage/numerical/backends/ppl_backend_test.py +13 -0
  146. sage/numerical/backends/scip_backend.cpython-314-x86_64-linux-gnu.so +0 -0
  147. sage/numerical/backends/scip_backend.pxd +22 -0
  148. sage/numerical/backends/scip_backend.pyx +1289 -0
  149. sage/numerical/backends/scip_backend_test.py +13 -0
  150. sage/numerical/interactive_simplex_method.py +5338 -0
  151. sage/numerical/knapsack.py +665 -0
  152. sage/numerical/linear_functions.cpython-314-x86_64-linux-gnu.so +0 -0
  153. sage/numerical/linear_functions.pxd +31 -0
  154. sage/numerical/linear_functions.pyx +1648 -0
  155. sage/numerical/linear_tensor.py +470 -0
  156. sage/numerical/linear_tensor_constraints.py +448 -0
  157. sage/numerical/linear_tensor_element.cpython-314-x86_64-linux-gnu.so +0 -0
  158. sage/numerical/linear_tensor_element.pxd +6 -0
  159. sage/numerical/linear_tensor_element.pyx +459 -0
  160. sage/numerical/mip.cpython-314-x86_64-linux-gnu.so +0 -0
  161. sage/numerical/mip.pxd +40 -0
  162. sage/numerical/mip.pyx +3667 -0
  163. sage/numerical/sdp.cpython-314-x86_64-linux-gnu.so +0 -0
  164. sage/numerical/sdp.pxd +39 -0
  165. sage/numerical/sdp.pyx +1433 -0
  166. sage/rings/all__sagemath_polyhedra.py +3 -0
  167. sage/rings/polynomial/all__sagemath_polyhedra.py +10 -0
  168. sage/rings/polynomial/omega.py +982 -0
  169. sage/schemes/all__sagemath_polyhedra.py +2 -0
  170. sage/schemes/toric/all.py +10 -0
  171. sage/schemes/toric/chow_group.py +1248 -0
  172. sage/schemes/toric/divisor.py +2082 -0
  173. sage/schemes/toric/divisor_class.cpython-314-x86_64-linux-gnu.so +0 -0
  174. sage/schemes/toric/divisor_class.pyx +322 -0
  175. sage/schemes/toric/fano_variety.py +1606 -0
  176. sage/schemes/toric/homset.py +650 -0
  177. sage/schemes/toric/ideal.py +451 -0
  178. sage/schemes/toric/library.py +1322 -0
  179. sage/schemes/toric/morphism.py +1958 -0
  180. sage/schemes/toric/points.py +1032 -0
  181. sage/schemes/toric/sheaf/all.py +1 -0
  182. sage/schemes/toric/sheaf/constructor.py +302 -0
  183. sage/schemes/toric/sheaf/klyachko.py +921 -0
  184. sage/schemes/toric/toric_subscheme.py +905 -0
  185. sage/schemes/toric/variety.py +3460 -0
  186. sage/schemes/toric/weierstrass.py +1078 -0
  187. sage/schemes/toric/weierstrass_covering.py +457 -0
  188. sage/schemes/toric/weierstrass_higher.py +288 -0
  189. sage_wheels/share/reflexive_polytopes/Full2d/zzdb.info +10 -0
  190. sage_wheels/share/reflexive_polytopes/Full2d/zzdb.v03 +0 -0
  191. sage_wheels/share/reflexive_polytopes/Full2d/zzdb.v04 +0 -0
  192. sage_wheels/share/reflexive_polytopes/Full2d/zzdb.v05 +1 -0
  193. sage_wheels/share/reflexive_polytopes/Full2d/zzdb.v06 +1 -0
  194. sage_wheels/share/reflexive_polytopes/Full3d/zzdb.info +22 -0
  195. sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v04 +0 -0
  196. sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v05 +0 -0
  197. sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v06 +0 -0
  198. sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v07 +0 -0
  199. sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v08 +0 -0
  200. sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v09 +0 -0
  201. sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v10 +0 -0
  202. sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v11 +1 -0
  203. sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v12 +1 -0
  204. sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v13 +1 -0
  205. sage_wheels/share/reflexive_polytopes/reflexive_polytopes_2d +80 -0
  206. sage_wheels/share/reflexive_polytopes/reflexive_polytopes_3d +37977 -0
@@ -0,0 +1,1231 @@
1
+ # sage_setup: distribution = sagemath-polyhedra
2
+ r"""
3
+ InteractiveLP Backend
4
+
5
+ AUTHORS:
6
+
7
+ - Nathann Cohen (2010-10) : generic_backend template
8
+ - Matthias Koeppe (2016-03) : this backend
9
+ """
10
+
11
+ # ****************************************************************************
12
+ # Copyright (C) 2010 Nathann Cohen <nathann.cohen@gmail.com>
13
+ # Copyright (C) 2016 Matthias Koeppe <mkoeppe@math.ucdavis.edu>
14
+ #
15
+ # This program is free software: you can redistribute it and/or modify
16
+ # it under the terms of the GNU General Public License as published by
17
+ # the Free Software Foundation, either version 2 of the License, or
18
+ # (at your option) any later version.
19
+ # https://www.gnu.org/licenses/
20
+ # ****************************************************************************
21
+
22
+ from sage.numerical.mip import MIPSolverException
23
+ from sage.numerical.interactive_simplex_method import InteractiveLPProblem, default_variable_name
24
+ from sage.modules.free_module_element import vector
25
+ from copy import copy
26
+
27
+
28
+ cdef class InteractiveLPBackend:
29
+ """
30
+ MIP Backend that works with :class:`InteractiveLPProblem`.
31
+
32
+ This backend should be used only for linear programs over general fields,
33
+ or for educational purposes. For fast computations with floating point
34
+ arithmetic, use one of the numerical backends. For exact computations
35
+ with rational numbers, use backend 'PPL'.
36
+
37
+ There is no support for integer variables.
38
+
39
+ EXAMPLES::
40
+
41
+ sage: from sage.numerical.backends.generic_backend import get_solver
42
+ sage: p = get_solver(solver = "InteractiveLP")
43
+ """
44
+
45
+ def __cinit__(self, maximization=True, base_ring=None):
46
+ """
47
+ Cython constructor.
48
+
49
+ EXAMPLES::
50
+
51
+ sage: from sage.numerical.backends.generic_backend import get_solver
52
+ sage: p = get_solver(solver = "InteractiveLP")
53
+
54
+ This backend can work with irrational algebraic numbers::
55
+
56
+ sage: # needs sage.groups sage.rings.number_field
57
+ sage: poly = polytopes.dodecahedron(base_ring=AA)
58
+ sage: lp, x = poly.to_linear_program(solver='InteractiveLP', return_variable=True)
59
+ sage: lp.set_objective(x[0] + x[1] + x[2])
60
+ sage: lp.solve()
61
+ 2.291796067500631?
62
+ sage: lp.get_values(x[0], x[1], x[2])
63
+ [0.763932022500211?, 0.763932022500211?, 0.763932022500211?]
64
+ sage: lp.set_objective(x[0] - x[1] - x[2])
65
+ sage: lp.solve()
66
+ 2.291796067500631?
67
+ sage: lp.get_values(x[0], x[1], x[2])
68
+ [0.763932022500211?, -0.763932022500211?, -0.763932022500211?]
69
+ """
70
+
71
+ if base_ring is None:
72
+ from sage.rings.rational_field import QQ
73
+ base_ring = QQ
74
+
75
+ self.lp = InteractiveLPProblem([], [], [], base_ring=base_ring)
76
+ self.set_verbosity(0)
77
+
78
+ if maximization:
79
+ self.set_sense(+1)
80
+ else:
81
+ self.set_sense(-1)
82
+
83
+ self.row_names = []
84
+
85
+ cpdef __copy__(self):
86
+ """
87
+ Return a copy of ``self``.
88
+
89
+ EXAMPLES::
90
+
91
+ sage: from sage.numerical.backends.generic_backend import get_solver
92
+ sage: p = MixedIntegerLinearProgram(solver = "InteractiveLP")
93
+ sage: b = p.new_variable()
94
+ sage: p.add_constraint(b[1] + b[2] <= 6)
95
+ sage: p.set_objective(b[1] + b[2])
96
+ sage: cp = copy(p.get_backend())
97
+ sage: cp.solve()
98
+ 0
99
+ sage: cp.get_objective_value()
100
+ 6
101
+ """
102
+ cdef InteractiveLPBackend cp = type(self)(base_ring=self.base_ring())
103
+ cp.lp = self.lp # it's considered immutable; so no need to copy.
104
+ cp.row_names = copy(self.row_names)
105
+ cp.prob_name = self.prob_name
106
+ return cp
107
+
108
+ cpdef base_ring(self):
109
+ """
110
+ Return the base ring.
111
+
112
+ OUTPUT: a ring; the coefficients that the chosen solver supports
113
+
114
+ EXAMPLES::
115
+
116
+ sage: from sage.numerical.backends.generic_backend import get_solver
117
+ sage: p = get_solver(solver = "InteractiveLP")
118
+ sage: p.base_ring()
119
+ Rational Field
120
+ """
121
+ return self.lp.base_ring()
122
+
123
+ def _variable_type_from_bounds(self, lower_bound, upper_bound):
124
+ """
125
+ Return a string designating a variable type in `InteractiveLPProblem`.
126
+
127
+ INPUT:
128
+
129
+ - ``lower_bound`` -- the lower bound of the variable
130
+
131
+ - ``upper_bound`` -- the upper bound of the variable
132
+
133
+ OUTPUT: string, one of ``''``, ``'<='``, ``'>='``
134
+
135
+ The function raises an error if this pair of bounds cannot be
136
+ represented by an `InteractiveLPProblem` variable type.
137
+
138
+ EXAMPLES::
139
+
140
+ sage: from sage.numerical.backends.generic_backend import get_solver
141
+ sage: p = get_solver(solver = "InteractiveLP")
142
+ sage: p._variable_type_from_bounds(0, None)
143
+ '>='
144
+ sage: p._variable_type_from_bounds(None, 0)
145
+ '<='
146
+ sage: p._variable_type_from_bounds(None, None)
147
+ ''
148
+ sage: p._variable_type_from_bounds(None, 5)
149
+ Traceback (most recent call last):
150
+ ...
151
+ NotImplementedError: General variable bounds not supported
152
+ """
153
+ if lower_bound is None:
154
+ if upper_bound is None:
155
+ return ""
156
+ elif upper_bound == 0:
157
+ return "<="
158
+ else:
159
+ raise NotImplementedError("General variable bounds not supported")
160
+ elif lower_bound == 0:
161
+ if upper_bound is None:
162
+ return ">="
163
+ else:
164
+ raise NotImplementedError("General variable bounds not supported")
165
+ else:
166
+ raise NotImplementedError("General variable bounds not supported")
167
+
168
+ cpdef int add_variable(self, lower_bound=0, upper_bound=None,
169
+ binary=False, continuous=True, integer=False,
170
+ obj=None, name=None, coefficients=None) except -1:
171
+ ## coefficients is an extension in this backend,
172
+ ## and a proposed addition to the interface, to unify this with add_col.
173
+ """
174
+ Add a variable.
175
+
176
+ This amounts to adding a new column to the matrix. By default,
177
+ the variable is both nonnegative and real.
178
+
179
+ In this backend, variables are always continuous (real).
180
+ If integer variables are requested via the parameters
181
+ ``binary`` and ``integer``, an error will be raised.
182
+
183
+ INPUT:
184
+
185
+ - ``lower_bound`` -- the lower bound of the variable (default: 0)
186
+
187
+ - ``upper_bound`` -- the upper bound of the variable (default: ``None``)
188
+
189
+ - ``binary`` -- ``True`` if the variable is binary (default: ``False``)
190
+
191
+ - ``continuous`` -- ``True`` if the variable is continuous (default: ``True``)
192
+
193
+ - ``integer`` -- ``True`` if the variable is integral (default: ``False``)
194
+
195
+ - ``obj`` -- (optional) coefficient of this variable in the objective function (default: 0)
196
+
197
+ - ``name`` -- an optional name for the newly added variable (default: ``None``)
198
+
199
+ - ``coefficients`` -- (optional) an iterable of pairs ``(i, v)``. In each
200
+ pair, ``i`` is a variable index (integer) and ``v`` is a
201
+ value (element of :meth:`base_ring`).
202
+
203
+ OUTPUT: the index of the newly created variable
204
+
205
+ EXAMPLES::
206
+
207
+ sage: from sage.numerical.backends.generic_backend import get_solver
208
+ sage: p = get_solver(solver = "InteractiveLP")
209
+ sage: p.ncols()
210
+ 0
211
+ sage: p.add_variable()
212
+ 0
213
+ sage: p.ncols()
214
+ 1
215
+ sage: p.add_variable(continuous=True, integer=True)
216
+ Traceback (most recent call last):
217
+ ...
218
+ ValueError: ...
219
+ sage: p.add_variable(name='x',obj=1)
220
+ 1
221
+ sage: p.col_name(1)
222
+ 'x'
223
+ sage: p.objective_coefficient(1)
224
+ 1
225
+ """
226
+ A, b, c, x, constraint_types, variable_types, problem_type, ring, d = self._AbcxCVPRd()
227
+ cdef int vtype = int(binary) + int(continuous) + int(integer)
228
+ if vtype == 0:
229
+ continuous = True
230
+ elif vtype != 1:
231
+ raise ValueError("Exactly one parameter of 'binary', 'integer' and 'continuous' must be 'True'.")
232
+ if not continuous:
233
+ raise NotImplementedError("Integer variables are not supported")
234
+ variable_types = variable_types + (self._variable_type_from_bounds(lower_bound, upper_bound),)
235
+ col = vector(ring, self.nrows())
236
+ if coefficients is not None:
237
+ for (i, v) in coefficients:
238
+ col[i] = v
239
+ A = A.augment(col)
240
+ if obj is None:
241
+ obj = 0
242
+ c = tuple(c) + (obj,)
243
+ if name is None:
244
+ var_names = default_variable_name("primal decision")
245
+ name = "{}{:d}".format(var_names, self.ncols() + 1)
246
+ x = tuple(x) + (name,)
247
+ self.lp = InteractiveLPProblem(A, b, c, x,
248
+ constraint_types, variable_types,
249
+ problem_type, ring, objective_constant_term=d)
250
+ return self.ncols() - 1
251
+
252
+ cpdef set_variable_type(self, int variable, int vtype):
253
+ """
254
+ Set the type of a variable.
255
+
256
+ In this backend, variables are always continuous (real).
257
+ If integer or binary variables are requested via the parameter
258
+ ``vtype``, an error will be raised.
259
+
260
+ INPUT:
261
+
262
+ - ``variable`` -- integer; the variable's id
263
+
264
+ - ``vtype`` -- integer:
265
+
266
+ * 1 Integer
267
+ * 0 Binary
268
+ * -1 Continuous
269
+
270
+ EXAMPLES::
271
+
272
+ sage: from sage.numerical.backends.generic_backend import get_solver
273
+ sage: p = get_solver(solver = "InteractiveLP")
274
+ sage: p.ncols()
275
+ 0
276
+ sage: p.add_variable()
277
+ 0
278
+ sage: p.set_variable_type(0,-1)
279
+ sage: p.is_variable_continuous(0)
280
+ True
281
+ """
282
+ if vtype == -1:
283
+ pass
284
+ else:
285
+ raise NotImplementedError()
286
+
287
+ def _AbcxCVPRd(self):
288
+ """
289
+ Retrieve all problem data from the LP.
290
+
291
+ EXAMPLES::
292
+
293
+ sage: from sage.numerical.backends.generic_backend import get_solver
294
+ sage: p = get_solver(solver = "InteractiveLP")
295
+ sage: p._AbcxCVPRd()
296
+ ([], (), (), (), (), (), 'max', Rational Field, 0)
297
+ """
298
+ A, b, c, x = self.lp.Abcx()
299
+ constraint_types = self.lp.constraint_types()
300
+ variable_types = self.lp.variable_types()
301
+ problem_type = self.lp.problem_type()
302
+ base_ring = self.lp.base_ring()
303
+ d = self.lp.objective_constant_term()
304
+ return A, b, c, x, constraint_types, variable_types, problem_type, base_ring, d
305
+
306
+ cpdef set_sense(self, int sense):
307
+ """
308
+ Set the direction (maximization/minimization).
309
+
310
+ INPUT:
311
+
312
+ - ``sense`` -- integer:
313
+
314
+ * +1 => Maximization
315
+ * -1 => Minimization
316
+
317
+ EXAMPLES::
318
+
319
+ sage: from sage.numerical.backends.generic_backend import get_solver
320
+ sage: p = get_solver(solver = "InteractiveLP")
321
+ sage: p.is_maximization()
322
+ True
323
+ sage: p.set_sense(-1)
324
+ sage: p.is_maximization()
325
+ False
326
+ """
327
+ A, b, c, x, constraint_types, variable_types, problem_type, ring, d = self._AbcxCVPRd()
328
+ if sense == +1:
329
+ problem_type = "max"
330
+ else:
331
+ problem_type = "min"
332
+ self.lp = InteractiveLPProblem(A, b, c, x,
333
+ constraint_types, variable_types,
334
+ problem_type, ring, objective_constant_term=d)
335
+
336
+ cpdef objective_coefficient(self, int variable, coeff=None):
337
+ """
338
+ Set or get the coefficient of a variable in the objective
339
+ function
340
+
341
+ INPUT:
342
+
343
+ - ``variable`` -- integer; the variable's id
344
+
345
+ - ``coeff`` -- double; its coefficient
346
+
347
+ EXAMPLES::
348
+
349
+ sage: from sage.numerical.backends.generic_backend import get_solver
350
+ sage: p = get_solver(solver = "InteractiveLP")
351
+ sage: p.add_variable()
352
+ 0
353
+ sage: p.objective_coefficient(0)
354
+ 0
355
+ sage: p.objective_coefficient(0,2)
356
+ sage: p.objective_coefficient(0)
357
+ 2
358
+ """
359
+ if coeff is None:
360
+ return self.lp.objective_coefficients()[variable]
361
+ else:
362
+ A, b, c, x, constraint_types, variable_types, problem_type, ring, d = self._AbcxCVPRd()
363
+ c = list(c)
364
+ c[variable] = coeff
365
+ self.lp = InteractiveLPProblem(A, b, c, x,
366
+ constraint_types, variable_types,
367
+ problem_type, ring, objective_constant_term=d)
368
+
369
+ cpdef objective_constant_term(self, d=None):
370
+ """
371
+ Set or get the constant term in the objective function.
372
+
373
+ INPUT:
374
+
375
+ - ``d`` -- double; its coefficient. If ``None`` (default), return the
376
+ current value.
377
+
378
+ EXAMPLES::
379
+
380
+ sage: from sage.numerical.backends.generic_backend import get_solver
381
+ sage: p = get_solver(solver = "InteractiveLP")
382
+ sage: p.objective_constant_term()
383
+ 0
384
+ sage: p.objective_constant_term(42)
385
+ sage: p.objective_constant_term()
386
+ 42
387
+ """
388
+ if d is None:
389
+ return self.lp.objective_constant_term()
390
+ else:
391
+ A, b, c, x, constraint_types, variable_types, problem_type, ring, _ = self._AbcxCVPRd()
392
+ self.lp = InteractiveLPProblem(A, b, c, x,
393
+ constraint_types, variable_types,
394
+ problem_type, ring, objective_constant_term=d)
395
+
396
+ cpdef set_objective(self, list coeff, d=0):
397
+ """
398
+ Set the objective function.
399
+
400
+ INPUT:
401
+
402
+ - ``coeff`` -- list of real values, whose i-th element is the
403
+ coefficient of the i-th variable in the objective function
404
+
405
+ - ``d`` -- real; the constant term in the linear function (set to `0`
406
+ by default)
407
+
408
+ EXAMPLES::
409
+
410
+ sage: from sage.numerical.backends.generic_backend import get_solver
411
+ sage: p = get_solver(solver = "InteractiveLP")
412
+ sage: p.add_variables(5)
413
+ 4
414
+ sage: p.set_objective([1, 1, 2, 1, 3])
415
+ sage: [p.objective_coefficient(x) for x in range(5)]
416
+ [1, 1, 2, 1, 3]
417
+
418
+ Constants in the objective function are respected::
419
+
420
+ sage: p = MixedIntegerLinearProgram(solver='InteractiveLP')
421
+ sage: x,y = p[0], p[1]
422
+ sage: p.add_constraint(2*x + 3*y, max = 6)
423
+ sage: p.add_constraint(3*x + 2*y, max = 6)
424
+ sage: p.set_objective(x + y + 7)
425
+ sage: p.solve()
426
+ 47/5
427
+
428
+ TESTS:
429
+
430
+ Constants also work the right way for min::
431
+
432
+ sage: p = MixedIntegerLinearProgram(solver='InteractiveLP', maximization=False)
433
+ sage: x,y = p[0], p[1]
434
+ sage: p.add_constraint(2*x + 3*y, max = 6)
435
+ sage: p.add_constraint(3*x + 2*y, max = 6)
436
+ sage: p.set_objective(-x - y - 7)
437
+ sage: p.solve()
438
+ -47/5
439
+ """
440
+ A, b, _, x, constraint_types, variable_types, problem_type, ring, _ = self._AbcxCVPRd()
441
+ c = coeff
442
+ self.lp = InteractiveLPProblem(A, b, c, x,
443
+ constraint_types, variable_types,
444
+ problem_type, ring, objective_constant_term=d)
445
+
446
+ cpdef set_verbosity(self, int level):
447
+ """
448
+ Set the log (verbosity) level.
449
+
450
+ INPUT:
451
+
452
+ - ``level`` -- integer; from 0 (no verbosity) to 3
453
+
454
+ EXAMPLES::
455
+
456
+ sage: from sage.numerical.backends.generic_backend import get_solver
457
+ sage: p = get_solver(solver = "InteractiveLP")
458
+ sage: p.set_verbosity(2)
459
+ """
460
+ self.verbosity = level
461
+
462
+ cpdef remove_constraint(self, int i):
463
+ r"""
464
+ Remove a constraint.
465
+
466
+ INPUT:
467
+
468
+ - ``i`` -- index of the constraint to remove
469
+
470
+ EXAMPLES::
471
+
472
+ sage: p = MixedIntegerLinearProgram(solver='InteractiveLP')
473
+ sage: v = p.new_variable(nonnegative=True)
474
+ sage: x,y = v[0], v[1]
475
+ sage: p.add_constraint(2*x + 3*y, max = 6)
476
+ sage: p.add_constraint(3*x + 2*y, max = 6)
477
+ sage: p.set_objective(x + y + 7)
478
+ sage: p.solve()
479
+ 47/5
480
+ sage: p.remove_constraint(0)
481
+ sage: p.solve()
482
+ 10
483
+ sage: p.get_values([x,y])
484
+ [0, 3]
485
+ """
486
+ A, b, c, x, constraint_types, variable_types, problem_type, ring, d = self._AbcxCVPRd()
487
+ A = A.delete_rows((i,))
488
+ b = list(b)
489
+ del b[i]
490
+ constraint_types = list(constraint_types)
491
+ del constraint_types[i]
492
+ self.lp = InteractiveLPProblem(A, b, c, x,
493
+ constraint_types, variable_types,
494
+ problem_type, ring, objective_constant_term=d)
495
+
496
+ cpdef add_linear_constraint(self, coefficients, lower_bound, upper_bound, name=None):
497
+ """
498
+ Add a linear constraint.
499
+
500
+ INPUT:
501
+
502
+ - ``coefficients`` -- an iterable of pairs ``(i, v)``. In each
503
+ pair, ``i`` is a variable index (integer) and ``v`` is a
504
+ value (element of :meth:`base_ring`).
505
+
506
+ - ``lower_bound`` -- element of :meth:`base_ring` or
507
+ ``None``; the lower bound
508
+
509
+ - ``upper_bound`` -- element of :meth:`base_ring` or
510
+ ``None``; the upper bound
511
+
512
+ - ``name`` -- string or ``None``; optional name for this row
513
+
514
+ EXAMPLES::
515
+
516
+ sage: from sage.numerical.backends.generic_backend import get_solver
517
+ sage: p = get_solver(solver = "InteractiveLP")
518
+ sage: p.add_variables(5)
519
+ 4
520
+ sage: p.add_linear_constraint( zip(range(5), range(5)), 2, 2)
521
+ sage: p.row(0)
522
+ ([1, 2, 3, 4], [1, 2, 3, 4])
523
+ sage: p.row_bounds(0)
524
+ (2, 2)
525
+ sage: p.add_linear_constraint( zip(range(5), range(5)), 1, 1, name='foo')
526
+ sage: p.row_name(1)
527
+ 'foo'
528
+ """
529
+ A, b, c, x, constraint_types, variable_types, problem_type, ring, d = self._AbcxCVPRd()
530
+ if lower_bound is None:
531
+ if upper_bound is None:
532
+ raise ValueError("At least one of lower_bound and upper_bound must be provided")
533
+ else:
534
+ constraint_types = constraint_types + ("<=",)
535
+ b = tuple(b) + (upper_bound,)
536
+ else:
537
+ if upper_bound is None:
538
+ constraint_types = constraint_types + (">=",)
539
+ b = tuple(b) + (lower_bound,)
540
+ elif lower_bound == upper_bound:
541
+ constraint_types = constraint_types + ("==",)
542
+ b = tuple(b) + (lower_bound,)
543
+ else:
544
+ raise NotImplementedError("Ranged constraints are not supported")
545
+
546
+ row = vector(ring, self.ncols())
547
+ for (i, v) in coefficients:
548
+ row[i] = v
549
+ A = A.stack(row)
550
+
551
+ self.row_names.append(name)
552
+
553
+ self.lp = InteractiveLPProblem(A, b, c, x,
554
+ constraint_types, variable_types,
555
+ problem_type, ring, objective_constant_term=d)
556
+
557
+ cpdef add_col(self, indices, coeffs):
558
+ """
559
+ Add a column.
560
+
561
+ INPUT:
562
+
563
+ - ``indices`` -- list of integers; this list contains the
564
+ indices of the constraints in which the variable's
565
+ coefficient is nonzero
566
+
567
+ - ``coeffs`` -- list of real values; associates a coefficient
568
+ to the variable in each of the constraints in which it
569
+ appears. Namely, the i-th entry of ``coeffs`` corresponds to
570
+ the coefficient of the variable in the constraint
571
+ represented by the i-th entry in ``indices``.
572
+
573
+ .. NOTE::
574
+
575
+ ``indices`` and ``coeffs`` are expected to be of the same length.
576
+
577
+ EXAMPLES::
578
+
579
+ sage: from sage.numerical.backends.generic_backend import get_solver
580
+ sage: p = get_solver(solver = "InteractiveLP")
581
+ sage: p.ncols()
582
+ 0
583
+ sage: p.nrows()
584
+ 0
585
+ sage: p.add_linear_constraints(5, 0, None)
586
+ sage: p.add_col(list(range(5)), list(range(5)))
587
+ sage: p.nrows()
588
+ 5
589
+ """
590
+ self.add_variable(coefficients=zip(indices, coeffs))
591
+
592
+ cpdef int solve(self) except -1:
593
+ """
594
+ Solve the problem.
595
+
596
+ .. NOTE::
597
+
598
+ This method raises ``MIPSolverException`` exceptions when
599
+ the solution cannot be computed for any reason (none
600
+ exists, or the LP solver was not able to find it, etc...)
601
+
602
+ EXAMPLES::
603
+
604
+ sage: from sage.numerical.backends.generic_backend import get_solver
605
+ sage: p = get_solver(solver = "InteractiveLP")
606
+ sage: p.add_linear_constraints(5, 0, None)
607
+ sage: p.add_col(list(range(5)), list(range(5)))
608
+ sage: p.solve()
609
+ 0
610
+ sage: p.objective_coefficient(0,1)
611
+ sage: p.solve()
612
+ Traceback (most recent call last):
613
+ ...
614
+ MIPSolverException: ...
615
+ """
616
+ ## FIXME: standard_form should allow to pass slack names (which we would take from row_names).
617
+ ## FIXME: Perhaps also pass the problem name as objective name
618
+ lp_std_form, transformation = self.lp.standard_form(transformation=True)
619
+ self.lp_std_form, self.std_form_transformation = lp_std_form, transformation
620
+ output = lp_std_form.run_revised_simplex_method()
621
+ ## FIXME: Display output as a side effect if verbosity is high enough
622
+ d = self.final_dictionary = lp_std_form.final_revised_dictionary()
623
+ if d.is_optimal():
624
+ if lp_std_form.auxiliary_variable() in d.basic_variables():
625
+ raise MIPSolverException("InteractiveLP: Problem has no feasible solution")
626
+ else:
627
+ return 0
628
+ else:
629
+ raise MIPSolverException("InteractiveLP: Problem is unbounded")
630
+
631
+ cpdef get_objective_value(self):
632
+ """
633
+ Return the value of the objective function.
634
+
635
+ .. NOTE::
636
+
637
+ Behavior is undefined unless ``solve`` has been called before.
638
+
639
+ EXAMPLES::
640
+
641
+ sage: from sage.numerical.backends.generic_backend import get_solver
642
+ sage: p = get_solver(solver = "InteractiveLP")
643
+ sage: p.add_variables(2)
644
+ 1
645
+ sage: p.add_linear_constraint([(0,1), (1,2)], None, 3)
646
+ sage: p.set_objective([2, 5])
647
+ sage: p.solve()
648
+ 0
649
+ sage: p.get_objective_value()
650
+ 15/2
651
+ sage: p.get_variable_value(0)
652
+ 0
653
+ sage: p.get_variable_value(1)
654
+ 3/2
655
+ """
656
+ d = self.final_dictionary
657
+ v = d.objective_value()
658
+ if self.lp_std_form.is_negative():
659
+ v = - v
660
+ return v
661
+
662
+ cpdef get_variable_value(self, int variable):
663
+ """
664
+ Return the value of a variable given by the solver.
665
+
666
+ .. NOTE::
667
+
668
+ Behavior is undefined unless ``solve`` has been called before.
669
+
670
+ EXAMPLES::
671
+
672
+ sage: from sage.numerical.backends.generic_backend import get_solver
673
+ sage: p = get_solver(solver = "InteractiveLP")
674
+ sage: p.add_variables(2)
675
+ 1
676
+ sage: p.add_linear_constraint([(0,1), (1, 2)], None, 3)
677
+ sage: p.set_objective([2, 5])
678
+ sage: p.solve()
679
+ 0
680
+ sage: p.get_objective_value()
681
+ 15/2
682
+ sage: p.get_variable_value(0)
683
+ 0
684
+ sage: p.get_variable_value(1)
685
+ 3/2
686
+ """
687
+ solution = self.std_form_transformation(self.final_dictionary.basic_solution())
688
+ return solution[variable]
689
+
690
+ cpdef int ncols(self) noexcept:
691
+ """
692
+ Return the number of columns/variables.
693
+
694
+ EXAMPLES::
695
+
696
+ sage: from sage.numerical.backends.generic_backend import get_solver
697
+ sage: p = get_solver(solver = "InteractiveLP")
698
+ sage: p.ncols()
699
+ 0
700
+ sage: p.add_variables(2)
701
+ 1
702
+ sage: p.ncols()
703
+ 2
704
+ """
705
+ return self.lp.n_variables()
706
+
707
+ cpdef int nrows(self) noexcept:
708
+ """
709
+ Return the number of rows/constraints.
710
+
711
+ EXAMPLES::
712
+
713
+ sage: from sage.numerical.backends.generic_backend import get_solver
714
+ sage: p = get_solver(solver = "InteractiveLP")
715
+ sage: p.nrows()
716
+ 0
717
+ sage: p.add_linear_constraints(2, 0, None)
718
+ sage: p.nrows()
719
+ 2
720
+ """
721
+ return self.lp.n_constraints()
722
+
723
+ cpdef bint is_maximization(self) noexcept:
724
+ """
725
+ Test whether the problem is a maximization
726
+
727
+ EXAMPLES::
728
+
729
+ sage: from sage.numerical.backends.generic_backend import get_solver
730
+ sage: p = get_solver(solver = "InteractiveLP")
731
+ sage: p.is_maximization()
732
+ True
733
+ sage: p.set_sense(-1)
734
+ sage: p.is_maximization()
735
+ False
736
+ """
737
+ return self.lp.problem_type() == "max"
738
+
739
+ cpdef problem_name(self, name=None):
740
+ """
741
+ Return or define the problem's name.
742
+
743
+ INPUT:
744
+
745
+ - ``name`` -- string; the problem's name. When set to
746
+ ``None`` (default), the method returns the problem's name.
747
+
748
+ EXAMPLES::
749
+
750
+ sage: from sage.numerical.backends.generic_backend import get_solver
751
+ sage: p = get_solver(solver = "InteractiveLP")
752
+ sage: p.problem_name("There_once_was_a_french_fry")
753
+ sage: print(p.problem_name())
754
+ There_once_was_a_french_fry
755
+ """
756
+ if name is None:
757
+ if self.prob_name is not None:
758
+ return self.prob_name
759
+ else:
760
+ return ""
761
+ else:
762
+ self.prob_name = str(name)
763
+
764
+ cpdef row(self, int i):
765
+ """
766
+ Return a row.
767
+
768
+ INPUT:
769
+
770
+ - ``index`` -- integer; the constraint's id
771
+
772
+ OUTPUT:
773
+
774
+ A pair ``(indices, coeffs)`` where ``indices`` lists the
775
+ entries whose coefficient is nonzero, and to which ``coeffs``
776
+ associates their coefficient on the model of the
777
+ ``add_linear_constraint`` method.
778
+
779
+ EXAMPLES::
780
+
781
+ sage: from sage.numerical.backends.generic_backend import get_solver
782
+ sage: p = get_solver(solver = "InteractiveLP")
783
+ sage: p.add_variables(5)
784
+ 4
785
+ sage: p.add_linear_constraint(zip(range(5), range(5)), 0, None)
786
+ sage: p.row(0)
787
+ ([1, 2, 3, 4], [1, 2, 3, 4])
788
+ """
789
+ A, b, c, x = self.lp.Abcx()
790
+ indices = []
791
+ coeffs = []
792
+ for j in range(self.ncols()):
793
+ if A[i][j] != 0:
794
+ indices.append(j)
795
+ coeffs.append(A[i][j])
796
+ return (indices, coeffs)
797
+
798
+ cpdef row_bounds(self, int index):
799
+ """
800
+ Return the bounds of a specific constraint.
801
+
802
+ INPUT:
803
+
804
+ - ``index`` -- integer; the constraint's id
805
+
806
+ OUTPUT:
807
+
808
+ A pair ``(lower_bound, upper_bound)``. Each of them can be set
809
+ to ``None`` if the constraint is not bounded in the
810
+ corresponding direction, and is a real value otherwise.
811
+
812
+ EXAMPLES::
813
+
814
+ sage: from sage.numerical.backends.generic_backend import get_solver
815
+ sage: p = get_solver(solver = "InteractiveLP")
816
+ sage: p.add_variables(5)
817
+ 4
818
+ sage: p.add_linear_constraint(zip(range(5), range(5)), 2, 2)
819
+ sage: p.row_bounds(0)
820
+ (2, 2)
821
+ """
822
+ A, b, c, x = self.lp.Abcx()
823
+ constraint_types = self.lp.constraint_types()
824
+ if constraint_types[index] == '>=':
825
+ return (b[index], None)
826
+ elif constraint_types[index] == '<=':
827
+ return (None, b[index])
828
+ elif constraint_types[index] == '==':
829
+ return (b[index], b[index])
830
+ else:
831
+ raise ValueError("Bad constraint_type")
832
+
833
+ cpdef col_bounds(self, int index):
834
+ """
835
+ Return the bounds of a specific variable.
836
+
837
+ INPUT:
838
+
839
+ - ``index`` -- integer; the variable's id
840
+
841
+ OUTPUT:
842
+
843
+ A pair ``(lower_bound, upper_bound)``. Each of them can be set
844
+ to ``None`` if the variable is not bounded in the
845
+ corresponding direction, and is a real value otherwise.
846
+
847
+ EXAMPLES::
848
+
849
+ sage: from sage.numerical.backends.generic_backend import get_solver
850
+ sage: p = get_solver(solver = "InteractiveLP")
851
+ sage: p.add_variable(lower_bound=None)
852
+ 0
853
+ sage: p.col_bounds(0)
854
+ (None, None)
855
+ sage: p.variable_lower_bound(0, 0)
856
+ sage: p.col_bounds(0)
857
+ (0, None)
858
+ """
859
+ t = self.lp.variable_types()[index]
860
+ if t == ">=":
861
+ return (0, None)
862
+ elif t == "<=":
863
+ return (None, 0)
864
+ elif t == "":
865
+ return (None, None)
866
+ else:
867
+ raise ValueError("Bad _variable_types")
868
+
869
+ cpdef bint is_variable_binary(self, int index) noexcept:
870
+ """
871
+ Test whether the given variable is of binary type.
872
+
873
+ INPUT:
874
+
875
+ - ``index`` -- integer; the variable's id
876
+
877
+ EXAMPLES::
878
+
879
+ sage: from sage.numerical.backends.generic_backend import get_solver
880
+ sage: p = get_solver(solver = "InteractiveLP")
881
+ sage: p.ncols()
882
+ 0
883
+ sage: p.add_variable()
884
+ 0
885
+ sage: p.is_variable_binary(0)
886
+ False
887
+ """
888
+ return False
889
+
890
+ cpdef bint is_variable_integer(self, int index) noexcept:
891
+ """
892
+ Test whether the given variable is of integer type.
893
+
894
+ INPUT:
895
+
896
+ - ``index`` -- integer; the variable's id
897
+
898
+ EXAMPLES::
899
+
900
+ sage: from sage.numerical.backends.generic_backend import get_solver
901
+ sage: p = get_solver(solver = "InteractiveLP")
902
+ sage: p.ncols()
903
+ 0
904
+ sage: p.add_variable()
905
+ 0
906
+ sage: p.is_variable_integer(0)
907
+ False
908
+ """
909
+ return False
910
+
911
+ cpdef bint is_variable_continuous(self, int index) noexcept:
912
+ """
913
+ Test whether the given variable is of continuous/real type.
914
+
915
+ INPUT:
916
+
917
+ - ``index`` -- integer; the variable's id
918
+
919
+ EXAMPLES::
920
+
921
+ sage: from sage.numerical.backends.generic_backend import get_solver
922
+ sage: p = get_solver(solver = "InteractiveLP")
923
+ sage: p.ncols()
924
+ 0
925
+ sage: p.add_variable()
926
+ 0
927
+ sage: p.is_variable_continuous(0)
928
+ True
929
+ """
930
+ return True
931
+
932
+ cpdef row_name(self, int index):
933
+ """
934
+ Return the ``index``-th row name.
935
+
936
+ INPUT:
937
+
938
+ - ``index`` -- integer; the row's id
939
+
940
+ EXAMPLES::
941
+
942
+ sage: from sage.numerical.backends.generic_backend import get_solver
943
+ sage: p = get_solver(solver = "InteractiveLP")
944
+ sage: p.add_linear_constraints(1, 2, None, names=['Empty constraint 1'])
945
+ sage: p.row_name(0)
946
+ 'Empty constraint 1'
947
+ """
948
+ return self.row_names[index]
949
+
950
+ cpdef col_name(self, int index):
951
+ """
952
+ Return the ``index``-th column name.
953
+
954
+ INPUT:
955
+
956
+ - ``index`` -- integer; the column id
957
+
958
+ - ``name`` -- (``char *``) its name; when set to ``NULL``
959
+ (default), the method returns the current name
960
+
961
+ EXAMPLES::
962
+
963
+ sage: from sage.numerical.backends.generic_backend import get_solver
964
+ sage: p = get_solver(solver = "InteractiveLP")
965
+ sage: p.add_variable(name='I_am_a_variable')
966
+ 0
967
+ sage: p.col_name(0)
968
+ 'I_am_a_variable'
969
+ """
970
+ return str(self.lp.decision_variables()[index])
971
+
972
+ cpdef variable_upper_bound(self, int index, value=False):
973
+ """
974
+ Return or define the upper bound on a variable.
975
+
976
+ INPUT:
977
+
978
+ - ``index`` -- integer; the variable's id
979
+
980
+ - ``value`` -- real value, or ``None`` to mean that the
981
+ variable has not upper bound. When set to ``False``
982
+ (default), the method returns the current value.
983
+
984
+ EXAMPLES::
985
+
986
+ sage: from sage.numerical.backends.generic_backend import get_solver
987
+ sage: p = get_solver(solver = "InteractiveLP")
988
+ sage: p.add_variable(lower_bound=None)
989
+ 0
990
+ sage: p.col_bounds(0)
991
+ (None, None)
992
+ sage: p.variable_upper_bound(0) is None
993
+ True
994
+ sage: p.variable_upper_bound(0, 0)
995
+ sage: p.col_bounds(0)
996
+ (None, 0)
997
+ sage: p.variable_upper_bound(0)
998
+ 0
999
+ sage: p.variable_upper_bound(0, None)
1000
+ sage: p.variable_upper_bound(0) is None
1001
+ True
1002
+ """
1003
+ bounds = self.col_bounds(index)
1004
+ if value is False:
1005
+ return bounds[1]
1006
+ else:
1007
+ if value != bounds[1]:
1008
+ bounds = (bounds[0], value)
1009
+ A, b, c, x, constraint_types, variable_types, problem_type, ring, d = self._AbcxCVPRd()
1010
+ variable_types = list(variable_types)
1011
+ variable_types[index] = self._variable_type_from_bounds(*bounds)
1012
+ self.lp = InteractiveLPProblem(A, b, c, x,
1013
+ constraint_types, variable_types,
1014
+ problem_type, ring, objective_constant_term=d)
1015
+
1016
+ cpdef variable_lower_bound(self, int index, value=False):
1017
+ """
1018
+ Return or define the lower bound on a variable.
1019
+
1020
+ INPUT:
1021
+
1022
+ - ``index`` -- integer; the variable's id
1023
+
1024
+ - ``value`` -- real value, or ``None`` to mean that the
1025
+ variable has no lower bound. When set to ``False``
1026
+ (default), the method returns the current value.
1027
+
1028
+ EXAMPLES::
1029
+
1030
+ sage: from sage.numerical.backends.generic_backend import get_solver
1031
+ sage: p = get_solver(solver = "InteractiveLP")
1032
+ sage: p.add_variable(lower_bound=None)
1033
+ 0
1034
+ sage: p.col_bounds(0)
1035
+ (None, None)
1036
+ sage: p.variable_lower_bound(0) is None
1037
+ True
1038
+ sage: p.variable_lower_bound(0, 0)
1039
+ sage: p.col_bounds(0)
1040
+ (0, None)
1041
+ sage: p.variable_lower_bound(0)
1042
+ 0
1043
+ sage: p.variable_lower_bound(0, None)
1044
+ sage: p.variable_lower_bound(0) is None
1045
+ True
1046
+ """
1047
+ bounds = self.col_bounds(index)
1048
+ if value is False:
1049
+ return bounds[0]
1050
+ else:
1051
+ if value != bounds[0]:
1052
+ bounds = (value, bounds[1])
1053
+ A, b, c, x, constraint_types, variable_types, problem_type, ring, d = self._AbcxCVPRd()
1054
+ variable_types = list(variable_types)
1055
+ variable_types[index] = self._variable_type_from_bounds(*bounds)
1056
+ self.lp = InteractiveLPProblem(A, b, c, x,
1057
+ constraint_types, variable_types,
1058
+ problem_type, ring, objective_constant_term=d)
1059
+
1060
+ cpdef bint is_variable_basic(self, int index) noexcept:
1061
+ """
1062
+ Test whether the given variable is basic.
1063
+
1064
+ This assumes that the problem has been solved with the simplex method
1065
+ and a basis is available. Otherwise an exception will be raised.
1066
+
1067
+ INPUT:
1068
+
1069
+ - ``index`` -- integer; the variable's id
1070
+
1071
+ EXAMPLES::
1072
+
1073
+ sage: p = MixedIntegerLinearProgram(maximization=True,\
1074
+ ....: solver='InteractiveLP')
1075
+ sage: x = p.new_variable(nonnegative=True)
1076
+ sage: p.add_constraint(-x[0] + x[1] <= 2)
1077
+ sage: p.add_constraint(8 * x[0] + 2 * x[1] <= 17)
1078
+ sage: p.set_objective(11/2 * x[0] - 3 * x[1])
1079
+ sage: b = p.get_backend()
1080
+ sage: # Backend-specific commands to instruct solver to use simplex method here
1081
+ sage: b.solve()
1082
+ 0
1083
+ sage: b.is_variable_basic(0)
1084
+ True
1085
+ sage: b.is_variable_basic(1)
1086
+ False
1087
+ """
1088
+ return self.lp_std_form.decision_variables()[index] in self.final_dictionary.basic_variables()
1089
+
1090
+ cpdef bint is_variable_nonbasic_at_lower_bound(self, int index) noexcept:
1091
+ """
1092
+ Test whether the given variable is nonbasic at lower bound.
1093
+
1094
+ This assumes that the problem has been solved with the simplex method
1095
+ and a basis is available. Otherwise an exception will be raised.
1096
+
1097
+ INPUT:
1098
+
1099
+ - ``index`` -- integer; the variable's id
1100
+
1101
+ EXAMPLES::
1102
+
1103
+ sage: p = MixedIntegerLinearProgram(maximization=True,\
1104
+ ....: solver='InteractiveLP')
1105
+ sage: x = p.new_variable(nonnegative=True)
1106
+ sage: p.add_constraint(-x[0] + x[1] <= 2)
1107
+ sage: p.add_constraint(8 * x[0] + 2 * x[1] <= 17)
1108
+ sage: p.set_objective(11/2 * x[0] - 3 * x[1])
1109
+ sage: b = p.get_backend()
1110
+ sage: # Backend-specific commands to instruct solver to use simplex method here
1111
+ sage: b.solve()
1112
+ 0
1113
+ sage: b.is_variable_nonbasic_at_lower_bound(0)
1114
+ False
1115
+ sage: b.is_variable_nonbasic_at_lower_bound(1)
1116
+ True
1117
+ """
1118
+ return self.lp_std_form.decision_variables()[index] in self.final_dictionary.nonbasic_variables()
1119
+
1120
+ cpdef bint is_slack_variable_basic(self, int index) noexcept:
1121
+ """
1122
+ Test whether the slack variable of the given row is basic.
1123
+
1124
+ This assumes that the problem has been solved with the simplex method
1125
+ and a basis is available. Otherwise an exception will be raised.
1126
+
1127
+ INPUT:
1128
+
1129
+ - ``index`` -- integer; the variable's id
1130
+
1131
+ EXAMPLES::
1132
+
1133
+ sage: p = MixedIntegerLinearProgram(maximization=True,\
1134
+ ....: solver='InteractiveLP')
1135
+ sage: x = p.new_variable(nonnegative=True)
1136
+ sage: p.add_constraint(-x[0] + x[1] <= 2)
1137
+ sage: p.add_constraint(8 * x[0] + 2 * x[1] <= 17)
1138
+ sage: p.set_objective(11/2 * x[0] - 3 * x[1])
1139
+ sage: b = p.get_backend()
1140
+ sage: # Backend-specific commands to instruct solver to use simplex method here
1141
+ sage: b.solve()
1142
+ 0
1143
+ sage: b.is_slack_variable_basic(0)
1144
+ True
1145
+ sage: b.is_slack_variable_basic(1)
1146
+ False
1147
+ """
1148
+ return self.lp_std_form.slack_variables()[index] in self.final_dictionary.basic_variables()
1149
+
1150
+ cpdef bint is_slack_variable_nonbasic_at_lower_bound(self, int index) noexcept:
1151
+ """
1152
+ Test whether the given variable is nonbasic at lower bound.
1153
+
1154
+ This assumes that the problem has been solved with the simplex method
1155
+ and a basis is available. Otherwise an exception will be raised.
1156
+
1157
+ INPUT:
1158
+
1159
+ - ``index`` -- integer; the variable's id
1160
+
1161
+ EXAMPLES::
1162
+
1163
+ sage: p = MixedIntegerLinearProgram(maximization=True,\
1164
+ ....: solver='InteractiveLP')
1165
+ sage: x = p.new_variable(nonnegative=True)
1166
+ sage: p.add_constraint(-x[0] + x[1] <= 2)
1167
+ sage: p.add_constraint(8 * x[0] + 2 * x[1] <= 17)
1168
+ sage: p.set_objective(11/2 * x[0] - 3 * x[1])
1169
+ sage: b = p.get_backend()
1170
+ sage: # Backend-specific commands to instruct solver to use simplex method here
1171
+ sage: b.solve()
1172
+ 0
1173
+ sage: b.is_slack_variable_nonbasic_at_lower_bound(0)
1174
+ False
1175
+ sage: b.is_slack_variable_nonbasic_at_lower_bound(1)
1176
+ True
1177
+ """
1178
+ return self.lp_std_form.slack_variables()[index] in self.final_dictionary.nonbasic_variables()
1179
+
1180
+ cpdef dictionary(self):
1181
+ # Proposed addition to the general interface,
1182
+ # which would for other solvers return backend dictionaries (#18804)
1183
+ """
1184
+ Return a dictionary representing the current basis.
1185
+
1186
+ EXAMPLES::
1187
+
1188
+ sage: p = MixedIntegerLinearProgram(maximization=True,\
1189
+ ....: solver='InteractiveLP')
1190
+ sage: x = p.new_variable(nonnegative=True)
1191
+ sage: p.add_constraint(-x[0] + x[1] <= 2)
1192
+ sage: p.add_constraint(8 * x[0] + 2 * x[1] <= 17)
1193
+ sage: p.set_objective(11/2 * x[0] - 3 * x[1])
1194
+ sage: b = p.get_backend()
1195
+ sage: # Backend-specific commands to instruct solver to use simplex method here
1196
+ sage: b.solve()
1197
+ 0
1198
+ sage: d = b.dictionary(); d
1199
+ LP problem dictionary ...
1200
+ sage: set(d.basic_variables())
1201
+ {x1, x3}
1202
+ sage: d.basic_solution()
1203
+ (17/8, 0)
1204
+
1205
+ TESTS:
1206
+
1207
+ Compare with a dictionary obtained in another way::
1208
+
1209
+ sage: lp, basis = p.interactive_lp_problem()
1210
+ sage: lp.dictionary(*basis).basic_solution()
1211
+ (17/8, 0)
1212
+ """
1213
+ return self.final_dictionary
1214
+
1215
+ cpdef interactive_lp_problem(self):
1216
+ """
1217
+ Return the :class:`InteractiveLPProblem` object associated with this backend.
1218
+
1219
+ EXAMPLES::
1220
+
1221
+ sage: p = MixedIntegerLinearProgram(maximization=True,\
1222
+ ....: solver='InteractiveLP')
1223
+ sage: x = p.new_variable(nonnegative=True)
1224
+ sage: p.add_constraint(-x[0] + x[1] <= 2)
1225
+ sage: p.add_constraint(8 * x[0] + 2 * x[1] <= 17)
1226
+ sage: p.set_objective(11/2 * x[0] - 3 * x[1])
1227
+ sage: b = p.get_backend()
1228
+ sage: b.interactive_lp_problem()
1229
+ LP problem ...
1230
+ """
1231
+ return self.lp