Symbolic Equations and Inequalities

Sage can solve symbolic equations and inequalities. For example, we derive the quadratic formula as follows:

sage: a,b,c = var('a,b,c')
sage: qe = (a*x^2 + b*x + c == 0)
sage: qe
a*x^2 + b*x + c == 0
sage: print(solve(qe, x))                                                           # needs sage.libs.maxima
[
x == -1/2*(b + sqrt(b^2 - 4*a*c))/a,
x == -1/2*(b - sqrt(b^2 - 4*a*c))/a
]
>>> from sage.all import *
>>> a,b,c = var('a,b,c')
>>> qe = (a*x**Integer(2) + b*x + c == Integer(0))
>>> qe
a*x^2 + b*x + c == 0
>>> print(solve(qe, x))                                                           # needs sage.libs.maxima
[
x == -1/2*(b + sqrt(b^2 - 4*a*c))/a,
x == -1/2*(b - sqrt(b^2 - 4*a*c))/a
]
a,b,c = var('a,b,c')
qe = (a*x^2 + b*x + c == 0)
qe
print(solve(qe, x))                                                           # needs sage.libs.maxima

The operator, left hand side, and right hand side

Operators:

sage: eqn = x^3 + 2/3 >= x - pi
sage: eqn.operator()
<built-in function ge>
sage: (x^3 + 2/3 < x - pi).operator()
<built-in function lt>
sage: (x^3 + 2/3 == x - pi).operator()
<built-in function eq>
>>> from sage.all import *
>>> eqn = x**Integer(3) + Integer(2)/Integer(3) >= x - pi
>>> eqn.operator()
<built-in function ge>
>>> (x**Integer(3) + Integer(2)/Integer(3) < x - pi).operator()
<built-in function lt>
>>> (x**Integer(3) + Integer(2)/Integer(3) == x - pi).operator()
<built-in function eq>
eqn = x^3 + 2/3 >= x - pi
eqn.operator()
(x^3 + 2/3 < x - pi).operator()
(x^3 + 2/3 == x - pi).operator()

Left hand side:

sage: eqn = x^3 + 2/3 >= x - pi
sage: eqn.lhs()
x^3 + 2/3
sage: eqn.left()
x^3 + 2/3
sage: eqn.left_hand_side()
x^3 + 2/3
>>> from sage.all import *
>>> eqn = x**Integer(3) + Integer(2)/Integer(3) >= x - pi
>>> eqn.lhs()
x^3 + 2/3
>>> eqn.left()
x^3 + 2/3
>>> eqn.left_hand_side()
x^3 + 2/3
eqn = x^3 + 2/3 >= x - pi
eqn.lhs()
eqn.left()
eqn.left_hand_side()

Right hand side:

sage: (x + sqrt(2) >= sqrt(3) + 5/2).right()
sqrt(3) + 5/2
sage: (x + sqrt(2) >= sqrt(3) + 5/2).rhs()
sqrt(3) + 5/2
sage: (x + sqrt(2) >= sqrt(3) + 5/2).right_hand_side()
sqrt(3) + 5/2
>>> from sage.all import *
>>> (x + sqrt(Integer(2)) >= sqrt(Integer(3)) + Integer(5)/Integer(2)).right()
sqrt(3) + 5/2
>>> (x + sqrt(Integer(2)) >= sqrt(Integer(3)) + Integer(5)/Integer(2)).rhs()
sqrt(3) + 5/2
>>> (x + sqrt(Integer(2)) >= sqrt(Integer(3)) + Integer(5)/Integer(2)).right_hand_side()
sqrt(3) + 5/2
(x + sqrt(2) >= sqrt(3) + 5/2).right()
(x + sqrt(2) >= sqrt(3) + 5/2).rhs()
(x + sqrt(2) >= sqrt(3) + 5/2).right_hand_side()

Arithmetic

Add two symbolic equations:

sage: var('a,b')
(a, b)
sage: m = 144 == -10 * a + b
sage: n = 136 == 10 * a + b
sage: m + n
280 == 2*b
sage: int(-144) + m
0 == -10*a + b - 144
>>> from sage.all import *
>>> var('a,b')
(a, b)
>>> m = Integer(144) == -Integer(10) * a + b
>>> n = Integer(136) == Integer(10) * a + b
>>> m + n
280 == 2*b
>>> int(-Integer(144)) + m
0 == -10*a + b - 144
var('a,b')
m = 144 == -10 * a + b
n = 136 == 10 * a + b
m + n
int(-144) + m

Subtract two symbolic equations:

sage: var('a,b')
(a, b)
sage: m = 144 == 20 * a + b
sage: n = 136 == 10 * a + b
sage: m - n
8 == 10*a
sage: int(144) - m
0 == -20*a - b + 144
>>> from sage.all import *
>>> var('a,b')
(a, b)
>>> m = Integer(144) == Integer(20) * a + b
>>> n = Integer(136) == Integer(10) * a + b
>>> m - n
8 == 10*a
>>> int(Integer(144)) - m
0 == -20*a - b + 144
var('a,b')
m = 144 == 20 * a + b
n = 136 == 10 * a + b
m - n
int(144) - m

Multiply two symbolic equations:

sage: x = var('x')
sage: m = x == 5*x + 1
sage: n = sin(x) == sin(x+2*pi, hold=True)
sage: m * n
x*sin(x) == (5*x + 1)*sin(2*pi + x)
sage: m = 2*x == 3*x^2 - 5
sage: int(-1) * m
-2*x == -3*x^2 + 5
>>> from sage.all import *
>>> x = var('x')
>>> m = x == Integer(5)*x + Integer(1)
>>> n = sin(x) == sin(x+Integer(2)*pi, hold=True)
>>> m * n
x*sin(x) == (5*x + 1)*sin(2*pi + x)
>>> m = Integer(2)*x == Integer(3)*x**Integer(2) - Integer(5)
>>> int(-Integer(1)) * m
-2*x == -3*x^2 + 5
x = var('x')
m = x == 5*x + 1
n = sin(x) == sin(x+2*pi, hold=True)
m * n
m = 2*x == 3*x^2 - 5
int(-1) * m

Divide two symbolic equations:

sage: x = var('x')
sage: m = x == 5*x + 1
sage: n = sin(x) == sin(x+2*pi, hold=True)
sage: m/n
x/sin(x) == (5*x + 1)/sin(2*pi + x)
sage: m = x != 5*x + 1
sage: n = sin(x) != sin(x+2*pi, hold=True)
sage: m/n
x/sin(x) != (5*x + 1)/sin(2*pi + x)
>>> from sage.all import *
>>> x = var('x')
>>> m = x == Integer(5)*x + Integer(1)
>>> n = sin(x) == sin(x+Integer(2)*pi, hold=True)
>>> m/n
x/sin(x) == (5*x + 1)/sin(2*pi + x)
>>> m = x != Integer(5)*x + Integer(1)
>>> n = sin(x) != sin(x+Integer(2)*pi, hold=True)
>>> m/n
x/sin(x) != (5*x + 1)/sin(2*pi + x)
x = var('x')
m = x == 5*x + 1
n = sin(x) == sin(x+2*pi, hold=True)
m/n
m = x != 5*x + 1
n = sin(x) != sin(x+2*pi, hold=True)
m/n

Substitution

Substitution into relations:

sage: x, a = var('x, a')
sage: eq = (x^3 + a == sin(x/a)); eq
x^3 + a == sin(x/a)
sage: eq.substitute(x=5*x)
125*x^3 + a == sin(5*x/a)
sage: eq.substitute(a=1)
x^3 + 1 == sin(x)
sage: eq.substitute(a=x)
x^3 + x == sin(1)
sage: eq.substitute(a=x, x=1)
x + 1 == sin(1/x)
sage: eq.substitute({a:x, x:1})
x + 1 == sin(1/x)
>>> from sage.all import *
>>> x, a = var('x, a')
>>> eq = (x**Integer(3) + a == sin(x/a)); eq
x^3 + a == sin(x/a)
>>> eq.substitute(x=Integer(5)*x)
125*x^3 + a == sin(5*x/a)
>>> eq.substitute(a=Integer(1))
x^3 + 1 == sin(x)
>>> eq.substitute(a=x)
x^3 + x == sin(1)
>>> eq.substitute(a=x, x=Integer(1))
x + 1 == sin(1/x)
>>> eq.substitute({a:x, x:Integer(1)})
x + 1 == sin(1/x)
x, a = var('x, a')
eq = (x^3 + a == sin(x/a)); eq
eq.substitute(x=5*x)
eq.substitute(a=1)
eq.substitute(a=x)
eq.substitute(a=x, x=1)
eq.substitute({a:x, x:1})

You can even substitute multivariable and matrix expressions:

sage: x,y = var('x, y')
sage: M = Matrix([[x+1,y],[x^2,y^3]]); M
[x + 1     y]
[  x^2   y^3]
sage: M.substitute({x:0,y:1})
[1 1]
[0 1]
>>> from sage.all import *
>>> x,y = var('x, y')
>>> M = Matrix([[x+Integer(1),y],[x**Integer(2),y**Integer(3)]]); M
[x + 1     y]
[  x^2   y^3]
>>> M.substitute({x:Integer(0),y:Integer(1)})
[1 1]
[0 1]
x,y = var('x, y')
M = Matrix([[x+1,y],[x^2,y^3]]); M
M.substitute({x:0,y:1})

Solving

We can solve equations:

sage: # needs sage.libs.maxima
sage: x = var('x')
sage: S = solve(x^3 - 1 == 0, x)
sage: S
[x == 1/2*I*sqrt(3) - 1/2, x == -1/2*I*sqrt(3) - 1/2, x == 1]
sage: S[0]
x == 1/2*I*sqrt(3) - 1/2
sage: S[0].right()
1/2*I*sqrt(3) - 1/2
sage: S = solve(x^3 - 1 == 0, x, solution_dict=True)
sage: S
[{x: 1/2*I*sqrt(3) - 1/2}, {x: -1/2*I*sqrt(3) - 1/2}, {x: 1}]
sage: z = 5
sage: solve(z^2 == sqrt(3),z)
Traceback (most recent call last):
...
TypeError: 5 is not a valid variable
>>> from sage.all import *
>>> # needs sage.libs.maxima
>>> x = var('x')
>>> S = solve(x**Integer(3) - Integer(1) == Integer(0), x)
>>> S
[x == 1/2*I*sqrt(3) - 1/2, x == -1/2*I*sqrt(3) - 1/2, x == 1]
>>> S[Integer(0)]
x == 1/2*I*sqrt(3) - 1/2
>>> S[Integer(0)].right()
1/2*I*sqrt(3) - 1/2
>>> S = solve(x**Integer(3) - Integer(1) == Integer(0), x, solution_dict=True)
>>> S
[{x: 1/2*I*sqrt(3) - 1/2}, {x: -1/2*I*sqrt(3) - 1/2}, {x: 1}]
>>> z = Integer(5)
>>> solve(z**Integer(2) == sqrt(Integer(3)),z)
Traceback (most recent call last):
...
TypeError: 5 is not a valid variable
# needs sage.libs.maxima
x = var('x')
S = solve(x^3 - 1 == 0, x)
S
S[0]
S[0].right()
S = solve(x^3 - 1 == 0, x, solution_dict=True)
S
z = 5
solve(z^2 == sqrt(3),z)

