passagemath-polyhedra 10.6.31rc3__cp314-cp314-musllinux_1_2_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 (208) 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 +208 -0
  4. passagemath_polyhedra-10.6.31rc3.dist-info/WHEEL +5 -0
  5. passagemath_polyhedra-10.6.31rc3.dist-info/top_level.txt +2 -0
  6. passagemath_polyhedra.libs/libgcc_s-0cd532bd.so.1 +0 -0
  7. passagemath_polyhedra.libs/libgmp-0e7fc84e.so.10.5.0 +0 -0
  8. passagemath_polyhedra.libs/libgomp-8949ffbe.so.1.0.0 +0 -0
  9. passagemath_polyhedra.libs/libstdc++-5d72f927.so.6.0.33 +0 -0
  10. sage/all__sagemath_polyhedra.py +50 -0
  11. sage/game_theory/all.py +8 -0
  12. sage/game_theory/catalog.py +6 -0
  13. sage/game_theory/catalog_normal_form_games.py +923 -0
  14. sage/game_theory/cooperative_game.py +844 -0
  15. sage/game_theory/matching_game.py +1181 -0
  16. sage/game_theory/normal_form_game.py +2697 -0
  17. sage/game_theory/parser.py +275 -0
  18. sage/geometry/all__sagemath_polyhedra.py +22 -0
  19. sage/geometry/cone.py +6940 -0
  20. sage/geometry/cone_catalog.py +847 -0
  21. sage/geometry/cone_critical_angles.py +1027 -0
  22. sage/geometry/convex_set.py +1119 -0
  23. sage/geometry/fan.py +3743 -0
  24. sage/geometry/fan_isomorphism.py +389 -0
  25. sage/geometry/fan_morphism.py +1884 -0
  26. sage/geometry/hasse_diagram.py +202 -0
  27. sage/geometry/hyperplane_arrangement/affine_subspace.py +390 -0
  28. sage/geometry/hyperplane_arrangement/all.py +1 -0
  29. sage/geometry/hyperplane_arrangement/arrangement.py +3895 -0
  30. sage/geometry/hyperplane_arrangement/check_freeness.py +145 -0
  31. sage/geometry/hyperplane_arrangement/hyperplane.py +773 -0
  32. sage/geometry/hyperplane_arrangement/library.py +825 -0
  33. sage/geometry/hyperplane_arrangement/ordered_arrangement.py +642 -0
  34. sage/geometry/hyperplane_arrangement/plot.py +520 -0
  35. sage/geometry/integral_points.py +35 -0
  36. sage/geometry/integral_points_generic_dense.cpython-314-x86_64-linux-musl.so +0 -0
  37. sage/geometry/integral_points_generic_dense.pyx +7 -0
  38. sage/geometry/lattice_polytope.py +5894 -0
  39. sage/geometry/linear_expression.py +773 -0
  40. sage/geometry/newton_polygon.py +767 -0
  41. sage/geometry/point_collection.cpython-314-x86_64-linux-musl.so +0 -0
  42. sage/geometry/point_collection.pyx +1008 -0
  43. sage/geometry/polyhedral_complex.py +2616 -0
  44. sage/geometry/polyhedron/all.py +8 -0
  45. sage/geometry/polyhedron/backend_cdd.py +460 -0
  46. sage/geometry/polyhedron/backend_cdd_rdf.py +231 -0
  47. sage/geometry/polyhedron/backend_field.py +347 -0
  48. sage/geometry/polyhedron/backend_normaliz.py +2503 -0
  49. sage/geometry/polyhedron/backend_number_field.py +168 -0
  50. sage/geometry/polyhedron/backend_polymake.py +765 -0
  51. sage/geometry/polyhedron/backend_ppl.py +582 -0
  52. sage/geometry/polyhedron/base.py +1206 -0
  53. sage/geometry/polyhedron/base0.py +1444 -0
  54. sage/geometry/polyhedron/base1.py +886 -0
  55. sage/geometry/polyhedron/base2.py +812 -0
  56. sage/geometry/polyhedron/base3.py +1845 -0
  57. sage/geometry/polyhedron/base4.py +1262 -0
  58. sage/geometry/polyhedron/base5.py +2700 -0
  59. sage/geometry/polyhedron/base6.py +1741 -0
  60. sage/geometry/polyhedron/base7.py +997 -0
  61. sage/geometry/polyhedron/base_QQ.py +1258 -0
  62. sage/geometry/polyhedron/base_RDF.py +98 -0
  63. sage/geometry/polyhedron/base_ZZ.py +934 -0
  64. sage/geometry/polyhedron/base_mutable.py +215 -0
  65. sage/geometry/polyhedron/base_number_field.py +122 -0
  66. sage/geometry/polyhedron/cdd_file_format.py +155 -0
  67. sage/geometry/polyhedron/combinatorial_polyhedron/all.py +1 -0
  68. sage/geometry/polyhedron/combinatorial_polyhedron/base.cpython-314-x86_64-linux-musl.so +0 -0
  69. sage/geometry/polyhedron/combinatorial_polyhedron/base.pxd +76 -0
  70. sage/geometry/polyhedron/combinatorial_polyhedron/base.pyx +3859 -0
  71. sage/geometry/polyhedron/combinatorial_polyhedron/combinatorial_face.cpython-314-x86_64-linux-musl.so +0 -0
  72. sage/geometry/polyhedron/combinatorial_polyhedron/combinatorial_face.pxd +39 -0
  73. sage/geometry/polyhedron/combinatorial_polyhedron/combinatorial_face.pyx +1038 -0
  74. sage/geometry/polyhedron/combinatorial_polyhedron/conversions.cpython-314-x86_64-linux-musl.so +0 -0
  75. sage/geometry/polyhedron/combinatorial_polyhedron/conversions.pxd +9 -0
  76. sage/geometry/polyhedron/combinatorial_polyhedron/conversions.pyx +501 -0
  77. sage/geometry/polyhedron/combinatorial_polyhedron/face_data_structure.pxd +207 -0
  78. sage/geometry/polyhedron/combinatorial_polyhedron/face_iterator.cpython-314-x86_64-linux-musl.so +0 -0
  79. sage/geometry/polyhedron/combinatorial_polyhedron/face_iterator.pxd +102 -0
  80. sage/geometry/polyhedron/combinatorial_polyhedron/face_iterator.pyx +2274 -0
  81. sage/geometry/polyhedron/combinatorial_polyhedron/face_list_data_structure.cpython-314-x86_64-linux-musl.so +0 -0
  82. sage/geometry/polyhedron/combinatorial_polyhedron/face_list_data_structure.pxd +370 -0
  83. sage/geometry/polyhedron/combinatorial_polyhedron/face_list_data_structure.pyx +84 -0
  84. sage/geometry/polyhedron/combinatorial_polyhedron/list_of_faces.cpython-314-x86_64-linux-musl.so +0 -0
  85. sage/geometry/polyhedron/combinatorial_polyhedron/list_of_faces.pxd +31 -0
  86. sage/geometry/polyhedron/combinatorial_polyhedron/list_of_faces.pyx +587 -0
  87. sage/geometry/polyhedron/combinatorial_polyhedron/polyhedron_face_lattice.cpython-314-x86_64-linux-musl.so +0 -0
  88. sage/geometry/polyhedron/combinatorial_polyhedron/polyhedron_face_lattice.pxd +52 -0
  89. sage/geometry/polyhedron/combinatorial_polyhedron/polyhedron_face_lattice.pyx +560 -0
  90. sage/geometry/polyhedron/constructor.py +773 -0
  91. sage/geometry/polyhedron/double_description.py +753 -0
  92. sage/geometry/polyhedron/double_description_inhomogeneous.py +564 -0
  93. sage/geometry/polyhedron/face.py +1060 -0
  94. sage/geometry/polyhedron/generating_function.py +1810 -0
  95. sage/geometry/polyhedron/lattice_euclidean_group_element.py +178 -0
  96. sage/geometry/polyhedron/library.py +3502 -0
  97. sage/geometry/polyhedron/misc.py +121 -0
  98. sage/geometry/polyhedron/modules/all.py +1 -0
  99. sage/geometry/polyhedron/modules/formal_polyhedra_module.py +155 -0
  100. sage/geometry/polyhedron/palp_database.py +447 -0
  101. sage/geometry/polyhedron/parent.py +1279 -0
  102. sage/geometry/polyhedron/plot.py +1986 -0
  103. sage/geometry/polyhedron/ppl_lattice_polygon.py +556 -0
  104. sage/geometry/polyhedron/ppl_lattice_polytope.py +1257 -0
  105. sage/geometry/polyhedron/representation.py +1723 -0
  106. sage/geometry/pseudolines.py +515 -0
  107. sage/geometry/relative_interior.py +445 -0
  108. sage/geometry/toric_plotter.py +1103 -0
  109. sage/geometry/triangulation/all.py +2 -0
  110. sage/geometry/triangulation/base.cpython-314-x86_64-linux-musl.so +0 -0
  111. sage/geometry/triangulation/base.pyx +963 -0
  112. sage/geometry/triangulation/data.h +147 -0
  113. sage/geometry/triangulation/data.pxd +4 -0
  114. sage/geometry/triangulation/element.py +914 -0
  115. sage/geometry/triangulation/functions.h +10 -0
  116. sage/geometry/triangulation/functions.pxd +4 -0
  117. sage/geometry/triangulation/point_configuration.py +2256 -0
  118. sage/geometry/triangulation/triangulations.h +49 -0
  119. sage/geometry/triangulation/triangulations.pxd +7 -0
  120. sage/geometry/voronoi_diagram.py +319 -0
  121. sage/interfaces/all__sagemath_polyhedra.py +1 -0
  122. sage/interfaces/polymake.py +2028 -0
  123. sage/numerical/all.py +13 -0
  124. sage/numerical/all__sagemath_polyhedra.py +11 -0
  125. sage/numerical/backends/all.py +1 -0
  126. sage/numerical/backends/all__sagemath_polyhedra.py +1 -0
  127. sage/numerical/backends/cvxopt_backend.cpython-314-x86_64-linux-musl.so +0 -0
  128. sage/numerical/backends/cvxopt_backend.pyx +1006 -0
  129. sage/numerical/backends/cvxopt_backend_test.py +19 -0
  130. sage/numerical/backends/cvxopt_sdp_backend.cpython-314-x86_64-linux-musl.so +0 -0
  131. sage/numerical/backends/cvxopt_sdp_backend.pyx +382 -0
  132. sage/numerical/backends/cvxpy_backend.cpython-314-x86_64-linux-musl.so +0 -0
  133. sage/numerical/backends/cvxpy_backend.pxd +41 -0
  134. sage/numerical/backends/cvxpy_backend.pyx +934 -0
  135. sage/numerical/backends/cvxpy_backend_test.py +13 -0
  136. sage/numerical/backends/generic_backend_test.py +24 -0
  137. sage/numerical/backends/interactivelp_backend.cpython-314-x86_64-linux-musl.so +0 -0
  138. sage/numerical/backends/interactivelp_backend.pxd +36 -0
  139. sage/numerical/backends/interactivelp_backend.pyx +1231 -0
  140. sage/numerical/backends/interactivelp_backend_test.py +12 -0
  141. sage/numerical/backends/logging_backend.py +391 -0
  142. sage/numerical/backends/matrix_sdp_backend.cpython-314-x86_64-linux-musl.so +0 -0
  143. sage/numerical/backends/matrix_sdp_backend.pxd +15 -0
  144. sage/numerical/backends/matrix_sdp_backend.pyx +478 -0
  145. sage/numerical/backends/ppl_backend.cpython-314-x86_64-linux-musl.so +0 -0
  146. sage/numerical/backends/ppl_backend.pyx +1126 -0
  147. sage/numerical/backends/ppl_backend_test.py +13 -0
  148. sage/numerical/backends/scip_backend.cpython-314-x86_64-linux-musl.so +0 -0
  149. sage/numerical/backends/scip_backend.pxd +22 -0
  150. sage/numerical/backends/scip_backend.pyx +1289 -0
  151. sage/numerical/backends/scip_backend_test.py +13 -0
  152. sage/numerical/interactive_simplex_method.py +5338 -0
  153. sage/numerical/knapsack.py +665 -0
  154. sage/numerical/linear_functions.cpython-314-x86_64-linux-musl.so +0 -0
  155. sage/numerical/linear_functions.pxd +31 -0
  156. sage/numerical/linear_functions.pyx +1648 -0
  157. sage/numerical/linear_tensor.py +470 -0
  158. sage/numerical/linear_tensor_constraints.py +448 -0
  159. sage/numerical/linear_tensor_element.cpython-314-x86_64-linux-musl.so +0 -0
  160. sage/numerical/linear_tensor_element.pxd +6 -0
  161. sage/numerical/linear_tensor_element.pyx +459 -0
  162. sage/numerical/mip.cpython-314-x86_64-linux-musl.so +0 -0
  163. sage/numerical/mip.pxd +40 -0
  164. sage/numerical/mip.pyx +3667 -0
  165. sage/numerical/sdp.cpython-314-x86_64-linux-musl.so +0 -0
  166. sage/numerical/sdp.pxd +39 -0
  167. sage/numerical/sdp.pyx +1433 -0
  168. sage/rings/all__sagemath_polyhedra.py +3 -0
  169. sage/rings/polynomial/all__sagemath_polyhedra.py +10 -0
  170. sage/rings/polynomial/omega.py +982 -0
  171. sage/schemes/all__sagemath_polyhedra.py +2 -0
  172. sage/schemes/toric/all.py +10 -0
  173. sage/schemes/toric/chow_group.py +1248 -0
  174. sage/schemes/toric/divisor.py +2082 -0
  175. sage/schemes/toric/divisor_class.cpython-314-x86_64-linux-musl.so +0 -0
  176. sage/schemes/toric/divisor_class.pyx +322 -0
  177. sage/schemes/toric/fano_variety.py +1606 -0
  178. sage/schemes/toric/homset.py +650 -0
  179. sage/schemes/toric/ideal.py +451 -0
  180. sage/schemes/toric/library.py +1322 -0
  181. sage/schemes/toric/morphism.py +1958 -0
  182. sage/schemes/toric/points.py +1032 -0
  183. sage/schemes/toric/sheaf/all.py +1 -0
  184. sage/schemes/toric/sheaf/constructor.py +302 -0
  185. sage/schemes/toric/sheaf/klyachko.py +921 -0
  186. sage/schemes/toric/toric_subscheme.py +905 -0
  187. sage/schemes/toric/variety.py +3460 -0
  188. sage/schemes/toric/weierstrass.py +1078 -0
  189. sage/schemes/toric/weierstrass_covering.py +457 -0
  190. sage/schemes/toric/weierstrass_higher.py +288 -0
  191. sage_wheels/share/reflexive_polytopes/Full2d/zzdb.info +10 -0
  192. sage_wheels/share/reflexive_polytopes/Full2d/zzdb.v03 +0 -0
  193. sage_wheels/share/reflexive_polytopes/Full2d/zzdb.v04 +0 -0
  194. sage_wheels/share/reflexive_polytopes/Full2d/zzdb.v05 +1 -0
  195. sage_wheels/share/reflexive_polytopes/Full2d/zzdb.v06 +1 -0
  196. sage_wheels/share/reflexive_polytopes/Full3d/zzdb.info +22 -0
  197. sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v04 +0 -0
  198. sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v05 +0 -0
  199. sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v06 +0 -0
  200. sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v07 +0 -0
  201. sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v08 +0 -0
  202. sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v09 +0 -0
  203. sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v10 +0 -0
  204. sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v11 +1 -0
  205. sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v12 +1 -0
  206. sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v13 +1 -0
  207. sage_wheels/share/reflexive_polytopes/reflexive_polytopes_2d +80 -0
  208. sage_wheels/share/reflexive_polytopes/reflexive_polytopes_3d +37977 -0
@@ -0,0 +1,1289 @@
1
+ # sage_setup: distribution = sagemath-polyhedra
2
+ # distutils: language = c++
3
+ # sage.doctest: optional - pyscipopt
4
+ """
5
+ SCIP Backend
6
+
7
+ AUTHORS:
8
+
9
+ - Nathann Cohen (2010-10): generic backend
10
+ - Matthias Koeppe (2017): stubs
11
+ - Moritz Firsching (2018-04): rest
12
+ """
13
+ # *****************************************************************************
14
+ # Copyright (C) 2010 Nathann Cohen <nathann.cohen@gmail.com>
15
+ # 2017-2022 Matthias Koeppe
16
+ # 2018 Moritz Firsching
17
+ #
18
+ # This program is free software: you can redistribute it and/or modify
19
+ # it under the terms of the GNU General Public License as published by
20
+ # the Free Software Foundation, either version 2 of the License, or
21
+ # (at your option) any later version.
22
+ # https://www.gnu.org/licenses/
23
+ # *****************************************************************************
24
+
25
+ from os.path import splitext
26
+ from sage.numerical.mip import MIPSolverException
27
+ from pyscipopt import Model
28
+
29
+
30
+ cdef class SCIPBackend(GenericBackend):
31
+ """
32
+ MIP Backend that uses the SCIP solver.
33
+
34
+ TESTS:
35
+
36
+ General backend testsuite::
37
+
38
+ sage: p = MixedIntegerLinearProgram(solver='SCIP')
39
+ sage: TestSuite(p.get_backend()).run(skip='_test_pickling')
40
+ """
41
+
42
+ def __cinit__(self, maximization=True):
43
+ """
44
+ Constructor.
45
+
46
+ EXAMPLES::
47
+
48
+ sage: p = MixedIntegerLinearProgram(solver='SCIP')
49
+ """
50
+ self.model = Model('')
51
+ if maximization:
52
+ self.set_sense(1)
53
+ else:
54
+ self.set_sense(-1)
55
+ self.obj_constant_term = 0.0
56
+ self.variables = []
57
+ self.model.hideOutput()
58
+ # always set this to None if the list of constraints may change
59
+ self.constraints = None
60
+
61
+ def get_constraints(self):
62
+ """
63
+ Get all constraints of the problem.
64
+
65
+ EXAMPLES::
66
+
67
+ sage: from sage.numerical.backends.generic_backend import get_solver
68
+ sage: lp = get_solver(solver='SCIP')
69
+ sage: lp.add_variables(3)
70
+ 2
71
+ sage: lp.add_linear_constraint(zip([0, 1, 2], [8, 6, 1]), None, 48)
72
+ sage: lp.add_linear_constraint(zip([0, 1, 2], [2, 1.5, 0.5]), None, 8)
73
+
74
+ sage: lp.get_constraints()
75
+ [c1, c2]
76
+ sage: lp.row(1) # indirect doctest
77
+ ([0, 1, 2], [2.0, 1.5, 0.5])
78
+ """
79
+ if self.constraints is None:
80
+ self.constraints = self.model.getConss()
81
+ return self.constraints
82
+
83
+ cpdef _get_model(self):
84
+ """
85
+ Get the model as a pyscipopt Model.
86
+
87
+ EXAMPLES::
88
+
89
+ sage: from sage.numerical.backends.generic_backend import get_solver
90
+ sage: p = get_solver(solver = "SCIP")
91
+ sage: p._get_model()
92
+ <pyscipopt.scip.Model object at ...
93
+ """
94
+ return self.model
95
+
96
+ cpdef int add_variable(self, lower_bound=0.0, upper_bound=None,
97
+ binary=False, continuous=False, integer=False,
98
+ obj=0.0, name=None) except -1:
99
+ """
100
+ Add a variable.
101
+
102
+ This amounts to adding a new column to the matrix. By default,
103
+ the variable is both positive, real and the coefficient in the
104
+ objective function is 0.0.
105
+
106
+ INPUT:
107
+
108
+ - ``lower_bound`` -- the lower bound of the variable (default: 0)
109
+
110
+ - ``upper_bound`` -- the upper bound of the variable (default: ``None``)
111
+
112
+ - ``binary`` -- ``True`` if the variable is binary (default: ``False``)
113
+
114
+ - ``continuous`` -- ``True`` if the variable is binary (default: ``True``)
115
+
116
+ - ``integer`` -- ``True`` if the variable is binary (default: ``False``)
117
+
118
+ - ``obj`` -- (optional) coefficient of this variable in the objective function (default: 0.0)
119
+
120
+ - ``name`` -- an optional name for the newly added variable (default: ``None``)
121
+
122
+ OUTPUT: the index of the newly created variable
123
+
124
+ EXAMPLES::
125
+
126
+ sage: from sage.numerical.backends.generic_backend import get_solver
127
+ sage: p = get_solver(solver = "SCIP")
128
+ sage: p.ncols()
129
+ 0
130
+ sage: p.add_variable()
131
+ 0
132
+ sage: p.ncols()
133
+ 1
134
+ sage: p.add_variable(binary=True)
135
+ 1
136
+ sage: p.add_variable(lower_bound=-2.0, integer=True)
137
+ 2
138
+ sage: p.add_variable(continuous=True, integer=True)
139
+ Traceback (most recent call last):
140
+ ...
141
+ ValueError: ...
142
+ sage: p.add_variable(name='x', obj=1.0)
143
+ 3
144
+ sage: p.col_name(3)
145
+ 'x'
146
+ sage: p.objective_coefficient(3)
147
+ 1.0
148
+ """
149
+ if self.model.getStatus() != 'unknown':
150
+ self.model.freeTransform()
151
+ cdef int vtype = int(bool(binary)) + int(bool(continuous)) + int(bool(integer))
152
+ if vtype == 0:
153
+ continuous = True
154
+ elif vtype != 1:
155
+ raise ValueError("Exactly one parameter of 'binary', 'integer'"
156
+ "and 'continuous' must be 'True'.")
157
+
158
+ if name is None:
159
+ vname = ''
160
+ else:
161
+ assert type(name) in [str, unicode]
162
+ vname = name
163
+
164
+ if continuous:
165
+ vtypestr = 'C'
166
+ if binary:
167
+ vtypestr = 'B'
168
+ if integer:
169
+ vtypestr = 'I'
170
+
171
+ v = self.model.addVar(name=vname, vtype=vtypestr, ub=upper_bound,
172
+ lb=lower_bound, obj=obj, pricedVar=False)
173
+ index = v.getIndex()
174
+ assert index == self.ncols()
175
+ self.variables.append(v)
176
+
177
+ return index
178
+
179
+ cpdef set_variable_type(self, int variable, int vtype):
180
+ """
181
+ Set the type of a variable.
182
+
183
+ INPUT:
184
+
185
+ - ``variable`` -- integer; the variable's id
186
+
187
+ - ``vtype`` -- integer:
188
+
189
+ * 1 Integer
190
+ * 0 Binary
191
+ * -1 Real
192
+
193
+ EXAMPLES::
194
+
195
+ sage: from sage.numerical.backends.generic_backend import get_solver
196
+ sage: p = get_solver(solver = "SCIP")
197
+ sage: p.ncols()
198
+ 0
199
+ sage: p.add_variable()
200
+ 0
201
+ sage: p.set_variable_type(0,1)
202
+ sage: p.is_variable_integer(0)
203
+ True
204
+ """
205
+ if self.model.getStatus() != 'unknown':
206
+ self.model.freeTransform()
207
+ vtypenames = {1: 'I', 0: 'B', -1: 'C'}
208
+ self.model.chgVarType(var=self.variables[variable], vtype=vtypenames[vtype])
209
+
210
+ cpdef set_sense(self, int sense):
211
+ """
212
+ Set the direction (maximization/minimization).
213
+
214
+ INPUT:
215
+
216
+ - ``sense`` -- integer:
217
+
218
+ * +1 => Maximization
219
+ * -1 => Minimization
220
+
221
+ EXAMPLES::
222
+
223
+ sage: from sage.numerical.backends.generic_backend import get_solver
224
+ sage: p = get_solver(solver = "SCIP")
225
+ sage: p.is_maximization()
226
+ True
227
+ sage: p.set_sense(-1)
228
+ sage: p.is_maximization()
229
+ False
230
+ """
231
+ if self.model.getStatus() != 'unknown':
232
+ self.model.freeTransform()
233
+ if sense == 1:
234
+ self.model.setMaximize()
235
+ elif sense == -1:
236
+ self.model.setMinimize()
237
+ else:
238
+ raise AssertionError("sense must be either 1 or -1")
239
+
240
+ cpdef objective_coefficient(self, int variable, coeff=None):
241
+ """
242
+ Set or get the coefficient of a variable in the objective function.
243
+
244
+ INPUT:
245
+
246
+ - ``variable`` -- integer; the variable's id
247
+
248
+ - ``coeff`` -- double; its coefficient or ``None`` for
249
+ reading (default: ``None``)
250
+
251
+ EXAMPLES::
252
+
253
+ sage: from sage.numerical.backends.generic_backend import get_solver
254
+ sage: p = get_solver(solver = "SCIP")
255
+ sage: p.add_variable()
256
+ 0
257
+ sage: p.objective_coefficient(0)
258
+ 0.0
259
+ sage: p.objective_coefficient(0,2)
260
+ sage: p.objective_coefficient(0)
261
+ 2.0
262
+ """
263
+ if self.model.getStatus() != 'unknown':
264
+ self.model.freeTransform()
265
+ if coeff is None:
266
+ return self.variables[variable].getObj()
267
+ else:
268
+ objexpr = self.model.getObjective()
269
+ var = self.variables[variable]
270
+ linfun = sum([e * c for e, c in objexpr.terms.iteritems() if e != var]) + var * coeff
271
+ self.model.setObjective(linfun, sense=self.model.getObjectiveSense())
272
+
273
+ cpdef problem_name(self, name=None):
274
+ """
275
+ Return or define the problem's name.
276
+
277
+ INPUT:
278
+
279
+ - ``name`` -- string; the problem's name. When set to
280
+ ``None`` (default), the method returns the problem's name.
281
+
282
+ EXAMPLES::
283
+
284
+ sage: from sage.numerical.backends.generic_backend import get_solver
285
+ sage: p = get_solver(solver = "SCIP")
286
+ sage: p.problem_name("Nomen est omen")
287
+ sage: p.problem_name()
288
+ 'Nomen est omen'
289
+ """
290
+ if name is None:
291
+ return self.model.getProbName()
292
+ else:
293
+ self.model.setProbName(name)
294
+
295
+ cpdef set_objective(self, list coeff, d=0.0):
296
+ """
297
+ Set the objective function.
298
+
299
+ INPUT:
300
+
301
+ - ``coeff`` -- list of real values, whose i-th element is the
302
+ coefficient of the i-th variable in the objective function
303
+
304
+ - ``d`` -- double; the constant term in the linear function (set to `0`
305
+ by default)
306
+
307
+ EXAMPLES::
308
+
309
+ sage: from sage.numerical.backends.generic_backend import get_solver
310
+ sage: p = get_solver(solver = "SCIP")
311
+ sage: p.add_variables(5)
312
+ 4
313
+ sage: p.set_objective([1, 1, 2, 1, 3])
314
+ sage: [p.objective_coefficient(x) for x in range(5)]
315
+ [1.0, 1.0, 2.0, 1.0, 3.0]
316
+ """
317
+ if self.model.getStatus() != 'unknown':
318
+ self.model.freeTransform()
319
+ linfun = sum([c * x for c, x in zip(coeff, self.variables)]) + d
320
+ self.model.setObjective(linfun, sense=self.model.getObjectiveSense())
321
+
322
+ cpdef set_verbosity(self, int level):
323
+ """
324
+ Set the verbosity level.
325
+
326
+ INPUT:
327
+
328
+ - ``level`` -- integer; from 0 (no verbosity) to 1
329
+
330
+ EXAMPLES::
331
+
332
+ sage: from sage.numerical.backends.generic_backend import get_solver
333
+ sage: p = get_solver(solver = "SCIP")
334
+ sage: p.set_verbosity(1)
335
+
336
+ TODOs::
337
+
338
+ - Currently, the output is written to stdout, even when running
339
+ Jupyter: https://github.com/SCIP-Interfaces/PySCIPOpt/issues/116 .
340
+ This should be fixed upstream
341
+ - get access to more verbosity levels (e.g. via parameter settings)
342
+ """
343
+ if level == 0:
344
+ self.model.hideOutput()
345
+ elif level == 1:
346
+ self.model.hideOutput(False)
347
+ else:
348
+ raise AssertionError('level must be "0" or "1"')
349
+
350
+ cpdef remove_constraint(self, int i):
351
+ r"""
352
+ Remove a constraint from ``self``.
353
+
354
+ INPUT:
355
+
356
+ - ``i`` -- index of the constraint to remove
357
+
358
+ EXAMPLES::
359
+
360
+ sage: p = MixedIntegerLinearProgram(solver='SCIP')
361
+ sage: x, y = p['x'], p['y']
362
+ sage: p.add_constraint(2*x + 3*y <= 6)
363
+ sage: p.add_constraint(3*x + 2*y <= 6)
364
+ sage: p.add_constraint(x >= 0)
365
+ sage: p.set_objective(x + y + 7)
366
+ sage: p.set_integer(x); p.set_integer(y)
367
+ sage: p.solve()
368
+ 9.0
369
+ sage: p.remove_constraint(0)
370
+ sage: p.solve()
371
+ 10.0
372
+
373
+ Removing fancy constraints does not make Sage crash::
374
+
375
+ sage: MixedIntegerLinearProgram(solver='SCIP').remove_constraint(-2)
376
+ Traceback (most recent call last):
377
+ ...
378
+ ValueError: The constraint's index i must satisfy 0 <= i < number_of_constraints
379
+ """
380
+ if i < 0 or i >= self.nrows():
381
+ raise ValueError("The constraint's index i must satisfy 0 <= i < number_of_constraints")
382
+ if self.model.getStatus() != 'unknown':
383
+ self.model.freeTransform()
384
+ self.constraints = None
385
+ self.model.delCons(self.get_constraints()[i])
386
+ self.constraints = None
387
+
388
+ cpdef remove_constraints(self, constraints):
389
+ r"""
390
+ Remove several constraints.
391
+
392
+ INPUT:
393
+
394
+ - ``constraints`` -- an iterable containing the indices of the rows to remove
395
+
396
+ EXAMPLES::
397
+
398
+ sage: from sage.numerical.backends.generic_backend import get_solver
399
+ sage: p = get_solver(solver='SCIP')
400
+ sage: p.add_variables(2)
401
+ 1
402
+ sage: p.add_linear_constraint([(0, 2), (1, 3)], None, 6)
403
+ sage: p.add_linear_constraint([(0, 3), (1, 2)], None, 6)
404
+ sage: p.row(0)
405
+ ([0, 1], [2.0, 3.0])
406
+ sage: p.remove_constraints([0, 1])
407
+ sage: p.nrows()
408
+ 0
409
+ """
410
+ if isinstance(constraints, int):
411
+ self.remove_constraint(constraints)
412
+ return
413
+
414
+ if self.model.getStatus() != 'unknown':
415
+ self.model.freeTransform()
416
+ self.constraints = None
417
+
418
+ all_constraints = self.get_constraints()
419
+ to_remove = [all_constraints[i] for i in constraints]
420
+ for constraint in to_remove:
421
+ self.model.delCons(constraint)
422
+ self.constraints = None
423
+
424
+ cpdef add_linear_constraint(self, coefficients, lower_bound, upper_bound, name=None):
425
+ """
426
+ Add a linear constraint.
427
+
428
+ INPUT:
429
+
430
+ - ``coefficients`` an iterable with ``(c, v)`` pairs where ``c``
431
+ is a variable index (integer) and ``v`` is a value (real
432
+ value).
433
+
434
+ - ``lower_bound`` -- a lower bound, either a real value or ``None``
435
+
436
+ - ``upper_bound`` -- an upper bound, either a real value or ``None``
437
+
438
+ - ``name`` -- an optional name for this row (default: ``None``)
439
+
440
+ EXAMPLES::
441
+
442
+ sage: from sage.numerical.backends.generic_backend import get_solver
443
+ sage: p = get_solver(solver = "SCIP")
444
+ sage: p.add_variables(5)
445
+ 4
446
+ sage: p.add_linear_constraint( zip(range(5), range(5)), 2.0, 2.0)
447
+ sage: p.row_bounds(0)
448
+ (2.0, 2.0)
449
+ sage: p.add_linear_constraint( zip(range(5), range(5)), 1.0, 1.0, name='foo')
450
+ sage: p.row_name(1)
451
+ 'foo'
452
+ """
453
+ if self.model.getStatus() != 'unknown':
454
+ self.model.freeTransform()
455
+ mvars = self.variables
456
+ from pyscipopt.scip import quicksum
457
+ linfun = quicksum([v * mvars[c] for c, v in coefficients])
458
+ # we introduced patch 0001 for pyscipopt, in order to handle the case
459
+ # when linfun is an empty expression.
460
+ if name is None:
461
+ name = ''
462
+
463
+ if lower_bound is None:
464
+ lower_bound = -self.model.infinity()
465
+ if upper_bound is None:
466
+ upper_bound = self.model.infinity()
467
+
468
+ cons = lower_bound <= (linfun <= upper_bound)
469
+ self.model.addCons(cons, name=name)
470
+ self.constraints = None
471
+
472
+ cpdef row(self, int index):
473
+ r"""
474
+ Return a row.
475
+
476
+ INPUT:
477
+
478
+ - ``index`` -- integer; the constraint's id
479
+
480
+ OUTPUT:
481
+
482
+ A pair ``(indices, coeffs)`` where ``indices`` lists the
483
+ entries whose coefficient is nonzero, and to which ``coeffs``
484
+ associates their coefficient on the model of the
485
+ ``add_linear_constraint`` method.
486
+
487
+ EXAMPLES::
488
+
489
+
490
+ sage: from sage.numerical.backends.generic_backend import get_solver
491
+ sage: p = get_solver(solver = "SCIP")
492
+ sage: p.add_variables(5)
493
+ 4
494
+ sage: p.add_linear_constraint(zip(range(5), range(5)), 2, 2)
495
+ sage: p.row(0)
496
+ ([1, 2, 3, 4], [1.0, 2.0, 3.0, 4.0])
497
+ sage: p.row_bounds(0)
498
+ (2.0, 2.0)
499
+ """
500
+ namedvars = [var.name for var in self.variables]
501
+ valslinear = self.model.getValsLinear(self.get_constraints()[index])
502
+ cdef list indices = []
503
+ cdef list values = []
504
+ for var, coeff in valslinear.iteritems():
505
+ indices.append(namedvars.index(var))
506
+ values.append(coeff)
507
+ return (indices, values)
508
+
509
+ cpdef row_bounds(self, int index):
510
+ """
511
+ Return the bounds of a specific constraint.
512
+
513
+ INPUT:
514
+
515
+ - ``index`` -- integer; the constraint's id
516
+
517
+ OUTPUT:
518
+
519
+ A pair ``(lower_bound, upper_bound)``. Each of them can be set
520
+ to ``None`` if the constraint is not bounded in the
521
+ corresponding direction, and is a real value otherwise.
522
+
523
+ EXAMPLES::
524
+
525
+ sage: from sage.numerical.backends.generic_backend import get_solver
526
+ sage: p = get_solver(solver = "SCIP")
527
+ sage: p.add_variables(5)
528
+ 4
529
+ sage: p.add_linear_constraint(zip(range(5), range(5)), 2, 2)
530
+ sage: p.row_bounds(0)
531
+ (2.0, 2.0)
532
+ """
533
+ cons = self.get_constraints()[index]
534
+ lhs = self.model.getLhs(cons)
535
+ rhs = self.model.getRhs(cons)
536
+ if lhs == -self.model.infinity():
537
+ lhs = None
538
+ if rhs == self.model.infinity():
539
+ rhs = None
540
+ return (lhs, rhs)
541
+
542
+ cpdef col_bounds(self, int index):
543
+ """
544
+ Return the bounds of a specific variable.
545
+
546
+ INPUT:
547
+
548
+ - ``index`` -- integer; the variable's id
549
+
550
+ OUTPUT:
551
+
552
+ A pair ``(lower_bound, upper_bound)``. Each of them can be set
553
+ to ``None`` if the variable is not bounded in the
554
+ corresponding direction, and is a real value otherwise.
555
+
556
+ EXAMPLES::
557
+
558
+ sage: from sage.numerical.backends.generic_backend import get_solver
559
+ sage: p = get_solver(solver = "SCIP")
560
+ sage: p.add_variable()
561
+ 0
562
+ sage: p.col_bounds(0)
563
+ (0.0, None)
564
+ sage: p.variable_upper_bound(0, 5)
565
+ sage: p.col_bounds(0)
566
+ (0.0, 5.0)
567
+ """
568
+ var = self.variables[index]
569
+ lb = var.getLbOriginal()
570
+ if lb == -self.model.infinity():
571
+ lb = None
572
+ ub = var.getUbOriginal()
573
+ if ub == self.model.infinity():
574
+ ub = None
575
+ return (lb, ub)
576
+
577
+ cpdef add_col(self, indices, coeffs):
578
+ """
579
+ Add a column.
580
+
581
+ INPUT:
582
+
583
+ - ``indices`` -- list of integers; this list contains the
584
+ indices of the constraints in which the variable's
585
+ coefficient is nonzero
586
+
587
+ - ``coeffs`` -- list of real values; associates a coefficient
588
+ to the variable in each of the constraints in which it
589
+ appears. Namely, the i-th entry of ``coeffs`` corresponds to
590
+ the coefficient of the variable in the constraint
591
+ represented by the i-th entry in ``indices``.
592
+
593
+ .. NOTE::
594
+
595
+ ``indices`` and ``coeffs`` are expected to be of the same
596
+ length.
597
+
598
+ EXAMPLES::
599
+
600
+ sage: from sage.numerical.backends.generic_backend import get_solver
601
+ sage: p = get_solver(solver = "SCIP")
602
+ sage: p.ncols()
603
+ 0
604
+ sage: p.nrows()
605
+ 0
606
+ sage: p.add_linear_constraints(5, 0, None)
607
+ sage: p.add_col(range(5), range(5))
608
+ sage: p.nrows()
609
+ 5
610
+ """
611
+ mcons = self.get_constraints()
612
+ self.constraints = None # is this necessary?
613
+ # after update of
614
+ index = self.add_variable(lower_bound=-self.model.infinity())
615
+ var = self.variables[index]
616
+
617
+ for i, coeff in zip(indices, coeffs):
618
+ self.model.addConsCoeff(var=var, cons=mcons[i], coeff=coeff)
619
+
620
+ cpdef int solve(self) except -1:
621
+ """
622
+ Solve the problem.
623
+
624
+ Sage uses SCIP's implementation of the branch-and-cut algorithm
625
+ to solve the mixed-integer linear program.
626
+ (If all variables are continuous, the algorithm reduces to solving the
627
+ linear program by the simplex method.)
628
+
629
+ EXAMPLES::
630
+
631
+ sage: lp = MixedIntegerLinearProgram(solver = 'SCIP', maximization = False)
632
+ sage: x, y = lp[0], lp[1]
633
+ sage: lp.add_constraint(-2*x + y <= 1)
634
+ sage: lp.add_constraint(x - y <= 1)
635
+ sage: lp.add_constraint(x + y >= 2)
636
+ sage: lp.set_objective(x + y)
637
+ sage: lp.set_integer(x)
638
+ sage: lp.set_integer(y)
639
+ sage: lp.solve()
640
+ 2.0
641
+ sage: lp.get_values([x, y])
642
+ [1.0, 1.0]
643
+
644
+ .. NOTE::
645
+
646
+ This method raises ``MIPSolverException`` exceptions when
647
+ the solution can not be computed for any reason (none
648
+ exists, or the LP solver was not able to find it, etc...)
649
+
650
+ EXAMPLES::
651
+
652
+ sage: from sage.numerical.backends.generic_backend import get_solver
653
+ sage: p = get_solver(solver = "SCIP")
654
+ sage: p.add_linear_constraints(5, 0, None)
655
+ sage: p.add_col(range(5), range(5))
656
+ sage: p.solve()
657
+ 0
658
+ sage: p.objective_coefficient(0,1)
659
+ sage: p.solve()
660
+ Traceback (most recent call last):
661
+ ...
662
+ MIPSolverException: ...
663
+
664
+ sage: lp = MixedIntegerLinearProgram(solver = "SCIP")
665
+ sage: v = lp.new_variable(nonnegative=True)
666
+ sage: lp.add_constraint(v[1] +v[2] -2.0 *v[3], max=-1.0)
667
+ sage: lp.add_constraint(v[0] -4.0/3 *v[1] +1.0/3 *v[2], max=-1.0/3)
668
+ sage: lp.add_constraint(v[0] +0.5 *v[1] -0.5 *v[2] +0.25 *v[3], max=-0.25)
669
+ sage: lp.solve()
670
+ 0.0
671
+
672
+ Solving a LP within the acceptable gap. No exception is raised, even if
673
+ the result is not optimal. To do this, we try to compute the maximum
674
+ number of disjoint balls (of diameter 1) in a hypercube::
675
+
676
+ sage: g = graphs.CubeGraph(9)
677
+ sage: p = MixedIntegerLinearProgram(solver = "SCIP")
678
+
679
+ sage: b = p.new_variable(binary=True)
680
+ sage: p.set_objective(p.sum(b[v] for v in g))
681
+ sage: for v in g:
682
+ ....: p.add_constraint(b[v] + p.sum(b[u] for u in g.neighbors(v)) <= 1)
683
+ sage: p.add_constraint(b[v] == 1) # Force an easy non-0 solution
684
+ sage: p.solver_parameter("limits/absgap", 100)
685
+ sage: p.solve() # rel tol 100
686
+ 1
687
+ """
688
+ if self.model.getStatus() != 'unknown' or self.model.getStage() > 1:
689
+ # This should actually be self.model.freeReoptSolve, but it seems to fail.
690
+ self.model.freeTransform()
691
+ self.model.optimize()
692
+
693
+ status = self.model.getStatus()
694
+
695
+ if status == 'unbounded':
696
+ raise MIPSolverException("SCIP: Solution is unbounded")
697
+ elif status == 'infeasible':
698
+ raise MIPSolverException("SCIP: There is no feasible solution")
699
+ # elif status == 'timelimit':
700
+ # raise MIPSolverException("SCIP: Time limit reached")
701
+ return 0
702
+
703
+ cpdef get_objective_value(self):
704
+ """
705
+ Return the value of the objective function.
706
+
707
+ .. NOTE::
708
+
709
+ Behaviour is undefined unless ``solve`` has been called before.
710
+
711
+ EXAMPLES::
712
+
713
+ sage: from sage.numerical.backends.generic_backend import get_solver
714
+ sage: p = get_solver(solver = "SCIP")
715
+ sage: p.add_variables(2)
716
+ 1
717
+ sage: p.add_linear_constraint([[0, 1], [1, 2]], None, 3)
718
+ sage: p.set_objective([2, 5])
719
+ sage: p.solve()
720
+ 0
721
+ sage: p.get_objective_value()
722
+ 7.5
723
+ sage: p.get_variable_value(0) # abs tol 1e-15
724
+ 0.0
725
+ sage: p.get_variable_value(1)
726
+ 1.5
727
+ """
728
+ return self.model.getObjVal()
729
+
730
+ cpdef best_known_objective_bound(self):
731
+ r"""
732
+ Return the value of the currently best known bound.
733
+
734
+ This method returns the current best upper (resp. lower) bound on the
735
+ optimal value of the objective function in a maximization
736
+ (resp. minimization) problem. It is equal to the output of
737
+ :meth:`get_objective_value` if the MILP found an optimal solution, but
738
+ it can differ if it was interrupted manually or after a time limit (cf
739
+ :meth:`solver_parameter`).
740
+
741
+ .. NOTE::
742
+
743
+ Has no meaning unless ``solve`` has been called before.
744
+
745
+ EXAMPLES::
746
+
747
+ sage: # needs sage.graphs
748
+ sage: g = graphs.CubeGraph(9)
749
+ sage: p = MixedIntegerLinearProgram(solver='SCIP')
750
+ sage: p.solver_parameter("limits/gap", 100)
751
+ sage: b = p.new_variable(binary=True)
752
+ sage: p.set_objective(p.sum(b[v] for v in g))
753
+ sage: for v in g:
754
+ ....: p.add_constraint(b[v]+p.sum(b[u] for u in g.neighbors(v)) <= 1)
755
+ sage: p.add_constraint(b[v] == 1) # Force an easy non-0 solution
756
+ sage: p.solve() # rel tol 100
757
+ 1.0
758
+ sage: backend = p.get_backend()
759
+ sage: backend.best_known_objective_bound() # random
760
+ 31.0
761
+ """
762
+ return self.model.getPrimalbound()
763
+
764
+ cpdef get_relative_objective_gap(self):
765
+ r"""
766
+ Return the relative objective gap of the best known solution.
767
+
768
+ For a minimization problem, this value is computed by
769
+ `(\texttt{bestinteger} - \texttt{bestobjective}) / (1e-10 +
770
+ |\texttt{bestobjective}|)`, where ``bestinteger`` is the value returned
771
+ by :meth:`get_objective_value` and ``bestobjective`` is the value
772
+ returned by :meth:`best_known_objective_bound`. For a maximization
773
+ problem, the value is computed by `(\texttt{bestobjective} -
774
+ \texttt{bestinteger}) / (1e-10 + |\texttt{bestobjective}|)`.
775
+
776
+ .. NOTE::
777
+
778
+ Has no meaning unless ``solve`` has been called before.
779
+
780
+ EXAMPLES::
781
+
782
+ sage: # needs sage.graphs
783
+ sage: g = graphs.CubeGraph(9)
784
+ sage: p = MixedIntegerLinearProgram(solver='SCIP')
785
+ sage: p.solver_parameter("limits/gap", 100)
786
+ sage: b = p.new_variable(binary=True)
787
+ sage: p.set_objective(p.sum(b[v] for v in g))
788
+ sage: for v in g:
789
+ ....: p.add_constraint(b[v]+p.sum(b[u] for u in g.neighbors(v)) <= 1)
790
+ sage: p.add_constraint(b[v] == 1) # Force an easy non-0 solution
791
+ sage: p.solve() # rel tol 100
792
+ 1.0
793
+ sage: backend = p.get_backend()
794
+ sage: backend.get_relative_objective_gap() # random
795
+ 46.99999999999999
796
+
797
+ TESTS:
798
+
799
+ Just make sure that the variable *has* been defined, and is not just
800
+ undefined::
801
+
802
+ sage: backend.get_relative_objective_gap() > 1 # needs sage.graphs
803
+ True
804
+ """
805
+ return self.model.getGap()
806
+
807
+ cpdef get_variable_value(self, int variable):
808
+ """
809
+ Return the value of a variable given by the solver.
810
+
811
+ .. NOTE::
812
+
813
+ Behaviour is undefined unless ``solve`` has been called before.
814
+
815
+ EXAMPLES::
816
+
817
+ sage: from sage.numerical.backends.generic_backend import get_solver
818
+ sage: p = get_solver(solver = "SCIP")
819
+ sage: p.add_variables(2)
820
+ 1
821
+ sage: p.add_linear_constraint([[0, 1], [1, 2]], None, 3)
822
+ sage: p.set_objective([2, 5])
823
+ sage: p.solve()
824
+ 0
825
+ sage: p.get_objective_value()
826
+ 7.5
827
+ sage: p.get_variable_value(0) # abs tol 1e-15
828
+ 0.0
829
+ sage: p.get_variable_value(1)
830
+ 1.5
831
+ """
832
+ return self.model.getVal(self.variables[variable])
833
+
834
+ cpdef get_row_prim(self, int i):
835
+ r"""
836
+ Return the value of the auxiliary variable associated with i-th row.
837
+
838
+ .. NOTE::
839
+
840
+ Behaviour is undefined unless ``solve`` has been called before.
841
+
842
+ EXAMPLES::
843
+
844
+ sage: from sage.numerical.backends.generic_backend import get_solver
845
+ sage: lp = get_solver(solver = "SCIP")
846
+ sage: lp.add_variables(3)
847
+ 2
848
+ sage: lp.add_linear_constraint(zip([0, 1, 2], [8, 6, 1]), None, 48)
849
+ sage: lp.add_linear_constraint(zip([0, 1, 2], [4, 2, 1.5]), None, 20)
850
+ sage: lp.add_linear_constraint(zip([0, 1, 2], [2, 1.5, 0.5]), None, 8)
851
+ sage: lp.set_objective([60, 30, 20])
852
+ sage: lp.solver_parameter('presolving/maxrounds',0)
853
+ sage: lp.solve()
854
+ 0
855
+ sage: lp.get_objective_value()
856
+ 280.0
857
+ sage: lp.get_row_prim(0)
858
+ 24.0
859
+ sage: lp.get_row_prim(1)
860
+ 20.0
861
+ sage: lp.get_row_prim(2)
862
+ 8.0
863
+ """
864
+ return self.model.getActivity(self.get_constraints()[i])
865
+
866
+ cpdef int ncols(self) noexcept:
867
+ """
868
+ Return the number of columns/variables.
869
+
870
+ EXAMPLES::
871
+
872
+ sage: from sage.numerical.backends.generic_backend import get_solver
873
+ sage: p = get_solver(solver = "SCIP")
874
+ sage: p.ncols()
875
+ 0
876
+ sage: p.add_variables(2)
877
+ 1
878
+ sage: p.ncols()
879
+ 2
880
+ """
881
+ return len(self.variables)
882
+
883
+ cpdef int nrows(self) noexcept:
884
+ """
885
+ Return the number of rows/constraints.
886
+
887
+ EXAMPLES::
888
+
889
+ sage: from sage.numerical.backends.generic_backend import get_solver
890
+ sage: p = get_solver(solver = "SCIP")
891
+ sage: p.nrows()
892
+ 0
893
+ sage: p.add_linear_constraints(2, 2, None)
894
+ sage: p.nrows()
895
+ 2
896
+
897
+ TESTS::
898
+
899
+ After calling :meth:`remove_constraints` we know that
900
+ `self.constraints is None`. `SCIP` keeps track of the number
901
+ of constraints, so we can do the optimization::
902
+
903
+ sage: from sage.numerical.backends.generic_backend import get_solver
904
+ sage: p = get_solver(solver='SCIP')
905
+ sage: p.add_variables(2)
906
+ 1
907
+ sage: p.add_linear_constraint([(0, 2), (1, 3)], None, 6)
908
+ sage: p.row(0)
909
+ ([0, 1], [2.0, 3.0])
910
+ sage: p.remove_constraints([0])
911
+ sage: p.nrows()
912
+ 0
913
+ """
914
+ if self.constraints is None:
915
+ return self.model.getNConss()
916
+ return len(self.get_constraints())
917
+
918
+ cpdef col_name(self, int index):
919
+ """
920
+ Return the ``index``-th col name.
921
+
922
+ INPUT:
923
+
924
+ - ``index`` -- integer; the col's id
925
+
926
+ EXAMPLES::
927
+
928
+ sage: from sage.numerical.backends.generic_backend import get_solver
929
+ sage: p = get_solver(solver = "SCIP")
930
+ sage: p.add_variable(name='I am a variable')
931
+ 0
932
+ sage: p.col_name(0)
933
+ 'I am a variable'
934
+ """
935
+ return self.variables[index].name
936
+
937
+ cpdef row_name(self, int index):
938
+ """
939
+ Return the ``index``-th row name.
940
+
941
+ INPUT:
942
+
943
+ - ``index`` -- integer; the row's id
944
+
945
+ EXAMPLES::
946
+
947
+ sage: from sage.numerical.backends.generic_backend import get_solver
948
+ sage: p = get_solver(solver = "SCIP")
949
+ sage: p.add_linear_constraints(1, 2, None, names=['Empty constraint 1'])
950
+ sage: p.row_name(0)
951
+ 'Empty constraint 1'
952
+ """
953
+ return self.get_constraints()[index].name
954
+
955
+ cpdef bint is_variable_binary(self, int index) noexcept:
956
+ """
957
+ Test whether the given variable is of binary type.
958
+
959
+ INPUT:
960
+
961
+ - ``index`` -- integer; the variable's id
962
+
963
+ EXAMPLES::
964
+
965
+ sage: from sage.numerical.backends.generic_backend import get_solver
966
+ sage: p = get_solver(solver = "SCIP")
967
+ sage: p.ncols()
968
+ 0
969
+ sage: p.add_variable()
970
+ 0
971
+ sage: p.set_variable_type(0,0)
972
+ sage: p.is_variable_binary(0)
973
+ True
974
+ """
975
+ return self.variables[index].vtype() == 'BINARY'
976
+
977
+ cpdef bint is_variable_integer(self, int index) noexcept:
978
+ """
979
+ Test whether the given variable is of integer type.
980
+
981
+ INPUT:
982
+
983
+ - ``index`` -- integer; the variable's id
984
+
985
+ EXAMPLES::
986
+
987
+ sage: from sage.numerical.backends.generic_backend import get_solver
988
+ sage: p = get_solver(solver = "SCIP")
989
+ sage: p.ncols()
990
+ 0
991
+ sage: p.add_variable()
992
+ 0
993
+ sage: p.set_variable_type(0,1)
994
+ sage: p.is_variable_integer(0)
995
+ True
996
+ """
997
+ return self.variables[index].vtype() == 'INTEGER'
998
+
999
+ cpdef bint is_variable_continuous(self, int index) noexcept:
1000
+ """
1001
+ Test whether the given variable is of continuous/real type.
1002
+
1003
+ INPUT:
1004
+
1005
+ - ``index`` -- integer; the variable's id
1006
+
1007
+ EXAMPLES::
1008
+
1009
+ sage: from sage.numerical.backends.generic_backend import get_solver
1010
+ sage: p = get_solver(solver = "SCIP")
1011
+ sage: p.ncols()
1012
+ 0
1013
+ sage: p.add_variable()
1014
+ 0
1015
+ sage: p.is_variable_continuous(0)
1016
+ True
1017
+ sage: p.set_variable_type(0,1)
1018
+ sage: p.is_variable_continuous(0)
1019
+ False
1020
+ """
1021
+ return self.variables[index].vtype() == 'CONTINUOUS'
1022
+
1023
+ cpdef bint is_maximization(self) noexcept:
1024
+ """
1025
+ Test whether the problem is a maximization
1026
+
1027
+ EXAMPLES::
1028
+
1029
+ sage: from sage.numerical.backends.generic_backend import get_solver
1030
+ sage: p = get_solver(solver = "SCIP")
1031
+ sage: p.is_maximization()
1032
+ True
1033
+ sage: p.set_sense(-1)
1034
+ sage: p.is_maximization()
1035
+ False
1036
+ """
1037
+ return self.model.getObjectiveSense() != 'minimize'
1038
+
1039
+ cpdef variable_upper_bound(self, int index, value=False):
1040
+ """
1041
+ Return or define the upper bound on a variable.
1042
+
1043
+ INPUT:
1044
+
1045
+ - ``index`` -- integer; the variable's id
1046
+
1047
+ - ``value`` -- real value, or ``None`` to mean that the
1048
+ variable has not upper bound. When set to ``False``
1049
+ (default), the method returns the current value.
1050
+
1051
+ EXAMPLES::
1052
+
1053
+ sage: from sage.numerical.backends.generic_backend import get_solver
1054
+ sage: p = get_solver(solver = "SCIP")
1055
+ sage: p.add_variable()
1056
+ 0
1057
+ sage: p.col_bounds(0)
1058
+ (0.0, None)
1059
+ sage: p.variable_upper_bound(0, 5)
1060
+ sage: p.col_bounds(0)
1061
+ (0.0, 5.0)
1062
+
1063
+ TESTS:
1064
+
1065
+ :issue:`14581`::
1066
+
1067
+ sage: P = MixedIntegerLinearProgram(solver='SCIP')
1068
+ sage: x = P["x"]
1069
+ sage: P.set_max(x, 0)
1070
+ sage: P.get_max(x)
1071
+ 0.0
1072
+
1073
+ Check that :issue:`10232` is fixed::
1074
+
1075
+ sage: p = get_solver(solver='SCIP')
1076
+ sage: p.variable_upper_bound(2)
1077
+ Traceback (most recent call last):
1078
+ ...
1079
+ ValueError: The variable's id must satisfy 0 <= id < number_of_variables
1080
+ sage: p.variable_upper_bound(3, 5)
1081
+ Traceback (most recent call last):
1082
+ ...
1083
+ ValueError: The variable's id must satisfy 0 <= id < number_of_variables
1084
+
1085
+ sage: p.add_variable()
1086
+ 0
1087
+ sage: p.variable_upper_bound(0, 'hey!')
1088
+ Traceback (most recent call last):
1089
+ ...
1090
+ TypeError: must be real number, not str
1091
+ """
1092
+ if index < 0 or index >= self.ncols():
1093
+ raise ValueError("The variable's id must satisfy 0 <= id < number_of_variables")
1094
+ var = self.variables[index]
1095
+ if value is False:
1096
+ return var.getUbOriginal()
1097
+ else:
1098
+ self.model.chgVarUb(var=var, ub=value)
1099
+
1100
+ cpdef variable_lower_bound(self, int index, value=False):
1101
+ """
1102
+ Return or define the lower bound on a variable.
1103
+
1104
+ INPUT:
1105
+
1106
+ - ``index`` -- integer; the variable's id
1107
+
1108
+ - ``value`` -- real value, or ``None`` to mean that the
1109
+ variable has not lower bound. When set to ``False``
1110
+ (default), the method returns the current value.
1111
+
1112
+ EXAMPLES::
1113
+
1114
+ sage: from sage.numerical.backends.generic_backend import get_solver
1115
+ sage: p = get_solver(solver = "SCIP")
1116
+ sage: p.add_variable()
1117
+ 0
1118
+ sage: p.col_bounds(0)
1119
+ (0.0, None)
1120
+ sage: p.variable_lower_bound(0, 5)
1121
+ sage: p.col_bounds(0)
1122
+ (5.0, None)
1123
+
1124
+ TESTS:
1125
+
1126
+ :issue:`14581`::
1127
+
1128
+ sage: P = MixedIntegerLinearProgram(solver='SCIP')
1129
+ sage: x = P["x"]
1130
+ sage: P.set_min(x, 5)
1131
+ sage: P.set_min(x, 0)
1132
+ sage: P.get_min(x)
1133
+ 0.0
1134
+
1135
+ Check that :issue:`10232` is fixed::
1136
+
1137
+ sage: p = get_solver(solver='SCIP')
1138
+ sage: p.variable_lower_bound(2)
1139
+ Traceback (most recent call last):
1140
+ ...
1141
+ ValueError: The variable's id must satisfy 0 <= id < number_of_variables
1142
+ sage: p.variable_lower_bound(3, 5)
1143
+ Traceback (most recent call last):
1144
+ ...
1145
+ ValueError: The variable's id must satisfy 0 <= id < number_of_variables
1146
+
1147
+ sage: p.add_variable()
1148
+ 0
1149
+ sage: p.variable_lower_bound(0, 'hey!')
1150
+ Traceback (most recent call last):
1151
+ ...
1152
+ TypeError: must be real number, not str
1153
+ """
1154
+ if index < 0 or index >= self.ncols():
1155
+ raise ValueError("The variable's id must satisfy 0 <= id < number_of_variables")
1156
+ var = self.variables[index]
1157
+ if value is False:
1158
+ return var.getLbOriginal()
1159
+ else:
1160
+ self.model.chgVarLb(var=var, lb=value)
1161
+
1162
+ cpdef write_cip(self, filename):
1163
+ """
1164
+ Write the problem to a ``.cip`` file.
1165
+
1166
+ INPUT:
1167
+
1168
+ - ``filename`` -- string
1169
+
1170
+ EXAMPLES::
1171
+
1172
+ sage: from sage.numerical.backends.generic_backend import get_solver
1173
+ sage: p = get_solver(solver = "SCIP")
1174
+ sage: p.add_variables(2)
1175
+ 1
1176
+ sage: p.add_linear_constraint([[0, 1], [1, 2]], None, 3)
1177
+ sage: p.set_objective([2, 5])
1178
+ sage: import tempfile
1179
+ sage: with tempfile.NamedTemporaryFile(suffix='.cip') as f:
1180
+ ....: p.write_cip(f.name)
1181
+ wrote problem to file ...
1182
+ """
1183
+ self.model.writeProblem(filename)
1184
+
1185
+ cpdef write_lp(self, filename):
1186
+ """
1187
+ Write the problem to a ``.lp`` file.
1188
+
1189
+ INPUT:
1190
+
1191
+ - ``filename`` -- string
1192
+
1193
+ EXAMPLES::
1194
+
1195
+ sage: from sage.numerical.backends.generic_backend import get_solver
1196
+ sage: p = get_solver(solver = "SCIP")
1197
+ sage: p.add_variables(2)
1198
+ 1
1199
+ sage: p.add_linear_constraint([[0, 1], [1, 2]], None, 3)
1200
+ sage: p.set_objective([2, 5])
1201
+ sage: import tempfile
1202
+ sage: with tempfile.NamedTemporaryFile(suffix='.lp') as f:
1203
+ ....: p.write_lp(f.name)
1204
+ wrote problem to file ...
1205
+ """
1206
+ filenamestr = filename
1207
+ fname, fext = splitext(filenamestr)
1208
+
1209
+ if fext.lower() != 'lp':
1210
+ filenamestr = filename + '.lp'
1211
+
1212
+ self.model.writeProblem(filenamestr)
1213
+
1214
+ cpdef write_mps(self, filename, int modern):
1215
+ """
1216
+ Write the problem to a ``.mps`` file.
1217
+
1218
+ INPUT:
1219
+
1220
+ - ``filename`` -- string
1221
+
1222
+ EXAMPLES::
1223
+
1224
+ sage: from sage.numerical.backends.generic_backend import get_solver
1225
+ sage: p = get_solver(solver = "SCIP")
1226
+ sage: p.add_variables(2)
1227
+ 1
1228
+ sage: p.add_linear_constraint([[0, 1], [1, 2]], None, 3)
1229
+ sage: p.set_objective([2, 5])
1230
+ sage: import tempfile
1231
+ sage: with tempfile.NamedTemporaryFile(suffix='.mps') as f:
1232
+ ....: p.write_mps(f.name, 2)
1233
+ wrote problem to file ...
1234
+ """
1235
+ filenamestr = filename
1236
+ fname, fext = splitext(filenamestr)
1237
+
1238
+ if fext.lower() != 'mps':
1239
+ filenamestr = filename + '.mps'
1240
+
1241
+ self.model.writeProblem(filenamestr)
1242
+
1243
+ cpdef __copy__(self):
1244
+ """
1245
+ Return a copy of ``self``.
1246
+
1247
+ EXAMPLES::
1248
+
1249
+ sage: from sage.numerical.backends.generic_backend import get_solver
1250
+ sage: p = MixedIntegerLinearProgram(solver = "SCIP")
1251
+ sage: b = p.new_variable()
1252
+ sage: p.add_constraint(b[1] + b[2] <= 6)
1253
+ sage: p.set_objective(b[1] + b[2])
1254
+ sage: copy(p).solve()
1255
+ 6.0
1256
+ """
1257
+ cdef SCIPBackend cp = type(self)(maximization=self.is_maximization())
1258
+ cp.model = Model(sourceModel=self.model, origcopy=True)
1259
+ cp.problem_name(self.problem_name())
1260
+ cp.obj_constant_term = self.obj_constant_term
1261
+ cp.variables = cp.model.getVars()
1262
+ return cp
1263
+
1264
+ cpdef solver_parameter(self, name, value=None):
1265
+ """
1266
+ Return or define a solver parameter.
1267
+
1268
+ INPUT:
1269
+
1270
+ - ``name`` -- string; the parameter
1271
+
1272
+ - ``value`` -- the parameter's value if it is to be defined,
1273
+ or ``None`` (default) to obtain its current value
1274
+
1275
+ EXAMPLES:
1276
+
1277
+ sage: from sage.numerical.backends.generic_backend import get_solver
1278
+ sage: p = get_solver(solver='SCIP')
1279
+ sage: p.solver_parameter("limits/time", 1)
1280
+ sage: p.solver_parameter("limits/time")
1281
+ 1.0
1282
+ """
1283
+ if value is not None:
1284
+ if name.lower() == 'timelimit':
1285
+ self.model.setRealParam("limits/time", float(value))
1286
+ else:
1287
+ self.model.setParam(name, value)
1288
+ else:
1289
+ return self.model.getParam(name)