Manipulating Equations and Inequalities

Equations
"Defining Variables" discussed assignments such as x=y which set x equal to y. Here we discuss equations, which test equality. The equation x==y tests whether x is equal to y.
This tests whether 2+2 and 4 are equal. The result is the symbol True:
It is very important that you do not confuse x=y with x==y. While x=y is an imperative statement that actually causes an assignment to be done, x==y merely tests whether x and y are equal, and causes no explicit action. If you have used the C programming language, you will recognize that the notation for assignment and testing in the Wolfram Language is the same as in C.
x=y
assigns x to have value y
x==y
tests whether x and y are equal
Assignments and tests.
This assigns x to have value 4:
If you ask for x, you now get 4:
This tests whether x is equal to 4. In this case, it is:
x is equal to 4, not 6:
This removes the value assigned to x:
The tests we have used so far involve only numbers, and always give a definite answer, either True or False. You can also do tests on symbolic expressions.
The Wolfram Language cannot get a definite result for this test unless you give x a specific numerical value:
If you replace x by the specific numerical value 4, the test gives False:
Even when you do tests on symbolic expressions, there are some cases where you can get definite results. An important one is when you test the equality of two expressions that are identical. Whatever the numerical values of the variables in these expressions may be, the Wolfram Language knows that the expressions must always be equal.
The two expressions are identical, so the result is True, whatever the value of x may be:
The Wolfram Language does not try to tell whether these expressions are equal. In this case, using Expand would make them have the same form:
Expressions like x==4 represent equations in the Wolfram Language. There are many functions in the Wolfram Language for manipulating and solving equations.
This is an equation in the Wolfram Language:"Solving Equations" discusses how to solve it for x:
You can assign a name to the equation:
If you ask for eqn, you now get the equation:
Solving Equations
An expression like x^2+2x-7==0 represents an equation in the Wolfram Language. You will often need to solve equations like this, to find out for what values of x they are true.
This gives the two solutions to the quadratic equation . The solutions are given as replacements for x:
Here are the numerical values of the solutions:
You can get a list of the actual solutions for x by applying the rules generated by Solve to x using the replacement operator:
You can equally well apply the rules to any other expression involving x:
Solve[lhs==rhs,x]
solve an equation, giving a list of rules for x
x/.solution
use the list of rules to get values for x
expr/.solution
use the list of rules to get values for an expression
Finding and using solutions to equations.
Solve always tries to give you explicit formulas for the solutions to equations. However, it is a basic mathematical result that, for sufficiently complicated equations, explicit algebraic formulas in terms of radicals cannot be given. If you have an algebraic equation in one variable, and the highest power of the variable is at most four, then the Wolfram Language can always give you formulas for the solutions. However, if the highest power is five or more, it may be mathematically impossible to give explicit algebraic formulas for all the solutions.
The Wolfram Language can always solve algebraic equations in one variable when the highest power is less than five:
It can solve some equations that involve higher powers:
There are some equations, however, for which it is mathematically impossible to find explicit formulas for the solutions. The Wolfram Language uses Root objects to represent the solutions in this case:
Even though you cannot get explicit formulas, you can still evaluate the solutions numerically:
In addition to being able to solve purely algebraic equations, the Wolfram Language can also solve some equations involving other functions.
After printing a warning, the Wolfram Language returns one solution to this equation:
It is important to realize that an equation such as actually has an infinite number of possible solutions, in this case differing by multiples of . However, Solve by default returns just one solution, but prints a message telling you that other solutions may exist. You can use Reduce to get more information.
There is no explicit "closed form" solution for a transcendental equation like this:
You can find an approximate numerical solution using FindRoot, and giving a starting value for x:
Solve can also handle equations involving symbolic functions. In such cases, it again prints a warning, then gives results in terms of formal inverse functions.
The Wolfram Language returns a result in terms of the formal inverse function of f:
Solve[{lhs1==rhs1,lhs2==rhs2,},{x,y,}]
solve a set of simultaneous equations for x, y,
Solving sets of simultaneous equations.
You can also use the Wolfram Language to solve sets of simultaneous equations. You simply give the list of equations, and specify the list of variables to solve for.
Here is a list of two simultaneous equations, to be solved for the variables x and y:
Here are some more complicated simultaneous equations. The two solutions are given as two lists of replacements for x and y:
This uses the solutions to evaluate the expression x+y:
The Wolfram Language can solve any set of simultaneous linear or polynomial equations.
When you are working with sets of equations in several variables, it is often convenient to reorganize the equations by eliminating some variables between them.
This eliminates y between the two equations, giving a single equation for x:
If you have several equations, there is no guarantee that there exists any consistent solution for a particular variable.
There is no consistent solution to these equations, so the Wolfram Language returns {}, indicating that the set of solutions is empty:
There is also no consistent solution to these equations for almost all values of a:
The general question of whether a set of equations has any consistent solution is quite a subtle one. For example, for most values of a, the equations {x==1,x==a} are inconsistent, so there is no possible solution for x. However, if a is equal to 1, then the equations do have a solution. Solve is set up to give you generic solutions to equations. It discards any solutions that exist only when special constraints between parameters are satisfied.
If you use Reduce instead of Solve, the Wolfram Language will however keep all the possible solutions to a set of equations, including those that require special conditions on parameters.
This shows that the equations have a solution only when a==1. The notation a==1&&x==1 represents the requirement that both a==1 and x==1 should be True:
This gives the complete set of possible solutions to the equation. The answer is stated in terms of a combination of simpler equations. && indicates equations that must simultaneously be true; || indicates alternatives:
This gives a more complicated combination of equations:
This gives a symbolic representation of all solutions:
Solve[lhs==rhs,x]
solve an equation for x
Solve[{lhs1==rhs1,lhs2==rhs2,},{x,y,}]
solve a set of simultaneous equations for x, y,
Eliminate[{lhs1==rhs1,lhs2==rhs2,},{x,}]
eliminate x, in a set of simultaneous equations
Reduce[{lhs1==rhs1,lhs2==rhs2,},{x,y,}]
give a set of simplified equations, including all possible solutions
Functions for solving and manipulating equations.
Reduce also has powerful capabilities for handling equations specifically over real numbers or integers. "Equations and Inequalities over Domains" discusses this in more detail.
This reduces the equation assuming x and y are complex:
This includes the conditions for x and y to be real:
This gives only the integer solutions:
The Representation of Equations and Solutions
The Wolfram System treats equations as logical statements. If you type in an equation like x^2+3x==2, the Wolfram System interprets this as a logical statement that asserts that x^2+3x is equal to 2. If you have assigned an explicit value to x, say x=4, then the Wolfram System can explicitly determine that the logical statement x^2+3x==2 is False.
If you have not assigned any explicit value to x, however, the Wolfram System cannot work out whether x^2+3x==2 is True or False. As a result, it leaves the equation in the symbolic form x^2+3x==2.
You can manipulate symbolic equations in the Wolfram System in many ways. One common goal is to rearrange the equations so as to "solve" for a particular set of variables.
Here is a symbolic equation:
You can use the function Reduce to reduce the equation so as to give "solutions" for x. The result, like the original equation, can be viewed as a logical statement:
The quadratic equation x^2+3x==2 can be thought of as an implicit statement about the value of x. As shown in the example above, you can use the function Reduce to get a more explicit statement about the value of x. The expression produced by Reduce has the form x==r1||x==r2. This expression is again a logical statement, which asserts that either x is equal to r1, or x is equal to r2. The values of x that are consistent with this statement are exactly the same as the ones that are consistent with the original quadratic equation. For many purposes, however, the form that Reduce gives is much more useful than the original equation.
You can combine and manipulate equations just like other logical statements. You can use logical connectives such as || and && to specify alternative or simultaneous conditions. You can use functions like LogicalExpand, as well as FullSimplify, to simplify collections of equations.
For many purposes, you will find it convenient to manipulate equations simply as logical statements. Sometimes, however, you will actually want to use explicit solutions to equations in other calculations. In such cases, it is convenient to convert equations that are stated in the form lhs==rhs into transformation rules of the form lhs->rhs. Once you have the solutions to an equation in the form of explicit transformation rules, you can substitute the solutions into expressions by using the /. operator.
Reduce produces a logical statement about the values of x corresponding to the roots of the quadratic equation:
ToRules converts the logical statement into an explicit list of transformation rules:
You can now use the transformation rules to substitute the solutions for x into expressions involving x:
The function Solve produces transformation rules for solutions directly:
Equations in One Variable
The main equations that Solve and related Wolfram Language functions deal with are polynomial equations.
It is easy to solve a linear equation in x:
One can also solve quadratic equations just by applying a simple formula:
The Wolfram Language can also find exact solutions to cubic equations. Here is the first solution to a comparatively simple cubic equation:
For cubic and quartic equations the results are often complicated, but for all equations with degrees up to four the Wolfram Language is always able to give explicit formulas for the solutions.
An important feature of these formulas is that they involve only radicals: arithmetic combinations of square roots, cube roots and higher roots.
It is a fundamental mathematical fact, however, that for equations of degree five or higher, it is no longer possible in general to give explicit formulas for solutions in terms of radicals.
There are some specific equations for which this is still possible, but in the vast majority of cases it is not.
This constructs a degree six polynomial:
For a polynomial that factors in the way this one does, it is straightforward for Solve to find the roots:
This constructs a polynomial of degree eight:
The polynomial does not factor, but it can be decomposed into nested polynomials, so Solve can again find explicit formulas for the roots:
Root[f,k]
the k th root of the equation f[x]==0
Implicit representation for roots.
No explicit formulas for the solution to this equation can be given in terms of radicals, so the Wolfram Language uses an implicit symbolic representation:
This finds a numerical approximation to each root:
If what you want in the end is a numerical solution, it is usually much faster to use NSolve from the outset:
Root objects provide an exact, though implicit, representation for the roots of a polynomial. You can work with them much as you would work with Sqrt[2] or any other expression that represents an exact numerical quantity.
Here is the Root object representing the first root of the polynomial discussed above:
This is a numerical approximation to its value:
Round does an exact computation to find the closest integer to the root:
If you substitute the root into the original polynomial, and then simplify the result, you get zero:
This finds the product of all the roots of the original polynomial:
The complex conjugate of the third root is the second root:
If the only symbolic parameter that exists in an equation is the variable that you are solving for, then all the solutions to the equation will just be numbers. But if there are other symbolic parameters in the equation, then the solutions will typically be functions of these parameters.
The solution to this equation can again be represented by Root objects, but now each Root object involves the parameter a:
When a is replaced with 1, the Root objects can be simplified, and some are given as explicit radicals:
This shows the behavior of the first root as a function of a:
This finds the derivative of the first root with respect to a:
If you give Solve any thdegree polynomial equation, then it will always return exactly solutions, although some of these may be represented by Root objects. If there are degenerate solutions, then the number of times that each particular solution appears will be equal to its multiplicity.
Solve gives two identical solutions to this equation:
Here are the first four solutions to a tenth degree equation. The solutions come in pairs:
The Wolfram Language also knows how to solve equations which are not explicitly in the form of polynomials.
Here is an equation involving square roots:
And here is one involving logarithms:
So long as it can reduce an equation to some kind of polynomial form, the Wolfram Language will always be able to represent its solution in terms of Root objects. However, with more general equations, involving, say, transcendental functions, there is no systematic way to use Root objects, or even necessarily to find numerical approximations.
Here is a simple transcendental equation for x:
There is no solution to this equation in terms of standard functions:
The Wolfram Language can nevertheless find a numerical solution even in this case:
Polynomial equations in one variable only ever have a finite number of solutions. But transcendental equations often have an infinite number. Typically the reason for this is that functions like Sin in effect have infinitely many possible inverses. With the default option setting InverseFunctions->True, Solve will nevertheless assume that there is a definite inverse for any such function. Solve may then be able to return particular solutions in terms of this inverse function.
The Wolfram Language returns a particular solution in terms of ArcSin, but prints a warning indicating that other solutions are lost:
Here the answer comes out in terms of ProductLog:
If you ask Solve to solve an equation involving an arbitrary function like f, it will by default try to construct a formal solution in terms of inverse functions.
Solve by default uses a formal inverse for the function f:
This is the structure of the inverse function:
InverseFunction[f]
the inverse function of f
InverseFunction[f,k,n]
the inverse function of the nargument function f with respect to its k th argument
Inverse functions.
This returns an explicit inverse function:
The Wolfram Language can do formal operations on inverse functions:
While Solve can only give specific solutions to an equation, Reduce can give a representation of a whole solution set. For transcendental equations, it often ends up introducing new parameters, say with values ranging over all possible integers.
This is a complete representation of the solution set:
Here again is a representation of the general solution:
As discussed at more length in "Equations and Inequalities over Domains", Reduce allows you to restrict the domains of variables. Sometimes this will let you generate definite solutions to transcendental equationsor show that they do not exist.
With the domain of x restricted, this yields definite solutions:
With x constrained to be real, only one solution is possible:
Reduce knows there can be no solution here:
Counting and Isolating Polynomial Roots