We can also solve equations involving matrices. The following example defines a multivariable function f(x,y), then solves for where the partial derivatives with respect to x and y are zero. Then it substitutes one of the solutions into the Hessian matrix H for f:

sage: # needs sage.libs.maxima
sage: f(x,y) = x^2*y+y^2+y
sage: solutions = solve(list(f.diff()),[x,y],solution_dict=True)
sage: solutions == [{x: -I, y: 0}, {x: I, y: 0}, {x: 0, y: -1/2}]
True
sage: H = f.diff(2) # Hessian matrix
sage: H.subs(solutions[2])
[(x, y) |--> -1  (x, y) |--> 0]
[ (x, y) |--> 0  (x, y) |--> 2]
sage: H(x,y).subs(solutions[2])
[-1  0]
[ 0  2]
>>> from sage.all import *
>>> # needs sage.libs.maxima
>>> __tmp__=var("x,y"); f = symbolic_expression(x**Integer(2)*y+y**Integer(2)+y).function(x,y)
>>> solutions = solve(list(f.diff()),[x,y],solution_dict=True)
>>> solutions == [{x: -I, y: Integer(0)}, {x: I, y: Integer(0)}, {x: Integer(0), y: -Integer(1)/Integer(2)}]
True
>>> H = f.diff(Integer(2)) # Hessian matrix
>>> H.subs(solutions[Integer(2)])
[(x, y) |--> -1  (x, y) |--> 0]
[ (x, y) |--> 0  (x, y) |--> 2]
>>> H(x,y).subs(solutions[Integer(2)])
[-1  0]
[ 0  2]
# needs sage.libs.maxima
f(x,y) = x^2*y+y^2+y
solutions = solve(list(f.diff()),[x,y],solution_dict=True)
solutions == [{x: -I, y: 0}, {x: I, y: 0}, {x: 0, y: -1/2}]
H = f.diff(2) # Hessian matrix
H.subs(solutions[2])
H(x,y).subs(solutions[2])

We illustrate finding multiplicities of solutions:

sage: # needs sage.libs.maxima
sage: f = (x-1)^5*(x^2+1)
sage: solve(f == 0, x)
[x == -I, x == I, x == 1]
sage: solve(f == 0, x, multiplicities=True)
([x == -I, x == I, x == 1], [1, 1, 5])
>>> from sage.all import *
>>> # needs sage.libs.maxima
>>> f = (x-Integer(1))**Integer(5)*(x**Integer(2)+Integer(1))
>>> solve(f == Integer(0), x)
[x == -I, x == I, x == 1]
>>> solve(f == Integer(0), x, multiplicities=True)
([x == -I, x == I, x == 1], [1, 1, 5])
# needs sage.libs.maxima
f = (x-1)^5*(x^2+1)
solve(f == 0, x)
solve(f == 0, x, multiplicities=True)

We can also solve many inequalities:

sage: solve(1/(x-1) <= 8, x)                                                        # needs sage.libs.maxima
[[x < 1], [x >= (9/8)]]
>>> from sage.all import *
>>> solve(Integer(1)/(x-Integer(1)) <= Integer(8), x)                                                        # needs sage.libs.maxima
[[x < 1], [x >= (9/8)]]
solve(1/(x-1) <= 8, x)                                                        # needs sage.libs.maxima

We can numerically find roots of equations:

sage: (x == sin(x)).find_root(-2,2)                                                 # needs scipy
0.0
sage: (x^5 + 3*x + 2 == 0).find_root(-2,2,x)                                        # needs scipy
-0.6328345202421523
sage: (cos(x) == sin(x)).find_root(10,20)                                           # needs scipy
19.634954084936208
>>> from sage.all import *
>>> (x == sin(x)).find_root(-Integer(2),Integer(2))                                                 # needs scipy
0.0
>>> (x**Integer(5) + Integer(3)*x + Integer(2) == Integer(0)).find_root(-Integer(2),Integer(2),x)                                        # needs scipy
-0.6328345202421523
>>> (cos(x) == sin(x)).find_root(Integer(10),Integer(20))                                           # needs scipy
19.634954084936208
(x == sin(x)).find_root(-2,2)                                                 # needs scipy
(x^5 + 3*x + 2 == 0).find_root(-2,2,x)                                        # needs scipy
(cos(x) == sin(x)).find_root(10,20)                                           # needs scipy

We illustrate some valid error conditions:

sage: (cos(x) != sin(x)).find_root(10,20)                                           # needs scipy
Traceback (most recent call last):
...
ValueError: Symbolic equation must be an equality.
sage: (SR(3)==SR(2)).find_root(-1,1)                                                # needs scipy
Traceback (most recent call last):
...
RuntimeError: no zero in the interval, since constant expression is not 0.
>>> from sage.all import *
>>> (cos(x) != sin(x)).find_root(Integer(10),Integer(20))                                           # needs scipy
Traceback (most recent call last):
...
ValueError: Symbolic equation must be an equality.
>>> (SR(Integer(3))==SR(Integer(2))).find_root(-Integer(1),Integer(1))                                                # needs scipy
Traceback (most recent call last):
...
RuntimeError: no zero in the interval, since constant expression is not 0.
(cos(x) != sin(x)).find_root(10,20)                                           # needs scipy
(SR(3)==SR(2)).find_root(-1,1)                                                # needs scipy

There must be at most one variable:

sage: x, y = var('x,y')
sage: (x == y).find_root(-2,2)                                                      # needs scipy
Traceback (most recent call last):
...
NotImplementedError: root finding currently only implemented in 1 dimension.
>>> from sage.all import *
>>> x, y = var('x,y')
>>> (x == y).find_root(-Integer(2),Integer(2))                                                      # needs scipy
Traceback (most recent call last):
...
NotImplementedError: root finding currently only implemented in 1 dimension.
x, y = var('x,y')
(x == y).find_root(-2,2)                                                      # needs scipy

Assumptions

Forgetting assumptions:

sage: var('x,y')
(x, y)
sage: forget() #Clear assumptions
sage: assume(x>0, y < 2)
sage: assumptions()
[x > 0, y < 2]
sage: (y < 2).forget()
sage: assumptions()
[x > 0]
sage: forget()
sage: assumptions()
[]
>>> from sage.all import *
>>> var('x,y')
(x, y)
>>> forget() #Clear assumptions
>>> assume(x>Integer(0), y < Integer(2))
>>> assumptions()
[x > 0, y < 2]
>>> (y < Integer(2)).forget()
>>> assumptions()
[x > 0]
>>> forget()
>>> assumptions()
[]
var('x,y')
forget() #Clear assumptions
assume(x>0, y < 2)
assumptions()
(y < 2).forget()
assumptions()
forget()
assumptions()

Miscellaneous

Conversion to Maxima:

sage: # needs sage.libs.maxima
sage: from sage.interfaces.maxima_lib import maxima
sage: x = var('x')
sage: eq = (x^(3/5) >= pi^2 + e^i)
sage: eq._maxima_init_()
'(_SAGE_VAR_x)^(3/5) >= ((%pi)^(2))+(exp(0+%i*1))'
sage: e1 = x^3 + x == sin(2*x)
sage: z = e1._maxima_()
sage: z.parent() is sage.calculus.calculus.maxima
True
sage: z = e1._maxima_(maxima)
sage: z.parent() is sage.interfaces.maxima_lib.maxima
True
sage: z = maxima(e1)
sage: z.parent() is sage.interfaces.maxima_lib.maxima
True
>>> from sage.all import *
>>> # needs sage.libs.maxima
>>> from sage.interfaces.maxima_lib import maxima
>>> x = var('x')
>>> eq = (x**(Integer(3)/Integer(5)) >= pi**Integer(2) + e**i)
>>> eq._maxima_init_()
'(_SAGE_VAR_x)^(3/5) >= ((%pi)^(2))+(exp(0+%i*1))'
>>> e1 = x**Integer(3) + x == sin(Integer(2)*x)
>>> z = e1._maxima_()
>>> z.parent() is sage.calculus.calculus.maxima
True
>>> z = e1._maxima_(maxima)
>>> z.parent() is sage.interfaces.maxima_lib.maxima
True
>>> z = maxima(e1)
>>> z.parent() is sage.interfaces.maxima_lib.maxima
True
# needs sage.libs.maxima
from sage.interfaces.maxima_lib import maxima
x = var('x')
eq = (x^(3/5) >= pi^2 + e^i)
eq._maxima_init_()
e1 = x^3 + x == sin(2*x)
z = e1._maxima_()
z.parent() is sage.calculus.calculus.maxima
z = e1._maxima_(maxima)
z.parent() is sage.interfaces.maxima_lib.maxima
z = maxima(e1)
z.parent() is sage.interfaces.maxima_lib.maxima

Conversion to Maple:

sage: x = var('x')
sage: eq = (x == 2)
sage: eq._maple_init_()
'x = 2'
>>> from sage.all import *
>>> x = var('x')
>>> eq = (x == Integer(2))
>>> eq._maple_init_()
'x = 2'
x = var('x')
eq = (x == 2)
eq._maple_init_()

Comparison:

sage: x = var('x')
sage: (x>0) == (x>0)
True
sage: (x>0) == (x>1)
False
sage: (x>0) != (x>1)
True
>>> from sage.all import *
>>> x = var('x')
>>> (x>Integer(0)) == (x>Integer(0))
True
>>> (x>Integer(0)) == (x>Integer(1))
False
>>> (x>Integer(0)) != (x>Integer(1))
True
x = var('x')
(x>0) == (x>0)
(x>0) == (x>1)
(x>0) != (x>1)

Variables appearing in the relation:

sage: var('x,y,z,w')
(x, y, z, w)
sage: f =  (x+y+w) == (x^2 - y^2 - z^3);   f
w + x + y == -z^3 + x^2 - y^2
sage: f.variables()
(w, x, y, z)
>>> from sage.all import *
>>> var('x,y,z,w')
(x, y, z, w)
>>> f =  (x+y+w) == (x**Integer(2) - y**Integer(2) - z**Integer(3));   f
w + x + y == -z^3 + x^2 - y^2
>>> f.variables()
(w, x, y, z)
var('x,y,z,w')
f =  (x+y+w) == (x^2 - y^2 - z^3);   f
f.variables()

LaTeX output:

sage: latex(x^(3/5) >= pi)
x^{\frac{3}{5}} \geq \pi
>>> from sage.all import *
>>> latex(x**(Integer(3)/Integer(5)) >= pi)
x^{\frac{3}{5}} \geq \pi
latex(x^(3/5) >= pi)

When working with the symbolic complex number \(I\), notice that comparisons do not automatically simplify even in trivial situations:

sage: SR(I)^2 == -1
-1 == -1
sage: SR(I)^2 < 0
-1 < 0
sage: (SR(I)+1)^4 > 0
-4 > 0
>>> from sage.all import *
>>> SR(I)**Integer(2) == -Integer(1)
-1 == -1
>>> SR(I)**Integer(2) < Integer(0)
-1 < 0
>>> (SR(I)+Integer(1))**Integer(4) > Integer(0)
-4 > 0
SR(I)^2 == -1
SR(I)^2 < 0
(SR(I)+1)^4 > 0

Nevertheless, if you force the comparison, you get the right answer (upstream Issue #7160):

sage: bool(SR(I)^2 == -1)
True
sage: bool(SR(I)^2 < 0)
True
sage: bool((SR(I)+1)^4 > 0)
False
>>> from sage.all import *
>>> bool(SR(I)**Integer(2) == -Integer(1))
True
>>> bool(SR(I)**Integer(2) < Integer(0))
True
>>> bool((SR(I)+Integer(1))**Integer(4) > Integer(0))
False
bool(SR(I)^2 == -1)
bool(SR(I)^2 < 0)
bool((SR(I)+1)^4 > 0)

More Examples

sage: x,y,a = var('x,y,a')
sage: f = x^2 + y^2 == 1
sage: f.solve(x)                                                                    # needs sage.libs.maxima
[x == -sqrt(-y^2 + 1), x == sqrt(-y^2 + 1)]
>>> from sage.all import *
>>> x,y,a = var('x,y,a')
>>> f = x**Integer(2) + y**Integer(2) == Integer(1)
>>> f.solve(x)                                                                    # needs sage.libs.maxima
[x == -sqrt(-y^2 + 1), x == sqrt(-y^2 + 1)]
x,y,a = var('x,y,a')
f = x^2 + y^2 == 1
f.solve(x)                                                                    # needs sage.libs.maxima

sage: f = x^5 + a
sage: solve(f == 0, x)                                                              # needs sage.libs.maxima
[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)]
>>> from sage.all import *
>>> f = x**Integer(5) + a
>>> solve(f == Integer(0), x)                                                              # needs sage.libs.maxima
[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)]
f = x^5 + a
solve(f == 0, x)                                                              # needs sage.libs.maxima

You can also do arithmetic with inequalities, as illustrated below:

sage: var('x y')
(x, y)
sage: f = x + 3 == y - 2
sage: f
x + 3 == y - 2
sage: g = f - 3; g
x == y - 5
sage: h =  x^3 + sqrt(2) == x*y*sin(x)
sage: h
x^3 + sqrt(2) == x*y*sin(x)
sage: h - sqrt(2)
x^3 == x*y*sin(x) - sqrt(2)
sage: h + f
x^3 + x + sqrt(2) + 3 == x*y*sin(x) + y - 2
sage: f = x + 3 < y - 2
sage: g = 2 < x+10
sage: f - g
x + 1 < -x + y - 12
sage: f + g
x + 5 < x + y + 8
sage: f*(-1)
-x - 3 < -y + 2
>>> from sage.all import *
>>> var('x y')
(x, y)
>>> f = x + Integer(3) == y - Integer(2)
>>> f
x + 3 == y - 2
>>> g = f - Integer(3); g
x == y - 5
>>> h =  x**Integer(3) + sqrt(Integer(2)) == x*y*sin(x)
>>> h
x^3 + sqrt(2) == x*y*sin(x)
>>> h - sqrt(Integer(2))
x^3 == x*y*sin(x) - sqrt(2)
>>> h + f
x^3 + x + sqrt(2) + 3 == x*y*sin(x) + y - 2
>>> f = x + Integer(3) < y - Integer(2)
>>> g = Integer(2) < x+Integer(10)
>>> f - g
x + 1 < -x + y - 12
>>> f + g
x + 5 < x + y + 8
>>> f*(-Integer(1))
-x - 3 < -y + 2
var('x y')
f = x + 3 == y - 2
f
g = f - 3; g
h =  x^3 + sqrt(2) == x*y*sin(x)
h
h - sqrt(2)
h + f
f = x + 3 < y - 2
g = 2 < x+10
f - g
f + g
f*(-1)

AUTHORS:

  • Bobby Moretti: initial version (based on a trick that Robert Bradshaw suggested).

  • William Stein: second version

  • William Stein (2007-07-16): added arithmetic with symbolic equations

sage.symbolic.relation.check_relation_maxima(relation)[source]

Return True if this (in)equality is definitely true. Return False if it is false or the algorithm for testing (in)equality is inconclusive.

EXAMPLES:

sage: # needs sage.libs.maxima
sage: from sage.symbolic.relation import check_relation_maxima
sage: k = var('k')
sage: pol = 1/(k-1) - 1/k -1/k/(k-1)
sage: check_relation_maxima(pol == 0)
True
sage: f = sin(x)^2 + cos(x)^2 - 1
sage: check_relation_maxima(f == 0)
True
sage: check_relation_maxima( x == x )
True
sage: check_relation_maxima( x != x )
False
sage: check_relation_maxima( x > x )
False
sage: check_relation_maxima( x^2 > x )
False
sage: check_relation_maxima( x + 2 > x )
True
sage: check_relation_maxima( x - 2 > x )
False
>>> from sage.all import *
>>> # needs sage.libs.maxima
>>> from sage.symbolic.relation import check_relation_maxima
>>> k = var('k')
>>> pol = Integer(1)/(k-Integer(1)) - Integer(1)/k -Integer(1)/k/(k-Integer(1))
>>> check_relation_maxima(pol == Integer(0))
True
>>> f = sin(x)**Integer(2) + cos(x)**Integer(2) - Integer(1)
>>> check_relation_maxima(f == Integer(0))
True
>>> check_relation_maxima( x == x )
True
>>> check_relation_maxima( x != x )
False
>>> check_relation_maxima( x > x )
False
>>> check_relation_maxima( x**Integer(2) > x )
False
>>> check_relation_maxima( x + Integer(2) > x )
True
>>> check_relation_maxima( x - Integer(2) > x )
False
# needs sage.libs.maxima
from sage.symbolic.relation import check_relation_maxima
k = var('k')
pol = 1/(k-1) - 1/k -1/k/(k-1)
check_relation_maxima(pol == 0)
f = sin(x)^2 + cos(x)^2 - 1
check_relation_maxima(f == 0)
check_relation_maxima( x == x )
check_relation_maxima( x != x )
check_relation_maxima( x > x )
check_relation_maxima( x^2 > x )
check_relation_maxima( x + 2 > x )
check_relation_maxima( x - 2 > x )

Here are some examples involving assumptions:

sage: # needs sage.libs.maxima
sage: x, y, z = var('x, y, z')
sage: assume(x>=y,y>=z,z>=x)
sage: check_relation_maxima(x==z)
True
sage: check_relation_maxima(z<x)
False
sage: check_relation_maxima(z>y)
False
sage: check_relation_maxima(y==z)
True
sage: forget()
sage: assume(x>=1,x<=1)
sage: check_relation_maxima(x==1)
True
sage: check_relation_maxima(x>1)
False
sage: check_relation_maxima(x>=1)
True
sage: check_relation_maxima(x!=1)
False
sage: forget()
sage: assume(x>0)
sage: check_relation_maxima(x==0)
False
sage: check_relation_maxima(x>-1)
True
sage: check_relation_maxima(x!=0)
True
sage: check_relation_maxima(x!=1)
False
sage: forget()
>>> from sage.all import *
>>> # needs sage.libs.maxima
>>> x, y, z = var('x, y, z')
>>> assume(x>=y,y>=z,z>=x)
>>> check_relation_maxima(x==z)
True
>>> check_relation_maxima(z<x)
False
>>> check_relation_maxima(z>y)
False
>>> check_relation_maxima(y==z)
True
>>> forget()
>>> assume(x>=Integer(1),x<=Integer(1))
>>> check_relation_maxima(x==Integer(1))
True
>>> check_relation_maxima(x>Integer(1))
False
>>> check_relation_maxima(x>=Integer(1))
True
>>> check_relation_maxima(x!=Integer(1))
False
>>> forget()
>>> assume(x>Integer(0))
>>> check_relation_maxima(x==Integer(0))
False
>>> check_relation_maxima(x>-Integer(1))
True
>>> check_relation_maxima(x!=Integer(0))
True
>>> check_relation_maxima(x!=Integer(1))
False
>>> forget()
# needs sage.libs.maxima
x, y, z = var('x, y, z')
assume(x>=y,y>=z,z>=x)
check_relation_maxima(x==z)
check_relation_maxima(z<x)
check_relation_maxima(z>y)
check_relation_maxima(y==z)
forget()
assume(x>=1,x<=1)
check_relation_maxima(x==1)
check_relation_maxima(x>1)
check_relation_maxima(x>=1)
check_relation_maxima(x!=1)
forget()
assume(x>0)
check_relation_maxima(x==0)
check_relation_maxima(x>-1)
check_relation_maxima(x!=0)
check_relation_maxima(x!=1)
forget()

Here is an example that illustrates that False may mean inconclusive:

sage: # needs sage.libs.maxima
sage: x = SR.var('x')
sage: assume(x, 'integer')
sage: check_relation_maxima( x == 1 )
False
sage: check_relation_maxima( x != 1 )
False
sage: assume( x > 2 )
sage: check_relation_maxima( x != 1 )
True
sage: forget()
>>> from sage.all import *
>>> # needs sage.libs.maxima
>>> x = SR.var('x')
>>> assume(x, 'integer')
>>> check_relation_maxima( x == Integer(1) )
False
>>> check_relation_maxima( x != Integer(1) )
False
>>> assume( x > Integer(2) )
>>> check_relation_maxima( x != Integer(1) )
True
>>> forget()
# needs sage.libs.maxima
x = SR.var('x')
assume(x, 'integer')
check_relation_maxima( x == 1 )
check_relation_maxima( x != 1 )
assume( x > 2 )
check_relation_maxima( x != 1 )
forget()
sage.symbolic.relation.check_relation_maxima_neq_as_not_eq(relation)[source]

A variant of check_relation_maxima() that treats \(x != y\) as \(not (x == y)\) for consistency with Python’s boolean semantics.

For inequality relations (!=), this function checks the corresponding equality and returns its logical negation, ensuring that bool(x != y) == not bool(x == y).

EXAMPLES:

sage: # needs sage.libs.maxima
sage: from sage.symbolic.relation import check_relation_maxima_neq_as_not_eq
sage: x = var('x')
sage: check_relation_maxima_neq_as_not_eq(x != x)
False
sage: check_relation_maxima_neq_as_not_eq(x == x)
True
sage: check_relation_maxima_neq_as_not_eq(x != 1)
True
sage: check_relation_maxima_neq_as_not_eq(x == 1)
False
>>> from sage.all import *
>>> # needs sage.libs.maxima
>>> from sage.symbolic.relation import check_relation_maxima_neq_as_not_eq
>>> x = var('x')
>>> check_relation_maxima_neq_as_not_eq(x != x)
False
>>> check_relation_maxima_neq_as_not_eq(x == x)
True
>>> check_relation_maxima_neq_as_not_eq(x != Integer(1))
True
>>> check_relation_maxima_neq_as_not_eq(x == Integer(1))
False
# needs sage.libs.maxima
from sage.symbolic.relation import check_relation_maxima_neq_as_not_eq
x = var('x')
check_relation_maxima_neq_as_not_eq(x != x)
check_relation_maxima_neq_as_not_eq(x == x)
check_relation_maxima_neq_as_not_eq(x != 1)
check_relation_maxima_neq_as_not_eq(x == 1)
sage.symbolic.relation.solve(f, explicit_solutions, multiplicities, to_poly_solve, solution_dict, algorithm, domain, *args)[source]

Algebraically solve an equation or system of equations (over the complex numbers) for given variables. Inequalities and systems of inequalities are also supported.

INPUT:

  • f – equation or system of equations (given by a list or tuple)

  • *args – variables to solve for

  • solution_dict – boolean (default: False); if True or nonzero, return a list of dictionaries containing the solutions. If there are no solutions, return an empty list (rather than a list containing an empty dictionary). Likewise, if there’s only a single solution, return a list containing one dictionary with that solution.

There are a few optional keywords if you are trying to solve a single equation. They may only be used in that context.

  • multiplicities – boolean (default: False); if True, return corresponding multiplicities. This keyword is incompatible with to_poly_solve=True and does not make any sense when solving inequalities.

  • explicit_solutions – boolean (default: False); require that all roots be explicit rather than implicit. Not used when solving inequalities.

  • to_poly_solve – boolean (default: False) or string; use Maxima’s to_poly_solver package to search for more possible solutions, but possibly encounter approximate solutions. This keyword is incompatible with multiplicities=True and is not used when solving inequalities. Setting to_poly_solve to ‘force’ (string) omits Maxima’s solve command (useful when some solutions of trigonometric equations are lost).

  • algorithm – string (default: 'maxima'); to use SymPy’s solvers set this to ‘sympy’. Note that SymPy is always used for diophantine equations. Another choice, if it is installed, is ‘giac’.

  • domain – string (default: 'complex'); setting this to ‘real’ changes the way SymPy solves single equations; inequalities are always solved in the real domain.

EXAMPLES:

sage: # needs sage.libs.maxima
sage: x, y = var('x, y')
sage: solve([x+y==6, x-y==4], x, y)
[[x == 5, y == 1]]
sage: solve([x^2+y^2 == 1, y^2 == x^3 + x + 1], x, y)
[[x == -1/2*I*sqrt(3) - 1/2, y == -sqrt(-1/2*I*sqrt(3) + 3/2)],
 [x == -1/2*I*sqrt(3) - 1/2, y == sqrt(-1/2*I*sqrt(3) + 3/2)],
 [x == 1/2*I*sqrt(3) - 1/2, y == -sqrt(1/2*I*sqrt(3) + 3/2)],
 [x == 1/2*I*sqrt(3) - 1/2, y == sqrt(1/2*I*sqrt(3) + 3/2)],
 [x == 0, y == -1],
 [x == 0, y == 1]]
sage: solve([sqrt(x) + sqrt(y) == 5, x + y == 10], x, y)
[[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]]
sage: solutions = solve([x^2+y^2 == 1, y^2 == x^3 + x + 1], x, y, solution_dict=True)
sage: for solution in solutions: print("{} , {}".format(solution[x].n(digits=3), solution[y].n(digits=3)))
-0.500 - 0.866*I , -1.27 + 0.341*I
-0.500 - 0.866*I , 1.27 - 0.341*I
-0.500 + 0.866*I , -1.27 - 0.341*I
-0.500 + 0.866*I , 1.27 + 0.341*I
0.000 , -1.00
0.000 , 1.00
>>> from sage.all import *
>>> # needs sage.libs.maxima
>>> x, y = var('x, y')
>>> solve([x+y==Integer(6), x-y==Integer(4)], x, y)
[[x == 5, y == 1]]
>>> solve([x**Integer(2)+y**Integer(2) == Integer(1), y**Integer(2) == x**Integer(3) + x + Integer(1)], x, y)
[[x == -1/2*I*sqrt(3) - 1/2, y == -sqrt(-1/2*I*sqrt(3) + 3/2)],
 [x == -1/2*I*sqrt(3) - 1/2, y == sqrt(-1/2*I*sqrt(3) + 3/2)],
 [x == 1/2*I*sqrt(3) - 1/2, y == -sqrt(1/2*I*sqrt(3) + 3/2)],
 [x == 1/2*I*sqrt(3) - 1/2, y == sqrt(1/2*I*sqrt(3) + 3/2)],
 [x == 0, y == -1],
 [x == 0, y == 1]]
>>> solve([sqrt(x) + sqrt(y) == Integer(5), x + y == Integer(10)], x, y)
[[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]]
>>> solutions = solve([x**Integer(2)+y**Integer(2) == Integer(1), y**Integer(2) == x**Integer(3) + x + Integer(1)], x, y, solution_dict=True)
>>> for solution in solutions: print("{} , {}".format(solution[x].n(digits=Integer(3)), solution[y].n(digits=Integer(3))))
-0.500 - 0.866*I , -1.27 + 0.341*I
-0.500 - 0.866*I , 1.27 - 0.341*I
-0.500 + 0.866*I , -1.27 - 0.341*I
-0.500 + 0.866*I , 1.27 + 0.341*I
0.000 , -1.00
0.000 , 1.00
# needs sage.libs.maxima
x, y = var('x, y')
solve([x+y==6, x-y==4], x, y)
solve([x^2+y^2 == 1, y^2 == x^3 + x + 1], x, y)
solve([sqrt(x) + sqrt(y) == 5, x + y == 10], x, y)
solutions = solve([x^2+y^2 == 1, y^2 == x^3 + x + 1], x, y, solution_dict=True)
for solution in solutions: print("{} , {}".format(solution[x].n(digits=3), solution[y].n(digits=3)))

Whenever possible, answers will be symbolic, but with systems of equations, at times approximations will be given by Maxima, due to the underlying algorithm:

sage: # needs sage.libs.maxima
sage: sols = solve([x^3==y,y^2==x], [x,y]); sols[-1], sols[0] # abs tol 1e-15
([x == 0, y == 0],
 [x == (0.3090169943749475 + 0.9510565162951535*I),
  y == (-0.8090169943749475 - 0.5877852522924731*I)])
sage: sols[0][0].rhs().pyobject().parent()
Complex Double Field
sage: solve([y^6==y],y)
[y == 1/4*sqrt(5) + 1/4*I*sqrt(2*sqrt(5) + 10) - 1/4,
 y == -1/4*sqrt(5) + 1/4*I*sqrt(-2*sqrt(5) + 10) - 1/4,
 y == -1/4*sqrt(5) - 1/4*I*sqrt(-2*sqrt(5) + 10) - 1/4,
 y == 1/4*sqrt(5) - 1/4*I*sqrt(2*sqrt(5) + 10) - 1/4,
 y == 1,
 y == 0]
sage: solve( [y^6 == y], y)==solve( y^6 == y, y)
True
>>> from sage.all import *
>>> # needs sage.libs.maxima
>>> sols = solve([x**Integer(3)==y,y**Integer(2)==x], [x,y]); sols[-Integer(1)], sols[Integer(0)] # abs tol 1e-15
([x == 0, y == 0],
 [x == (0.3090169943749475 + 0.9510565162951535*I),
  y == (-0.8090169943749475 - 0.5877852522924731*I)])
>>> sols[Integer(0)][Integer(0)].rhs().pyobject().parent()
Complex Double Field
>>> solve([y**Integer(6)==y],y)
[y == 1/4*sqrt(5) + 1/4*I*sqrt(2*sqrt(5) + 10) - 1/4,
 y == -1/4*sqrt(5) + 1/4*I*sqrt(-2*sqrt(5) + 10) - 1/4,
 y == -1/4*sqrt(5) - 1/4*I*sqrt(-2*sqrt(5) + 10) - 1/4,
 y == 1/4*sqrt(5) - 1/4*I*sqrt(2*sqrt(5) + 10) - 1/4,
 y == 1,
 y == 0]
>>> solve( [y**Integer(6) == y], y)==solve( y**Integer(6) == y, y)
True
# needs sage.libs.maxima
sols = solve([x^3==y,y^2==x], [x,y]); sols[-1], sols[0] # abs tol 1e-15
sols[0][0].rhs().pyobject().parent()
solve([y^6==y],y)
solve( [y^6 == y], y)==solve( y^6 == y, y)

Here we demonstrate very basic use of the optional keywords:

sage: # needs sage.libs.maxima
sage: ((x^2-1)^2).solve(x)
[x == -1, x == 1]
sage: ((x^2-1)^2).solve(x,multiplicities=True)
([x == -1, x == 1], [2, 2])
sage: solve(sin(x)==x,x)
[x == sin(x)]
sage: solve(sin(x)==x,x,explicit_solutions=True)
[]
sage: solve(abs(1-abs(1-x)) == 10, x)
[abs(abs(x - 1) - 1) == 10]
sage: solve(abs(1-abs(1-x)) == 10, x, to_poly_solve=True)
[x == -10, x == 12]

sage: from sage.symbolic.expression import Expression
sage: Expression.solve(x^2==1, x)                                               # needs sage.libs.maxima
[x == -1, x == 1]
>>> from sage.all import *
>>> # needs sage.libs.maxima
>>> ((x**Integer(2)-Integer(1))**Integer(2)).solve(x)
[x == -1, x == 1]
>>> ((x**Integer(2)-Integer(1))**Integer(2)).solve(x,multiplicities=True)
([x == -1, x == 1], [2, 2])
>>> solve(sin(x)==x,x)
[x == sin(x)]
>>> solve(sin(x)==x,x,explicit_solutions=True)
[]
>>> solve(abs(Integer(1)-abs(Integer(1)-x)) == Integer(10), x)
[abs(abs(x - 1) - 1) == 10]
>>> solve(abs(Integer(1)-abs(Integer(1)-x)) == Integer(10), x, to_poly_solve=True)
[x == -10, x == 12]

>>> from sage.symbolic.expression import Expression
>>> Expression.solve(x**Integer(2)==Integer(1), x)                                               # needs sage.libs.maxima
[x == -1, x == 1]
# needs sage.libs.maxima
((x^2-1)^2).solve(x)
((x^2-1)^2).solve(x,multiplicities=True)
solve(sin(x)==x,x)
solve(sin(x)==x,x,explicit_solutions=True)
solve(abs(1-abs(1-x)) == 10, x)
solve(abs(1-abs(1-x)) == 10, x, to_poly_solve=True)
from sage.symbolic.expression import Expression
Expression.solve(x^2==1, x)                                               # needs sage.libs.maxima

We must solve with respect to actual variables:

sage: z = 5
sage: solve([8*z + y == 3, -z + 7*y == 0], y, z)                                # needs sage.libs.maxima
Traceback (most recent call last):
...
TypeError: 5 is not a valid variable
>>> from sage.all import *
>>> z = Integer(5)
>>> solve([Integer(8)*z + y == Integer(3), -z + Integer(7)*y == Integer(0)], y, z)                                # needs sage.libs.maxima
Traceback (most recent call last):
...
TypeError: 5 is not a valid variable
z = 5
solve([8*z + y == 3, -z + 7*y == 0], y, z)                                # needs sage.libs.maxima

If we ask for dictionaries containing the solutions, we get them:

sage: # needs sage.libs.maxima
sage: solve([x^2 - 1], x, solution_dict=True)
[{x: -1}, {x: 1}]
sage: solve([x^2 - 4*x + 4], x, solution_dict=True)
[{x: 2}]
sage: res = solve([x^2 == y, y == 4], x, y, solution_dict=True)
sage: for soln in res: print("x: %s, y: %s" % (soln[x], soln[y]))
x: 2, y: 4
x: -2, y: 4
>>> from sage.all import *
>>> # needs sage.libs.maxima
>>> solve([x**Integer(2) - Integer(1)], x, solution_dict=True)
[{x: -1}, {x: 1}]
>>> solve([x**Integer(2) - Integer(4)*x + Integer(4)], x, solution_dict=True)
[{x: 2}]
>>> res = solve([x**Integer(2) == y, y == Integer(4)], x, y, solution_dict=True)
>>> for soln in res: print("x: %s, y: %s" % (soln[x], soln[y]))
x: 2, y: 4
x: -2, y: 4
# needs sage.libs.maxima
solve([x^2 - 1], x, solution_dict=True)
solve([x^2 - 4*x + 4], x, solution_dict=True)
res = solve([x^2 == y, y == 4], x, y, solution_dict=True)
for soln in res: print("x: %s, y: %s" % (soln[x], soln[y]))

If there is a parameter in the answer, that will show up as a new variable. In the following example, r1 is an arbitrary constant (because of the r):

sage: # needs sage.libs.maxima
sage: forget()
sage: x, y = var('x,y')
sage: solve([x + y == 3, 2*x + 2*y == 6], x, y)
[[x == -r1 + 3, y == r1]]
sage: var('b, c')
(b, c)
sage: solve((b-1)*(c-1), [b,c])
[[b == 1, c == r...], [b == r..., c == 1]]
>>> from sage.all import *
>>> # needs sage.libs.maxima
>>> forget()
>>> x, y = var('x,y')
>>> solve([x + y == Integer(3), Integer(2)*x + Integer(2)*y == Integer(6)], x, y)
[[x == -r1 + 3, y == r1]]
>>> var('b, c')
(b, c)
>>> solve((b-Integer(1))*(c-Integer(1)), [b,c])
[[b == 1, c == r...], [b == r..., c == 1]]
# needs sage.libs.maxima
forget()
x, y = var('x,y')
solve([x + y == 3, 2*x + 2*y == 6], x, y)
var('b, c')
solve((b-1)*(c-1), [b,c])

Especially with trigonometric functions, the dummy variable may be implicitly an integer (hence the z):

sage: # needs sage.libs.maxima
sage: solve(sin(x) == cos(x), x, to_poly_solve=True)
[x == 1/4*pi + pi*z...]
sage: solve([cos(x)*sin(x) == 1/2, x + y == 0], x, y)
[[x == 1/4*pi + pi*z..., y == -1/4*pi - pi*z...]]
>>> from sage.all import *
>>> # needs sage.libs.maxima
>>> solve(sin(x) == cos(x), x, to_poly_solve=True)
[x == 1/4*pi + pi*z...]
>>> solve([cos(x)*sin(x) == Integer(1)/Integer(2), x + y == Integer(0)], x, y)
[[x == 1/4*pi + pi*z..., y == -1/4*pi - pi*z...]]
# needs sage.libs.maxima
solve(sin(x) == cos(x), x, to_poly_solve=True)
solve([cos(x)*sin(x) == 1/2, x + y == 0], x, y)

Expressions which are not equations are assumed to be set equal to zero, as with \(x\) in the following example:

sage: solve([x, y == 2], x, y)                                                  # needs sage.libs.maxima
[[x == 0, y == 2]]
>>> from sage.all import *
>>> solve([x, y == Integer(2)], x, y)                                                  # needs sage.libs.maxima
[[x == 0, y == 2]]
solve([x, y == 2], x, y)                                                  # needs sage.libs.maxima

If True appears in the list of equations it is ignored, and if False appears in the list then no solutions are returned. E.g., note that the first 3==3 evaluates to True, not to a symbolic equation.

sage: # needs sage.libs.maxima
sage: solve([3==3, 1.00000000000000*x^3 == 0], x)
[x == 0]
sage: solve([1.00000000000000*x^3 == 0], x)
[x == 0]
>>> from sage.all import *
>>> # needs sage.libs.maxima
>>> solve([Integer(3)==Integer(3), RealNumber('1.00000000000000')*x**Integer(3) == Integer(0)], x)
[x == 0]
>>> solve([RealNumber('1.00000000000000')*x**Integer(3) == Integer(0)], x)
[x == 0]
# needs sage.libs.maxima
solve([3==3, 1.00000000000000*x^3 == 0], x)
solve([1.00000000000000*x^3 == 0], x)

Here, the first equation evaluates to False, so there are no solutions:

sage: solve([1==3, 1.00000000000000*x^3 == 0], x)                               # needs sage.libs.maxima
[]
>>> from sage.all import *
>>> solve([Integer(1)==Integer(3), RealNumber('1.00000000000000')*x**Integer(3) == Integer(0)], x)                               # needs sage.libs.maxima
[]
solve([1==3, 1.00000000000000*x^3 == 0], x)                               # needs sage.libs.maxima

Completely symbolic solutions are supported:

sage: # needs sage.libs.maxima
sage: var('s,j,b,m,g')
(s, j, b, m, g)
sage: sys = [m*(1-s) - b*s*j, b*s*j-g*j]
sage: solve(sys, s, j)
[[s == 1, j == 0], [s == g/b, j == (b - g)*m/(b*g)]]
sage: solve(sys, (s,j))
[[s == 1, j == 0], [s == g/b, j == (b - g)*m/(b*g)]]
sage: solve(sys, [s,j])
[[s == 1, j == 0], [s == g/b, j == (b - g)*m/(b*g)]]

sage: z = var('z')
sage: solve((x-z)^2 == 2, x)                                                    # needs sage.libs.maxima
[x == z - sqrt(2), x == z + sqrt(2)]
>>> from sage.all import *
>>> # needs sage.libs.maxima
>>> var('s,j,b,m,g')
(s, j, b, m, g)
>>> sys = [m*(Integer(1)-s) - b*s*j, b*s*j-g*j]
>>> solve(sys, s, j)
[[s == 1, j == 0], [s == g/b, j == (b - g)*m/(b*g)]]
>>> solve(sys, (s,j))
[[s == 1, j == 0], [s == g/b, j == (b - g)*m/(b*g)]]
>>> solve(sys, [s,j])
[[s == 1, j == 0], [s == g/b, j == (b - g)*m/(b*g)]]

>>> z = var('z')
>>> solve((x-z)**Integer(2) == Integer(2), x)                                                    # needs sage.libs.maxima
[x == z - sqrt(2), x == z + sqrt(2)]
# needs sage.libs.maxima
var('s,j,b,m,g')
sys = [m*(1-s) - b*s*j, b*s*j-g*j]
solve(sys, s, j)
solve(sys, (s,j))
solve(sys, [s,j])
z = var('z')
solve((x-z)^2 == 2, x)                                                    # needs sage.libs.maxima

Inequalities can be also solved:

sage: # needs sage.libs.maxima
sage: solve(x^2 > 8, x)
[[x < -2*sqrt(2)], [x > 2*sqrt(2)]]
sage: x, y = var('x,y'); (ln(x) - ln(y) > 0).solve(x)
[[log(x) - log(y) > 0]]
sage: x, y = var('x,y'); (ln(x) > ln(y)).solve(x)  # random
[[0 < y, y < x, 0 < x]]
[[y < x, 0 < y]]
>>> from sage.all import *
>>> # needs sage.libs.maxima
>>> solve(x**Integer(2) > Integer(8), x)
[[x < -2*sqrt(2)], [x > 2*sqrt(2)]]
>>> x, y = var('x,y'); (ln(x) - ln(y) > Integer(0)).solve(x)
[[log(x) - log(y) > 0]]
>>> x, y = var('x,y'); (ln(x) > ln(y)).solve(x)  # random
[[0 < y, y < x, 0 < x]]
[[y < x, 0 < y]]
# needs sage.libs.maxima
solve(x^2 > 8, x)
x, y = var('x,y'); (ln(x) - ln(y) > 0).solve(x)
x, y = var('x,y'); (ln(x) > ln(y)).solve(x)  # random

A simple example to show the use of the keyword multiplicities:

sage: # needs sage.libs.maxima
sage: ((x^2-1)^2).solve(x)
[x == -1, x == 1]
sage: ((x^2-1)^2).solve(x, multiplicities=True)
([x == -1, x == 1], [2, 2])
sage: ((x^2-1)^2).solve(x, multiplicities=True, to_poly_solve=True)
Traceback (most recent call last):
...
NotImplementedError: to_poly_solve does not return multiplicities
>>> from sage.all import *
>>> # needs sage.libs.maxima
>>> ((x**Integer(2)-Integer(1))**Integer(2)).solve(x)
[x == -1, x == 1]
>>> ((x**Integer(2)-Integer(1))**Integer(2)).solve(x, multiplicities=True)
([x == -1, x == 1], [2, 2])
>>> ((x**Integer(2)-Integer(1))**Integer(2)).solve(x, multiplicities=True, to_poly_solve=True)
Traceback (most recent call last):
...
NotImplementedError: to_poly_solve does not return multiplicities
# needs sage.libs.maxima
((x^2-1)^2).solve(x)
((x^2-1)^2).solve(x, multiplicities=True)
((x^2-1)^2).solve(x, multiplicities=True, to_poly_solve=True)

Here is how the explicit_solutions keyword functions:

sage: # needs sage.libs.maxima
sage: solve(sin(x) == x, x)
[x == sin(x)]
sage: solve(sin(x) == x, x, explicit_solutions=True)
[]
sage: solve(x*sin(x) == x^2, x)
[x == 0, x == sin(x)]
sage: solve(x*sin(x) == x^2, x, explicit_solutions=True)
[x == 0]
>>> from sage.all import *
>>> # needs sage.libs.maxima
>>> solve(sin(x) == x, x)
[x == sin(x)]
>>> solve(sin(x) == x, x, explicit_solutions=True)
[]
>>> solve(x*sin(x) == x**Integer(2), x)
[x == 0, x == sin(x)]
>>> solve(x*sin(x) == x**Integer(2), x, explicit_solutions=True)
[x == 0]
# needs sage.libs.maxima
solve(sin(x) == x, x)
solve(sin(x) == x, x, explicit_solutions=True)
solve(x*sin(x) == x^2, x)
solve(x*sin(x) == x^2, x, explicit_solutions=True)

The following examples show the use of the keyword to_poly_solve:

sage: # needs sage.libs.maxima
sage: solve(abs(1-abs(1-x)) == 10, x)
[abs(abs(x - 1) - 1) == 10]
sage: solve(abs(1-abs(1-x)) == 10, x, to_poly_solve=True)
[x == -10, x == 12]
sage: var('Q')
Q
sage: solve(Q*sqrt(Q^2 + 2) - 1, Q)
[Q == 1/sqrt(Q^2 + 2)]
>>> from sage.all import *
>>> # needs sage.libs.maxima
>>> solve(abs(Integer(1)-abs(Integer(1)-x)) == Integer(10), x)
[abs(abs(x - 1) - 1) == 10]
>>> solve(abs(Integer(1)-abs(Integer(1)-x)) == Integer(10), x, to_poly_solve=True)
[x == -10, x == 12]
>>> var('Q')
Q
>>> solve(Q*sqrt(Q**Integer(2) + Integer(2)) - Integer(1), Q)
[Q == 1/sqrt(Q^2 + 2)]
# needs sage.libs.maxima
solve(abs(1-abs(1-x)) == 10, x)
solve(abs(1-abs(1-x)) == 10, x, to_poly_solve=True)
var('Q')
solve(Q*sqrt(Q^2 + 2) - 1, Q)

The following example is a regression in Maxima 5.39.0. It used to be possible to get one more solution here, namely 1/sqrt(sqrt(2) + 1), see https://sourceforge.net/p/maxima/bugs/3276/:

sage: solve(Q*sqrt(Q^2 + 2) - 1, Q, to_poly_solve=True)                         # needs sage.libs.maxima
[Q == -sqrt(-sqrt(2) - 1), Q == sqrt(sqrt(2) + 1)*(sqrt(2) - 1)]
>>> from sage.all import *
>>> solve(Q*sqrt(Q**Integer(2) + Integer(2)) - Integer(1), Q, to_poly_solve=True)                         # needs sage.libs.maxima
[Q == -sqrt(-sqrt(2) - 1), Q == sqrt(sqrt(2) + 1)*(sqrt(2) - 1)]
solve(Q*sqrt(Q^2 + 2) - 1, Q, to_poly_solve=True)                         # needs sage.libs.maxima

An effort is made to only return solutions that satisfy the current assumptions:

sage: # needs sage.libs.maxima
sage: solve(x^2 == 4, x)
[x == -2, x == 2]
sage: assume(x < 0)
sage: solve(x^2 == 4, x)
[x == -2]
sage: solve((x^2-4)^2 == 0, x, multiplicities=True)
([x == -2], [2])
sage: solve(x^2 == 2, x)
[x == -sqrt(2)]
sage: z = var('z')
sage: solve(x^2 == 2 - z, x)
[x == -sqrt(-z + 2)]
sage: assume(x, 'rational')
sage: solve(x^2 == 2, x)
[]
>>> from sage.all import *
>>> # needs sage.libs.maxima
>>> solve(x**Integer(2) == Integer(4), x)
[x == -2, x == 2]
>>> assume(x < Integer(0))
>>> solve(x**Integer(2) == Integer(4), x)
[x == -2]
>>> solve((x**Integer(2)-Integer(4))**Integer(2) == Integer(0), x, multiplicities=True)
([x == -2], [2])
>>> solve(x**Integer(2) == Integer(2), x)
[x == -sqrt(2)]
>>> z = var('z')
>>> solve(x**Integer(2) == Integer(2) - z, x)
[x == -sqrt(-z + 2)]
>>> assume(x, 'rational')
>>> solve(x**Integer(2) == Integer(2), x)
[]
# needs sage.libs.maxima
solve(x^2 == 4, x)
assume(x < 0)
solve(x^2 == 4, x)
solve((x^2-4)^2 == 0, x, multiplicities=True)
solve(x^2 == 2, x)
z = var('z')
solve(x^2 == 2 - z, x)
assume(x, 'rational')
solve(x^2 == 2, x)

In some cases it may be worthwhile to directly use to_poly_solve if one suspects some answers are being missed:

sage: # needs sage.libs.maxima
sage: forget()
sage: solve(cos(x) == 0, x)
[x == 1/2*pi]
sage: solve(cos(x) == 0, x, to_poly_solve=True)
[x == 1/2*pi]
sage: solve(cos(x) == 0, x, to_poly_solve='force')
[x == 1/2*pi + pi*z...]
>>> from sage.all import *
>>> # needs sage.libs.maxima
>>> forget()
>>> solve(cos(x) == Integer(0), x)
[x == 1/2*pi]
>>> solve(cos(x) == Integer(0), x, to_poly_solve=True)
[x == 1/2*pi]
>>> solve(cos(x) == Integer(0), x, to_poly_solve='force')
[x == 1/2*pi + pi*z...]
# needs sage.libs.maxima
forget()
solve(cos(x) == 0, x)
solve(cos(x) == 0, x, to_poly_solve=True)
solve(cos(x) == 0, x, to_poly_solve='force')

The same may also apply if a returned unsolved expression has a denominator, but the original one did not:

sage: # needs sage.libs.maxima
sage: solve(cos(x) * sin(x) == 1/2, x, to_poly_solve=True)
[sin(x) == 1/2/cos(x)]
sage: solve(cos(x) * sin(x) == 1/2, x, to_poly_solve=True, explicit_solutions=True)
[x == 1/4*pi + pi*z...]
sage: solve(cos(x) * sin(x) == 1/2, x, to_poly_solve='force')
[x == 1/4*pi + pi*z...]
>>> from sage.all import *
>>> # needs sage.libs.maxima
>>> solve(cos(x) * sin(x) == Integer(1)/Integer(2), x, to_poly_solve=True)
[sin(x) == 1/2/cos(x)]
>>> solve(cos(x) * sin(x) == Integer(1)/Integer(2), x, to_poly_solve=True, explicit_solutions=True)
[x == 1/4*pi + pi*z...]
>>> solve(cos(x) * sin(x) == Integer(1)/Integer(2), x, to_poly_solve='force')
[x == 1/4*pi + pi*z...]
# needs sage.libs.maxima
solve(cos(x) * sin(x) == 1/2, x, to_poly_solve=True)
solve(cos(x) * sin(x) == 1/2, x, to_poly_solve=True, explicit_solutions=True)
solve(cos(x) * sin(x) == 1/2, x, to_poly_solve='force')

We use use_grobner in Maxima if no solution is obtained from Maxima’s to_poly_solve:

sage: # needs sage.libs.maxima
sage: x,y = var('x y')
sage: c1(x,y) = (x-5)^2 + y^2 - 16
sage: c2(x,y) = (y-3)^2 + x^2 - 9
sage: solve([c1(x,y), c2(x,y)], [x,y])
[[x == -9/68*sqrt(55) + 135/68, y == -15/68*sqrt(55) + 123/68],
 [x == 9/68*sqrt(55) + 135/68, y == 15/68*sqrt(55) + 123/68]]
>>> from sage.all import *
>>> # needs sage.libs.maxima
>>> x,y = var('x y')
>>> __tmp__=var("x,y"); c1 = symbolic_expression((x-Integer(5))**Integer(2) + y**Integer(2) - Integer(16)).function(x,y)
>>> __tmp__=var("x,y"); c2 = symbolic_expression((y-Integer(3))**Integer(2) + x**Integer(2) - Integer(9)).function(x,y)
>>> solve([c1(x,y), c2(x,y)], [x,y])
[[x == -9/68*sqrt(55) + 135/68, y == -15/68*sqrt(55) + 123/68],
 [x == 9/68*sqrt(55) + 135/68, y == 15/68*sqrt(55) + 123/68]]
# needs sage.libs.maxima
x,y = var('x y')
c1(x,y) = (x-5)^2 + y^2 - 16
c2(x,y) = (y-3)^2 + x^2 - 9
solve([c1(x,y), c2(x,y)], [x,y])

We use SymPy for Diophantine equations, see Expression.solve_diophantine:

sage: x, z = var('x z')
sage: assume(x, 'integer')
sage: assume(z, 'integer')
sage: solve((x-z)^2==2, x)
[]
sage: forget()
>>> from sage.all import *
>>> x, z = var('x z')
>>> assume(x, 'integer')
>>> assume(z, 'integer')
>>> solve((x-z)**Integer(2)==Integer(2), x)
[]
>>> forget()
x, z = var('x z')
assume(x, 'integer')
assume(z, 'integer')
solve((x-z)^2==2, x)
forget()

The following shows some more of SymPy’s capabilities that cannot be handled by Maxima:

sage: _ = var('t')
sage: x, y = var('x y')
sage: r = solve([x^2 - y^2/exp(x), y-1], x, y,
....:           algorithm='sympy', solution_dict=True)
sage: (r[0][x], r[0][y])
(2*lambert_w(-1/2), 1)
sage: solve(-2*x**3 + 4*x**2 - 2*x + 6 > 0, x, algorithm='sympy')
[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]
sage: solve(sqrt(2*x^2 - 7) - (3 - x), x, algorithm='sympy')
[x == -8, x == 2]
sage: solve(sqrt(2*x + 9) - sqrt(x + 1) - sqrt(x + 4), x, algorithm='sympy')
[x == 0]
sage: r = solve([x + y + z + t, -z - t], x, y, z, t,
....:           algorithm='sympy', solution_dict=True)
sage: (r[0][x], r[0][z])
(-y, -t)
sage: r = solve([x^2 + y + z, y + x^2 + z, x + y + z^2], x, y, z,
....:           algorithm='sympy', solution_dict=True)
sage: (r[0][x], r[0][y])
(z, -(z + 1)*z)
sage: (r[1][x], r[1][y])
(-z + 1, -z^2 + z - 1)
sage: solve(abs(x + 3) - 2*abs(x - 3), x, algorithm='sympy', domain='real')
[x == 1, x == 9]
>>> from sage.all import *
>>> _ = var('t')
>>> x, y = var('x y')
>>> r = solve([x**Integer(2) - y**Integer(2)/exp(x), y-Integer(1)], x, y,
...           algorithm='sympy', solution_dict=True)
>>> (r[Integer(0)][x], r[Integer(0)][y])
(2*lambert_w(-1/2), 1)
>>> solve(-Integer(2)*x**Integer(3) + Integer(4)*x**Integer(2) - Integer(2)*x + Integer(6) > Integer(0), x, algorithm='sympy')
[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]
>>> solve(sqrt(Integer(2)*x**Integer(2) - Integer(7)) - (Integer(3) - x), x, algorithm='sympy')
[x == -8, x == 2]
>>> solve(sqrt(Integer(2)*x + Integer(9)) - sqrt(x + Integer(1)) - sqrt(x + Integer(4)), x, algorithm='sympy')
[x == 0]
>>> r = solve([x + y + z + t, -z - t], x, y, z, t,
...           algorithm='sympy', solution_dict=True)
>>> (r[Integer(0)][x], r[Integer(0)][z])
(-y, -t)
>>> r = solve([x**Integer(2) + y + z, y + x**Integer(2) + z, x + y + z**Integer(2)], x, y, z,
...           algorithm='sympy', solution_dict=True)
>>> (r[Integer(0)][x], r[Integer(0)][y])
(z, -(z + 1)*z)
>>> (r[Integer(1)][x], r[Integer(1)][y])
(-z + 1, -z^2 + z - 1)
>>> solve(abs(x + Integer(3)) - Integer(2)*abs(x - Integer(3)), x, algorithm='sympy', domain='real')
[x == 1, x == 9]
_ = var('t')
x, y = var('x y')
r = solve([x^2 - y^2/exp(x), y-1], x, y,
          algorithm='sympy', solution_dict=True)
