passagemath-symbolics 10.6.40__cp314-cp314t-macosx_13_0_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-symbolics might be problematic. Click here for more details.

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