passagemath-symbolics 10.8.1a1__cp314-cp314t-musllinux_1_2_aarch64.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.
Files changed (181) hide show
  1. passagemath_symbolics/__init__.py +3 -0
  2. passagemath_symbolics-10.8.1a1.dist-info/METADATA +186 -0
  3. passagemath_symbolics-10.8.1a1.dist-info/RECORD +181 -0
  4. passagemath_symbolics-10.8.1a1.dist-info/WHEEL +5 -0
  5. passagemath_symbolics-10.8.1a1.dist-info/top_level.txt +3 -0
  6. sage/all__sagemath_symbolics.py +17 -0
  7. sage/calculus/all.py +14 -0
  8. sage/calculus/calculus.py +2838 -0
  9. sage/calculus/desolvers.py +1864 -0
  10. sage/calculus/predefined.py +51 -0
  11. sage/calculus/tests.py +225 -0
  12. sage/calculus/var.cpython-314t-aarch64-linux-musl.so +0 -0
  13. sage/calculus/var.pyx +401 -0
  14. sage/dynamics/all__sagemath_symbolics.py +6 -0
  15. sage/dynamics/complex_dynamics/all.py +5 -0
  16. sage/dynamics/complex_dynamics/mandel_julia.py +765 -0
  17. sage/dynamics/complex_dynamics/mandel_julia_helper.cpython-314t-aarch64-linux-musl.so +0 -0
  18. sage/dynamics/complex_dynamics/mandel_julia_helper.pyx +1034 -0
  19. sage/ext/all__sagemath_symbolics.py +1 -0
  20. sage/ext_data/kenzo/CP2.txt +45 -0
  21. sage/ext_data/kenzo/CP3.txt +349 -0
  22. sage/ext_data/kenzo/CP4.txt +4774 -0
  23. sage/ext_data/kenzo/README.txt +49 -0
  24. sage/ext_data/kenzo/S4.txt +20 -0
  25. sage/ext_data/magma/latex/latex.m +1021 -0
  26. sage/ext_data/magma/latex/latex.spec +1 -0
  27. sage/ext_data/magma/sage/basic.m +356 -0
  28. sage/ext_data/magma/sage/sage.spec +1 -0
  29. sage/ext_data/magma/spec +9 -0
  30. sage/geometry/all__sagemath_symbolics.py +8 -0
  31. sage/geometry/hyperbolic_space/all.py +5 -0
  32. sage/geometry/hyperbolic_space/hyperbolic_coercion.py +755 -0
  33. sage/geometry/hyperbolic_space/hyperbolic_constants.py +5 -0
  34. sage/geometry/hyperbolic_space/hyperbolic_geodesic.py +2419 -0
  35. sage/geometry/hyperbolic_space/hyperbolic_interface.py +206 -0
  36. sage/geometry/hyperbolic_space/hyperbolic_isometry.py +1083 -0
  37. sage/geometry/hyperbolic_space/hyperbolic_model.py +1502 -0
  38. sage/geometry/hyperbolic_space/hyperbolic_point.py +621 -0
  39. sage/geometry/riemannian_manifolds/all.py +7 -0
  40. sage/geometry/riemannian_manifolds/parametrized_surface3d.py +1632 -0
  41. sage/geometry/riemannian_manifolds/surface3d_generators.py +461 -0
  42. sage/interfaces/all__sagemath_symbolics.py +1 -0
  43. sage/interfaces/magma.py +2991 -0
  44. sage/interfaces/magma_free.py +90 -0
  45. sage/interfaces/maple.py +1402 -0
  46. sage/interfaces/mathematica.py +1345 -0
  47. sage/interfaces/mathics.py +1312 -0
  48. sage/interfaces/sympy.py +1398 -0
  49. sage/interfaces/sympy_wrapper.py +197 -0
  50. sage/interfaces/tides.py +938 -0
  51. sage/libs/all__sagemath_symbolics.py +6 -0
  52. sage/manifolds/all.py +7 -0
  53. sage/manifolds/calculus_method.py +553 -0
  54. sage/manifolds/catalog.py +437 -0
  55. sage/manifolds/chart.py +4010 -0
  56. sage/manifolds/chart_func.py +3416 -0
  57. sage/manifolds/continuous_map.py +2183 -0
  58. sage/manifolds/continuous_map_image.py +155 -0
  59. sage/manifolds/differentiable/affine_connection.py +2475 -0
  60. sage/manifolds/differentiable/all.py +1 -0
  61. sage/manifolds/differentiable/automorphismfield.py +1383 -0
  62. sage/manifolds/differentiable/automorphismfield_group.py +604 -0
  63. sage/manifolds/differentiable/bundle_connection.py +1445 -0
  64. sage/manifolds/differentiable/characteristic_cohomology_class.py +1840 -0
  65. sage/manifolds/differentiable/chart.py +1241 -0
  66. sage/manifolds/differentiable/curve.py +1028 -0
  67. sage/manifolds/differentiable/de_rham_cohomology.py +541 -0
  68. sage/manifolds/differentiable/degenerate.py +559 -0
  69. sage/manifolds/differentiable/degenerate_submanifold.py +1668 -0
  70. sage/manifolds/differentiable/diff_form.py +1660 -0
  71. sage/manifolds/differentiable/diff_form_module.py +1062 -0
  72. sage/manifolds/differentiable/diff_map.py +1315 -0
  73. sage/manifolds/differentiable/differentiable_submanifold.py +291 -0
  74. sage/manifolds/differentiable/examples/all.py +1 -0
  75. sage/manifolds/differentiable/examples/euclidean.py +2517 -0
  76. sage/manifolds/differentiable/examples/real_line.py +897 -0
  77. sage/manifolds/differentiable/examples/sphere.py +1186 -0
  78. sage/manifolds/differentiable/examples/symplectic_space.py +187 -0
  79. sage/manifolds/differentiable/examples/symplectic_space_test.py +40 -0
  80. sage/manifolds/differentiable/integrated_curve.py +4035 -0
  81. sage/manifolds/differentiable/levi_civita_connection.py +841 -0
  82. sage/manifolds/differentiable/manifold.py +4254 -0
  83. sage/manifolds/differentiable/manifold_homset.py +1826 -0
  84. sage/manifolds/differentiable/metric.py +3032 -0
  85. sage/manifolds/differentiable/mixed_form.py +1507 -0
  86. sage/manifolds/differentiable/mixed_form_algebra.py +559 -0
  87. sage/manifolds/differentiable/multivector_module.py +800 -0
  88. sage/manifolds/differentiable/multivectorfield.py +1522 -0
  89. sage/manifolds/differentiable/poisson_tensor.py +268 -0
  90. sage/manifolds/differentiable/pseudo_riemannian.py +755 -0
  91. sage/manifolds/differentiable/pseudo_riemannian_submanifold.py +1839 -0
  92. sage/manifolds/differentiable/scalarfield.py +1343 -0
  93. sage/manifolds/differentiable/scalarfield_algebra.py +472 -0
  94. sage/manifolds/differentiable/symplectic_form.py +912 -0
  95. sage/manifolds/differentiable/symplectic_form_test.py +220 -0
  96. sage/manifolds/differentiable/tangent_space.py +412 -0
  97. sage/manifolds/differentiable/tangent_vector.py +616 -0
  98. sage/manifolds/differentiable/tensorfield.py +4665 -0
  99. sage/manifolds/differentiable/tensorfield_module.py +963 -0
  100. sage/manifolds/differentiable/tensorfield_paral.py +2450 -0
  101. sage/manifolds/differentiable/tensorfield_paral_test.py +16 -0
  102. sage/manifolds/differentiable/vector_bundle.py +1725 -0
  103. sage/manifolds/differentiable/vectorfield.py +1717 -0
  104. sage/manifolds/differentiable/vectorfield_module.py +2445 -0
  105. sage/manifolds/differentiable/vectorframe.py +1832 -0
  106. sage/manifolds/family.py +270 -0
  107. sage/manifolds/local_frame.py +1490 -0
  108. sage/manifolds/manifold.py +3090 -0
  109. sage/manifolds/manifold_homset.py +452 -0
  110. sage/manifolds/operators.py +359 -0
  111. sage/manifolds/point.py +994 -0
  112. sage/manifolds/scalarfield.py +3718 -0
  113. sage/manifolds/scalarfield_algebra.py +629 -0
  114. sage/manifolds/section.py +3111 -0
  115. sage/manifolds/section_module.py +831 -0
  116. sage/manifolds/structure.py +229 -0
  117. sage/manifolds/subset.py +2721 -0
  118. sage/manifolds/subsets/all.py +1 -0
  119. sage/manifolds/subsets/closure.py +131 -0
  120. sage/manifolds/subsets/pullback.py +883 -0
  121. sage/manifolds/topological_submanifold.py +891 -0
  122. sage/manifolds/trivialization.py +733 -0
  123. sage/manifolds/utilities.py +1348 -0
  124. sage/manifolds/vector_bundle.py +1347 -0
  125. sage/manifolds/vector_bundle_fiber.py +332 -0
  126. sage/manifolds/vector_bundle_fiber_element.py +111 -0
  127. sage/matrix/all__sagemath_symbolics.py +1 -0
  128. sage/matrix/matrix_symbolic_dense.cpython-314t-aarch64-linux-musl.so +0 -0
  129. sage/matrix/matrix_symbolic_dense.pxd +6 -0
  130. sage/matrix/matrix_symbolic_dense.pyx +1030 -0
  131. sage/matrix/matrix_symbolic_sparse.cpython-314t-aarch64-linux-musl.so +0 -0
  132. sage/matrix/matrix_symbolic_sparse.pxd +6 -0
  133. sage/matrix/matrix_symbolic_sparse.pyx +1038 -0
  134. sage/modules/all__sagemath_symbolics.py +1 -0
  135. sage/modules/vector_callable_symbolic_dense.py +105 -0
  136. sage/modules/vector_symbolic_dense.py +116 -0
  137. sage/modules/vector_symbolic_sparse.py +118 -0
  138. sage/rings/all__sagemath_symbolics.py +4 -0
  139. sage/rings/asymptotic/all.py +6 -0
  140. sage/rings/asymptotic/asymptotic_expansion_generators.py +1485 -0
  141. sage/rings/asymptotic/asymptotic_ring.py +4858 -0
  142. sage/rings/asymptotic/asymptotics_multivariate_generating_functions.py +4106 -0
  143. sage/rings/asymptotic/growth_group.py +5373 -0
  144. sage/rings/asymptotic/growth_group_cartesian.py +1400 -0
  145. sage/rings/asymptotic/term_monoid.py +5205 -0
  146. sage/rings/function_field/all__sagemath_symbolics.py +2 -0
  147. sage/rings/polynomial/all__sagemath_symbolics.py +1 -0
  148. sage/symbolic/all.py +15 -0
  149. sage/symbolic/assumptions.py +987 -0
  150. sage/symbolic/benchmark.py +93 -0
  151. sage/symbolic/callable.py +456 -0
  152. sage/symbolic/callable.pyi +66 -0
  153. sage/symbolic/comparison_impl.pyi +38 -0
  154. sage/symbolic/complexity_measures.py +35 -0
  155. sage/symbolic/constants.py +1286 -0
  156. sage/symbolic/constants_c_impl.pyi +10 -0
  157. sage/symbolic/expression_conversion_algebraic.py +310 -0
  158. sage/symbolic/expression_conversion_sympy.py +317 -0
  159. sage/symbolic/expression_conversions.py +1727 -0
  160. sage/symbolic/function_factory.py +355 -0
  161. sage/symbolic/function_factory.pyi +41 -0
  162. sage/symbolic/getitem_impl.pyi +24 -0
  163. sage/symbolic/integration/all.py +1 -0
  164. sage/symbolic/integration/external.py +271 -0
  165. sage/symbolic/integration/integral.py +1075 -0
  166. sage/symbolic/maxima_wrapper.py +162 -0
  167. sage/symbolic/operators.py +267 -0
  168. sage/symbolic/operators.pyi +61 -0
  169. sage/symbolic/pynac_constant_impl.pyi +13 -0
  170. sage/symbolic/pynac_function_impl.pyi +8 -0
  171. sage/symbolic/random_tests.py +461 -0
  172. sage/symbolic/relation.py +2062 -0
  173. sage/symbolic/ring.cpython-314t-aarch64-linux-musl.so +0 -0
  174. sage/symbolic/ring.pxd +5 -0
  175. sage/symbolic/ring.pyi +110 -0
  176. sage/symbolic/ring.pyx +1393 -0
  177. sage/symbolic/series_impl.pyi +10 -0
  178. sage/symbolic/subring.py +1025 -0
  179. sage/symbolic/symengine.py +19 -0
  180. sage/symbolic/tests.py +40 -0
  181. sage/symbolic/units.py +1468 -0
@@ -0,0 +1,2062 @@
1
+ # sage_setup: distribution = sagemath-symbolics
2
+ r"""
3
+ Symbolic Equations and Inequalities
4
+
5
+ Sage can solve symbolic equations and inequalities. For
6
+ example, we derive the quadratic formula as follows::
7
+
8
+ sage: a,b,c = var('a,b,c')
9
+ sage: qe = (a*x^2 + b*x + c == 0)
10
+ sage: qe
11
+ a*x^2 + b*x + c == 0
12
+ sage: print(solve(qe, x))
13
+ [
14
+ x == -1/2*(b + sqrt(b^2 - 4*a*c))/a,
15
+ x == -1/2*(b - sqrt(b^2 - 4*a*c))/a
16
+ ]
17
+
18
+
19
+ The operator, left hand side, and right hand side
20
+ --------------------------------------------------
21
+
22
+ Operators::
23
+
24
+ sage: eqn = x^3 + 2/3 >= x - pi
25
+ sage: eqn.operator()
26
+ <built-in function ge>
27
+ sage: (x^3 + 2/3 < x - pi).operator()
28
+ <built-in function lt>
29
+ sage: (x^3 + 2/3 == x - pi).operator()
30
+ <built-in function eq>
31
+
32
+ Left hand side::
33
+
34
+ sage: eqn = x^3 + 2/3 >= x - pi
35
+ sage: eqn.lhs()
36
+ x^3 + 2/3
37
+ sage: eqn.left()
38
+ x^3 + 2/3
39
+ sage: eqn.left_hand_side()
40
+ x^3 + 2/3
41
+
42
+ Right hand side::
43
+
44
+ sage: (x + sqrt(2) >= sqrt(3) + 5/2).right()
45
+ sqrt(3) + 5/2
46
+ sage: (x + sqrt(2) >= sqrt(3) + 5/2).rhs()
47
+ sqrt(3) + 5/2
48
+ sage: (x + sqrt(2) >= sqrt(3) + 5/2).right_hand_side()
49
+ sqrt(3) + 5/2
50
+
51
+
52
+ Arithmetic
53
+ ----------
54
+ Add two symbolic equations::
55
+
56
+ sage: var('a,b')
57
+ (a, b)
58
+ sage: m = 144 == -10 * a + b
59
+ sage: n = 136 == 10 * a + b
60
+ sage: m + n
61
+ 280 == 2*b
62
+ sage: int(-144) + m
63
+ 0 == -10*a + b - 144
64
+
65
+ Subtract two symbolic equations::
66
+
67
+ sage: var('a,b')
68
+ (a, b)
69
+ sage: m = 144 == 20 * a + b
70
+ sage: n = 136 == 10 * a + b
71
+ sage: m - n
72
+ 8 == 10*a
73
+ sage: int(144) - m
74
+ 0 == -20*a - b + 144
75
+
76
+ Multiply two symbolic equations::
77
+
78
+ sage: x = var('x')
79
+ sage: m = x == 5*x + 1
80
+ sage: n = sin(x) == sin(x+2*pi, hold=True)
81
+ sage: m * n
82
+ x*sin(x) == (5*x + 1)*sin(2*pi + x)
83
+ sage: m = 2*x == 3*x^2 - 5
84
+ sage: int(-1) * m
85
+ -2*x == -3*x^2 + 5
86
+
87
+ Divide two symbolic equations::
88
+
89
+ sage: x = var('x')
90
+ sage: m = x == 5*x + 1
91
+ sage: n = sin(x) == sin(x+2*pi, hold=True)
92
+ sage: m/n
93
+ x/sin(x) == (5*x + 1)/sin(2*pi + x)
94
+ sage: m = x != 5*x + 1
95
+ sage: n = sin(x) != sin(x+2*pi, hold=True)
96
+ sage: m/n
97
+ x/sin(x) != (5*x + 1)/sin(2*pi + x)
98
+
99
+ Substitution
100
+ ------------
101
+
102
+ Substitution into relations::
103
+
104
+ sage: x, a = var('x, a')
105
+ sage: eq = (x^3 + a == sin(x/a)); eq
106
+ x^3 + a == sin(x/a)
107
+ sage: eq.substitute(x=5*x)
108
+ 125*x^3 + a == sin(5*x/a)
109
+ sage: eq.substitute(a=1)
110
+ x^3 + 1 == sin(x)
111
+ sage: eq.substitute(a=x)
112
+ x^3 + x == sin(1)
113
+ sage: eq.substitute(a=x, x=1)
114
+ x + 1 == sin(1/x)
115
+ sage: eq.substitute({a:x, x:1})
116
+ x + 1 == sin(1/x)
117
+
118
+ You can even substitute multivariable and matrix
119
+ expressions::
120
+
121
+ sage: x,y = var('x, y')
122
+ sage: M = Matrix([[x+1,y],[x^2,y^3]]); M
123
+ [x + 1 y]
124
+ [ x^2 y^3]
125
+ sage: M.substitute({x:0,y:1})
126
+ [1 1]
127
+ [0 1]
128
+
129
+ Solving
130
+ -------
131
+
132
+ We can solve equations::
133
+
134
+ sage: x = var('x')
135
+ sage: S = solve(x^3 - 1 == 0, x)
136
+ sage: S
137
+ [x == 1/2*I*sqrt(3) - 1/2, x == -1/2*I*sqrt(3) - 1/2, x == 1]
138
+ sage: S[0]
139
+ x == 1/2*I*sqrt(3) - 1/2
140
+ sage: S[0].right()
141
+ 1/2*I*sqrt(3) - 1/2
142
+ sage: S = solve(x^3 - 1 == 0, x, solution_dict=True)
143
+ sage: S
144
+ [{x: 1/2*I*sqrt(3) - 1/2}, {x: -1/2*I*sqrt(3) - 1/2}, {x: 1}]
145
+ sage: z = 5
146
+ sage: solve(z^2 == sqrt(3),z)
147
+ Traceback (most recent call last):
148
+ ...
149
+ TypeError: 5 is not a valid variable
150
+
151
+ We can also solve equations involving matrices. The following
152
+ example defines a multivariable function ``f(x,y)``, then solves
153
+ for where the partial derivatives with respect to ``x``
154
+ and ``y`` are zero. Then it substitutes one of the solutions
155
+ into the Hessian matrix ``H`` for ``f``::
156
+
157
+ sage: f(x,y) = x^2*y+y^2+y
158
+ sage: solutions = solve(list(f.diff()),[x,y],solution_dict=True)
159
+ sage: solutions == [{x: -I, y: 0}, {x: I, y: 0}, {x: 0, y: -1/2}]
160
+ True
161
+ sage: H = f.diff(2) # Hessian matrix
162
+ sage: H.subs(solutions[2])
163
+ [(x, y) |--> -1 (x, y) |--> 0]
164
+ [ (x, y) |--> 0 (x, y) |--> 2]
165
+ sage: H(x,y).subs(solutions[2])
166
+ [-1 0]
167
+ [ 0 2]
168
+
169
+ We illustrate finding multiplicities of solutions::
170
+
171
+ sage: f = (x-1)^5*(x^2+1)
172
+ sage: solve(f == 0, x)
173
+ [x == -I, x == I, x == 1]
174
+ sage: solve(f == 0, x, multiplicities=True)
175
+ ([x == -I, x == I, x == 1], [1, 1, 5])
176
+
177
+ We can also solve many inequalities::
178
+
179
+ sage: solve(1/(x-1)<=8,x)
180
+ [[x < 1], [x >= (9/8)]]
181
+
182
+ We can numerically find roots of equations::
183
+
184
+ sage: (x == sin(x)).find_root(-2,2) # needs scipy
185
+ 0.0
186
+ sage: (x^5 + 3*x + 2 == 0).find_root(-2,2,x) # needs scipy
187
+ -0.6328345202421523
188
+ sage: (cos(x) == sin(x)).find_root(10,20) # needs scipy
189
+ 19.634954084936208
190
+
191
+ We illustrate some valid error conditions::
192
+
193
+ sage: (cos(x) != sin(x)).find_root(10,20) # needs scipy
194
+ Traceback (most recent call last):
195
+ ...
196
+ ValueError: Symbolic equation must be an equality.
197
+ sage: (SR(3)==SR(2)).find_root(-1,1) # needs scipy
198
+ Traceback (most recent call last):
199
+ ...
200
+ RuntimeError: no zero in the interval, since constant expression is not 0.
201
+
202
+ There must be at most one variable::
203
+
204
+ sage: x, y = var('x,y')
205
+ sage: (x == y).find_root(-2,2) # needs scipy
206
+ Traceback (most recent call last):
207
+ ...
208
+ NotImplementedError: root finding currently only implemented in 1 dimension.
209
+
210
+ Assumptions
211
+ -----------
212
+
213
+ Forgetting assumptions::
214
+
215
+ sage: var('x,y')
216
+ (x, y)
217
+ sage: forget() #Clear assumptions
218
+ sage: assume(x>0, y < 2)
219
+ sage: assumptions()
220
+ [x > 0, y < 2]
221
+ sage: (y < 2).forget()
222
+ sage: assumptions()
223
+ [x > 0]
224
+ sage: forget()
225
+ sage: assumptions()
226
+ []
227
+
228
+
229
+ Miscellaneous
230
+ -------------
231
+
232
+ Conversion to Maxima::
233
+
234
+ sage: from sage.interfaces.maxima_lib import maxima
235
+ sage: x = var('x')
236
+ sage: eq = (x^(3/5) >= pi^2 + e^i)
237
+ sage: eq._maxima_init_()
238
+ '(_SAGE_VAR_x)^(3/5) >= ((%pi)^(2))+(exp(0+%i*1))'
239
+ sage: e1 = x^3 + x == sin(2*x)
240
+ sage: z = e1._maxima_()
241
+ sage: z.parent() is sage.calculus.calculus.maxima
242
+ True
243
+ sage: z = e1._maxima_(maxima)
244
+ sage: z.parent() is sage.interfaces.maxima_lib.maxima
245
+ True
246
+ sage: z = maxima(e1)
247
+ sage: z.parent() is sage.interfaces.maxima_lib.maxima
248
+ True
249
+
250
+ Conversion to Maple::
251
+
252
+ sage: x = var('x')
253
+ sage: eq = (x == 2)
254
+ sage: eq._maple_init_()
255
+ 'x = 2'
256
+
257
+ Comparison::
258
+
259
+ sage: x = var('x')
260
+ sage: (x>0) == (x>0)
261
+ True
262
+ sage: (x>0) == (x>1)
263
+ False
264
+ sage: (x>0) != (x>1)
265
+ True
266
+
267
+ Variables appearing in the relation::
268
+
269
+ sage: var('x,y,z,w')
270
+ (x, y, z, w)
271
+ sage: f = (x+y+w) == (x^2 - y^2 - z^3); f
272
+ w + x + y == -z^3 + x^2 - y^2
273
+ sage: f.variables()
274
+ (w, x, y, z)
275
+
276
+ LaTeX output::
277
+
278
+ sage: latex(x^(3/5) >= pi)
279
+ x^{\frac{3}{5}} \geq \pi
280
+
281
+ When working with the symbolic complex number `I`, notice that comparisons do not
282
+ automatically simplify even in trivial situations::
283
+
284
+ sage: SR(I)^2 == -1
285
+ -1 == -1
286
+ sage: SR(I)^2 < 0
287
+ -1 < 0
288
+ sage: (SR(I)+1)^4 > 0
289
+ -4 > 0
290
+
291
+ Nevertheless, if you force the comparison, you get the right answer (:issue:`7160`)::
292
+
293
+ sage: bool(SR(I)^2 == -1)
294
+ True
295
+ sage: bool(SR(I)^2 < 0)
296
+ True
297
+ sage: bool((SR(I)+1)^4 > 0)
298
+ False
299
+
300
+ More Examples
301
+ -------------
302
+
303
+ ::
304
+
305
+ sage: x,y,a = var('x,y,a')
306
+ sage: f = x^2 + y^2 == 1
307
+ sage: f.solve(x)
308
+ [x == -sqrt(-y^2 + 1), x == sqrt(-y^2 + 1)]
309
+
310
+ ::
311
+
312
+ sage: f = x^5 + a
313
+ sage: solve(f==0,x)
314
+ [x == 1/4*(-a)^(1/5)*(sqrt(5) + I*sqrt(2*sqrt(5) + 10) - 1), x == -1/4*(-a)^(1/5)*(sqrt(5) - I*sqrt(-2*sqrt(5) + 10) + 1), x == -1/4*(-a)^(1/5)*(sqrt(5) + I*sqrt(-2*sqrt(5) + 10) + 1), x == 1/4*(-a)^(1/5)*(sqrt(5) - I*sqrt(2*sqrt(5) + 10) - 1), x == (-a)^(1/5)]
315
+
316
+ You can also do arithmetic with inequalities, as illustrated
317
+ below::
318
+
319
+ sage: var('x y')
320
+ (x, y)
321
+ sage: f = x + 3 == y - 2
322
+ sage: f
323
+ x + 3 == y - 2
324
+ sage: g = f - 3; g
325
+ x == y - 5
326
+ sage: h = x^3 + sqrt(2) == x*y*sin(x)
327
+ sage: h
328
+ x^3 + sqrt(2) == x*y*sin(x)
329
+ sage: h - sqrt(2)
330
+ x^3 == x*y*sin(x) - sqrt(2)
331
+ sage: h + f
332
+ x^3 + x + sqrt(2) + 3 == x*y*sin(x) + y - 2
333
+ sage: f = x + 3 < y - 2
334
+ sage: g = 2 < x+10
335
+ sage: f - g
336
+ x + 1 < -x + y - 12
337
+ sage: f + g
338
+ x + 5 < x + y + 8
339
+ sage: f*(-1)
340
+ -x - 3 < -y + 2
341
+
342
+ TESTS:
343
+
344
+ We test serializing symbolic equations::
345
+
346
+ sage: eqn = x^3 + 2/3 >= x
347
+ sage: loads(dumps(eqn))
348
+ x^3 + 2/3 >= x
349
+ sage: loads(dumps(eqn)) == eqn
350
+ True
351
+
352
+ AUTHORS:
353
+
354
+ - Bobby Moretti: initial version (based on a trick that Robert
355
+ Bradshaw suggested).
356
+
357
+ - William Stein: second version
358
+
359
+ - William Stein (2007-07-16): added arithmetic with symbolic equations
360
+ """
361
+ import operator
362
+ from itertools import product
363
+
364
+
365
+ def check_relation_maxima(relation):
366
+ """
367
+ Return ``True`` if this (in)equality is definitely true. Return ``False``
368
+ if it is false or the algorithm for testing (in)equality is inconclusive.
369
+
370
+ EXAMPLES::
371
+
372
+ sage: from sage.symbolic.relation import check_relation_maxima
373
+ sage: k = var('k')
374
+ sage: pol = 1/(k-1) - 1/k -1/k/(k-1)
375
+ sage: check_relation_maxima(pol == 0)
376
+ True
377
+ sage: f = sin(x)^2 + cos(x)^2 - 1
378
+ sage: check_relation_maxima(f == 0)
379
+ True
380
+ sage: check_relation_maxima( x == x )
381
+ True
382
+ sage: check_relation_maxima( x != x )
383
+ False
384
+ sage: check_relation_maxima( x > x )
385
+ False
386
+ sage: check_relation_maxima( x^2 > x )
387
+ False
388
+ sage: check_relation_maxima( x + 2 > x )
389
+ True
390
+ sage: check_relation_maxima( x - 2 > x )
391
+ False
392
+
393
+ Here are some examples involving assumptions::
394
+
395
+ sage: x, y, z = var('x, y, z')
396
+ sage: assume(x>=y,y>=z,z>=x)
397
+ sage: check_relation_maxima(x==z)
398
+ True
399
+ sage: check_relation_maxima(z<x)
400
+ False
401
+ sage: check_relation_maxima(z>y)
402
+ False
403
+ sage: check_relation_maxima(y==z)
404
+ True
405
+ sage: forget()
406
+ sage: assume(x>=1,x<=1)
407
+ sage: check_relation_maxima(x==1)
408
+ True
409
+ sage: check_relation_maxima(x>1)
410
+ False
411
+ sage: check_relation_maxima(x>=1)
412
+ True
413
+ sage: check_relation_maxima(x!=1)
414
+ False
415
+ sage: forget()
416
+ sage: assume(x>0)
417
+ sage: check_relation_maxima(x==0)
418
+ False
419
+ sage: check_relation_maxima(x>-1)
420
+ True
421
+ sage: check_relation_maxima(x!=0)
422
+ True
423
+ sage: check_relation_maxima(x!=1)
424
+ False
425
+ sage: forget()
426
+
427
+ Here is an example that illustrates that ``False`` may mean inconclusive::
428
+
429
+ sage: x = SR.var('x')
430
+ sage: assume(x, 'integer')
431
+ sage: check_relation_maxima( x == 1 )
432
+ False
433
+ sage: check_relation_maxima( x != 1 )
434
+ False
435
+ sage: assume( x > 2 )
436
+ sage: check_relation_maxima( x != 1 )
437
+ True
438
+ sage: forget()
439
+
440
+ TESTS:
441
+
442
+ Ensure that ``canonicalize_radical()`` and ``simplify_log`` are not
443
+ used inappropriately, :issue:`17389`. Either one would simplify ``f``
444
+ to zero below::
445
+
446
+ sage: x,y = SR.var('x,y')
447
+ sage: assume(y, 'complex')
448
+ sage: f = log(x*y) - (log(x) + log(y))
449
+ sage: f(x=-1, y=i)
450
+ -2*I*pi
451
+ sage: check_relation_maxima(f == 0)
452
+ False
453
+ sage: forget()
454
+
455
+ Ensure that the ``sqrt(x^2)`` -> ``abs(x)`` simplification is not
456
+ performed when testing equality::
457
+
458
+ sage: assume(x, 'complex')
459
+ sage: f = sqrt(x^2) - abs(x)
460
+ sage: check_relation_maxima(f == 0)
461
+ False
462
+ sage: forget()
463
+
464
+ If assumptions are made, ``simplify_rectform()`` is used::
465
+
466
+ sage: assume(x, 'real')
467
+ sage: f1 = ( e^(I*x) - e^(-I*x) ) / ( I*e^(I*x) + I*e^(-I*x) )
468
+ sage: f2 = sin(x)/cos(x)
469
+ sage: check_relation_maxima(f1 - f2 == 0)
470
+ True
471
+ sage: forget()
472
+
473
+ But not if ``x`` itself is complex::
474
+
475
+ sage: assume(x, 'complex')
476
+ sage: f1 = ( e^(I*x) - e^(-I*x) ) / ( I*e^(I*x) + I*e^(-I*x) )
477
+ sage: f2 = sin(x)/cos(x)
478
+ sage: check_relation_maxima(f1 - f2 == 0)
479
+ False
480
+ sage: forget()
481
+
482
+ If assumptions are made, then ``simplify_factorial()`` is used::
483
+
484
+ sage: n,k = SR.var('n,k')
485
+ sage: assume(n, 'integer')
486
+ sage: assume(k, 'integer')
487
+ sage: f1 = factorial(n+1)/factorial(n)
488
+ sage: f2 = n + 1
489
+ sage: check_relation_maxima(f1 - f2 == 0)
490
+ True
491
+ sage: forget()
492
+
493
+ In case an equation is to be solved for non-integers, ''assume()''
494
+ is used::
495
+
496
+ sage: k = var('k')
497
+ sage: assume(k,'noninteger')
498
+ sage: solve([k^3==1],k)
499
+ [k == 1/2*I*sqrt(3) - 1/2, k == -1/2*I*sqrt(3) - 1/2]
500
+ sage: assumptions()
501
+ [k is noninteger]
502
+
503
+ Check that boolean values are handled correctly::
504
+
505
+ sage: check_relation_maxima(2 == 2)
506
+ True
507
+ sage: check_relation_maxima(2 == 3)
508
+ False
509
+ """
510
+ # Handle boolean values directly (e.g., when comparing Python integers)
511
+ if isinstance(relation, bool):
512
+ return relation
513
+
514
+ from sage.interfaces.maxima_lib import test_max_equal, test_max_notequal, test_max_relation
515
+
516
+ if relation.operator() == operator.eq: # operator is equality
517
+ try:
518
+ s = test_max_equal(relation.lhs(),relation.rhs())
519
+ except TypeError:
520
+ raise ValueError("unable to evaluate the predicate '%s'" % repr(relation))
521
+
522
+ elif relation.operator() == operator.ne: # operator is not equal
523
+ try:
524
+ s = test_max_notequal(relation.lhs(),relation.rhs())
525
+ except TypeError:
526
+ raise ValueError("unable to evaluate the predicate '%s'" % repr(relation))
527
+
528
+ else: # operator is < or > or <= or >=, which Maxima handles fine
529
+ try:
530
+ # For inequalities, use the full relation string
531
+ s = test_max_relation(relation)
532
+ except TypeError:
533
+ raise ValueError("unable to evaluate the predicate '%s'" % repr(relation))
534
+
535
+ if s is True:
536
+ return True
537
+ elif s is False:
538
+ return False # if neither of these, s=='unknown' and we try a few other tricks
539
+
540
+ if relation.operator() != operator.eq:
541
+ return False
542
+
543
+ difference = relation.lhs() - relation.rhs()
544
+ if difference.is_trivial_zero():
545
+ return True
546
+
547
+ # Try simplify_full() to see if left - right == 0.
548
+ # Note: simplify_full() does not include simplify_log(), which is
549
+ # unsafe for complex variables, so this is safe to call here.
550
+ try:
551
+ if difference.simplify_full().is_trivial_zero():
552
+ return True
553
+ except Exception:
554
+ pass
555
+ return False
556
+
557
+
558
+ def check_relation_maxima_neq_as_not_eq(relation):
559
+ """
560
+ A variant of :func:`check_relation_maxima` that treats `x != y`
561
+ as `not (x == y)` for consistency with Python's boolean semantics.
562
+
563
+ For inequality relations (!=), this function checks the corresponding
564
+ equality and returns its logical negation, ensuring that
565
+ ``bool(x != y) == not bool(x == y)``.
566
+
567
+ EXAMPLES::
568
+
569
+ sage: from sage.symbolic.relation import check_relation_maxima_neq_as_not_eq
570
+ sage: x = var('x')
571
+ sage: check_relation_maxima_neq_as_not_eq(x != x)
572
+ False
573
+ sage: check_relation_maxima_neq_as_not_eq(x == x)
574
+ True
575
+ sage: check_relation_maxima_neq_as_not_eq(x != 1)
576
+ True
577
+ sage: check_relation_maxima_neq_as_not_eq(x == 1)
578
+ False
579
+ """
580
+ # For inequality (!=), check equality and return the opposite.
581
+ # This ensures bool(x != y) == not bool(x == y) for semantic consistency.
582
+ if relation.operator() == operator.ne:
583
+ from sage.interfaces.maxima_lib import test_max_equal
584
+ return test_max_equal(relation.lhs(), relation.rhs()) is not True
585
+
586
+ # For all other relations, delegate to check_relation_maxima
587
+ return check_relation_maxima(relation)
588
+
589
+
590
+ def string_to_list_of_solutions(s):
591
+ r"""
592
+ Used internally by the symbolic solve command to convert the output
593
+ of Maxima's solve command to a list of solutions in Sage's symbolic
594
+ package.
595
+
596
+ EXAMPLES:
597
+
598
+ We derive the (monic) quadratic formula::
599
+
600
+ sage: var('x,a,b')
601
+ (x, a, b)
602
+ sage: solve(x^2 + a*x + b == 0, x)
603
+ [x == -1/2*a - 1/2*sqrt(a^2 - 4*b), x == -1/2*a + 1/2*sqrt(a^2 - 4*b)]
604
+
605
+ Behind the scenes when the above is evaluated the function
606
+ :func:`string_to_list_of_solutions` is called with input the
607
+ string `s` below::
608
+
609
+ sage: s = '[x=-(sqrt(a^2-4*b)+a)/2,x=(sqrt(a^2-4*b)-a)/2]'
610
+ sage: sage.symbolic.relation.string_to_list_of_solutions(s)
611
+ [x == -1/2*a - 1/2*sqrt(a^2 - 4*b), x == -1/2*a + 1/2*sqrt(a^2 - 4*b)]
612
+ """
613
+ from sage.calculus.calculus import symbolic_expression_from_maxima_string
614
+ from sage.categories.objects import Objects
615
+ from sage.structure.sequence import Sequence
616
+ v = symbolic_expression_from_maxima_string(s, equals_sub=True)
617
+ return Sequence(v, universe=Objects(), cr_str=True)
618
+
619
+
620
+ def _normalize_to_relational(f):
621
+ """
622
+ Normalize the input to a relational expression or a list of relational expressions.
623
+
624
+ TESTS::
625
+
626
+ sage: from sage.symbolic.relation import _normalize_to_relational
627
+ sage: x, y = var('x, y')
628
+ sage: _normalize_to_relational(x == 1)
629
+ x == 1
630
+ sage: _normalize_to_relational([x == 1, y == 2])
631
+ [x == 1, y == 2]
632
+ sage: _normalize_to_relational(x - 1)
633
+ x - 1 == 0
634
+ sage: _normalize_to_relational([x - 1, y - 2])
635
+ [x - 1 == 0, y - 2 == 0]
636
+ sage: _normalize_to_relational((x - 1, y - 2))
637
+ [x - 1 == 0, y - 2 == 0]
638
+ sage: _normalize_to_relational(1)
639
+ False
640
+ """
641
+ if isinstance(f, (list, tuple)):
642
+ return [_normalize_to_relational(g) for g in f]
643
+ from sage.symbolic.expression import Expression
644
+ if isinstance(f, bool) or (isinstance(f, Expression) and f.is_relational()):
645
+ return f
646
+ return f == 0
647
+
648
+
649
+ def _normalize_to_nonrelational(f):
650
+ """
651
+ Normalize the input to a non-relational expression or a list of non-relational expressions.
652
+
653
+ TESTS::
654
+
655
+ sage: from sage.symbolic.relation import _normalize_to_nonrelational
656
+ sage: x, y = var('x, y')
657
+ sage: _normalize_to_nonrelational(x == 1)
658
+ x - 1
659
+ sage: _normalize_to_nonrelational([x == 1, y == 2])
660
+ [x - 1, y - 2]
661
+ sage: _normalize_to_nonrelational(x - 1)
662
+ x - 1
663
+ sage: _normalize_to_nonrelational([x - 1, y - 2])
664
+ [x - 1, y - 2]
665
+ sage: _normalize_to_nonrelational((x - 1, y - 2))
666
+ [x - 1, y - 2]
667
+ sage: _normalize_to_nonrelational(1)
668
+ 1
669
+ sage: _normalize_to_nonrelational(True)
670
+ 0
671
+ sage: _normalize_to_nonrelational(False)
672
+ 1
673
+ """
674
+ if isinstance(f, (list, tuple)):
675
+ return [_normalize_to_nonrelational(g) for g in f]
676
+ if isinstance(f, bool):
677
+ return 0 if f else 1
678
+ from sage.symbolic.expression import Expression
679
+ if isinstance(f, Expression) and f.is_relational():
680
+ assert f.operator() == operator.eq
681
+ return f.lhs() - f.rhs()
682
+ return f
683
+
684
+
685
+ def _normalize_to_list_expressions(f) -> list:
686
+ """
687
+ Normalize either a single equation or a list of equations into a list of
688
+ equations.
689
+
690
+ TESTS::
691
+
692
+ sage: from sage.symbolic.relation import _normalize_to_list_expressions
693
+ sage: x, y = var('x, y')
694
+ sage: _normalize_to_list_expressions(x == 1)
695
+ [x == 1]
696
+ sage: _normalize_to_list_expressions([x == 1, y == 2])
697
+ [x == 1, y == 2]
698
+ sage: _normalize_to_list_expressions({})
699
+ Traceback (most recent call last):
700
+ ...
701
+ TypeError: must be a symbolic expression or a list of symbolic expressions
702
+ """
703
+ from sage.symbolic.expression import Expression
704
+ if isinstance(f, (Expression, bool)):
705
+ f = [f]
706
+ if not isinstance(f, (list, tuple)) or not all(isinstance(s, (Expression, bool)) for s in f):
707
+ raise TypeError("must be a symbolic expression or a list of symbolic expressions")
708
+ return f
709
+
710
+
711
+ ###########
712
+ # Solving #
713
+ ###########
714
+
715
+
716
+ def solve(f, *args, explicit_solutions=None, multiplicities=None, to_poly_solve=None,
717
+ solution_dict=False, algorithm=None, domain=None):
718
+ r"""
719
+ Algebraically solve an equation or system of equations (over the
720
+ complex numbers) for given variables. Inequalities and systems
721
+ of inequalities are also supported.
722
+
723
+ INPUT:
724
+
725
+ - ``f`` -- equation or system of equations (given by a list or tuple)
726
+
727
+ - ``*args`` -- variables to solve for
728
+
729
+ - ``solution_dict`` -- boolean (default: ``False``); if ``True`` or nonzero,
730
+ return a list of dictionaries containing the solutions. If there
731
+ are no solutions, return an empty list (rather than a list containing
732
+ an empty dictionary). Likewise, if there's only a single solution,
733
+ return a list containing one dictionary with that solution.
734
+
735
+ There are a few optional keywords if you are trying to solve a single
736
+ equation. They may only be used in that context.
737
+
738
+ - ``multiplicities`` -- boolean (default: ``False``); if True,
739
+ return corresponding multiplicities. This keyword is
740
+ incompatible with ``to_poly_solve=True`` and does not make
741
+ any sense when solving inequalities.
742
+
743
+ - ``explicit_solutions`` -- boolean (default: ``False``); require that
744
+ all roots be explicit rather than implicit. Not used
745
+ when solving inequalities.
746
+
747
+ - ``to_poly_solve`` -- boolean (default: ``False``) or string; use
748
+ Maxima's ``to_poly_solver`` package to search for more possible
749
+ solutions, but possibly encounter approximate solutions.
750
+ This keyword is incompatible with ``multiplicities=True``
751
+ and is not used when solving inequalities. Setting ``to_poly_solve``
752
+ to 'force' (string) omits Maxima's solve command (useful when
753
+ some solutions of trigonometric equations are lost).
754
+
755
+ - ``algorithm`` -- string (default: ``'maxima'``); to use SymPy's
756
+ solvers set this to 'sympy'. Note that SymPy is always used
757
+ for diophantine equations. Another choice, if it is installed,
758
+ is 'giac'.
759
+
760
+ - ``domain`` -- string (default: ``'complex'``); setting this to 'real'
761
+ changes the way SymPy solves single equations; inequalities
762
+ are always solved in the real domain.
763
+
764
+ EXAMPLES::
765
+
766
+ sage: x, y = var('x, y')
767
+ sage: solve([x+y==6, x-y==4], x, y)
768
+ [[x == 5, y == 1]]
769
+ sage: solve([x^2+y^2 == 1, y^2 == x^3 + x + 1], x, y)
770
+ [[x == -1/2*I*sqrt(3) - 1/2, y == -sqrt(-1/2*I*sqrt(3) + 3/2)],
771
+ [x == -1/2*I*sqrt(3) - 1/2, y == sqrt(-1/2*I*sqrt(3) + 3/2)],
772
+ [x == 1/2*I*sqrt(3) - 1/2, y == -sqrt(1/2*I*sqrt(3) + 3/2)],
773
+ [x == 1/2*I*sqrt(3) - 1/2, y == sqrt(1/2*I*sqrt(3) + 3/2)],
774
+ [x == 0, y == -1],
775
+ [x == 0, y == 1]]
776
+ sage: solve([sqrt(x) + sqrt(y) == 5, x + y == 10], x, y)
777
+ [[x == -5/2*I*sqrt(5) + 5, y == 5/2*I*sqrt(5) + 5], [x == 5/2*I*sqrt(5) + 5, y == -5/2*I*sqrt(5) + 5]]
778
+ sage: solutions = solve([x^2+y^2 == 1, y^2 == x^3 + x + 1], x, y, solution_dict=True)
779
+ sage: for solution in solutions: print("{} , {}".format(solution[x].n(digits=3), solution[y].n(digits=3)))
780
+ -0.500 - 0.866*I , -1.27 + 0.341*I
781
+ -0.500 - 0.866*I , 1.27 - 0.341*I
782
+ -0.500 + 0.866*I , -1.27 - 0.341*I
783
+ -0.500 + 0.866*I , 1.27 + 0.341*I
784
+ 0.000 , -1.00
785
+ 0.000 , 1.00
786
+
787
+ Whenever possible, answers will be symbolic, but with systems of
788
+ equations, at times approximations will be given by Maxima, due to the
789
+ underlying algorithm::
790
+
791
+ sage: sols = solve([x^3==y,y^2==x], [x,y]); sols[-1], sols[0] # abs tol 1e-15
792
+ ([x == 0, y == 0],
793
+ [x == (0.3090169943749475 + 0.9510565162951535*I),
794
+ y == (-0.8090169943749475 - 0.5877852522924731*I)])
795
+ sage: sols[0][0].rhs().pyobject().parent()
796
+ Complex Double Field
797
+
798
+ sage: solve([y^6==y],y)
799
+ [y == 1/4*sqrt(5) + 1/4*I*sqrt(2*sqrt(5) + 10) - 1/4,
800
+ y == -1/4*sqrt(5) + 1/4*I*sqrt(-2*sqrt(5) + 10) - 1/4,
801
+ y == -1/4*sqrt(5) - 1/4*I*sqrt(-2*sqrt(5) + 10) - 1/4,
802
+ y == 1/4*sqrt(5) - 1/4*I*sqrt(2*sqrt(5) + 10) - 1/4,
803
+ y == 1,
804
+ y == 0]
805
+ sage: solve( [y^6 == y], y)==solve( y^6 == y, y)
806
+ True
807
+
808
+ Here we demonstrate very basic use of the optional keywords::
809
+
810
+ sage: ((x^2-1)^2).solve(x)
811
+ [x == -1, x == 1]
812
+ sage: ((x^2-1)^2).solve(x,multiplicities=True)
813
+ ([x == -1, x == 1], [2, 2])
814
+ sage: solve(sin(x)==x,x)
815
+ [x == sin(x)]
816
+ sage: solve(sin(x)==x,x,explicit_solutions=True)
817
+ []
818
+ sage: solve(abs(1-abs(1-x)) == 10, x)
819
+ [abs(abs(x - 1) - 1) == 10]
820
+ sage: solve(abs(1-abs(1-x)) == 10, x, to_poly_solve=True)
821
+ [x == -10, x == 12]
822
+
823
+ sage: from sage.symbolic.expression import Expression
824
+ sage: Expression.solve(x^2==1,x)
825
+ [x == -1, x == 1]
826
+
827
+ We must solve with respect to actual variables::
828
+
829
+ sage: z = 5
830
+ sage: solve([8*z + y == 3, -z +7*y == 0],y,z)
831
+ Traceback (most recent call last):
832
+ ...
833
+ TypeError: 5 is not a valid variable
834
+
835
+ If we ask for dictionaries containing the solutions, we get them::
836
+
837
+ sage: solve([x^2-1],x,solution_dict=True)
838
+ [{x: -1}, {x: 1}]
839
+ sage: solve([x^2-4*x+4],x,solution_dict=True)
840
+ [{x: 2}]
841
+ sage: res = solve([x^2 == y, y == 4],x,y,solution_dict=True)
842
+ sage: for soln in res: print("x: %s, y: %s" % (soln[x], soln[y]))
843
+ x: 2, y: 4
844
+ x: -2, y: 4
845
+
846
+ If there is a parameter in the answer, that will show up as
847
+ a new variable. In the following example, ``r1`` is an arbitrary
848
+ constant (because of the ``r``)::
849
+
850
+ sage: forget()
851
+ sage: x, y = var('x,y')
852
+ sage: solve([x+y == 3, 2*x+2*y == 6],x,y)
853
+ [[x == -r1 + 3, y == r1]]
854
+
855
+ sage: var('b, c')
856
+ (b, c)
857
+ sage: solve((b-1)*(c-1), [b,c])
858
+ [[b == 1, c == r...], [b == r..., c == 1]]
859
+
860
+ Especially with trigonometric functions, the dummy variable may
861
+ be implicitly an integer (hence the ``z``)::
862
+
863
+ sage: solve( sin(x)==cos(x), x, to_poly_solve=True)
864
+ [x == 1/4*pi + pi*z...]
865
+ sage: solve([cos(x)*sin(x) == 1/2, x+y == 0],x,y)
866
+ [[x == 1/4*pi + pi*z..., y == -1/4*pi - pi*z...]]
867
+
868
+ Expressions which are not equations are assumed to be set equal
869
+ to zero, as with `x` in the following example::
870
+
871
+ sage: solve([x, y == 2],x,y)
872
+ [[x == 0, y == 2]]
873
+
874
+ If ``True`` appears in the list of equations it is
875
+ ignored, and if ``False`` appears in the list then no
876
+ solutions are returned. E.g., note that the first
877
+ ``3==3`` evaluates to ``True``, not to a
878
+ symbolic equation.
879
+
880
+ ::
881
+
882
+ sage: solve([3==3, 1.00000000000000*x^3 == 0], x)
883
+ [x == 0]
884
+ sage: solve([1.00000000000000*x^3 == 0], x)
885
+ [x == 0]
886
+
887
+ Here, the first equation evaluates to ``False``, so
888
+ there are no solutions::
889
+
890
+ sage: solve([1==3, 1.00000000000000*x^3 == 0], x)
891
+ []
892
+
893
+ Completely symbolic solutions are supported::
894
+
895
+ sage: var('s,j,b,m,g')
896
+ (s, j, b, m, g)
897
+ sage: sys = [ m*(1-s) - b*s*j, b*s*j-g*j ]
898
+ sage: solve(sys,s,j)
899
+ [[s == 1, j == 0], [s == g/b, j == (b - g)*m/(b*g)]]
900
+ sage: solve(sys,(s,j))
901
+ [[s == 1, j == 0], [s == g/b, j == (b - g)*m/(b*g)]]
902
+ sage: solve(sys,[s,j])
903
+ [[s == 1, j == 0], [s == g/b, j == (b - g)*m/(b*g)]]
904
+
905
+ sage: z = var('z')
906
+ sage: solve((x-z)^2==2, x)
907
+ [x == z - sqrt(2), x == z + sqrt(2)]
908
+
909
+ Inequalities can be also solved::
910
+
911
+ sage: solve(x^2>8,x)
912
+ [[x < -2*sqrt(2)], [x > 2*sqrt(2)]]
913
+ sage: x,y = var('x,y'); (ln(x)-ln(y)>0).solve(x)
914
+ [[log(x) - log(y) > 0]]
915
+ sage: x,y = var('x,y'); (ln(x)>ln(y)).solve(x) # random
916
+ [[0 < y, y < x, 0 < x]]
917
+ [[y < x, 0 < y]]
918
+
919
+ A simple example to show the use of the keyword
920
+ ``multiplicities``::
921
+
922
+ sage: ((x^2-1)^2).solve(x)
923
+ [x == -1, x == 1]
924
+ sage: ((x^2-1)^2).solve(x,multiplicities=True)
925
+ ([x == -1, x == 1], [2, 2])
926
+ sage: ((x^2-1)^2).solve(x,multiplicities=True,to_poly_solve=True)
927
+ Traceback (most recent call last):
928
+ ...
929
+ NotImplementedError: to_poly_solve does not return multiplicities
930
+
931
+ Here is how the ``explicit_solutions`` keyword functions::
932
+
933
+ sage: solve(sin(x)==x,x)
934
+ [x == sin(x)]
935
+ sage: solve(sin(x)==x,x,explicit_solutions=True)
936
+ []
937
+ sage: solve(x*sin(x)==x^2,x)
938
+ [x == 0, x == sin(x)]
939
+ sage: solve(x*sin(x)==x^2,x,explicit_solutions=True)
940
+ [x == 0]
941
+
942
+ The following examples show the use of the keyword ``to_poly_solve``::
943
+
944
+ sage: solve(abs(1-abs(1-x)) == 10, x)
945
+ [abs(abs(x - 1) - 1) == 10]
946
+ sage: solve(abs(1-abs(1-x)) == 10, x, to_poly_solve=True)
947
+ [x == -10, x == 12]
948
+
949
+ sage: var('Q')
950
+ Q
951
+ sage: solve(Q*sqrt(Q^2 + 2) - 1, Q)
952
+ [Q == 1/sqrt(Q^2 + 2)]
953
+
954
+ The following example is a regression in Maxima 5.39.0.
955
+ It used to be possible to get one more solution here,
956
+ namely ``1/sqrt(sqrt(2) + 1)``, see
957
+ https://sourceforge.net/p/maxima/bugs/3276/::
958
+
959
+ sage: solve(Q*sqrt(Q^2 + 2) - 1, Q, to_poly_solve=True)
960
+ [Q == -sqrt(-sqrt(2) - 1), Q == sqrt(sqrt(2) + 1)*(sqrt(2) - 1)]
961
+
962
+ An effort is made to only return solutions that satisfy
963
+ the current assumptions::
964
+
965
+ sage: solve(x^2==4, x)
966
+ [x == -2, x == 2]
967
+ sage: assume(x<0)
968
+ sage: solve(x^2==4, x)
969
+ [x == -2]
970
+ sage: solve((x^2-4)^2 == 0, x, multiplicities=True)
971
+ ([x == -2], [2])
972
+ sage: solve(x^2==2, x)
973
+ [x == -sqrt(2)]
974
+ sage: z = var('z')
975
+ sage: solve(x^2==2-z, x)
976
+ [x == -sqrt(-z + 2)]
977
+ sage: assume(x, 'rational')
978
+ sage: solve(x^2 == 2, x)
979
+ []
980
+
981
+ In some cases it may be worthwhile to directly use ``to_poly_solve``
982
+ if one suspects some answers are being missed::
983
+
984
+ sage: forget()
985
+ sage: solve(cos(x)==0, x)
986
+ [x == 1/2*pi]
987
+ sage: solve(cos(x)==0, x, to_poly_solve=True)
988
+ [x == 1/2*pi]
989
+ sage: solve(cos(x)==0, x, to_poly_solve='force')
990
+ [x == 1/2*pi + pi*z...]
991
+
992
+ The same may also apply if a returned unsolved expression has a
993
+ denominator, but the original one did not::
994
+
995
+ sage: solve(cos(x) * sin(x) == 1/2, x, to_poly_solve=True)
996
+ [sin(x) == 1/2/cos(x)]
997
+ sage: solve(cos(x) * sin(x) == 1/2, x, to_poly_solve=True, explicit_solutions=True)
998
+ [x == 1/4*pi + pi*z...]
999
+ sage: solve(cos(x) * sin(x) == 1/2, x, to_poly_solve='force')
1000
+ [x == 1/4*pi + pi*z...]
1001
+
1002
+ We use ``use_grobner`` in Maxima if no solution is obtained from
1003
+ Maxima's ``to_poly_solve``::
1004
+
1005
+ sage: x,y = var('x y')
1006
+ sage: c1(x,y) = (x-5)^2+y^2-16
1007
+ sage: c2(x,y) = (y-3)^2+x^2-9
1008
+ sage: solve([c1(x,y),c2(x,y)],[x,y])
1009
+ [[x == -9/68*sqrt(55) + 135/68, y == -15/68*sqrt(55) + 123/68],
1010
+ [x == 9/68*sqrt(55) + 135/68, y == 15/68*sqrt(55) + 123/68]]
1011
+
1012
+ We use SymPy for Diophantine equations, see
1013
+ ``Expression.solve_diophantine``::
1014
+
1015
+ sage: assume(x, 'integer')
1016
+ sage: assume(z, 'integer')
1017
+ sage: solve((x-z)^2==2, x)
1018
+ []
1019
+
1020
+ sage: forget()
1021
+
1022
+ The following shows some more of SymPy's capabilities that cannot be
1023
+ handled by Maxima::
1024
+
1025
+ sage: _ = var('t')
1026
+ sage: r = solve([x^2 - y^2/exp(x), y-1], x, y, algorithm='sympy', solution_dict=True)
1027
+ sage: (r[0][x], r[0][y])
1028
+ (2*lambert_w(-1/2), 1)
1029
+ sage: solve(-2*x**3 + 4*x**2 - 2*x + 6 > 0, x, algorithm='sympy')
1030
+ [x < 1/3*(1/2)^(1/3)*(9*sqrt(77) + 79)^(1/3) + 2/3*(1/2)^(2/3)/(9*sqrt(77) + 79)^(1/3) + 2/3]
1031
+ sage: solve(sqrt(2*x^2 - 7) - (3 - x),x,algorithm='sympy')
1032
+ [x == -8, x == 2]
1033
+ sage: solve(sqrt(2*x + 9) - sqrt(x + 1) - sqrt(x + 4),x,algorithm='sympy')
1034
+ [x == 0]
1035
+ sage: r = solve([x + y + z + t, -z - t], x, y, z, t, algorithm='sympy', solution_dict=True)
1036
+ sage: (r[0][x], r[0][z])
1037
+ (-y, -t)
1038
+ sage: r = solve([x^2+y+z, y+x^2+z, x+y+z^2], x, y,z, algorithm='sympy', solution_dict=True)
1039
+ sage: (r[0][x], r[0][y])
1040
+ (z, -(z + 1)*z)
1041
+ sage: (r[1][x], r[1][y])
1042
+ (-z + 1, -z^2 + z - 1)
1043
+ sage: solve(abs(x + 3) - 2*abs(x - 3),x,algorithm='sympy',domain='real')
1044
+ [x == 1, x == 9]
1045
+
1046
+ We cannot translate all results from SymPy but we can at least
1047
+ print them::
1048
+
1049
+ sage: solve(sinh(x) - 2*cosh(x),x,algorithm='sympy')
1050
+ [ImageSet(Lambda(_n, I*(2*_n*pi + pi/2) + log(sqrt(3))), Integers),
1051
+ ImageSet(Lambda(_n, I*(2*_n*pi - pi/2) + log(sqrt(3))), Integers)]
1052
+ sage: solve(2*sin(x) - 2*sin(2*x), x,algorithm='sympy')
1053
+ [ImageSet(Lambda(_n, 2*_n*pi), Integers),
1054
+ ImageSet(Lambda(_n, 2*_n*pi + pi), Integers),
1055
+ ImageSet(Lambda(_n, 2*_n*pi + 5*pi/3), Integers),
1056
+ ImageSet(Lambda(_n, 2*_n*pi + pi/3), Integers)]
1057
+
1058
+ sage: solve(x^5 + 3*x^3 + 7, x, algorithm='sympy')[0]
1059
+ x == complex_root_of(x^5 + 3*x^3 + 7, 0)
1060
+
1061
+ A basic interface to Giac is provided::
1062
+
1063
+ sage: # needs sage.libs.giac
1064
+ sage: solve([(2/3)^x-2], [x], algorithm='giac')
1065
+ [-log(2)/(log(3) - log(2))]
1066
+
1067
+ sage: # needs sage.libs.giac
1068
+ sage: f = (sin(x) - 8*cos(x)*sin(x))*(sin(x)^2 + cos(x)) - (2*cos(x)*sin(x) - sin(x))*(-2*sin(x)^2 + 2*cos(x)^2 - cos(x))
1069
+ sage: solve(f, x, algorithm='giac')
1070
+ [-2*arctan(sqrt(2)), 0, 2*arctan(sqrt(2)), pi]
1071
+
1072
+ sage: # needs sage.libs.giac
1073
+ sage: x, y = SR.var('x,y')
1074
+ sage: solve([x+y-4,x*y-3],[x,y],algorithm='giac')
1075
+ [[1, 3], [3, 1]]
1076
+
1077
+ TESTS::
1078
+
1079
+ sage: solve([sin(x)==x,y^2==x],x,y)
1080
+ [sin(x) == x, y^2 == x]
1081
+ sage: solve(0==1,x)
1082
+ []
1083
+
1084
+ Test if the empty list is returned, too, when (a list of)
1085
+ dictionaries (is) are requested (:issue:`8553`)::
1086
+
1087
+ sage: solve([SR(0)==1],x)
1088
+ []
1089
+ sage: solve([SR(0)==1],x,solution_dict=True)
1090
+ []
1091
+ sage: solve([x==1,x==-1],x)
1092
+ []
1093
+ sage: solve([x==1,x==-1],x,solution_dict=True)
1094
+ []
1095
+ sage: solve((x==1,x==-1),x,solution_dict=0)
1096
+ []
1097
+
1098
+ Relaxed form, suggested by Mike Hansen (:issue:`8553`)::
1099
+
1100
+ sage: solve([x^2-1],x,solution_dict=-1)
1101
+ [{x: -1}, {x: 1}]
1102
+ sage: solve([x^2-1],x,solution_dict=1)
1103
+ [{x: -1}, {x: 1}]
1104
+ sage: solve((x==1,x==-1),x,solution_dict=-1)
1105
+ []
1106
+ sage: solve((x==1,x==-1),x,solution_dict=1)
1107
+ []
1108
+
1109
+ This inequality holds for any real ``x`` (:issue:`8078`)::
1110
+
1111
+ sage: solve(x^4+2>0,x)
1112
+ [x < +Infinity]
1113
+
1114
+ Test for user friendly input handling :issue:`13645`::
1115
+
1116
+ sage: poly.<a,b> = PolynomialRing(RR)
1117
+ sage: solve([a+b+a*b == 1], a)
1118
+ Traceback (most recent call last):
1119
+ ...
1120
+ TypeError: a is not a valid variable
1121
+ sage: a,b = var('a,b')
1122
+ sage: solve([a+b+a*b == 1], a)
1123
+ [a == -(b - 1)/(b + 1)]
1124
+ sage: solve([a, b], (1, a))
1125
+ Traceback (most recent call last):
1126
+ ...
1127
+ TypeError: 1 is not a valid variable
1128
+ sage: solve([x == 1], (1, a))
1129
+ Traceback (most recent call last):
1130
+ ...
1131
+ TypeError: 1 is not a valid variable
1132
+ sage: x.solve((1,2))
1133
+ Traceback (most recent call last):
1134
+ ...
1135
+ TypeError: 1 is not a valid variable
1136
+
1137
+ Test that the original version of a system in the French Sage book
1138
+ now works (:issue:`14306`)::
1139
+
1140
+ sage: var('y,z')
1141
+ (y, z)
1142
+ sage: solve([x^2 * y * z == 18, x * y^3 * z == 24, x * y * z^4 == 6], x, y, z)
1143
+ [[x == 3, y == 2, z == 1],
1144
+ [x == (1.337215067... - 2.685489874...*I),
1145
+ y == (-1.700434271... + 1.052864325...*I),
1146
+ z == (0.9324722294... - 0.3612416661...*I)],
1147
+ ...]
1148
+
1149
+ :issue:`13286` fixed::
1150
+
1151
+ sage: solve([x-4], [x])
1152
+ [x == 4]
1153
+
1154
+ Test for a list of non-symbolic expressions as first argument
1155
+ (:issue:`31714`)::
1156
+
1157
+ sage: solve([1], x)
1158
+ Traceback (most recent call last):
1159
+ ...
1160
+ TypeError: must be a symbolic expression or a list of symbolic expressions
1161
+
1162
+ Automatic computation of the variables to solve for::
1163
+
1164
+ sage: var("x y")
1165
+ (x, y)
1166
+ sage: solve(x==1)
1167
+ [x == 1]
1168
+ sage: solve([x == 1, y == 2]) # random
1169
+ [[y == 2, x == 1]]
1170
+ sage: assert solve([x == 1, y == 2]) in ([[x == 1, y == 2]], [[y == 2, x == 1]])
1171
+ sage: solve([x == 1])
1172
+ [x == 1]
1173
+ sage: solve(x == 1)
1174
+ [x == 1]
1175
+
1176
+ Special case::
1177
+
1178
+ sage: solve([], [])
1179
+ [[]]
1180
+
1181
+ Coverage test::
1182
+
1183
+ sage: y = function('y')(x)
1184
+ sage: solve([diff(y)==x, diff(y)==x], y)
1185
+ Traceback (most recent call last):
1186
+ ...
1187
+ TypeError: y(x) is not a valid variable
1188
+ sage: solve([0==1], x, multiplicities=True)
1189
+ ([], [])
1190
+ sage: solve([0==0], [], multiplicities=True)
1191
+ ([[]], [1])
1192
+ sage: var("x y")
1193
+ (x, y)
1194
+ sage: solve([x==1, y==2], [x, y], algorithm='sympy', solution_dict=True)
1195
+ [{x: 1, y: 2}]
1196
+ sage: solve([x==1, y==2], [x, y], algorithm='sympy')
1197
+ [[x == 1, y == 2]]
1198
+ """
1199
+ from sage.structure.element import Expression
1200
+ f = _normalize_to_list_expressions(f)
1201
+
1202
+ # Normalize x to list of variables
1203
+ if not args:
1204
+ x = None
1205
+ else:
1206
+ x = args
1207
+ if len(x) == 1 and (isinstance(x[0], (list, tuple)) or x[0] is None):
1208
+ x = x[0]
1209
+ if x is None:
1210
+ x = list({v for s in f for v in s.variables()})
1211
+
1212
+ require_all_variables_to_be_symbol = len(f) > 1
1213
+ # we support y = function('y')(x); solve(diff(y)==x, y), in this case y = y(x) is not a symbol
1214
+ # but only if one equation is provided, otherwise it's unimplemented
1215
+ # there is also desolve()
1216
+ for i in x:
1217
+ complain = False
1218
+ if not isinstance(i, Expression):
1219
+ complain = True
1220
+ elif require_all_variables_to_be_symbol and not i.is_symbol():
1221
+ complain = True
1222
+ if complain:
1223
+ raise TypeError(f"{i} is not a valid variable")
1224
+
1225
+ # Handle special cases
1226
+ f = [s for s in f if s is not True]
1227
+ if any(s is False for s in f):
1228
+ if multiplicities:
1229
+ return [], []
1230
+ else:
1231
+ return []
1232
+
1233
+ if not x:
1234
+ if multiplicities:
1235
+ from sage.rings.integer_ring import ZZ
1236
+ return [[]], [ZZ.one()]
1237
+ else:
1238
+ return [[]]
1239
+
1240
+ if len(f) == 1:
1241
+ return _solve_expression(f[0], x, explicit_solutions, multiplicities, to_poly_solve, solution_dict, algorithm, domain)
1242
+
1243
+ if algorithm == 'sympy':
1244
+ from sympy import solve as ssolve
1245
+
1246
+ from sage.interfaces.sympy import sympy_set_to_list
1247
+ sympy_f = [s._sympy_() for s in f]
1248
+ sympy_vars = tuple([v._sympy_() for v in x])
1249
+ ret = ssolve(sympy_f, sympy_vars, dict=True)
1250
+ if isinstance(ret, dict):
1251
+ # it is not clear how this branch could be reached
1252
+ # because dict=True is passed above, however
1253
+ # it is kept just in case
1254
+ if solution_dict:
1255
+ l = []
1256
+ for d in ret:
1257
+ r = {}
1258
+ for (v, ex) in d.items():
1259
+ r[v._sage_()] = ex._sage_()
1260
+ l.append(r)
1261
+ return l
1262
+ else:
1263
+ return [[v._sage_() == ex._sage_()
1264
+ for v, ex in d.items()]
1265
+ for d in ret]
1266
+ elif isinstance(ret, list):
1267
+ if solution_dict:
1268
+ return [{v._sage_(): ex._sage_()
1269
+ for v, ex in d.items()} for d in ret]
1270
+ else:
1271
+ return [[v._sage_() == ex._sage_()
1272
+ for v, ex in d.items()] for d in ret]
1273
+ else:
1274
+ # it is not clear how this branch could be reached
1275
+ # because dict=True is passed above, however
1276
+ # it is kept just in case
1277
+ return sympy_set_to_list(ret, sympy_vars)
1278
+
1279
+ if algorithm == 'giac':
1280
+ return _giac_solver(f, x, solution_dict)
1281
+
1282
+ from sage.calculus.calculus import maxima
1283
+ m = maxima(f)
1284
+
1285
+ try:
1286
+ s = m.solve(x)
1287
+ except Exception: # if Maxima gave an error, try its to_poly_solve
1288
+ try:
1289
+ s = m.to_poly_solve(x)
1290
+ except TypeError as mess: # if that gives an error, raise an error.
1291
+ if "Error executing code in Maxima" in str(mess):
1292
+ raise ValueError(f"sage is unable to determine whether the system {f} can be solved for {x}")
1293
+ else:
1294
+ raise
1295
+
1296
+ if len(s) == 0: # if Maxima's solve gave no solutions, try its to_poly_solve
1297
+ try:
1298
+ s = m.to_poly_solve(x)
1299
+ except Exception: # if that gives an error, stick with no solutions
1300
+ s = []
1301
+
1302
+ if len(s) == 0: # if to_poly_solve gave no solutions, try use_grobner
1303
+ try:
1304
+ s = m.to_poly_solve(x, 'use_grobner=true')
1305
+ except Exception: # if that gives an error, stick with no solutions
1306
+ s = []
1307
+
1308
+ sol_list = string_to_list_of_solutions(repr(s))
1309
+
1310
+ # Relaxed form suggested by Mike Hansen (#8553):
1311
+ if solution_dict:
1312
+ if not sol_list: # fixes IndexError on empty solution list (#8553)
1313
+ return []
1314
+ if isinstance(sol_list[0], list):
1315
+ sol_dict = [{eq.left(): eq.right() for eq in solution}
1316
+ for solution in sol_list]
1317
+ else:
1318
+ sol_dict = [{eq.left(): eq.right()} for eq in sol_list]
1319
+
1320
+ return sol_dict
1321
+ else:
1322
+ return sol_list
1323
+
1324
+
1325
+ def _solve_expression(f, x, explicit_solutions, multiplicities,
1326
+ to_poly_solve, solution_dict, algorithm, domain):
1327
+ """
1328
+ Solve an expression ``f``. For more information, see :func:`solve`.
1329
+
1330
+ .. NOTE::
1331
+
1332
+ This is an auxiliary function only meant to be called
1333
+ from :func:`solve`.
1334
+
1335
+ TESTS:
1336
+
1337
+ :issue:`7325` (solving inequalities)::
1338
+
1339
+ sage: (x^2>1).solve(x)
1340
+ [[x < -1], [x > 1]]
1341
+
1342
+ Catch error message from Maxima::
1343
+
1344
+ sage: solve(acot(x),x)
1345
+ Traceback (most recent call last):
1346
+ ...
1347
+ TypeError: ECL says: cot: argument 0 isn't in the domain of cot.
1348
+
1349
+ ::
1350
+
1351
+ sage: solve(acot(x),x,to_poly_solve=True)
1352
+ Traceback (most recent call last):
1353
+ ...
1354
+ TypeError: ECL says: cot: argument 0 isn't in the domain of cot.
1355
+
1356
+ :issue:`7491` fixed::
1357
+
1358
+ sage: y = var('y')
1359
+ sage: solve(y==y,y)
1360
+ [y == r1]
1361
+ sage: solve(y==y,y,multiplicities=True)
1362
+ ([y == r1], [])
1363
+
1364
+ sage: from sage.symbolic.assumptions import GenericDeclaration
1365
+ sage: GenericDeclaration(x, 'rational').assume()
1366
+ sage: solve(x^2 == 2, x)
1367
+ []
1368
+ sage: forget()
1369
+
1370
+ :issue:`8390` fixed::
1371
+
1372
+ sage: solve(sin(x)==1/2,x)
1373
+ [x == 1/6*pi]
1374
+
1375
+ ::
1376
+
1377
+ sage: solve(sin(x)==1/2,x,to_poly_solve=True)
1378
+ [x == 1/6*pi]
1379
+
1380
+ ::
1381
+
1382
+ sage: solve(sin(x)==1/2, x, to_poly_solve='force')
1383
+ [x == 5/6*pi + 2*pi*z..., x == 1/6*pi + 2*pi*z...]
1384
+
1385
+ :issue:`11618` fixed::
1386
+
1387
+ sage: g(x)=0
1388
+ sage: solve(g(x)==0,x,solution_dict=True)
1389
+ [{x: r1}]
1390
+
1391
+ :issue:`17128`: fixed::
1392
+
1393
+ sage: var('x,y')
1394
+ (x, y)
1395
+ sage: f = x+y
1396
+ sage: sol = f.solve([x, y], solution_dict=True)
1397
+ sage: sol[0].get(x) + sol[0].get(y)
1398
+ 0
1399
+
1400
+ :issue:`16651` fixed::
1401
+
1402
+ sage: (x^7-x-1).solve(x, to_poly_solve=True) # abs tol 1e-6
1403
+ [x == 1.11277569705,
1404
+ x == (-0.363623519329 - 0.952561195261*I),
1405
+ x == (0.617093477784 - 0.900864951949*I),
1406
+ x == (-0.809857800594 - 0.262869645851*I),
1407
+ x == (-0.809857800594 + 0.262869645851*I),
1408
+ x == (0.617093477784 + 0.900864951949*I),
1409
+ x == (-0.363623519329 + 0.952561195261*I)]
1410
+
1411
+ :issue:`31452` fixed::
1412
+
1413
+ sage: solve([x==3], [x], solution_dict=True)
1414
+ [{x: 3}]
1415
+ sage: solve([x==3], [x], solution_dict=True, algorithm='sympy')
1416
+ [{x: 3}]
1417
+ """
1418
+ from sage.structure.element import Expression
1419
+
1420
+ if isinstance(x, (list, tuple)) and len(x) == 1:
1421
+ x = x[0]
1422
+
1423
+ if f.is_relational():
1424
+ if f.operator() is not operator.eq:
1425
+ if algorithm == 'sympy':
1426
+ from sympy import S, solveset
1427
+
1428
+ from sage.interfaces.sympy import sympy_set_to_list
1429
+ if isinstance(x, Expression) and x.is_symbol():
1430
+ sympy_vars = (x._sympy_(),)
1431
+ else:
1432
+ sympy_vars = tuple([v._sympy_() for v in x])
1433
+ ret = solveset(f._sympy_(), sympy_vars[0], S.Reals)
1434
+ return sympy_set_to_list(ret, sympy_vars)
1435
+ elif algorithm == 'giac':
1436
+ return _giac_solver(f, x, solution_dict)
1437
+ else:
1438
+ try:
1439
+ return solve_ineq(f) # trying solve_ineq_univar
1440
+ except Exception:
1441
+ pass
1442
+ try:
1443
+ return solve_ineq([f]) # trying solve_ineq_fourier
1444
+ except Exception:
1445
+ raise NotImplementedError("solving only implemented for equalities and few special inequalities, see solve_ineq")
1446
+ else:
1447
+ f = (f == 0)
1448
+
1449
+ if multiplicities and to_poly_solve:
1450
+ raise NotImplementedError("to_poly_solve does not return multiplicities")
1451
+ # check if all variables are assumed integer;
1452
+ # if so, we have a Diophantine
1453
+
1454
+ def has_integer_assumption(v) -> bool:
1455
+ from sage.symbolic.assumptions import GenericDeclaration, assumptions
1456
+ alist = assumptions()
1457
+ return any(isinstance(a, GenericDeclaration) and a.has(v) and
1458
+ a._assumption in ['even', 'odd', 'integer', 'integervalued']
1459
+ for a in alist)
1460
+ if f.variables() and all(has_integer_assumption(var) for var in f.variables()):
1461
+ return f.solve_diophantine(x, solution_dict=solution_dict)
1462
+
1463
+ if algorithm == 'sympy':
1464
+ from sympy import S, solveset
1465
+
1466
+ from sage.interfaces.sympy import sympy_set_to_list
1467
+ if isinstance(x, Expression) and x.is_symbol():
1468
+ sympy_vars = (x._sympy_(),)
1469
+ else:
1470
+ sympy_vars = tuple([v._sympy_() for v in x])
1471
+ if domain == 'real':
1472
+ ret = solveset(f._sympy_(), sympy_vars[0], S.Reals)
1473
+ else:
1474
+ ret = solveset(f._sympy_(), sympy_vars[0])
1475
+ ret = sympy_set_to_list(ret, sympy_vars)
1476
+ if solution_dict:
1477
+ ret = [{sol.left(): sol.right()} for sol in ret]
1478
+ return ret
1479
+
1480
+ if algorithm == 'giac':
1481
+ return _giac_solver(f, x, solution_dict)
1482
+
1483
+ # from here on, maxima is used for solution
1484
+ m = f._maxima_()
1485
+ P = m.parent()
1486
+ if explicit_solutions:
1487
+ P.eval('solveexplicit: true') # switches Maxima to looking for only explicit solutions
1488
+ try:
1489
+ if to_poly_solve != 'force':
1490
+ s = m.solve(x).str()
1491
+ else: # omit Maxima's solve command
1492
+ s = str([])
1493
+ except TypeError as mess: # if Maxima's solve has an error, we catch it
1494
+ if "Error executing code in Maxima" in str(mess):
1495
+ s = str([])
1496
+ else:
1497
+ raise
1498
+ if explicit_solutions:
1499
+ P.eval('solveexplicit: false') # switches Maxima back to default
1500
+
1501
+ if s == 'all':
1502
+ if solution_dict:
1503
+ ans = [{x: f.parent().var('r1')}]
1504
+ else:
1505
+ ans = [x == f.parent().var('r1')]
1506
+ if multiplicities:
1507
+ return ans, []
1508
+ else:
1509
+ return ans
1510
+
1511
+ X = string_to_list_of_solutions(s) # our initial list of solutions
1512
+
1513
+ if multiplicities: # to_poly_solve does not return multiplicities, so in this case we end here
1514
+ if len(X) == 0:
1515
+ return X, []
1516
+ else:
1517
+ ret_multiplicities = [int(e) for e in str(P.get('multiplicities'))[1:-1].split(',')]
1518
+
1519
+ ########################################################
1520
+ # Maxima's to_poly_solver package converts difficult #
1521
+ # equations to (quasi)-polynomial systems and uses #
1522
+ # Maxima's algsys function to try to solve them. #
1523
+ # This allows a much larger range of solved equations, #
1524
+ # but also allows for the possibility of approximate #
1525
+ # solutions being returned. #
1526
+ ########################################################
1527
+ if to_poly_solve:
1528
+ if len(X) == 0:
1529
+ # Maxima's solve gave no solutions
1530
+ solutions_so_far = [f]
1531
+ ignore_exceptions = True
1532
+ else:
1533
+ solutions_so_far = X
1534
+ ignore_exceptions = False
1535
+ X = []
1536
+ for eq in solutions_so_far:
1537
+ if eq.lhs().is_symbol() and (eq.lhs() == x) and (x not in eq.rhs().variables()):
1538
+ X.append(eq)
1539
+ continue
1540
+ try:
1541
+ m = eq._maxima_()
1542
+ s = m.to_poly_solve(x, options='algexact:true')
1543
+ T = string_to_list_of_solutions(repr(s))
1544
+ X.extend([t[0] for t in T])
1545
+ except TypeError as mess:
1546
+ if ignore_exceptions:
1547
+ continue
1548
+ elif "Error executing code in Maxima" in str(mess) or \
1549
+ "unable to make sense of Maxima expression" in \
1550
+ str(mess):
1551
+ if not explicit_solutions:
1552
+ X.append(eq) # we keep this implicit solution
1553
+ else:
1554
+ raise
1555
+
1556
+ # make sure all the assumptions are satisfied
1557
+ from sage.symbolic.assumptions import assumptions
1558
+ to_check = assumptions()
1559
+ if to_check:
1560
+ for ix, soln in reversed(list(enumerate(X))):
1561
+ if soln.lhs().is_symbol():
1562
+ if any(a.contradicts(soln) for a in to_check):
1563
+ del X[ix]
1564
+ if multiplicities:
1565
+ del ret_multiplicities[ix]
1566
+ continue
1567
+
1568
+ if solution_dict:
1569
+ if isinstance(x, (list, tuple)) and len(x) > 1:
1570
+ X = [{sol.left(): sol.right() for sol in b} for b in X]
1571
+ else:
1572
+ X = [{sol.left(): sol.right()} for sol in X]
1573
+
1574
+ if multiplicities:
1575
+ return X, ret_multiplicities
1576
+ else:
1577
+ return X
1578
+
1579
+
1580
+ def _giac_solver(f, x, solution_dict=False):
1581
+ """
1582
+ Solve a system of equations using libgiac.
1583
+
1584
+ INPUT:
1585
+
1586
+ - ``f`` -- equation or list of equations
1587
+ - ``x`` -- variable or list of variables
1588
+ - ``solution_dict`` -- boolean (default: ``False``)
1589
+
1590
+ EXAMPLES::
1591
+
1592
+ sage: # needs sage.libs.giac
1593
+ sage: solve([(2/3)^x-2], [x], algorithm='giac')
1594
+ [-log(2)/(log(3) - log(2))]
1595
+ sage: solve([(2/3)^x-2], [x], algorithm='giac', solution_dict=True)
1596
+ [{x: -log(2)/(log(3) - log(2))}]
1597
+
1598
+ sage: # needs sage.libs.giac
1599
+ sage: f = (sin(x) - 8*cos(x)*sin(x))*(sin(x)^2 + cos(x)) - (2*cos(x)*sin(x) - sin(x))*(-2*sin(x)^2 + 2*cos(x)^2 - cos(x))
1600
+ sage: solve(f, x, algorithm='giac')
1601
+ [-2*arctan(sqrt(2)), 0, 2*arctan(sqrt(2)), pi]
1602
+ sage: solve(f, x, algorithm='giac', solution_dict=True)
1603
+ [{x: -2*arctan(sqrt(2))}, {x: 0}, {x: 2*arctan(sqrt(2))}, {x: pi}]
1604
+
1605
+ sage: # needs sage.libs.giac
1606
+ sage: x, y = SR.var('x,y')
1607
+ sage: solve([x+y-7,x*y-10],[x,y],algorithm='giac')
1608
+ [[2, 5], [5, 2]]
1609
+ """
1610
+ from sage.libs.giac.giac import libgiac
1611
+ f = _normalize_to_list_expressions(_normalize_to_nonrelational(f))
1612
+ giac_f = libgiac(f)
1613
+ if isinstance(x, tuple):
1614
+ # Python tuple is translated to giac seq which we don't want
1615
+ # (if its length is > 1 then the library call errors out)
1616
+ x = list(x)
1617
+ giac_vars = libgiac(x)
1618
+ ret = giac_f.solve(giac_vars)
1619
+ sols = ret.sage()
1620
+ if solution_dict:
1621
+ if not sols:
1622
+ return []
1623
+ if isinstance(sols[0], list):
1624
+ return [dict(zip(x, solution)) for solution in sols]
1625
+ return [{x: sx} for sx in sols]
1626
+ return sols
1627
+
1628
+
1629
+ def solve_mod(eqns, modulus, solution_dict=False):
1630
+ r"""
1631
+ Return all solutions to an equation or list of equations modulo the
1632
+ given integer modulus. Each equation must involve only polynomials
1633
+ in 1 or many variables.
1634
+
1635
+ By default the solutions are returned as `n`-tuples, where `n`
1636
+ is the number of variables appearing anywhere in the given
1637
+ equations. The variables are in alphabetical order.
1638
+
1639
+ INPUT:
1640
+
1641
+ - ``eqns`` -- equation or list of equations
1642
+
1643
+ - ``modulus`` -- integer
1644
+
1645
+ - ``solution_dict`` -- boolean (default: ``False``); if ``True`` or nonzero,
1646
+ return a list of dictionaries containing the solutions. If there
1647
+ are no solutions, return an empty list (rather than a list containing
1648
+ an empty dictionary). Likewise, if there's only a single solution,
1649
+ return a list containing one dictionary with that solution.
1650
+
1651
+ EXAMPLES::
1652
+
1653
+ sage: var('x,y')
1654
+ (x, y)
1655
+ sage: solve_mod([x^2 + 2 == x, x^2 + y == y^2], 14)
1656
+ [(4, 2), (4, 6), (4, 9), (4, 13)]
1657
+ sage: solve_mod([x^2 == 1, 4*x == 11], 15)
1658
+ [(14,)]
1659
+
1660
+ Fermat's equation modulo 3 with exponent 5::
1661
+
1662
+ sage: var('x,y,z')
1663
+ (x, y, z)
1664
+ sage: solve_mod([x^5 + y^5 == z^5], 3)
1665
+ [(0, 0, 0), (0, 1, 1), (0, 2, 2), (1, 0, 1), (1, 1, 2), (1, 2, 0), (2, 0, 2), (2, 1, 0), (2, 2, 1)]
1666
+
1667
+ We can solve with respect to a bigger modulus if it consists only of small prime factors::
1668
+
1669
+ sage: # needs sage.libs.pari
1670
+ sage: [d] = solve_mod([5*x + y == 3, 2*x - 3*y == 9], 3*5*7*11*19*23*29, solution_dict=True)
1671
+ sage: d[x]
1672
+ 12915279
1673
+ sage: d[y]
1674
+ 8610183
1675
+
1676
+ For cases where there are relatively few solutions and the prime
1677
+ factors are small, this can be efficient even if the modulus itself
1678
+ is large::
1679
+
1680
+ sage: sorted(solve_mod([x^2 == 41], 10^20)) # needs sage.libs.pari
1681
+ [(4538602480526452429,), (11445932736758703821,), (38554067263241296179,),
1682
+ (45461397519473547571,), (54538602480526452429,), (61445932736758703821,),
1683
+ (88554067263241296179,), (95461397519473547571,)]
1684
+
1685
+ We solve a simple equation modulo 2::
1686
+
1687
+ sage: x,y = var('x,y')
1688
+ sage: solve_mod([x == y], 2) # needs sage.libs.pari
1689
+ [(0, 0), (1, 1)]
1690
+
1691
+ .. warning::
1692
+
1693
+ The current implementation splits the modulus into prime
1694
+ powers, then naively enumerates all possible solutions
1695
+ (starting modulo primes and then working up through prime
1696
+ powers), and finally combines the solution using the Chinese
1697
+ Remainder Theorem. The interface is good, but the algorithm is
1698
+ very inefficient if the modulus has some larger prime factors! Sage
1699
+ *does* have the ability to do something much faster in certain
1700
+ cases at least by using Groebner basis, linear algebra
1701
+ techniques, etc. But for a lot of toy problems this function as
1702
+ is might be useful. At least it establishes an interface.
1703
+
1704
+ TESTS:
1705
+
1706
+ Make sure that we short-circuit in at least some cases::
1707
+
1708
+ sage: solve_mod([2*x==1], 2*next_prime(10^50)) # needs sage.libs.pari
1709
+ []
1710
+
1711
+ Try multi-equation cases::
1712
+
1713
+ sage: x, y, z = var("x y z")
1714
+ sage: solve_mod([2*x^2 + x*y, -x*y+2*y^2+x-2*y, -2*x^2+2*x*y-y^2-x-y], 12) # needs sage.libs.pari
1715
+ [(0, 0), (4, 4), (0, 3), (4, 7)]
1716
+ sage: eqs = [-y^2+z^2, -x^2+y^2-3*z^2-z-1, -y*z-z^2-x-y+2, -x^2-12*z^2-y+z]
1717
+ sage: solve_mod(eqs, 11) # needs sage.libs.pari
1718
+ [(8, 5, 6)]
1719
+
1720
+ Confirm that modulus 1 now behaves as it should::
1721
+
1722
+ sage: x, y = var("x y")
1723
+ sage: solve_mod([x==1], 1) # needs sage.libs.pari
1724
+ [(0,)]
1725
+ sage: solve_mod([2*x^2+x*y, -x*y+2*y^2+x-2*y, -2*x^2+2*x*y-y^2-x-y], 1) # needs sage.libs.pari
1726
+ [(0, 0)]
1727
+ """
1728
+ from sage.matrix.constructor import matrix
1729
+ from sage.modules.free_module_element import vector
1730
+ from sage.rings.finite_rings.integer_mod_ring import Integers
1731
+ from sage.rings.integer import Integer
1732
+ from sage.rings.integer_ring import crt_basis
1733
+ from sage.structure.element import Expression
1734
+
1735
+ if not isinstance(eqns, (list, tuple)):
1736
+ eqns = [eqns]
1737
+ eqns = [eq if isinstance(eq, Expression) else (eq.lhs() - eq.rhs()) for eq in eqns]
1738
+ modulus = Integer(modulus)
1739
+ if modulus < 1:
1740
+ raise ValueError("the modulus must be a positive integer")
1741
+ vars = list(set(sum([list(e.variables()) for e in eqns], [])))
1742
+ vars.sort(key=repr)
1743
+
1744
+ if modulus == 1: # degenerate case
1745
+ ans = [tuple(Integers(1)(0) for v in vars)]
1746
+ return ans
1747
+
1748
+ factors = modulus.factor()
1749
+ crt_basis = vector(Integers(modulus), crt_basis([p**i for p, i in factors]))
1750
+ solutions = []
1751
+
1752
+ has_solution = True
1753
+ for p, i in factors:
1754
+ solution = _solve_mod_prime_power(eqns, p, i, vars)
1755
+ if len(solution) > 0:
1756
+ solutions.append(solution)
1757
+ else:
1758
+ has_solution = False
1759
+ break
1760
+
1761
+ ans = []
1762
+ if has_solution:
1763
+ for solution in product(*solutions):
1764
+ solution_mat = matrix(Integers(modulus), solution)
1765
+ ans.append(tuple(c.dot_product(crt_basis) for c in solution_mat.columns()))
1766
+
1767
+ # if solution_dict == True:
1768
+ # Relaxed form suggested by Mike Hansen (#8553):
1769
+ if solution_dict:
1770
+ return [dict(zip(vars, solution)) for solution in ans]
1771
+ return ans
1772
+
1773
+
1774
+ def _solve_mod_prime_power(eqns, p, m, vars):
1775
+ r"""
1776
+ Internal help function for solve_mod, does little checking since it expects
1777
+ solve_mod to do that
1778
+
1779
+ Return all solutions to an equation or list of equations modulo p^m.
1780
+ Each equation must involve only polynomials
1781
+ in 1 or many variables.
1782
+
1783
+ The solutions are returned as `n`-tuples, where `n`
1784
+ is the number of variables in vars.
1785
+
1786
+ INPUT:
1787
+
1788
+ - ``eqns`` -- equation or list of equations
1789
+
1790
+ - ``p`` -- a prime
1791
+
1792
+ - ``i`` -- integer > 0
1793
+
1794
+ - ``vars`` -- list of variables to solve for
1795
+
1796
+ EXAMPLES::
1797
+
1798
+ sage: var('x,y')
1799
+ (x, y)
1800
+ sage: solve_mod([x^2 + 2 == x, x^2 + y == y^2], 14)
1801
+ [(4, 2), (4, 6), (4, 9), (4, 13)]
1802
+ sage: solve_mod([x^2 == 1, 4*x == 11], 15)
1803
+ [(14,)]
1804
+
1805
+ Fermat's equation modulo 3 with exponent 5::
1806
+
1807
+ sage: var('x,y,z')
1808
+ (x, y, z)
1809
+ sage: solve_mod([x^5 + y^5 == z^5], 3)
1810
+ [(0, 0, 0), (0, 1, 1), (0, 2, 2), (1, 0, 1), (1, 1, 2), (1, 2, 0), (2, 0, 2), (2, 1, 0), (2, 2, 1)]
1811
+
1812
+ We solve a simple equation modulo 2::
1813
+
1814
+ sage: x,y = var('x,y')
1815
+ sage: solve_mod([x == y], 2)
1816
+ [(0, 0), (1, 1)]
1817
+
1818
+
1819
+ .. warning::
1820
+
1821
+ Currently this constructs possible solutions by building up
1822
+ from the smallest prime factor of the modulus. The interface
1823
+ is good, but the algorithm is horrible if the modulus is not the
1824
+ product of many small primes! Sage *does* have the ability to
1825
+ do something much faster in certain cases at least by using the
1826
+ Chinese Remainder Theorem, Groebner basis, linear algebra
1827
+ techniques, etc. But for a lot of toy problems this function as
1828
+ is might be useful. At the very least, it establishes an
1829
+ interface.
1830
+
1831
+ TESTS:
1832
+
1833
+ Confirm we can reproduce the first few terms of :oeis:`A187719`::
1834
+
1835
+ sage: from sage.symbolic.relation import _solve_mod_prime_power
1836
+ sage: [sorted(_solve_mod_prime_power([x^2==41], 10, i, [x]))[0][0] for i in [1..13]]
1837
+ [1, 21, 71, 1179, 2429, 47571, 1296179, 8703821, 26452429, 526452429,
1838
+ 13241296179, 19473547571, 2263241296179]
1839
+ """
1840
+ from sage.modules.free_module_element import vector
1841
+ from sage.rings.finite_rings.integer_mod_ring import Integers
1842
+ from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
1843
+
1844
+ mrunning = 1
1845
+ ans = []
1846
+ for mi in range(m):
1847
+ mrunning *= p
1848
+ R = Integers(mrunning)
1849
+ S = PolynomialRing(R, len(vars), vars)
1850
+ eqns_mod = [S(eq) for eq in eqns]
1851
+ if mi == 0:
1852
+ possibles = product(*[range(len(R)) for _ in range(len(vars))])
1853
+ else:
1854
+ shifts = product(*[range(p) for _ in range(len(vars))])
1855
+ pairs = product(shifts, ans)
1856
+ possibles = (tuple(vector(t) + vector(shift) * (mrunning // p))
1857
+ for shift, t in pairs)
1858
+ ans = [t for t in possibles if all(e(*t) == 0 for e in eqns_mod)]
1859
+ if not ans:
1860
+ return ans
1861
+
1862
+ return ans
1863
+
1864
+
1865
+ def solve_ineq_univar(ineq):
1866
+ """
1867
+ Function solves rational inequality in one variable.
1868
+
1869
+ INPUT:
1870
+
1871
+ - ``ineq`` -- inequality in one variable
1872
+
1873
+ OUTPUT:
1874
+
1875
+ - ``list`` -- output is list of solutions as a list of simple inequalities
1876
+ output [A,B,C] means (A or B or C) each A, B, C is again a list and
1877
+ if A=[a,b], then A means (a and b). The list is empty if there is no
1878
+ solution.
1879
+
1880
+ EXAMPLES::
1881
+
1882
+ sage: from sage.symbolic.relation import solve_ineq_univar
1883
+ sage: solve_ineq_univar(x-1/x>0)
1884
+ [[x > -1, x < 0], [x > 1]]
1885
+
1886
+ sage: solve_ineq_univar(x^2-1/x>0)
1887
+ [[x < 0], [x > 1]]
1888
+
1889
+ sage: solve_ineq_univar((x^3-1)*x<=0)
1890
+ [[x >= 0, x <= 1]]
1891
+
1892
+ ALGORITHM:
1893
+
1894
+ Calls Maxima command ``solve_rat_ineq``
1895
+
1896
+ AUTHORS:
1897
+
1898
+ - Robert Marik (01-2010)
1899
+ """
1900
+ ineqvar = ineq.variables()
1901
+ if len(ineqvar) != 1:
1902
+ raise NotImplementedError("The command solve_ineq_univar accepts univariate inequalities only. Your variables are " + ineqvar)
1903
+ ineq0 = ineq._maxima_()
1904
+ ineq0.parent().eval("if solve_rat_ineq_loaded#true then (solve_rat_ineq_loaded:true,load(\"solve_rat_ineq.mac\")) ")
1905
+ sol = ineq0.solve_rat_ineq().sage()
1906
+ if repr(sol) == "all":
1907
+ from sage.rings.infinity import Infinity
1908
+ sol = [ineqvar[0] < Infinity]
1909
+ return sol
1910
+
1911
+
1912
+ def solve_ineq_fourier(ineq, vars=None):
1913
+ """
1914
+ Solve system of inequalities using Maxima and Fourier elimination.
1915
+
1916
+ Can be used for system of linear inequalities and for some types
1917
+ of nonlinear inequalities. For examples, see the example section
1918
+ below and http://maxima.cvs.sourceforge.net/viewvc/maxima/maxima/share/contrib/fourier_elim/rtest_fourier_elim.mac
1919
+
1920
+
1921
+ INPUT:
1922
+
1923
+ - ``ineq`` -- list with system of inequalities
1924
+
1925
+ - ``vars`` -- optionally list with variables for Fourier elimination
1926
+
1927
+ OUTPUT:
1928
+
1929
+ - ``list`` -- output is list of solutions as a list of simple inequalities
1930
+ output [A,B,C] means (A or B or C) each A, B, C is again a list and
1931
+ if A=[a,b], then A means (a and b). The list is empty if there is no
1932
+ solution.
1933
+
1934
+ EXAMPLES::
1935
+
1936
+ sage: from sage.symbolic.relation import solve_ineq_fourier
1937
+ sage: y = var('y')
1938
+ sage: solve_ineq_fourier([x+y<9,x-y>4],[x,y])
1939
+ [[y + 4 < x, x < -y + 9, y < (5/2)]]
1940
+ sage: solve_ineq_fourier([x+y<9,x-y>4],[y,x])[0][0](x=42)
1941
+ y < -33
1942
+
1943
+ sage: solve_ineq_fourier([x^2>=0])
1944
+ [[x < +Infinity]]
1945
+
1946
+ sage: solve_ineq_fourier([log(x)>log(y)],[x,y])
1947
+ [[y < x, 0 < y]]
1948
+ sage: solve_ineq_fourier([log(x)>log(y)],[y,x])
1949
+ [[0 < y, y < x, 0 < x]]
1950
+
1951
+ Note that different systems will find default variables in different
1952
+ orders, so the following is not tested::
1953
+
1954
+ sage: solve_ineq_fourier([log(x)>log(y)]) # random (one of the following appears)
1955
+ [[0 < y, y < x, 0 < x]]
1956
+ [[y < x, 0 < y]]
1957
+
1958
+ ALGORITHM:
1959
+
1960
+ Calls Maxima command ``fourier_elim``
1961
+
1962
+ AUTHORS:
1963
+
1964
+ - Robert Marik (01-2010)
1965
+ """
1966
+ if vars is None:
1967
+ setvars = set()
1968
+ for i in (ineq):
1969
+ setvars = setvars.union(set(i.variables()))
1970
+ vars = list(setvars)
1971
+ ineq0 = [i._maxima_() for i in ineq]
1972
+ ineq0[0].parent().eval("if fourier_elim_loaded#true then (fourier_elim_loaded:true,load(\"fourier_elim\"))")
1973
+ sol = ineq0[0].parent().fourier_elim(ineq0, vars)
1974
+ ineq0[0].parent().eval("or_to_list(x):=\
1975
+ if not atom(x) and op(x)=\"or\" then args(x) \
1976
+ else [x]")
1977
+ sol = sol.or_to_list().sage()
1978
+ if repr(sol) == "[emptyset]":
1979
+ sol = []
1980
+ if repr(sol) == "[universalset]":
1981
+ from sage.rings.infinity import Infinity
1982
+ sol = [[i < Infinity for i in vars]]
1983
+ return sol
1984
+
1985
+
1986
+ def solve_ineq(ineq, vars=None):
1987
+ """
1988
+ Solve inequalities and systems of inequalities using Maxima.
1989
+ Switches between rational inequalities
1990
+ (sage.symbolic.relation.solve_ineq_rational)
1991
+ and Fourier elimination (sage.symbolic.relation.solve_ineq_fouried).
1992
+ See the documentation of these functions for more details.
1993
+
1994
+ INPUT:
1995
+
1996
+ - ``ineq`` -- one inequality or a list of inequalities
1997
+
1998
+ Case1: If ``ineq`` is one equality, then it should be rational
1999
+ expression in one variable. This input is passed to
2000
+ sage.symbolic.relation.solve_ineq_univar function.
2001
+
2002
+ Case2: If ``ineq`` is a list involving one or more
2003
+ inequalities, than the input is passed to
2004
+ sage.symbolic.relation.solve_ineq_fourier function. This
2005
+ function can be used for system of linear inequalities and
2006
+ for some types of nonlinear inequalities. See
2007
+ http://maxima.cvs.sourceforge.net/viewvc/maxima/maxima/share/contrib/fourier_elim/rtest_fourier_elim.mac
2008
+ for a big gallery of problems covered by this algorithm.
2009
+
2010
+ - ``vars`` -- (optional) parameter with list of variables. This list
2011
+ is used only if Fourier elimination is used. If omitted or if
2012
+ rational inequality is solved, then variables are determined
2013
+ automatically.
2014
+
2015
+ OUTPUT:
2016
+
2017
+ - ``list`` -- output is list of solutions as a list of simple inequalities
2018
+ output [A,B,C] means (A or B or C) each A, B, C is again a list and
2019
+ if A=[a,b], then A means (a and b).
2020
+
2021
+ EXAMPLES::
2022
+
2023
+ sage: from sage.symbolic.relation import solve_ineq
2024
+
2025
+ Inequalities in one variable. The variable is detected automatically::
2026
+
2027
+ sage: solve_ineq(x^2-1>3)
2028
+ [[x < -2], [x > 2]]
2029
+
2030
+ sage: solve_ineq(1/(x-1)<=8)
2031
+ [[x < 1], [x >= (9/8)]]
2032
+
2033
+ System of inequalities with automatically detected inequalities::
2034
+
2035
+ sage: y = var('y')
2036
+ sage: solve_ineq([x-y<0,x+y-3<0],[y,x])
2037
+ [[x < y, y < -x + 3, x < (3/2)]]
2038
+ sage: solve_ineq([x-y<0,x+y-3<0],[x,y])
2039
+ [[x < min(-y + 3, y)]]
2040
+
2041
+ Note that although Sage will detect the variables automatically,
2042
+ the order it puts them in may depend on the system, so the following
2043
+ command is only guaranteed to give you one of the above answers::
2044
+
2045
+ sage: solve_ineq([x-y<0,x+y-3<0]) # random
2046
+ [[x < y, y < -x + 3, x < (3/2)]]
2047
+
2048
+ ALGORITHM:
2049
+
2050
+ Calls ``solve_ineq_fourier`` if inequalities are list and
2051
+ ``solve_ineq_univar`` of the inequality is symbolic expression. See
2052
+ the description of these commands for more details related to the
2053
+ set of inequalities which can be solved. The list is empty if
2054
+ there is no solution.
2055
+
2056
+ AUTHORS:
2057
+
2058
+ - Robert Marik (01-2010)
2059
+ """
2060
+ if isinstance(ineq, list):
2061
+ return solve_ineq_fourier(ineq, vars)
2062
+ return solve_ineq_univar(ineq)