(r[0][x], r[0][y])
solve(-2*x**3 + 4*x**2 - 2*x + 6 > 0, x, algorithm='sympy')
solve(sqrt(2*x^2 - 7) - (3 - x), x, algorithm='sympy')
solve(sqrt(2*x + 9) - sqrt(x + 1) - sqrt(x + 4), x, algorithm='sympy')
r = solve([x + y + z + t, -z - t], x, y, z, t,
          algorithm='sympy', solution_dict=True)
(r[0][x], r[0][z])
r = solve([x^2 + y + z, y + x^2 + z, x + y + z^2], x, y, z,
          algorithm='sympy', solution_dict=True)
(r[0][x], r[0][y])
(r[1][x], r[1][y])
solve(abs(x + 3) - 2*abs(x - 3), x, algorithm='sympy', domain='real')

We cannot translate all results from SymPy but we can at least print them:

sage: x = var('x')
sage: solve(sinh(x) - 2*cosh(x), x, algorithm='sympy')
[ImageSet(Lambda(_n, I*(2*_n*pi + pi/2) + log(sqrt(3))), Integers),
 ImageSet(Lambda(_n, I*(2*_n*pi - pi/2) + log(sqrt(3))), Integers)]
sage: solve(2*sin(x) - 2*sin(2*x), x, algorithm='sympy')
[ImageSet(Lambda(_n, 2*_n*pi), Integers),
 ImageSet(Lambda(_n, 2*_n*pi + pi), Integers),
 ImageSet(Lambda(_n, 2*_n*pi + 5*pi/3), Integers),
 ImageSet(Lambda(_n, 2*_n*pi + pi/3), Integers)]

sage: solve(x^5 + 3*x^3 + 7, x, algorithm='sympy')[0]
x == complex_root_of(x^5 + 3*x^3 + 7, 0)
>>> from sage.all import *
>>> x = var('x')
>>> solve(sinh(x) - Integer(2)*cosh(x), x, algorithm='sympy')
[ImageSet(Lambda(_n, I*(2*_n*pi + pi/2) + log(sqrt(3))), Integers),
 ImageSet(Lambda(_n, I*(2*_n*pi - pi/2) + log(sqrt(3))), Integers)]
>>> solve(Integer(2)*sin(x) - Integer(2)*sin(Integer(2)*x), x, algorithm='sympy')
[ImageSet(Lambda(_n, 2*_n*pi), Integers),
 ImageSet(Lambda(_n, 2*_n*pi + pi), Integers),
 ImageSet(Lambda(_n, 2*_n*pi + 5*pi/3), Integers),
 ImageSet(Lambda(_n, 2*_n*pi + pi/3), Integers)]

>>> solve(x**Integer(5) + Integer(3)*x**Integer(3) + Integer(7), x, algorithm='sympy')[Integer(0)]
x == complex_root_of(x^5 + 3*x^3 + 7, 0)
x = var('x')
solve(sinh(x) - 2*cosh(x), x, algorithm='sympy')
solve(2*sin(x) - 2*sin(2*x), x, algorithm='sympy')
solve(x^5 + 3*x^3 + 7, x, algorithm='sympy')[0]

A basic interface to Giac is provided:

sage: # needs sage.libs.giac
sage: x = var('x')
sage: solve([(2/3)^x - 2], [x], algorithm='giac')
[-log(2)/(log(3) - log(2))]
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))
sage: solve(f, x, algorithm='giac')
[-2*arctan(sqrt(2)), 0, 2*arctan(sqrt(2)), pi]
sage: x, y = SR.var('x,y')
sage: solve([x + y - 4, x*y - 3], [x,y], algorithm='giac')
[[1, 3], [3, 1]]
>>> from sage.all import *
>>> # needs sage.libs.giac
>>> x = var('x')
>>> solve([(Integer(2)/Integer(3))**x - Integer(2)], [x], algorithm='giac')
[-log(2)/(log(3) - log(2))]
>>> f = (sin(x) - Integer(8)*cos(x)*sin(x))*(sin(x)**Integer(2) + cos(x)) - (Integer(2)*cos(x)*sin(x) - sin(x))*(-Integer(2)*sin(x)**Integer(2) + Integer(2)*cos(x)**Integer(2) - cos(x))
>>> solve(f, x, algorithm='giac')
[-2*arctan(sqrt(2)), 0, 2*arctan(sqrt(2)), pi]
>>> x, y = SR.var('x,y')
>>> solve([x + y - Integer(4), x*y - Integer(3)], [x,y], algorithm='giac')
[[1, 3], [3, 1]]
# needs sage.libs.giac
x = var('x')
solve([(2/3)^x - 2], [x], algorithm='giac')
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))
solve(f, x, algorithm='giac')
x, y = SR.var('x,y')
solve([x + y - 4, x*y - 3], [x,y], algorithm='giac')
sage.symbolic.relation.solve_ineq(ineq, vars=None)[source]

Solve inequalities and systems of inequalities using Maxima. Switches between rational inequalities (sage.symbolic.relation.solve_ineq_rational) and Fourier elimination (sage.symbolic.relation.solve_ineq_fouried). See the documentation of these functions for more details.

INPUT:

  • ineq – one inequality or a list of inequalities

    Case1: If ineq is one equality, then it should be rational expression in one variable. This input is passed to sage.symbolic.relation.solve_ineq_univar function.

    Case2: If ineq is a list involving one or more inequalities, than the input is passed to sage.symbolic.relation.solve_ineq_fourier function. This function can be used for system of linear inequalities and for some types of nonlinear inequalities. See http://maxima.cvs.sourceforge.net/viewvc/maxima/maxima/share/contrib/fourier_elim/rtest_fourier_elim.mac for a big gallery of problems covered by this algorithm.

  • vars – (optional) parameter with list of variables. This list is used only if Fourier elimination is used. If omitted or if rational inequality is solved, then variables are determined automatically.

OUTPUT:

  • list – output is list of solutions as a list of simple inequalities output [A,B,C] means (A or B or C) each A, B, C is again a list and if A=[a,b], then A means (a and b).

EXAMPLES:

sage: from sage.symbolic.relation import solve_ineq
>>> from sage.all import *
>>> from sage.symbolic.relation import solve_ineq
from sage.symbolic.relation import solve_ineq

Inequalities in one variable. The variable is detected automatically:

sage: solve_ineq(x^2 - 1 > 3)                                                   # needs sage.libs.maxima
[[x < -2], [x > 2]]
sage: solve_ineq(1/(x-1) <= 8)                                                  # needs sage.libs.maxima
[[x < 1], [x >= (9/8)]]
>>> from sage.all import *
>>> solve_ineq(x**Integer(2) - Integer(1) > Integer(3))                                                   # needs sage.libs.maxima
[[x < -2], [x > 2]]
>>> solve_ineq(Integer(1)/(x-Integer(1)) <= Integer(8))                                                  # needs sage.libs.maxima
[[x < 1], [x >= (9/8)]]
solve_ineq(x^2 - 1 > 3)                                                   # needs sage.libs.maxima
solve_ineq(1/(x-1) <= 8)                                                  # needs sage.libs.maxima

System of inequalities with automatically detected inequalities:

sage: y = var('y')
sage: solve_ineq([x - y < 0, x + y - 3 < 0], [y,x])                             # needs sage.libs.maxima
[[x < y, y < -x + 3, x < (3/2)]]
sage: solve_ineq([x - y < 0, x + y - 3 < 0], [x,y])                             # needs sage.libs.maxima
[[x < min(-y + 3, y)]]
>>> from sage.all import *
>>> y = var('y')
>>> solve_ineq([x - y < Integer(0), x + y - Integer(3) < Integer(0)], [y,x])                             # needs sage.libs.maxima
[[x < y, y < -x + 3, x < (3/2)]]
>>> solve_ineq([x - y < Integer(0), x + y - Integer(3) < Integer(0)], [x,y])                             # needs sage.libs.maxima
[[x < min(-y + 3, y)]]
y = var('y')
solve_ineq([x - y < 0, x + y - 3 < 0], [y,x])                             # needs sage.libs.maxima
solve_ineq([x - y < 0, x + y - 3 < 0], [x,y])                             # needs sage.libs.maxima

Note that although Sage will detect the variables automatically, the order it puts them in may depend on the system, so the following command is only guaranteed to give you one of the above answers:

sage: solve_ineq([x - y < 0, x + y - 3 < 0])  # random                          # needs sage.libs.maxima
[[x < y, y < -x + 3, x < (3/2)]]
>>> from sage.all import *
>>> solve_ineq([x - y < Integer(0), x + y - Integer(3) < Integer(0)])  # random                          # needs sage.libs.maxima
[[x < y, y < -x + 3, x < (3/2)]]
solve_ineq([x - y < 0, x + y - 3 < 0])  # random                          # needs sage.libs.maxima

ALGORITHM:

Calls solve_ineq_fourier if inequalities are list and solve_ineq_univar of the inequality is symbolic expression. See the description of these commands for more details related to the set of inequalities which can be solved. The list is empty if there is no solution.

AUTHORS:

  • Robert Marik (01-2010)

sage.symbolic.relation.solve_ineq_fourier(ineq, vars=None)[source]

Solve system of inequalities using Maxima and Fourier elimination.

Can be used for system of linear inequalities and for some types of nonlinear inequalities. For examples, see the example section below and http://maxima.cvs.sourceforge.net/viewvc/maxima/maxima/share/contrib/fourier_elim/rtest_fourier_elim.mac

INPUT:

  • ineq – list with system of inequalities

  • vars – optionally list with variables for Fourier elimination

OUTPUT:

  • list – output is list of solutions as a list of simple inequalities output [A,B,C] means (A or B or C) each A, B, C is again a list and if A=[a,b], then A means (a and b). The list is empty if there is no solution.

EXAMPLES:

sage: # needs sage.libs.maxima
sage: from sage.symbolic.relation import solve_ineq_fourier
sage: y = var('y')
sage: solve_ineq_fourier([x + y < 9, x - y > 4], [x,y])
[[y + 4 < x, x < -y + 9, y < (5/2)]]
sage: solve_ineq_fourier([x + y < 9, x - y > 4], [y,x])[0][0](x=42)
y < -33
sage: solve_ineq_fourier([x^2 >= 0])
[[x < +Infinity]]
sage: solve_ineq_fourier([log(x) > log(y)], [x,y])
[[y < x, 0 < y]]
sage: solve_ineq_fourier([log(x) > log(y)], [y,x])
[[0 < y, y < x, 0 < x]]
>>> from sage.all import *
>>> # needs sage.libs.maxima
>>> from sage.symbolic.relation import solve_ineq_fourier
>>> y = var('y')
>>> solve_ineq_fourier([x + y < Integer(9), x - y > Integer(4)], [x,y])
[[y + 4 < x, x < -y + 9, y < (5/2)]]
>>> solve_ineq_fourier([x + y < Integer(9), x - y > Integer(4)], [y,x])[Integer(0)][Integer(0)](x=Integer(42))
y < -33
>>> solve_ineq_fourier([x**Integer(2) >= Integer(0)])
[[x < +Infinity]]
>>> solve_ineq_fourier([log(x) > log(y)], [x,y])
[[y < x, 0 < y]]
>>> solve_ineq_fourier([log(x) > log(y)], [y,x])
[[0 < y, y < x, 0 < x]]
# needs sage.libs.maxima
from sage.symbolic.relation import solve_ineq_fourier
y = var('y')
solve_ineq_fourier([x + y < 9, x - y > 4], [x,y])
solve_ineq_fourier([x + y < 9, x - y > 4], [y,x])[0][0](x=42)
solve_ineq_fourier([x^2 >= 0])
solve_ineq_fourier([log(x) > log(y)], [x,y])
solve_ineq_fourier([log(x) > log(y)], [y,x])

Note that different systems will find default variables in different orders, so the following is not tested:

sage: # needs sage.libs.maxima
sage: solve_ineq_fourier([log(x) > log(y)])  # random (one of the following appears)
[[0 < y, y < x, 0 < x]]
[[y < x, 0 < y]]
>>> from sage.all import *
>>> # needs sage.libs.maxima
>>> solve_ineq_fourier([log(x) > log(y)])  # random (one of the following appears)
[[0 < y, y < x, 0 < x]]
[[y < x, 0 < y]]
# needs sage.libs.maxima
solve_ineq_fourier([log(x) > log(y)])  # random (one of the following appears)

ALGORITHM:

Calls Maxima command fourier_elim

AUTHORS:

  • Robert Marik (01-2010)

sage.symbolic.relation.solve_ineq_univar(ineq)[source]

Function solves rational inequality in one variable.

INPUT:

  • ineq – inequality in one variable

OUTPUT:

  • list – output is list of solutions as a list of simple inequalities output [A,B,C] means (A or B or C) each A, B, C is again a list and if A=[a,b], then A means (a and b). The list is empty if there is no solution.

EXAMPLES:

sage: # needs sage.libs.maxima
sage: from sage.symbolic.relation import solve_ineq_univar
sage: solve_ineq_univar(x - 1/x > 0)
[[x > -1, x < 0], [x > 1]]
sage: solve_ineq_univar(x^2 - 1/x > 0)
[[x < 0], [x > 1]]
sage: solve_ineq_univar((x^3-1)*x <= 0)
[[x >= 0, x <= 1]]
>>> from sage.all import *
>>> # needs sage.libs.maxima
>>> from sage.symbolic.relation import solve_ineq_univar
>>> solve_ineq_univar(x - Integer(1)/x > Integer(0))
[[x > -1, x < 0], [x > 1]]
>>> solve_ineq_univar(x**Integer(2) - Integer(1)/x > Integer(0))
[[x < 0], [x > 1]]
>>> solve_ineq_univar((x**Integer(3)-Integer(1))*x <= Integer(0))
[[x >= 0, x <= 1]]
# needs sage.libs.maxima
from sage.symbolic.relation import solve_ineq_univar
solve_ineq_univar(x - 1/x > 0)
solve_ineq_univar(x^2 - 1/x > 0)
solve_ineq_univar((x^3-1)*x <= 0)

ALGORITHM:

Calls Maxima command solve_rat_ineq

AUTHORS:

  • Robert Marik (01-2010)

sage.symbolic.relation.solve_mod(eqns, modulus, solution_dict=False)[source]

Return all solutions to an equation or list of equations modulo the given integer modulus. Each equation must involve only polynomials in 1 or many variables.

By default the solutions are returned as \(n\)-tuples, where \(n\) is the number of variables appearing anywhere in the given equations. The variables are in alphabetical order.

INPUT:

  • eqns – equation or list of equations

  • modulus – integer

  • solution_dict – boolean (default: False); if True or nonzero, return a list of dictionaries containing the solutions. If there are no solutions, return an empty list (rather than a list containing an empty dictionary). Likewise, if there’s only a single solution, return a list containing one dictionary with that solution.

EXAMPLES:

sage: var('x,y')
(x, y)
sage: solve_mod([x^2 + 2 == x, x^2 + y == y^2], 14)
[(4, 2), (4, 6), (4, 9), (4, 13)]
sage: solve_mod([x^2 == 1, 4*x  == 11], 15)
[(14,)]
>>> from sage.all import *
>>> var('x,y')
(x, y)
>>> solve_mod([x**Integer(2) + Integer(2) == x, x**Integer(2) + y == y**Integer(2)], Integer(14))
[(4, 2), (4, 6), (4, 9), (4, 13)]
>>> solve_mod([x**Integer(2) == Integer(1), Integer(4)*x  == Integer(11)], Integer(15))
[(14,)]
var('x,y')
solve_mod([x^2 + 2 == x, x^2 + y == y^2], 14)
solve_mod([x^2 == 1, 4*x  == 11], 15)

Fermat’s equation modulo 3 with exponent 5:

sage: var('x,y,z')
(x, y, z)
sage: solve_mod([x^5 + y^5 == z^5], 3)
[(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)]
>>> from sage.all import *
>>> var('x,y,z')
(x, y, z)
>>> solve_mod([x**Integer(5) + y**Integer(5) == z**Integer(5)], Integer(3))
[(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)]
var('x,y,z')
solve_mod([x^5 + y^5 == z^5], 3)

We can solve with respect to a bigger modulus if it consists only of small prime factors:

sage: # needs sage.libs.pari
sage: [d] = solve_mod([5*x + y == 3, 2*x - 3*y == 9], 3*5*7*11*19*23*29, solution_dict=True)
sage: d[x]
12915279
sage: d[y]
8610183
>>> from sage.all import *
>>> # needs sage.libs.pari
>>> [d] = solve_mod([Integer(5)*x + y == Integer(3), Integer(2)*x - Integer(3)*y == Integer(9)], Integer(3)*Integer(5)*Integer(7)*Integer(11)*Integer(19)*Integer(23)*Integer(29), solution_dict=True)
>>> d[x]
12915279
>>> d[y]
8610183
# needs sage.libs.pari
[d] = solve_mod([5*x + y == 3, 2*x - 3*y == 9], 3*5*7*11*19*23*29, solution_dict=True)
d[x]
d[y]

For cases where there are relatively few solutions and the prime factors are small, this can be efficient even if the modulus itself is large:

sage: sorted(solve_mod([x^2 == 41], 10^20))                                     # needs sage.libs.pari
[(4538602480526452429,), (11445932736758703821,), (38554067263241296179,),
(45461397519473547571,), (54538602480526452429,), (61445932736758703821,),
(88554067263241296179,), (95461397519473547571,)]
>>> from sage.all import *
>>> sorted(solve_mod([x**Integer(2) == Integer(41)], Integer(10)**Integer(20)))                                     # needs sage.libs.pari
[(4538602480526452429,), (11445932736758703821,), (38554067263241296179,),
(45461397519473547571,), (54538602480526452429,), (61445932736758703821,),
(88554067263241296179,), (95461397519473547571,)]
sorted(solve_mod([x^2 == 41], 10^20))                                     # needs sage.libs.pari

We solve a simple equation modulo 2:

sage: x,y = var('x,y')
sage: solve_mod([x == y], 2)                                                    # needs sage.libs.pari
[(0, 0), (1, 1)]
>>> from sage.all import *
>>> x,y = var('x,y')
>>> solve_mod([x == y], Integer(2))                                                    # needs sage.libs.pari
[(0, 0), (1, 1)]
x,y = var('x,y')
solve_mod([x == y], 2)                                                    # needs sage.libs.pari

Warning

The current implementation splits the modulus into prime powers, then naively enumerates all possible solutions (starting modulo primes and then working up through prime powers), and finally combines the solution using the Chinese Remainder Theorem. The interface is good, but the algorithm is very inefficient if the modulus has some larger prime factors! Sage does have the ability to do something much faster in certain cases at least by using Groebner basis, linear algebra techniques, etc. But for a lot of toy problems this function as is might be useful. At least it establishes an interface.

sage.symbolic.relation.string_to_list_of_solutions(s)[source]

Used internally by the symbolic solve command to convert the output of Maxima’s solve command to a list of solutions in Sage’s symbolic package.

EXAMPLES:

We derive the (monic) quadratic formula:

sage: var('x,a,b')
(x, a, b)
sage: solve(x^2 + a*x + b == 0, x)                                              # needs sage.libs.maxima
[x == -1/2*a - 1/2*sqrt(a^2 - 4*b), x == -1/2*a + 1/2*sqrt(a^2 - 4*b)]
>>> from sage.all import *
>>> var('x,a,b')
(x, a, b)
>>> solve(x**Integer(2) + a*x + b == Integer(0), x)                                              # needs sage.libs.maxima
[x == -1/2*a - 1/2*sqrt(a^2 - 4*b), x == -1/2*a + 1/2*sqrt(a^2 - 4*b)]
var('x,a,b')
solve(x^2 + a*x + b == 0, x)                                              # needs sage.libs.maxima

Behind the scenes when the above is evaluated the function string_to_list_of_solutions() is called with input the string \(s\) below:

sage: s = '[x=-(sqrt(a^2-4*b)+a)/2,x=(sqrt(a^2-4*b)-a)/2]'
sage: sage.symbolic.relation.string_to_list_of_solutions(s)                     # needs sage.libs.maxima
 [x == -1/2*a - 1/2*sqrt(a^2 - 4*b), x == -1/2*a + 1/2*sqrt(a^2 - 4*b)]
>>> from sage.all import *
>>> s = '[x=-(sqrt(a^2-4*b)+a)/2,x=(sqrt(a^2-4*b)-a)/2]'
>>> sage.symbolic.relation.string_to_list_of_solutions(s)                     # needs sage.libs.maxima
 [x == -1/2*a - 1/2*sqrt(a^2 - 4*b), x == -1/2*a + 1/2*sqrt(a^2 - 4*b)]
s = '[x=-(sqrt(a^2-4*b)+a)/2,x=(sqrt(a^2-4*b)-a)/2]'
sage.symbolic.relation.string_to_list_of_solutions(s)                     # needs sage.libs.maxima