Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagelib
Path: blob/master/sage/symbolic/relation.py
4058 views
1
r"""
2
Symbolic Equations and Inequalities
3
4
Sage can solve symbolic equations and inequalities. For
5
example, we derive the quadratic formula as follows::
6
7
sage: a,b,c = var('a,b,c')
8
sage: qe = (a*x^2 + b*x + c == 0)
9
sage: qe
10
a*x^2 + b*x + c == 0
11
sage: print solve(qe, x)
12
[
13
x == -1/2*(b + sqrt(-4*a*c + b^2))/a,
14
x == -1/2*(b - sqrt(-4*a*c + b^2))/a
15
]
16
17
18
The operator, left hand side, and right hand side
19
--------------------------------------------------
20
21
Operators::
22
23
sage: eqn = x^3 + 2/3 >= x - pi
24
sage: eqn.operator()
25
<built-in function ge>
26
sage: (x^3 + 2/3 < x - pi).operator()
27
<built-in function lt>
28
sage: (x^3 + 2/3 == x - pi).operator()
29
<built-in function eq>
30
31
Left hand side::
32
33
sage: eqn = x^3 + 2/3 >= x - pi
34
sage: eqn.lhs()
35
x^3 + 2/3
36
sage: eqn.left()
37
x^3 + 2/3
38
sage: eqn.left_hand_side()
39
x^3 + 2/3
40
41
Right hand side::
42
43
sage: (x + sqrt(2) >= sqrt(3) + 5/2).right()
44
sqrt(3) + 5/2
45
sage: (x + sqrt(2) >= sqrt(3) + 5/2).rhs()
46
sqrt(3) + 5/2
47
sage: (x + sqrt(2) >= sqrt(3) + 5/2).right_hand_side()
48
sqrt(3) + 5/2
49
50
51
Arithmetic
52
----------
53
Add two symbolic equations::
54
55
sage: var('a,b')
56
(a, b)
57
sage: m = 144 == -10 * a + b
58
sage: n = 136 == 10 * a + b
59
sage: m + n
60
280 == 2*b
61
sage: int(-144) + m
62
0 == -10*a + b - 144
63
64
Subtract two symbolic equations::
65
66
sage: var('a,b')
67
(a, b)
68
sage: m = 144 == 20 * a + b
69
sage: n = 136 == 10 * a + b
70
sage: m - n
71
8 == 10*a
72
sage: int(144) - m
73
0 == -20*a - b + 144
74
75
Multiply two symbolic equations::
76
77
sage: x = var('x')
78
sage: m = x == 5*x + 1
79
sage: n = sin(x) == sin(x+2*pi)
80
sage: m * n
81
x*sin(x) == (5*x + 1)*sin(2*pi + x)
82
sage: m = 2*x == 3*x^2 - 5
83
sage: int(-1) * m
84
-2*x == -3*x^2 + 5
85
86
Divide two symbolic equations::
87
88
sage: x = var('x')
89
sage: m = x == 5*x + 1
90
sage: n = sin(x) == sin(x+2*pi)
91
sage: m/n
92
x/sin(x) == (5*x + 1)/sin(2*pi + x)
93
sage: m = x != 5*x + 1
94
sage: n = sin(x) != sin(x+2*pi)
95
sage: m/n
96
x/sin(x) != (5*x + 1)/sin(2*pi + x)
97
98
Substitution
99
------------
100
101
Substitution into relations::
102
103
sage: x, a = var('x, a')
104
sage: eq = (x^3 + a == sin(x/a)); eq
105
x^3 + a == sin(x/a)
106
sage: eq.substitute(x=5*x)
107
125*x^3 + a == sin(5*x/a)
108
sage: eq.substitute(a=1)
109
x^3 + 1 == sin(x)
110
sage: eq.substitute(a=x)
111
x^3 + x == sin(1)
112
sage: eq.substitute(a=x, x=1)
113
x + 1 == sin(1/x)
114
sage: eq.substitute({a:x, x:1})
115
x + 1 == sin(1/x)
116
117
Solving
118
-------
119
120
We can solve equations::
121
122
sage: x = var('x')
123
sage: S = solve(x^3 - 1 == 0, x)
124
sage: S
125
[x == 1/2*I*sqrt(3) - 1/2, x == -1/2*I*sqrt(3) - 1/2, x == 1]
126
sage: S[0]
127
x == 1/2*I*sqrt(3) - 1/2
128
sage: S[0].right()
129
1/2*I*sqrt(3) - 1/2
130
sage: S = solve(x^3 - 1 == 0, x, solution_dict=True)
131
sage: S
132
[{x: 1/2*I*sqrt(3) - 1/2}, {x: -1/2*I*sqrt(3) - 1/2}, {x: 1}]
133
sage: z = 5
134
sage: solve(z^2 == sqrt(3),z)
135
Traceback (most recent call last):
136
...
137
TypeError: 5 is not a valid variable.
138
139
We illustrate finding multiplicities of solutions::
140
141
sage: f = (x-1)^5*(x^2+1)
142
sage: solve(f == 0, x)
143
[x == -I, x == I, x == 1]
144
sage: solve(f == 0, x, multiplicities=True)
145
([x == -I, x == I, x == 1], [1, 1, 5])
146
147
We can also solve many inequalities::
148
149
sage: solve(1/(x-1)<=8,x)
150
[[x < 1], [x >= (9/8)]]
151
152
We can numerically find roots of equations::
153
154
sage: (x == sin(x)).find_root(-2,2)
155
0.0
156
sage: (x^5 + 3*x + 2 == 0).find_root(-2,2,x)
157
-0.6328345202421523
158
sage: (cos(x) == sin(x)).find_root(10,20)
159
19.634954084936208
160
161
We illustrate some valid error conditions::
162
163
sage: (cos(x) != sin(x)).find_root(10,20)
164
Traceback (most recent call last):
165
...
166
ValueError: Symbolic equation must be an equality.
167
sage: (SR(3)==SR(2)).find_root(-1,1)
168
Traceback (most recent call last):
169
...
170
RuntimeError: no zero in the interval, since constant expression is not 0.
171
172
There must be at most one variable::
173
174
sage: x, y = var('x,y')
175
sage: (x == y).find_root(-2,2)
176
Traceback (most recent call last):
177
...
178
NotImplementedError: root finding currently only implemented in 1 dimension.
179
180
Assumptions
181
-----------
182
183
Forgetting assumptions::
184
185
sage: var('x,y')
186
(x, y)
187
sage: forget() #Clear assumptions
188
sage: assume(x>0, y < 2)
189
sage: assumptions()
190
[x > 0, y < 2]
191
sage: (y < 2).forget()
192
sage: assumptions()
193
[x > 0]
194
sage: forget()
195
sage: assumptions()
196
[]
197
198
199
Miscellaneous
200
-------------
201
202
Conversion to Maxima::
203
204
sage: x = var('x')
205
sage: eq = (x^(3/5) >= pi^2 + e^i)
206
sage: eq._maxima_init_()
207
'(x)^(3/5) >= ((%pi)^(2))+(exp(0+%i*1))'
208
sage: e1 = x^3 + x == sin(2*x)
209
sage: z = e1._maxima_()
210
sage: z.parent() is sage.calculus.calculus.maxima
211
True
212
sage: z = e1._maxima_(maxima)
213
sage: z.parent() is maxima
214
True
215
sage: z = maxima(e1)
216
sage: z.parent() is maxima
217
True
218
219
Conversion to Maple::
220
221
sage: x = var('x')
222
sage: eq = (x == 2)
223
sage: eq._maple_init_()
224
'x = 2'
225
226
Comparison::
227
228
sage: x = var('x')
229
sage: (x>0) == (x>0)
230
True
231
sage: (x>0) == (x>1)
232
False
233
sage: (x>0) != (x>1)
234
True
235
236
Variables appearing in the relation::
237
238
sage: var('x,y,z,w')
239
(x, y, z, w)
240
sage: f = (x+y+w) == (x^2 - y^2 - z^3); f
241
w + x + y == x^2 - y^2 - z^3
242
sage: f.variables()
243
(w, x, y, z)
244
245
LaTeX output::
246
247
sage: latex(x^(3/5) >= pi)
248
x^{\left(\frac{3}{5}\right)} \geq \pi
249
250
251
More Examples
252
-------------
253
254
::
255
256
sage: x,y,a = var('x,y,a')
257
sage: f = x^2 + y^2 == 1
258
sage: f.solve(x)
259
[x == -sqrt(-y^2 + 1), x == sqrt(-y^2 + 1)]
260
261
::
262
263
sage: f = x^5 + a
264
sage: solve(f==0,x)
265
[x == (-a)^(1/5)*e^(2/5*I*pi), x == (-a)^(1/5)*e^(4/5*I*pi), x == (-a)^(1/5)*e^(-4/5*I*pi), x == (-a)^(1/5)*e^(-2/5*I*pi), x == (-a)^(1/5)]
266
267
You can also do arithmetic with inequalities, as illustrated
268
below::
269
270
sage: var('x y')
271
(x, y)
272
sage: f = x + 3 == y - 2
273
sage: f
274
x + 3 == y - 2
275
sage: g = f - 3; g
276
x == y - 5
277
sage: h = x^3 + sqrt(2) == x*y*sin(x)
278
sage: h
279
sqrt(2) + x^3 == x*y*sin(x)
280
sage: h - sqrt(2)
281
x^3 == x*y*sin(x) - sqrt(2)
282
sage: h + f
283
x + sqrt(2) + x^3 + 3 == x*y*sin(x) + y - 2
284
sage: f = x + 3 < y - 2
285
sage: g = 2 < x+10
286
sage: f - g
287
x + 1 < -x + y - 12
288
sage: f + g
289
x + 5 < x + y + 8
290
sage: f*(-1)
291
-x - 3 < -y + 2
292
293
TESTS:
294
295
We test serializing symbolic equations::
296
297
sage: eqn = x^3 + 2/3 >= x
298
sage: loads(dumps(eqn))
299
x^3 + 2/3 >= x
300
sage: loads(dumps(eqn)) == eqn
301
True
302
303
AUTHORS:
304
305
- Bobby Moretti: initial version (based on a trick that Robert
306
Bradshaw suggested).
307
308
- William Stein: second version
309
310
- William Stein (2007-07-16): added arithmetic with symbolic equations
311
312
"""
313
import operator
314
from sage.calculus.calculus import maxima
315
316
def test_relation_maxima(relation):
317
"""
318
Return True if this (in)equality is definitely true. Return False
319
if it is false or the algorithm for testing (in)equality is
320
inconclusive.
321
322
EXAMPLES::
323
324
sage: from sage.symbolic.relation import test_relation_maxima
325
sage: k = var('k')
326
sage: pol = 1/(k-1) - 1/k -1/k/(k-1);
327
sage: test_relation_maxima(pol == 0)
328
True
329
sage: f = sin(x)^2 + cos(x)^2 - 1
330
sage: test_relation_maxima(f == 0)
331
True
332
sage: test_relation_maxima( x == x )
333
True
334
sage: test_relation_maxima( x != x )
335
False
336
sage: test_relation_maxima( x > x )
337
False
338
sage: test_relation_maxima( x^2 > x )
339
False
340
sage: test_relation_maxima( x + 2 > x )
341
True
342
sage: test_relation_maxima( x - 2 > x )
343
False
344
345
Here are some examples involving assumptions::
346
347
sage: x, y, z = var('x, y, z')
348
sage: assume(x>=y,y>=z,z>=x)
349
sage: test_relation_maxima(x==z)
350
True
351
sage: test_relation_maxima(z<x)
352
False
353
sage: test_relation_maxima(z>y)
354
False
355
sage: test_relation_maxima(y==z)
356
True
357
sage: forget()
358
sage: assume(x>=1,x<=1)
359
sage: test_relation_maxima(x==1)
360
True
361
sage: test_relation_maxima(x>1)
362
False
363
sage: test_relation_maxima(x>=1)
364
True
365
sage: test_relation_maxima(x!=1)
366
False
367
sage: test_relation_maxima(x<>1) # alternate syntax for not equal
368
False
369
sage: forget()
370
sage: assume(x>0)
371
sage: test_relation_maxima(x==0)
372
False
373
sage: test_relation_maxima(x>-1)
374
True
375
sage: test_relation_maxima(x!=0)
376
True
377
sage: test_relation_maxima(x!=1)
378
False
379
sage: forget()
380
"""
381
m = relation._maxima_()
382
383
#Handle some basic cases first
384
if repr(m) in ['0=0']:
385
return True
386
elif repr(m) in ['0#0', '1#1']:
387
return False
388
389
if relation.operator() == operator.eq: # operator is equality
390
try:
391
s = m.parent()._eval_line('is (equal(%s,%s))'%(repr(m.lhs()),repr(m.rhs())))
392
except TypeError, msg:
393
raise ValueError, "unable to evaluate the predicate '%s'"%repr(relation)
394
395
elif relation.operator() == operator.ne: # operator is not equal
396
try:
397
s = m.parent()._eval_line('is (notequal(%s,%s))'%(repr(m.lhs()),repr(m.rhs())))
398
except TypeError, msg:
399
raise ValueError, "unable to evaluate the predicate '%s'"%repr(relation)
400
401
else: # operator is < or > or <= or >=, which Maxima handles fine
402
try:
403
s = m.parent()._eval_line('is (%s)'%repr(m))
404
except TypeError, msg:
405
raise ValueError, "unable to evaluate the predicate '%s'"%repr(relation)
406
407
if s == 'true':
408
return True
409
elif s == 'false':
410
return False # if neither of these, s=='unknown' and we try a few other tricks
411
412
if relation.operator() != operator.eq:
413
return False
414
415
difference = relation.lhs() - relation.rhs()
416
if repr(difference) == '0':
417
return True
418
419
#Try to apply some simplifications to see if left - right == 0
420
simp_list = [difference.simplify_log, difference.simplify_rational, difference.simplify_exp,difference.simplify_radical,difference.simplify_trig]
421
for f in simp_list:
422
try:
423
if repr( f() ).strip() == "0":
424
return True
425
break
426
except:
427
pass
428
return False
429
430
431
def string_to_list_of_solutions(s):
432
r"""
433
Used internally by the symbolic solve command to convert the output
434
of Maxima's solve command to a list of solutions in Sage's symbolic
435
package.
436
437
EXAMPLES:
438
439
We derive the (monic) quadratic formula::
440
441
sage: var('x,a,b')
442
(x, a, b)
443
sage: solve(x^2 + a*x + b == 0, x)
444
[x == -1/2*a - 1/2*sqrt(a^2 - 4*b), x == -1/2*a + 1/2*sqrt(a^2 - 4*b)]
445
446
Behind the scenes when the above is evaluated the function
447
:func:`string_to_list_of_solutions` is called with input the
448
string `s` below::
449
450
sage: s = '[x=-(sqrt(a^2-4*b)+a)/2,x=(sqrt(a^2-4*b)-a)/2]'
451
sage: sage.symbolic.relation.string_to_list_of_solutions(s)
452
[x == -1/2*a - 1/2*sqrt(a^2 - 4*b), x == -1/2*a + 1/2*sqrt(a^2 - 4*b)]
453
"""
454
from sage.categories.all import Objects
455
from sage.structure.sequence import Sequence
456
from sage.calculus.calculus import symbolic_expression_from_maxima_string
457
v = symbolic_expression_from_maxima_string(s, equals_sub=True)
458
return Sequence(v, universe=Objects(), cr_str=True)
459
460
###########
461
# Solving #
462
###########
463
464
def solve(f, *args, **kwds):
465
r"""
466
Algebraically solve an equation or system of equations (over the
467
complex numbers) for given variables. Inequalities and systems
468
of inequalities are also supported.
469
470
INPUT:
471
472
- ``f`` - equation or system of equations (given by a
473
list or tuple)
474
475
- ``*args`` - variables to solve for.
476
477
- ``solution_dict`` - bool (default: False); if True or non-zero,
478
return a list of dictionaries containing the solutions. If there
479
are no solutions, return an empty list (rather than a list containing
480
an empty dictionary). Likewise, if there's only a single solution,
481
return a list containing one dictionary with that solution.
482
483
EXAMPLES::
484
485
sage: x, y = var('x, y')
486
sage: solve([x+y==6, x-y==4], x, y)
487
[[x == 5, y == 1]]
488
sage: solve([x^2+y^2 == 1, y^2 == x^3 + x + 1], x, y)
489
[[x == -1/2*I*sqrt(3) - 1/2, y == -sqrt(-1/2*I*sqrt(3) + 3/2)],
490
[x == -1/2*I*sqrt(3) - 1/2, y == sqrt(-1/2*I*sqrt(3) + 3/2)],
491
[x == 1/2*I*sqrt(3) - 1/2, y == -sqrt(1/2*I*sqrt(3) + 3/2)],
492
[x == 1/2*I*sqrt(3) - 1/2, y == sqrt(1/2*I*sqrt(3) + 3/2)],
493
[x == 0, y == -1],
494
[x == 0, y == 1]]
495
sage: solve([sqrt(x) + sqrt(y) == 5, x + y == 10], x, y)
496
[[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]]
497
sage: solutions=solve([x^2+y^2 == 1, y^2 == x^3 + x + 1], x, y, solution_dict=True)
498
sage: for solution in solutions: print solution[x].n(digits=3), ",", solution[y].n(digits=3)
499
-0.500 - 0.866*I , -1.27 + 0.341*I
500
-0.500 - 0.866*I , 1.27 - 0.341*I
501
-0.500 + 0.866*I , -1.27 - 0.341*I
502
-0.500 + 0.866*I , 1.27 + 0.341*I
503
0.000 , -1.00
504
0.000 , 1.00
505
506
Whenever possible, answers will be symbolic, but with systems of
507
equations, at times approximations will be given, due to the
508
underlying algorithm in Maxima::
509
510
sage: sols = solve([x^3==y,y^2==x],[x,y]); sols[-1], sols[0]
511
([x == 0, y == 0], [x == (0.309016994375 + 0.951056516295*I), y == (-0.809016994375 - 0.587785252292*I)])
512
sage: sols[0][0].rhs().pyobject().parent()
513
Complex Double Field
514
515
If ``f`` is only one equation or expression, we use the solve method
516
for symbolic expressions, which defaults to exact answers only::
517
518
sage: solve([y^6==y],y)
519
[y == e^(2/5*I*pi), y == e^(4/5*I*pi), y == e^(-4/5*I*pi), y == e^(-2/5*I*pi), y == 1, y == 0]
520
sage: solve( [y^6 == y], y)==solve( y^6 == y, y)
521
True
522
523
.. note::
524
525
For more details about solving a single equations, see
526
the documentation for its solve.
527
528
::
529
530
sage: from sage.symbolic.expression import Expression
531
sage: Expression.solve(x^2==1,x)
532
[x == -1, x == 1]
533
534
We must solve with respect to actual variables::
535
536
sage: z = 5
537
sage: solve([8*z + y == 3, -z +7*y == 0],y,z)
538
Traceback (most recent call last):
539
...
540
TypeError: 5 is not a valid variable.
541
542
If we ask for dictionaries containing the solutions, we get them::
543
544
sage: solve([x^2-1],x,solution_dict=True)
545
[{x: -1}, {x: 1}]
546
sage: solve([x^2-4*x+4],x,solution_dict=True)
547
[{x: 2}]
548
sage: res = solve([x^2 == y, y == 4],x,y,solution_dict=True)
549
sage: for soln in res: print "x: %s, y: %s"%(soln[x], soln[y])
550
x: 2, y: 4
551
x: -2, y: 4
552
553
If there is a parameter in the answer, that will show up as
554
a new variable. In the following example, ``r1`` is a real free
555
variable (because of the ``r``)::
556
557
sage: solve([x+y == 3, 2*x+2*y == 6],x,y)
558
[[x == -r1 + 3, y == r1]]
559
560
Especially with trigonometric functions, the dummy variable may
561
be implicitly an integer (hence the ``z``)::
562
563
sage: solve([cos(x)*sin(x) == 1/2, x+y == 0],x,y)
564
[[x == 1/4*pi + pi*z68, y == -1/4*pi - pi*z68]]
565
566
Expressions which are not equations are assumed to be set equal
567
to zero, as with `x` in the following example::
568
569
sage: solve([x, y == 2],x,y)
570
[[x == 0, y == 2]]
571
572
If ``True`` appears in the list of equations it is
573
ignored, and if ``False`` appears in the list then no
574
solutions are returned. E.g., note that the first
575
``3==3`` evaluates to ``True``, not to a
576
symbolic equation.
577
578
::
579
580
sage: solve([3==3, 1.00000000000000*x^3 == 0], x)
581
[x == 0]
582
sage: solve([1.00000000000000*x^3 == 0], x)
583
[x == 0]
584
585
Here, the first equation evaluates to ``False``, so
586
there are no solutions::
587
588
sage: solve([1==3, 1.00000000000000*x^3 == 0], x)
589
[]
590
591
Completely symbolic solutions are supported::
592
593
sage: var('s,j,b,m,g')
594
(s, j, b, m, g)
595
sage: sys = [ m*(1-s) - b*s*j, b*s*j-g*j ];
596
sage: solve(sys,s,j)
597
[[s == 1, j == 0], [s == g/b, j == (b - g)*m/(b*g)]]
598
sage: solve(sys,(s,j))
599
[[s == 1, j == 0], [s == g/b, j == (b - g)*m/(b*g)]]
600
sage: solve(sys,[s,j])
601
[[s == 1, j == 0], [s == g/b, j == (b - g)*m/(b*g)]]
602
603
Inequalities can be also solved::
604
605
sage: solve(x^2>8,x)
606
[[x < -2*sqrt(2)], [x > 2*sqrt(2)]]
607
608
Use use_grobner if no solution is obtained from to_poly_solve::
609
610
sage: x,y=var('x y'); c1(x,y)=(x-5)^2+y^2-16; c2(x,y)=(y-3)^2+x^2-9
611
sage: solve([c1(x,y),c2(x,y)],[x,y])
612
[[x == -9/68*sqrt(55) + 135/68, y == -15/68*sqrt(5)*sqrt(11) + 123/68], [x == 9/68*sqrt(55) + 135/68, y == 15/68*sqrt(5)*sqrt(11) + 123/68]]
613
614
TESTS::
615
616
sage: solve([sin(x)==x,y^2==x],x,y)
617
[sin(x) == x, y^2 == x]
618
sage: solve(0==1,x)
619
Traceback (most recent call last):
620
...
621
TypeError: The first argument must be a symbolic expression or a list of symbolic expressions.
622
623
Test if the empty list is returned, too, when (a list of)
624
dictionaries (is) are requested (#8553)::
625
626
sage: solve([0==1],x)
627
[]
628
sage: solve([0==1],x,solution_dict=True)
629
[]
630
sage: solve([x==1,x==-1],x)
631
[]
632
sage: solve([x==1,x==-1],x,solution_dict=True)
633
[]
634
sage: solve((x==1,x==-1),x,solution_dict=0)
635
[]
636
637
Relaxed form, suggested by Mike Hansen (#8553)::
638
639
sage: solve([x^2-1],x,solution_dict=-1)
640
[{x: -1}, {x: 1}]
641
sage: solve([x^2-1],x,solution_dict=1)
642
[{x: -1}, {x: 1}]
643
sage: solve((x==1,x==-1),x,solution_dict=-1)
644
[]
645
sage: solve((x==1,x==-1),x,solution_dict=1)
646
[]
647
648
This inequality holds for any real ``x`` (trac #8078)::
649
650
sage: solve(x^4+2>0,x)
651
[x < +Infinity]
652
653
"""
654
from sage.symbolic.expression import is_Expression
655
if is_Expression(f): # f is a single expression
656
ans = f.solve(*args,**kwds)
657
return ans
658
659
if not isinstance(f, (list, tuple)):
660
raise TypeError("The first argument must be a symbolic expression or a list of symbolic expressions.")
661
662
if len(f)==1 and is_Expression(f[0]):
663
# f is a list with a single expression
664
return f[0].solve(*args,**kwds)
665
666
# f is a list of such expressions or equations
667
from sage.symbolic.ring import is_SymbolicVariable
668
669
if len(args)==0:
670
raise TypeError, "Please input variables to solve for."
671
if is_SymbolicVariable(args[0]):
672
variables = args
673
else:
674
variables = tuple(args[0])
675
676
for v in variables:
677
if not is_SymbolicVariable(v):
678
raise TypeError, "%s is not a valid variable."%v
679
680
try:
681
f = [s for s in f if s is not True]
682
except TypeError:
683
raise ValueError, "Unable to solve %s for %s"%(f, args)
684
685
if any(s is False for s in f):
686
return []
687
688
from sage.calculus.calculus import maxima
689
m = maxima(f)
690
691
try:
692
s = m.solve(variables)
693
except: # if Maxima gave an error, try its to_poly_solve
694
try:
695
s = m.to_poly_solve(variables)
696
except TypeError, mess: # if that gives an error, raise an error.
697
if "Error executing code in Maxima" in str(mess):
698
raise ValueError, "Sage is unable to determine whether the system %s can be solved for %s"%(f,args)
699
else:
700
raise
701
702
if len(s)==0: # if Maxima's solve gave no solutions, try its to_poly_solve
703
try:
704
s = m.to_poly_solve(variables)
705
except: # if that gives an error, stick with no solutions
706
s = []
707
708
if len(s)==0: # if to_poly_solve gave no solutions, try use_grobner
709
try:
710
s = m.to_poly_solve(variables,'use_grobner=true')
711
except: # if that gives an error, stick with no solutions
712
s = []
713
714
sol_list = string_to_list_of_solutions(repr(s))
715
716
# Relaxed form suggested by Mike Hansen (#8553):
717
if kwds.get('solution_dict', False):
718
if len(sol_list)==0: # fixes IndexError on empty solution list (#8553)
719
return []
720
if isinstance(sol_list[0], list):
721
sol_dict=[dict([[eq.left(),eq.right()] for eq in solution])
722
for solution in sol_list]
723
else:
724
sol_dict=[{eq.left():eq.right()} for eq in sol_list]
725
726
return sol_dict
727
else:
728
return sol_list
729
730
def solve_mod(eqns, modulus, solution_dict = False):
731
r"""
732
Return all solutions to an equation or list of equations modulo the
733
given integer modulus. Each equation must involve only polynomials
734
in 1 or many variables.
735
736
By default the solutions are returned as `n`-tuples, where `n`
737
is the number of variables appearing anywhere in the given
738
equations. The variables are in alphabetical order.
739
740
INPUT:
741
742
743
- ``eqns`` - equation or list of equations
744
745
- ``modulus`` - an integer
746
747
- ``solution_dict`` - bool (default: False); if True or non-zero,
748
return a list of dictionaries containing the solutions. If there
749
are no solutions, return an empty list (rather than a list containing
750
an empty dictionary). Likewise, if there's only a single solution,
751
return a list containing one dictionary with that solution.
752
753
754
EXAMPLES::
755
756
sage: var('x,y')
757
(x, y)
758
sage: solve_mod([x^2 + 2 == x, x^2 + y == y^2], 14)
759
[(4, 2), (4, 6), (4, 9), (4, 13)]
760
sage: solve_mod([x^2 == 1, 4*x == 11], 15)
761
[(14,)]
762
763
Fermat's equation modulo 3 with exponent 5::
764
765
sage: var('x,y,z')
766
(x, y, z)
767
sage: solve_mod([x^5 + y^5 == z^5], 3)
768
[(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)]
769
770
We can solve with respect to a bigger modulus if it consists only of small prime factors::
771
772
sage: [d] = solve_mod([5*x + y == 3, 2*x - 3*y == 9], 3*5*7*11*19*23*29, solution_dict = True)
773
sage: d[x]
774
12915279
775
sage: d[y]
776
8610183
777
778
For cases where there are relatively few solutions and the prime
779
factors are small, this can be efficient even if the modulus itself
780
is large::
781
782
sage: sorted(solve_mod([x^2 == 41], 10^20))
783
[(4538602480526452429,), (11445932736758703821,), (38554067263241296179,),
784
(45461397519473547571,), (54538602480526452429,), (61445932736758703821,),
785
(88554067263241296179,), (95461397519473547571,)]
786
787
We solve a simple equation modulo 2::
788
789
sage: x,y = var('x,y')
790
sage: solve_mod([x == y], 2)
791
[(0, 0), (1, 1)]
792
793
.. warning::
794
795
The current implementation splits the modulus into prime
796
powers, then naively enumerates all possible solutions
797
(starting modulo primes and then working up through prime
798
powers), and finally combines the solution using the Chinese
799
Remainder Theorem. The interface is good, but the algorithm is
800
very inefficient if the modulus has some larger prime factors! Sage
801
*does* have the ability to do something much faster in certain
802
cases at least by using Groebner basis, linear algebra
803
techniques, etc. But for a lot of toy problems this function as
804
is might be useful. At least it establishes an interface.
805
806
807
TESTS:
808
809
Make sure that we short-circuit in at least some cases::
810
811
sage: solve_mod([2*x==1], 2*next_prime(10^50))
812
[]
813
814
Try multi-equation cases::
815
816
sage: x, y, z = var("x y z")
817
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)
818
[(0, 0), (4, 4), (0, 3), (4, 7)]
819
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]
820
sage: solve_mod(eqs, 11)
821
[(8, 5, 6)]
822
823
Confirm that modulus 1 now behaves as it should::
824
825
sage: x, y = var("x y")
826
sage: solve_mod([x==1], 1)
827
[(0,)]
828
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)
829
[(0, 0)]
830
831
832
"""
833
from sage.rings.all import Integer, Integers, crt_basis
834
from sage.symbolic.expression import is_Expression
835
from sage.misc.all import cartesian_product_iterator
836
from sage.modules.all import vector
837
from sage.matrix.all import matrix
838
839
if not isinstance(eqns, (list, tuple)):
840
eqns = [eqns]
841
eqns = [eq if is_Expression(eq) else (eq.lhs()-eq.rhs()) for eq in eqns]
842
modulus = Integer(modulus)
843
if modulus < 1:
844
raise ValueError, "the modulus must be a positive integer"
845
vars = list(set(sum([list(e.variables()) for e in eqns], [])))
846
vars.sort(key=repr)
847
848
if modulus == 1: # degenerate case
849
ans = [tuple(Integers(1)(0) for v in vars)]
850
return ans
851
852
factors = modulus.factor()
853
crt_basis = vector(Integers(modulus), crt_basis([p**i for p,i in factors]))
854
solutions = []
855
856
has_solution = True
857
for p,i in factors:
858
solution =_solve_mod_prime_power(eqns, p, i, vars)
859
if len(solution) > 0:
860
solutions.append(solution)
861
else:
862
has_solution = False
863
break
864
865
866
ans = []
867
if has_solution:
868
for solution in cartesian_product_iterator(solutions):
869
solution_mat = matrix(Integers(modulus), solution)
870
ans.append(tuple(c.dot_product(crt_basis) for c in solution_mat.columns()))
871
872
# if solution_dict == True:
873
# Relaxed form suggested by Mike Hansen (#8553):
874
if solution_dict:
875
sol_dict = [dict(zip(vars, solution)) for solution in ans]
876
return sol_dict
877
else:
878
return ans
879
880
def _solve_mod_prime_power(eqns, p, m, vars):
881
r"""
882
Internal help function for solve_mod, does little checking since it expects
883
solve_mod to do that
884
885
Return all solutions to an equation or list of equations modulo p^m.
886
Each equation must involve only polynomials
887
in 1 or many variables.
888
889
The solutions are returned as `n`-tuples, where `n`
890
is the number of variables in vars.
891
892
INPUT:
893
894
895
- ``eqns`` - equation or list of equations
896
897
- ``p`` - a prime
898
899
- ``i`` - an integer > 0
900
901
- ``vars`` - a list of variables to solve for
902
903
904
EXAMPLES::
905
906
sage: var('x,y')
907
(x, y)
908
sage: solve_mod([x^2 + 2 == x, x^2 + y == y^2], 14)
909
[(4, 2), (4, 6), (4, 9), (4, 13)]
910
sage: solve_mod([x^2 == 1, 4*x == 11], 15)
911
[(14,)]
912
913
Fermat's equation modulo 3 with exponent 5::
914
915
sage: var('x,y,z')
916
(x, y, z)
917
sage: solve_mod([x^5 + y^5 == z^5], 3)
918
[(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)]
919
920
We solve a simple equation modulo 2::
921
922
sage: x,y = var('x,y')
923
sage: solve_mod([x == y], 2)
924
[(0, 0), (1, 1)]
925
926
927
.. warning::
928
929
Currently this constructs possible solutions by building up
930
from the smallest prime factor of the modulus. The interface
931
is good, but the algorithm is horrible if the modulus isn't the
932
product of many small primes! Sage *does* have the ability to
933
do something much faster in certain cases at least by using the
934
Chinese Remainder Theorem, Groebner basis, linear algebra
935
techniques, etc. But for a lot of toy problems this function as
936
is might be useful. At the very least, it establishes an
937
interface.
938
939
TESTS:
940
941
Confirm we can reproduce the first few terms of OEIS A187719::
942
943
sage: from sage.symbolic.relation import _solve_mod_prime_power
944
sage: [sorted(_solve_mod_prime_power([x^2==41], 10, i, [x]))[0][0] for i in [1..13]]
945
[1, 21, 71, 1179, 2429, 47571, 1296179, 8703821, 26452429, 526452429,
946
13241296179, 19473547571, 2263241296179]
947
948
"""
949
from sage.rings.all import Integers, PolynomialRing
950
from sage.modules.all import vector
951
from sage.misc.all import cartesian_product_iterator
952
953
mrunning = 1
954
ans = []
955
for mi in xrange(m):
956
mrunning *= p
957
R = Integers(mrunning)
958
S = PolynomialRing(R, len(vars), vars)
959
eqns_mod = [S(eq) for eq in eqns]
960
if mi == 0:
961
possibles = cartesian_product_iterator([xrange(len(R)) for _ in xrange(len(vars))])
962
else:
963
shifts = cartesian_product_iterator([xrange(p) for _ in xrange(len(vars))])
964
pairs = cartesian_product_iterator([shifts, ans])
965
possibles = (tuple(vector(t)+vector(shift)*(mrunning//p)) for shift, t in pairs)
966
ans = list(t for t in possibles if all(e(*t) == 0 for e in eqns_mod))
967
if not ans: return ans
968
969
return ans
970
971
def solve_ineq_univar(ineq):
972
"""
973
Function solves rational inequality in one variable.
974
975
INPUT:
976
977
- ``ineq`` - inequality in one variable
978
979
OUTPUT:
980
981
- ``list`` -- output is list of solutions as a list of simple inequalities
982
output [A,B,C] means (A or B or C) each A, B, C is again a list and
983
if A=[a,b], then A means (a and b). The list is empty if there is no
984
solution.
985
986
EXAMPLES::
987
988
sage: from sage.symbolic.relation import solve_ineq_univar
989
sage: solve_ineq_univar(x-1/x>0)
990
[[x > -1, x < 0], [x > 1]]
991
992
sage: solve_ineq_univar(x^2-1/x>0)
993
[[x < 0], [x > 1]]
994
995
sage: solve_ineq_univar((x^3-1)*x<=0)
996
[[x >= 0, x <= 1]]
997
998
ALGORITHM:
999
1000
Calls Maxima command solve_rat_ineq
1001
1002
AUTHORS:
1003
1004
- Robert Marik (01-2010)
1005
"""
1006
ineqvar = ineq.variables()
1007
if len(ineqvar) != 1:
1008
raise NotImplementedError, "The command solve_ineq_univar accepts univariate inequalities only. Your variables are ", ineqvar
1009
ineq0 = ineq._maxima_()
1010
ineq0.parent().eval("if solve_rat_ineq_loaded#true then (solve_rat_ineq_loaded:true,load(\"solve_rat_ineq.mac\")) ")
1011
sol = ineq0.solve_rat_ineq().sage()
1012
if repr(sol)=="all":
1013
from sage.rings.infinity import Infinity
1014
sol = [ineqvar[0]<Infinity]
1015
return sol
1016
1017
def solve_ineq_fourier(ineq,vars=None):
1018
"""
1019
Solves sytem of inequalities using Maxima and fourier elimination
1020
1021
Can be used for system of linear inequalities and for some types
1022
of nonlinear inequalities. For examples see the section EXAMPLES
1023
below and http://maxima.cvs.sourceforge.net/viewvc/maxima/maxima/share/contrib/fourier_elim/rtest_fourier_elim.mac
1024
1025
1026
INPUT:
1027
1028
- ``ineq`` - list with system of inequalities
1029
1030
- ``vars`` - optionally list with variables for fourier elimination.
1031
1032
OUTPUT:
1033
1034
- ``list`` - output is list of solutions as a list of simple inequalities
1035
output [A,B,C] means (A or B or C) each A, B, C is again a list and
1036
if A=[a,b], then A means (a and b). The list is empty if there is no
1037
solution.
1038
1039
EXAMPLES::
1040
1041
sage: from sage.symbolic.relation import solve_ineq_fourier
1042
sage: y=var('y')
1043
sage: solve_ineq_fourier([x+y<9,x-y>4],[x,y])
1044
[[y + 4 < x, x < -y + 9, y < (5/2)]]
1045
sage: solve_ineq_fourier([x+y<9,x-y>4],[y,x])
1046
[[y < min(x - 4, -x + 9)]]
1047
1048
sage: solve_ineq_fourier([x^2>=0])
1049
[[x < +Infinity]]
1050
1051
sage: solve_ineq_fourier([log(x)>log(y)],[x,y])
1052
[[y < x, 0 < y]]
1053
sage: solve_ineq_fourier([log(x)>log(y)],[y,x])
1054
[[0 < y, y < x, 0 < x]]
1055
1056
Note that different systems will find default variables in different
1057
orders, so the following is not tested::
1058
1059
sage: solve_ineq_fourier([log(x)>log(y)]) # not tested - one of the following appears
1060
[[0 < y, y < x, 0 < x]]
1061
[[y < x, 0 < y]]
1062
1063
ALGORITHM:
1064
1065
Calls Maxima command fourier_elim
1066
1067
AUTHORS:
1068
1069
- Robert Marik (01-2010)
1070
"""
1071
if vars is None:
1072
setvars = set([])
1073
for i in (ineq):
1074
setvars = setvars.union(set(i.variables()))
1075
vars =[i for i in setvars]
1076
ineq0 = [i._maxima_() for i in ineq]
1077
ineq0[0].parent().eval("if fourier_elim_loaded#true then (fourier_elim_loaded:true,load(\"fourier_elim\"))")
1078
sol = ineq0[0].parent().fourier_elim(ineq0,vars)
1079
ineq0[0].parent().eval("or_to_list(x):=\
1080
if not atom(x) and op(x)=\"or\" then args(x) \
1081
else [x]")
1082
sol = sol.or_to_list().sage()
1083
if repr(sol) == "[emptyset]":
1084
sol = []
1085
if repr(sol) == "[universalset]":
1086
from sage.rings.infinity import Infinity
1087
sol = [[i<Infinity for i in vars]]
1088
return sol
1089
1090
def solve_ineq(ineq, vars=None):
1091
"""
1092
Solves inequalities and systems of inequalities using Maxima.
1093
Switches between rational inequalities
1094
(sage.symbolic.relation.solve_ineq_rational)
1095
and fourier elimination (sage.symbolic.relation.solve_ineq_fouried).
1096
See the documentation of these functions for more details.
1097
1098
INPUT:
1099
1100
- ``ineq`` - one inequality or a list of inequalities
1101
1102
Case1: If ``ineq`` is one equality, then it should be rational
1103
expression in one varible. This input is passed to
1104
sage.symbolic.relation.solve_ineq_univar function.
1105
1106
Case2: If ``ineq`` is a list involving one or more
1107
inequalities, than the input is passed to
1108
sage.symbolic.relation.solve_ineq_fourier function. This
1109
function can be used for system of linear inequalities and
1110
for some types of nonlinear inequalities. See
1111
http://maxima.cvs.sourceforge.net/viewvc/maxima/maxima/share/contrib/fourier_elim/rtest_fourier_elim.mac
1112
for a big gallery of problems covered by this algorithm.
1113
1114
- ``vars`` - optional parameter with list of variables. This list
1115
is used only if fourier elimination is used. If omitted or if
1116
rational inequality is solved, then variables are determined
1117
automatically.
1118
1119
OUTPUT:
1120
1121
- ``list`` -- output is list of solutions as a list of simple inequalities
1122
output [A,B,C] means (A or B or C) each A, B, C is again a list and
1123
if A=[a,b], then A means (a and b).
1124
1125
EXAMPLES::
1126
1127
sage: from sage.symbolic.relation import solve_ineq
1128
1129
Inequalities in one variable. The variable is detected automatically::
1130
1131
sage: solve_ineq(x^2-1>3)
1132
[[x < -2], [x > 2]]
1133
1134
sage: solve_ineq(1/(x-1)<=8)
1135
[[x < 1], [x >= (9/8)]]
1136
1137
System of inequalities with automatically detected inequalities::
1138
1139
sage: y=var('y')
1140
sage: solve_ineq([x-y<0,x+y-3<0],[y,x])
1141
[[x < y, y < -x + 3, x < (3/2)]]
1142
sage: solve_ineq([x-y<0,x+y-3<0],[x,y])
1143
[[x < min(-y + 3, y)]]
1144
1145
Note that although Sage will detect the variables automatically,
1146
the order it puts them in may depend on the system, so the following
1147
command is only guaranteed to give you one of the above answers::
1148
1149
sage: solve_ineq([x-y<0,x+y-3<0]) # not tested - random
1150
[[x < y, y < -x + 3, x < (3/2)]]
1151
1152
ALGORITHM:
1153
1154
Calls solve_ineq_fourier if inequalities are list and
1155
solve_ineq_univar of the inequality is symbolic expression. See
1156
the description of these commands for more details related to the
1157
set of inequalities which can be solved. The list is empty if
1158
there is no solution.
1159
1160
AUTHORS:
1161
1162
- Robert Marik (01-2010)
1163
"""
1164
if isinstance(ineq,list):
1165
return(solve_ineq_fourier(ineq, vars))
1166
else:
1167
return(solve_ineq_univar(ineq))
1168
1169