Counting Roots of Polynomials

CountRoots[poly,x]
give the number of real roots of the polynomial poly in x
CountRoots[poly,{x,a,b}]
give the number of roots of the polynomial poly in x with
Counting roots of polynomials.
CountRoots accepts polynomials with Gaussian rational coefficients. The root count includes multiplicities.
This gives the number of real roots of :
This counts the roots of in the closed interval :
The roots of in the vertical axis segment between and consist of a triple root at and a single root at :
This counts 17 th-degree roots of unity in the closed unit square:
The coefficients of the polynomial can be Gaussian rationals:

Isolating Intervals

A set , where is or , is an isolating set for a root of a polynomial if is the only root of in . Isolating roots of a polynomial means finding disjoint isolating sets for all the roots of the polynomial.
RootIntervals[{poly1,poly2,}]
give a list of disjoint isolating intervals for the real roots of any of the polyi, together with a list of which polynomials actually have each successive root
RootIntervals[poly]
give disjoint isolating intervals for real roots of a single polynomial
RootIntervals[polys,Complexes]
give disjoint isolating intervals or rectangles for complex roots of polys
IsolatingInterval[a]
give an isolating interval for the algebraic number a
IsolatingInterval[a,dx]
give an isolating interval of width at most dx
Functions for isolating roots of polynomials.
RootIntervals accepts polynomials with rational number coefficients.
For a real root the returned isolating interval is a pair of rational numbers , such that either or . For a nonreal root the isolating rectangle returned is a pair of Gaussian rational numbers , such that and either or .
Here are isolating intervals for the real roots of :
The second list shows which interval contains a root of which polynomial:
This gives isolating intervals for all complex roots of :
Here are isolating intervals for the third- and fourth-degree roots of unity. The second interval contains a root common to both polynomials:
Here is an isolating interval for a root of a polynomial of degree seven:
This gives an isolating interval of width at most :
All numbers in the interval have the first 10 decimal digits in common:
Algebraic Numbers
Root[f,k]
the k th root of the polynomial equation f[x]==0
The representation of algebraic numbers.
When you enter a Root object, the polynomial that appears in it is automatically reduced to a minimal form:
This extracts the pure function which represents the polynomial, and applies it to x:
Root objects are the way that the Wolfram Language represents algebraic numbers. Algebraic numbers have the property that when you perform algebraic operations on them, you always get a single algebraic number as the result.
Here is the square root of an algebraic number:
RootReduce reduces this to a single Root object:
Here is a more complicated expression involving an algebraic number:
Again this can be reduced to a single Root object, albeit a fairly complicated one:
RootReduce[expr]
attempt to reduce expr to a single Root object
ToRadicals[expr]
attempt to transform Root objects to explicit radicals
Operations on algebraic numbers.
In this simple case the Root object is automatically expressed in terms of radicals:
When cubic polynomials are involved, Root objects are not automatically expressed in terms of radicals:
ToRadicals attempts to express all Root objects in terms of radicals:
If Solve and ToRadicals do not succeed in expressing the solution to a particular polynomial equation in terms of radicals, then it is a good guess that this fundamentally cannot be done. However, you should realize that there are some special cases in which a reduction to radicals is in principle possible, but the Wolfram System cannot find it. The simplest example is the equation , but here the solution in terms of radicals is very complicated. The equation is another example, where now is a solution.
This gives a Root object involving a degree six polynomial:
Even though a simple form in terms of radicals does exist, ToRadicals does not find it:
Beyond degree four, most polynomials do not have roots that can be expressed at all in terms of radicals. However, for degree five it turns out that the roots can always be expressed in terms of elliptic or hypergeometric functions. The results, however, are typically much too complicated to be useful in practice.
RootSum[f,form]
the sum of form[x] for all satisfying the polynomial equation f[x]==0
Normal[expr]
the form of expr with RootSum replaced by explicit sums of Root objects
Sums of roots.
This computes the sum of the reciprocals of the roots of :
Now no explicit result can be given in terms of radicals:
This expands the RootSum into an explicit sum involving Root objects:
RootApproximant[x]
converts the number x to one of the "simplest" algebraic numbers that approximates it well
RootApproximant[x,n]
finds an algebraic number of degree at most n that approximates x
This recovers from a numerical approximation:
In this case, the result has degree at most 4:
This confirms that the Root expression does correspond to :
Simultaneous Equations
You can give Solve a list of simultaneous equations to solve. Solve can find explicit solutions for a large class of simultaneous polynomial equations.
Here is a simple linear equation with two unknowns:
Here is a more complicated example. The result is a list of solutions, with each solution consisting of a list of transformation rules for the variables:
You can use the list of solutions with the /. operator:
Even when Solve cannot find explicit solutions, it often can "unwind" simultaneous equations to produce a symbolic result in terms of Root objects:
You can then use N to get a numerical result:
The variables that you use in Solve do not need to be single symbols. Often when you set up large collections of simultaneous equations, you will want to use expressions like a[i] as variables.
Here is a list of three equations for the a[i]:
This solves for some of the a[i]:
Solve[eqns,{x1,x2,}]
solve eqns for the specific objects xi
Solve[eqns]
try to solve eqns for all the objects that appear in them
Solving simultaneous equations.
If you do not explicitly specify objects to solve for, Solve will try to solve for all the variables:
Solve[{lhs1==rhs1,lhs2==rhs2,},vars]
Solve[lhs1==rhs1&&lhs2==rhs2&&,vars]
Solve[{lhs1,lhs2,}=={rhs1,rhs2,},vars]
Ways to present simultaneous equations to Solve.
If you construct simultaneous equations from matrices, you typically get equations between lists of expressions:
Solve converts equations involving lists to lists of equations:
You can use LogicalExpand to do the conversion explicitly:
In some kinds of computations, it is convenient to work with arrays of coefficients instead of explicit equations. You can construct such arrays from equations by using CoefficientArrays.
Generic and NonGeneric Solutions
If you have an equation like 2x==0, it is perfectly clear that the only possible solution is x->0. However, if you have an equation like ax==0, things are not so clear. If a is not equal to zero, then x->0 is again the only solution. However, if a is in fact equal to zero, then any value of x is a solution. You can see this by using Reduce.
Solve implicitly assumes that the parameter a does not have the special value 0:
Reduce, on the other hand, gives you all the possibilities, without assuming anything about the value of a:
A basic difference between Reduce and Solve is that Reduce gives all the possible solutions to a set of equations, while Solve gives only the generic ones. Solutions are considered "generic" if they involve conditions only on the variables that you explicitly solve for, and not on other parameters in the equations. Reduce and Solve also differ in that Reduce always returns combinations of equations, while Solve gives results in the form of transformation rules.
Solve[eqns,vars]
find generic solutions to equations
Reduce[eqns,vars]
reduce equations, maintaining all solutions
Solving equations.
This is the solution to an arbitrary linear equation given by Solve:
Reduce gives the full version, which includes the possibility a==b==0. In reading the output, note that && has higher precedence than ||:
Here is the full solution to a general quadratic equation. There are three alternatives. If a is nonzero, then there are two solutions for x, given by the standard quadratic formula. If a is zero, however, the equation reduces to a linear one. Finally, if a, b, and c are all zero, there is no restriction on x:
When you have several simultaneous equations, Reduce can show you under what conditions the equations have solutions. Solve shows you whether there are any generic solutions.
This shows there can never be any solution to these equations:
There is a solution to these equations, but only when a has the special value 1:
The solution is not generic, and is rejected by Solve:
But if a is constrained to have value 1, then Solve again returns a solution:
This equation is true for any value of x:
This is the kind of result Solve returns when you give an equation that is always true:
When you work with systems of linear equations, you can use Solve to get generic solutions, and Reduce to find out for what values of parameters solutions exist.
Here is a matrix whose element is :
The matrix has determinant zero:
This makes a set of three simultaneous equations:
Solve reports that there are no generic solutions:
Reduce, however, shows that there would be a solution if the parameters satisfied the special condition a==2b-c:
For nonlinear equations, the conditions for the existence of solutions can be much more complicated.
Here is a very simple pair of nonlinear equations:
Solve shows that the equations have no generic solutions:
Reduce gives the complete conditions for a solution to exist:
Eliminating Variables
When you write down a set of simultaneous equations in the Wolfram Language, you are specifying a collection of constraints between variables. When you use Solve, you are finding values for some of the variables in terms of others, subject to the constraints represented by the equations.
Solve[eqns,vars,elims]
find solutions for vars, eliminating the variables elims
Eliminate[eqns,elims]
rearrange equations to eliminate the variables elims
Eliminating variables.
Here are two equations involving x, y and the "parameters" a and b:
If you solve for both x and y, you get results in terms of a and b:
Similarly, if you solve for x and a, you get results in terms of y and b:
If you only want to solve for x, however, you have to specify whether you want to eliminate y or a or b. This eliminates y, and so gives the result in terms of a and b:
If you eliminate a, then you get a result in terms of y and b:
In some cases, you may want to construct explicitly equations in which variables have been eliminated. You can do this using Eliminate.
This combines the two equations in the list eqn, by eliminating the variable a:
This is what you get if you eliminate y instead of a:
As a more sophisticated example of Eliminate, consider the problem of writing in terms of the "symmetric polynomials" and .
To solve the problem, we simply have to write f in terms of a and b, eliminating the original variables x and y:
In dealing with sets of equations, it is common to consider some of the objects that appear as true "variables", and others as "parameters". In some cases, you may need to know for what values of parameters a particular relation between the variables is always satisfied.
SolveAlways[eqns,vars]
solve for the values of parameters for which the eqns are satisfied for all values of the vars
Solving for parameters that make relations always true.
This finds the values of parameters that make the equation hold for all x:
This equates two series:
This finds values of the undetermined coefficients:
Relational and Logical Operators
x==y
equal (also input as xy )
x!=y
unequal (also input as xy )
x>y
greater than
x>=y
greater than or equal to (also input as xy )
x<y
less than
x<=y
less than or equal to (also input as xy )
x==y==z
all equal
x!=y!=z
all unequal (distinct)
x>y>z
, etc.
strictly decreasing, etc.
Relational operators.
This tests whether 10 is less than 7. The result is False:
Not all of these numbers are unequal, so this gives False:
You can mix < and <=:
Since both of the quantities involved are numeric, the Wolfram Language can determine that this is true:
The Wolfram Language does not know whether this is true or false:
!p
not (also input as ¬ p )
p&&q&&
and (also input as pq )
p||q||
or (also input as pq )
Xor[p,q,]
exclusive or (also input as pq )
Nand[p,q,]
and
Nor[p,q,]
nand and nor (also input as and )
If[p,then,else]
give then if p is True, and else if p is False
LogicalExpand[expr]
expand out logical expressions
Logical operations.
Both tests give True, so the result is True:
You should remember that the logical operations ==, &&, and || are all double characters in the Wolfram Language. If you have used a programming language such as C, you will be familiar with this notation.
The Wolfram Language does not know whether this is true or false:
The Wolfram Language leaves this expression unchanged:
You can use LogicalExpand to expand out the terms:
Solving Logical Combinations of Equations
When you give a list of equations to Solve, it assumes that you want all the equations to be satisfied simultaneously. It is also possible to give Solve more complicated logical combinations of equations.
Solve assumes that the equations x+y==1 and x-y==2 are simultaneously valid:
Here is an alternative form, using the logical connective && explicitly:
This specifies that either x+y==1 or x-y==2. Solve gives two solutions for x, corresponding to these two possibilities:
Solve gives three solutions to this equation:
If you explicitly include the assertion that x!=0, one of the previous solutions is suppressed:
Here is a slightly more complicated example. Note that the precedence of || is lower than the precedence of &&, so the equation is interpreted as (x^3==x&&x!=1)||x^2==2, not x^3==x&&(x!=1||x^2==2):
When you use Solve, the final results you get are in the form of transformation rules. If you use Reduce or Eliminate, on the other hand, then your results are logical statements, which you can manipulate further.
This gives a logical statement representing the solutions of the equation x^2==x:
This finds values of x which satisfy x^5==x but do not satisfy the statement representing the solutions of x^2==x:
The logical statements produced by Reduce can be thought of as representations of the solution set for your equations. The logical connectives &&, || and so on then correspond to operations on these sets.
eqns1||eqns2
union of solution sets
eqns1&&eqns2
intersection of solution sets
!eqns
complement of a solution set
Implies[eqns1,eqns2]
the part of eqns1 that contains eqns2
Operations on solution sets.
You may often find it convenient to use special notations for logical connectives, as discussed in "Operators".
The input uses special notations for Implies and Or:
Inequalities
Just as the equation x^2+3x==2 asserts that x^2+3x is equal to 2, so also the inequality x^2+3x>2 asserts that x^2+3x is greater than 2. In the Wolfram Language, Reduce works not only on equations, but also on inequalities.
Reduce[{ineq1,ineq2,},x]
reduce a collection of inequalities in x
Manipulating univariate inequalities.
This pair of inequalities reduces to a single inequality:
These inequalities can never simultaneously be satisfied:
When applied to an equation, Reduce[eqn,x] tries to get a result consisting of simple equations for x of the form x==r1, . When applied to an inequality, Reduce[ineq,x] does the exactly analogous thing, and tries to get a result consisting of simple inequalities for x of the form l1<x<r1, .
This reduces a quadratic equation to two simple equations for x:
This reduces a quadratic inequality to two simple inequalities for x:
You can think of the result generated by Reduce[ineq,x] as representing a series of intervals, described by inequalities. Since the graph of a polynomial of degree can go up and down as many as times, a polynomial inequality of degree can give rise to as many as distinct intervals.
This inequality yields three distinct intervals:
The ends of the intervals are at roots and poles:
Solving this inequality requires introducing ProductLog:
Transcendental functions like have graphs that go up and down infinitely many times, so that infinitely many intervals can be generated.
The second inequality allows only finitely many intervals:
This is how Reduce represents infinitely many intervals:
Fairly simple inputs can give fairly complicated results:
If you have inequalities that involve <= as well as <, there may be isolated points where the inequalities can be satisfied. Reduce represents such points by giving equations.
This inequality can be satisfied at just two isolated points:
This yields both intervals and isolated points:
Reduce[{ineq1,ineq2,},{x1
,
x2
, }]
reduce a collection of inequalities in several variables
Multivariate inequalities.
For inequalities involving several variables, Reduce in effect yields nested collections of interval specifications, in which later variables have bounds that depend on earlier variables.
This represents the unit disk as nested inequalities for x and y:
In geometrical terms, any linear inequality divides space into two halves. Lists of linear inequalities thus define polyhedra, sometimes bounded, sometimes not. Reduce represents such polyhedra in terms of nested inequalities. The corners of the polyhedra always appear among the endpoints of these inequalities.
This defines a triangular region in the plane:
Even a single triangle may need to be described as two components:
Lists of inequalities in general represent regions of overlap between geometrical objects. Often the description of these can be quite complicated.
This represents the part of the unit disk on one side of a line:
Here is the intersection between two disks:
If the disks are too far apart, there is no intersection:
Here is an example involving a transcendental inequality:
If you have inequalities that involve parameters, Reduce automatically handles the different cases that can occur, just as it does for equations.
The form of the intervals depends on the value of a:
One gets a hyperbolic or an elliptical region, depending on the value of a:
Reduce tries to give you a complete description of the region defined by a set of inequalities. Sometimes, however, you may just want to find individual instances of values of variables that satisfy the inequalities. You can do this using FindInstance.
FindInstance[ineqs,{x1,x2,}]
try to find an instance of the xi satisfying ineqs
FindInstance[ineqs,vars,n]
try to find n instances
Finding individual points that satisfy inequalities.
This finds a specific instance that satisfies the inequalities:
This shows that there is no way to satisfy the inequalities:
FindInstance is in some ways an analog for inequalities of Solve for equations. For like Solve, it returns a list of rules giving specific values for variables. But while for equations these values can generically give an accurate representation of all solutions, for inequalities they can only correspond to isolated sample points within the regions described by the inequalities.
Every time you call FindInstance with specific input, it will give the same output. And when there are instances that correspond to special, limiting, points of some kind, it will preferentially return these. But in general, the distribution of instances returned by FindInstance will typically seem somewhat random. Each instance is, however, in effect a constructive proof that the inequalities you have given can in fact be satisfied.
If you ask for one point in the unit disk, FindInstance gives the origin:
This finds 500 points in the unit disk:
Their distribution seems somewhat random:
Equations and Inequalities over Domains
The Wolfram Language normally assumes that variables which appear in equations can stand for arbitrary complex numbers. But when you use Reduce, you can explicitly tell the Wolfram Language that the variables stand for objects in more restricted domains.
Reduce[expr,vars,dom]
reduce eqns over the domain dom
Complexes
complex numbers
Reals
real numbers
Integers
integers
Solving over domains.
Reduce by default assumes that x can be complex, and gives all five complex solutions:
But here it assumes that x is real, and gives only the real solutions:
And here it assumes that x is an integer, and gives only the integer solutions:
A single polynomial equation in one variable will always have a finite set of discrete solutions. And in such a case one can think of Reduce[eqns,vars,dom] as just filtering the solutions by selecting the ones that happen to lie in the domain dom.
But as soon as there are more variables, things can become more complicated, with solutions to equations corresponding to parametric curves or surfaces in which the values of some variables can depend on the values of others. Often this dependence can be described by some collection of equations or inequalities, but the form of these can change significantly when one goes from one domain to another.
This gives solutions over the complex numbers as simple formulas:
To represent solutions over the reals requires introducing an inequality:
Over the integers, the solution can be represented as equations for discrete points:
If your input involves only equations, then Reduce will by default assume that all variables are complex. But if your input involves inequalities, then Reduce will assume that any algebraic variables appearing in them are real, since inequalities can only compare real quantities.
Since the variables appear in an inequality, they are assumed to be real:
Complexes
polynomial!=0 , xi==Root[]
Reals
Root[]<xi<Root[] , xi==Root[]
Integers
arbitrarily complicated
Schematic building blocks for solutions to polynomial equations and inequalities.
For systems of polynomials over real and complex domains, the solutions always consist of a finite number of components, within which the values of variables are given by algebraic numbers or functions.
Here the components are distinguished by equations and inequations on x:
And here the components are distinguished by inequalities on x:
While in principle Reduce can always find the complete solution to any collection of polynomial equations and inequalities with real or complex variables, the results are often very complicated, with the number of components typically growing exponentially as the number of variables increases.
With 3 variables, the solution here already involves 8 components:
As soon as one introduces functions like Sin or Exp, even equations in single real or complex variables can have solutions with an infinite number of components. Reduce labels these components by introducing additional parameters. By default, the th parameter in a given solution will be named C[n]. In general you can specify that it should be named f[n] by giving the option setting GeneratedParameters->f.
The components here are labeled by the integer parameter c1:
Reduce can handle equations not only over real and complex variables, but also over integers. Solving such Diophantine equations can often be a very difficult problem.
Describing the solution to this equation over the reals is straightforward:
The solution over the integers involves the divisors of 8:
Solving an equation like this effectively requires factoring a large number:
Reduce can solve any system of linear equations or inequalities over the integers. With linear equations in variables, parameters typically need to be introduced. But with inequalities, a much larger number of parameters may be needed.
Three parameters are needed here, even though there are only two variables:
With two variables, Reduce can solve any quadratic equation over the integers. The result can be a Fibonaccilike sequence, represented in terms of powers of quadratic irrationals.
Here is the solution to a Pell equation:
The actual values for specific C[1] as integers, as they should be:
Reduce can handle many specific classes of equations over the integers.
Here Reduce finds the solution to a Thue equation:
Changing the righthand side to 3, the equation now has no solution:
Equations over the integers sometimes have seemingly quite random collections of solutions. And even small changes in equations can often lead them to have no solutions at all.
For polynomial equations over real and complex numbers, there is a definite decision procedure for determining whether or not any solution exists. But for polynomial equations over the integers, the unsolvability of Hilberts Tenth Problem demonstrates that there can never be any such general procedure.
For specific classes of equations, however, procedures can be found, and indeed many are implemented in Reduce. But handling different classes of equations can often seem to require whole different branches of number theory, and quite different kinds of computations. And in fact it is known that there are universal integer polynomial equations, for which filling in some variables can make solutions for other variables correspond to the output of absolutely any possible program. This then means that for such equations there can never in general be any closedform solution built from fixed elements like algebraic functions.
If one includes functions like Sin, then even for equations involving real and complex numbers the same issues can arise.
Reduce here effectively has to solve an equation over the integers:
Reduce[eqns,vars,Modulus->n]
find solutions modulo n
Handling equations involving integers modulo n.
Since there are only ever a finite number of possible solutions for integer equations modulo n, Reduce can systematically find them.
This finds all solutions modulo 4:
Reduce can also handle equations that involve several different moduli.
Here is an equation involving two different moduli:
Reduce[expr,vars,dom]
specify a default domain for all variables
Reduce[{expr1,,x1dom1,},vars]
explicitly specify individual domains for variables
Different ways to specify domains for variables.
This assumes that x is an integer, but y is a real:
Reduce normally treats complex variables as single objects. But in dealing with functions that are not analytic or have branch cuts, it sometimes has to break them into pairs of real variables Re[z] and Im[z].
The result involves separate real and imaginary parts:
Here again there is a separate condition on the imaginary part:
Reduce by default assumes that variables that appear algebraically in inequalities are real. But you can override this by explicitly specifying Complexes as the default domain. It is often useful in such cases to be able to specify that certain variables are still real.
Reduce by default assumes that x is a real:
This forces Reduce to consider the case where x can be complex:
Since x does not appear algebraically, Reduce immediately assumes that it can be complex:
Here x is a real, but y can be complex:
FindInstance[expr,{x1,x2,},dom]
try to find an instance of the xi in dom satisfying expr
FindInstance[expr,vars,dom,n]
try to find n instances
Complexes
the domain of complex numbers
Reals
the domain of real numbers
Integers
the domain of integers
Booleans
the domain of Booleans (True and False)
Finding particular solutions in domains.
Reduce always returns a complete representation of the solution to a system of equations or inequalities. Sometimes, however, you may just want to find particular sample solutions. You can do this using FindInstance.
If FindInstance[expr,vars,dom] returns {} then this means that the Wolfram Language has effectively proved that expr cannot be satisfied for any values of variables in the specified domain. When expr can be satisfied, FindInstance will normally pick quite arbitrarily among values that do this, as discussed for inequalities in "Inequalities: Manipulating Equations and Inequalities".
Particularly for integer equations, FindInstance can often find particular solutions to equations even when Reduce cannot find a complete solution. In such cases it usually returns one of the smallest solutions to the equations.
This finds the smallest integer point on an elliptic curve:
One feature of FindInstance is that it also works with Boolean expressions whose variables can have values True or False. You can use FindInstance to determine whether a particular expression is satisfiable, so that there is some choice of truth values for its variables that makes the expression True.
This expression cannot be satisfied for any choice of p and q:
But this can:
The Representation of Solution Sets
Any combination of equations or inequalities can be thought of as implicitly defining a region in some kind of space. The fundamental function of Reduce is to turn this type of implicit description into an explicit one.
An implicit description in terms of equations or inequalities is sufficient if you just want to test whether a point specified by values of variables is in the region. But to understand the structure of the region, or to generate points in it, you typically needs a more explicit description, of the kind obtained from Reduce.
Here are inequalities that implicitly define a semicircular region:
This shows that the point lies in the region:
Reduce gives a more explicit representation of the region:
If you pick a value for x consistent with the first inequality, you then immediately get an explicit inequality for y:
Reduce[expr,{x1,x2,}] is set up to describe regions by first giving fixed conditions for x1, then giving conditions for x2 that depend on x1, then conditions for x3 that depend on x1 and x2, and so on. This structure has the feature that it allows you to pick points by successively choosing values for each of the xi in turnin much the same way as when you uses iterators in functions like Table.
This gives a representation for the region in which you first pick a value for y, then x:
In some simple cases the region defined by a system of equations or inequalities will end up having only one component. In such cases, the output from Reduce will be of the form e1&&e2, where each of the ei is an equation or inequality involving variables up to xi.
In most cases, however, there will be several components, represented by output containing forms such as u1||u2||. Reduce typically tries to minimize the number of components used in describing a region. But in some cases multiple parametrizations may be needed to cover a single connected component, and each one of these will appear as a separate component in the output from Reduce.
In representing solution sets, it is common to find that several components can be described together by using forms such as &&(u1||u2)&&. Reduce by default does this so as to return its results as compactly as possible. You can use LogicalExpand to generate an expanded form in which each component appears separately.
In generating the most compact results, Reduce sometimes ends up making conditions on later variables xi depend on more of the earlier xi than is strictly necessary. You can force Reduce to generate results in which a particular xi only has minimal dependence on earlier xi by giving the option Backsubstitution->True. Usually this will lead to much larger output, although sometimes it may be easier to interpret.
By default, Reduce expresses the condition on y in terms of x:
Backsubstituting allows conditions for y to be given without involving x:
CylindricalDecomposition[expr,{x1,x2,}]
generate the cylindrical algebraic decomposition of the region defined by expr
GenericCylindricalDecomposition[expr,{x1,x2,}]
find the full-dimensional part of the decomposition of the region defined by expr, together with any hypersurfaces containing the rest of the region
SemialgebraicComponentInstances[expr,{x1,x2,}]
give at least one point in each connected component of the region defined by expr
Cylindrical algebraic decomposition.
For polynomial equations or inequalities over the reals, the structure of the result returned by Reduce is typically a cylindrical algebraic decomposition or CAD. Sometimes Reduce can yield a simpler form. But in all cases you can get the complete CAD by using CylindricalDecomposition. For systems containing inequalities only, GenericCylindricalDecomposition gives you "most" of the solution set and is often faster.
Here is the cylindrical algebraic decomposition of a region bounded by a hyperbola:
This gives the two-dimensional part of the solution set along with a curve containing the boundary:
This finds solutions from both parts of the solution set:
The results include a few points from each piece of the solution set:
Quantifiers
In a statement like x^4+x^2>0, the Wolfram Language treats the variable x as having a definite, though unspecified, value. Sometimes, however, it is useful to be able to make statements about whole collections of possible values for x. You can do this using quantifiers.
ForAll[x,expr]
expr holds for all values of x
ForAll[{x1,x2,},expr]expr
holds for all values of all the
xi
ForAll[{x1,x2,},cond,expr]expr
holds for all
xi
satisfying
cond
Exists[x,expr]
there exists a value of x for which expr holds
Exists[{x1,x2,},expr]
there exist values of the xi for which expr holds
Exists[{x1,},cond,expr]
there exist values of the xi satisfying cond for which expr holds
The structure of quantifiers.
You can work with quantifiers in the Wolfram Language much as you work with equations, inequalities, or logical connectives. In most cases, the quantifiers will not immediately be changed by evaluation. But they can be simplified or reduced by functions like FullSimplify and Reduce.
This asserts that an x exists that makes the inequality true. The output here is just a formatted version of the input:
FullSimplify establishes that the assertion is true:
This gives False, since the inequality fails when x is zero:
The Wolfram Language supports a version of the standard notation for quantifiers used in predicate logic and pure mathematics. You can input as \[ForAll] or EscfaEsc, and you can input as \[Exists] or EscexEsc. To make the notation precise, however, the Wolfram Language makes the quantified variable a subscript. The conditions on the variable can also be given in the subscript, separated by a comma.
xexprForAll[x,expr]
{x1,x2,}exprForAll[{x1,x2,},expr]
x,condexprForAll[x,cond,expr]
xexprExists[x,expr]
{x1,x2,}exprExists[{x1,x2,},expr]
x,condexprExists[x,cond,expr]
Notation for quantifiers.
Given a statement that involves quantifiers, there are certain important cases where it is possible to resolve it into an equivalent statement in which the quantifiers have been eliminated. Somewhat like solving an equation, such quantifier elimination turns an implicit statement about what is true for all x or for some x into an explicit statement about the conditions under which this holds.
Resolve[expr]
attempt to eliminate quantifiers from expr
Resolve[expr,dom]
attempt to eliminate quantifiers with all variables assumed to be in domain dom
Quantifier elimination.
This shows that an x exists that makes the equation true:
This shows that the equations can only be satisfied if c obeys a certain condition:
Resolve can always eliminate quantifiers from any collection of polynomial equations and inequations over complex numbers, and from any collection of polynomial equations and inequalities over real numbers. It can also eliminate quantifiers from Boolean expressions.
This finds the conditions for a quadratic form over the reals to be positive:
This shows that there is a way of assigning truth values to p and q that makes the expression true:
You can also use quantifiers with Reduce. If you give Reduce a collection of equations or inequalities, then it will try to produce a detailed representation of the complete solution set. But sometimes you may want to address a more global question, such as whether the solution set covers all values of x, or whether it covers none of these values. Quantifiers provide a convenient way to specify such questions.
This gives the complete structure of the solution set:
This instead just gives the condition for a solution to exist:
It is possible to formulate a great many mathematical questions in terms of quantifiers.
This finds the conditions for a circle to be contained within an arbitrary conic section:
This finds the conditions for a line to intersect a circle:
This defines q to be a general monic quartic:
This finds the condition for all pairs of roots to the quartic to be equal:
Although quantifier elimination over the integers is in general a computationally impossible problem, the Wolfram Language can do it in specific cases.
This shows that cannot be a rational number:
is, though:
Minimization and Maximization
Minimize[expr,{x1,x2,}]
minimize expr
Minimize[{expr,cons},{x1,x2,}]
minimize expr subject to the constraints cons
Maximize[expr,{x1,x2,}]
maximize expr
Maximize[{expr,cons},{x1,x2,}]
maximize expr subject to the constraints cons
Minimization and maximization.
Minimize and Maximize yield lists giving the value attained at the minimum or maximum, together with rules specifying where the minimum or maximum occurs.
This finds the minimum of a quadratic function:
Applying the rule for x gives the value at the minimum:
This maximizes with respect to x and y:
Minimize[expr,x] minimizes expr allowing x to range over all possible values from to . Minimize[{expr,cons},x] minimizes expr subject to the constraints cons being satisfied. The constraints can consist of any combination of equations and inequalities.
This finds the minimum subject to the constraint :
This finds the maximum within the unit circle:
This finds the maximum within an ellipse. The result is fairly complicated:
This finds the maximum along a line:
Minimize and Maximize can solve any linear programming problem in which both the objective function expr and the constraints cons involve the variables only linearly.
Here is a typical linear programming problem:
They can also in principle solve any polynomial programming problem in which the objective function and the constraints involve arbitrary polynomial functions of the variables. There are many important geometrical and other problems that can be formulated in this way.
This solves the simple geometrical problem of maximizing the area of a rectangle with fixed perimeter:
This finds the maximal volume of a cuboid that fits inside the unit sphere:
An important feature of Minimize and Maximize is that they always find global minima and maxima. Often functions will have various local minima and maxima at which derivatives vanish. But Minimize and Maximize use global methods to find absolute minima or maxima, not just local extrema.
Here is a function with many local maxima and minima:
Maximize finds the global maximum:
If you give functions that are unbounded, Minimize and Maximize will return and as the minima and maxima. And if you give constraints that can never be satisfied, they will return and as the minima and maxima, and Indeterminate as the values of variables.
One subtle issue is that Minimize and Maximize allow both nonstrict inequalities of the form , and strict ones of the form . With nonstrict inequalities there is no problem with a minimum or maximum lying exactly on the boundary . But with strict inequalities, a minimum or maximum must in principle be at least infinitesimally inside the boundary.
With a strict inequality, the Wolfram Language prints a warning, then returns the point on the boundary:
Minimize and Maximize normally assume that all variables you give are real. But by giving a constraint such as xIntegers you can specify that a variable must in fact be an integer.
This does maximization only over integer values of x and y:
Minimize and Maximize can compute maxima and minima of linear functions over the integers in bounded polyhedra. This is known as integer linear programming.
This does maximization over integer values of x and y in a triangle:
Minimize and Maximize can produce exact symbolic results for polynomial optimization problems with parameters.
This finds the minimum of a general quadratic polynomial:
MinValue[{f,cons},{x,y,}]
give the minimum value of f subject to the constraints cons
MaxValue[{f,cons},{x,y,}]
give the maximum value of f subject to the constraints cons
ArgMin[{f,cons},{x,y,}]
give a position at which f is minimized subject to the constraints cons
ArgMax[{f,cons},{x,y,}]
give a position at which f is maximized subject to the constraints cons
Computing values and positions of minima and maxima.
Maximize gives both the value and the position of a maximum:
Use MaxValue if you only need the maximum value:
For strict polynomial inequality constraints, computing only the maximum value may be much faster:
ArgMax gives a position at which the maximum value is attained: