## Symbolic Algebra

As is explained more fully in the Mathematica Programming section, the language Mathematica is built around is almost 100% symbolic, which makes it perfect for algebraic manipulations.

One of the simplest examples of things one can do in Mathematica is generate and combine polynomials:

 simplePolynomial[var_,order_]:=
Total@Table[RandomInteger[10]*Power[var,n],{n,order}];


We'll make a few of these polynomials and add them:

 pX1=simplePolynomial[x,2]
pX2=simplePolynomial[x,2]
pX1+pX2

 6 x+6 x^2

 8 x+9 x^2

 14 x+15 x^2


This works just as well at any polynomial order. Here we'll add five randomly generated polynomials of order less than or equal to 15 .

 Array[(simplePolynomial[x, RandomInteger[15]])&, 5]//Total

 22 x+26 x^2+15 x^3+28 x^4+10 x^5+9 x^6+12 x^7+13 x^8+19 x^9+11 x^10+9 x^11+13 x^12+6 x^13+4 x^14


Here's that again, but formatted nicer:

$$4 x^{14}+6 x^{13}+13 x^{12}+9 x^{11}+11 x^{10}+19 x^9+13 x^8+12 x^7+9 x^6+10 x^5+28 x^4+15 x^3+26 x^2+22 x$$

For those interested, the & specifies that what comes before should be treated as a function, but absent any variables we simply get our expression as a result.

### Simplify

For more complex things we'll need to explicitly simplify them:

 sphericalHarmonicSum=
Total@
Array[
SphericalHarmonicY[RandomInteger[5], RandomInteger[5], θ, ϕ]&,
5]


We can then have Mathematica simplify this expression for us more:

 Simplify[sphericalHarmonicSum]


$$\frac{1}{64} \sqrt{\frac{3}{2 \pi }} e^{i \phi } \sin (\theta ) \left(2 \left(\sqrt{11}+4\right) \sqrt{35} e^{i \phi } \sin (2 \theta )+3 \sqrt{385} e^{i \phi } \sin (4 \theta )-32\right)$$

Sometimes we also need to use the function FullSimplify to get everything simplified:

 FullSimplify[sphericalHarmonicSum]


$$\frac{1}{32} \sqrt{\frac{3}{2 \pi }} e^{i \phi } \sin (\theta ) \left(-16+\sqrt{35} e^{i \phi } \sin (2 \theta ) \left(3 \sqrt{11} \cos (2 \theta )+\sqrt{11}+4\right)\right)$$

It often makes sense to go for Simplify over FullSimplify , despite the fact that we can get more simplification out of FullSimplify , because sometimes the Simplify is all we need to see a pattern ourselves, while FullSimplify can over-simplify and obliterate that pattern.

It's good to keep in mind that while Mathematica may know more than we do, we're still smarter than it is.

### Solve

Mathematica can also solve equations for us. We'll try this on a nice quartic polynomial:

 polynomialInX=simplePolynomial[x, 4]


$$6 x^4+3 x^3+5 x^2+6 x$$

Note that there's no nice way to find the roots of this polynomial by hand. But Mathematica doesn't mind:

 Solve[polynomialInX==0,x]

 {
{x->0},
{x->1/6 (-1-9/(-94 + Sqrt[9565])^(1/3)+(-94 + Sqrt[9565])^(1/3))},
{x->-1/6+(3 (1 + I Sqrt[3]))/(4 (-94 + Sqrt[9565])^(1/3))-1/12 (1-I Sqrt[3]) (-94 + Sqrt[9565])^(1/3)},
{x->-1/6+(3 (1 - I Sqrt[3]))/(4 (-94 + Sqrt[9565])^(1/3))-1/12 (1+I Sqrt[3]) (-94 + Sqrt[9565])^(1/3)}
}


Here's one of those solutions in easier-to-read form:

$$\frac{1}{6} \left(\sqrt[3]{\sqrt{9565}-94}-\frac{9}{\sqrt[3]{\sqrt{9565}-94}}-1\right)$$

As mentioned before, Mathematica knows more math than any of us. It sees a quartic polynomial and knows that by the fundamental theorem of algebra there are four solutions to this equation, we just might need to find complex solutions.

Usually this isn't what we want, unfortunately. Happily Mathematica can dumb itself down for us.

 Solve[polynomialInX==0,x,Reals]

 { {x->0},{x->Root[6+5 #1+3 #1^2+6 #1^3&,1]} }


Notice that we get this odd Root expression. That's the way Mathematica represents a perfectly exact root. We can get its numerical one of two ways. Either we make the equation inexact:

 Solve[polynomialInX==0., x, Reals]

 { {x->-0.867733324263096},{x->0} }


Or we numericize after the fact:

 N[Solve[polynomialInX==0,x,Reals],6]

 { {x->0},{x->-0.86773332426309588196.} }


One useful thing to know with Solve is why the results are returned so oddly. Each list is a different solution, which is more important with multivariate equations, which we'll get to, but first let's see a nice way to get out our solutions in a simple list:

 x/.N[Solve[polynomialInX==0,x,Reals],6]

 {0,-0.86773332426309588196.}


The /. is an alias for ReplaceAll , which is described in more detail later in the Replacement Patterns section. For now let's just note that any time it sees var on the left hand side it looks for var->val on the right hand side and replaces var with that.

Now let's also see how we can plot these solutions:

 Show[
Plot[polynomialInX,{x,-2,2}],
ListPlot[Table[{x,0},
{x,x/.Solve[polynomialInX==0.,x,Reals]}]]
]


We have to use ListPlot to plot our discrete solutions, but we can see we get the result we expect.

We could even write a function that will solve the equation for an arbitrary value and plot the result:

 solveAndPlot[eqInX_,val_]:=
Show[
Plot[eqInX,{x,-2,2}],
ListPlot[Table[{x,val},
{x,x/.Solve[eqInX==(1.val),x,Reals]}]],
PlotLabel->
Row@{
HoldForm[eqInX==val]," @ ",
Row@Riffle[(x/.Solve[eqInX==(1.val),x,Reals]),", "]
}
];


Calling this on our solution:

 solveAndPlot[polynomialInX,50]


But that's getting distracted, I suppose.

### Multivariate Solve

Let's move to multivariate equations now:

 polynomialInXandY=simplePolynomial[x,3]+simplePolynomial[y,3]

 8 x+2 x^2+2 y+10 y^2+8 y^3


$$2 x^2+8 x+8 y^3+10 y^2+2 y$$

It can still solve this equation, although as it will admit, it may miss some solutions.

 Solve[polynomialInXandY == 0,{x,y}, Reals]

Solve::svars: "Equations may not give solutions for all \"solve\" variables."
 { {x->ConditionalExpression[-2-Sqrt[4 - y - 5 y^2 - 4 y^3],y<1/12 (-5+(829 - 6 Sqrt[19029])^(1/3)+(829 + 6 Sqrt[19029])^(1/3))]},{x->ConditionalExpression[-2+Sqrt[4 - y - 5 y^2 - 4 y^3],y<1/12 (-5+(829 - 6 Sqrt[19029])^(1/3)+(829 + 6 Sqrt[19029])^(1/3))]},{x->-2-√(4+1/12 (5-(829 - 6 Sqrt[19029])^(1/3)-(829 + 6 Sqrt[19029])^(1/3))-5/144 (-5 + (829 - 6 Sqrt[19029])^(1/3) + (829 + 6 Sqrt[19029])^(1/3))^2-1/432 (-5 + (829 - 6 Sqrt[19029])^(1/3) + (829 + 6 Sqrt[19029])^(1/3))^3),y->1/12 (-5+(829 - 6 Sqrt[19029])^(1/3)+(829 + 6 Sqrt[19029])^(1/3))} }


Here's one of the branches in human-readable form:

$$-\sqrt{-\frac{1}{432} \left(\sqrt[3]{6 \sqrt{19029}+829}+\sqrt[3]{829-6 \sqrt{19029}}-5\right)^3-\frac{5}{144} \left(\sqrt[3]{6 \sqrt{19029}+829}+\sqrt[3]{829-6 \sqrt{19029}}-5\right)^2+\frac{1}{12} \left(-\sqrt[3]{6 \sqrt{19029}+829}-\sqrt[3]{829-6 \sqrt{19029}}+5\right)+4}-2$$

Note that it also gives us these odd ConditionalExpression statements. This is because the solution could branch depending on how x and y interplay. Let's just get take one of these solutions:

 conditionalSoln=First[x/.Solve[polynomialInXandY == 0.,{x,y}, Reals]];
N[conditionalSoln]

Solve::svars: "Equations may not give solutions for all \"solve\" variables."
 ConditionalExpression[-2.-1. Sqrt[4. - 1. y - 5. y^2 - 4. y^3],y<0.6609358769285026]


And plot it:

 Plot[conditionalSoln,{y,-1,1},PlotLabel->"Value of X for given Y"]


We can force a given branch of this conditional expression, however, by telling Mathematica what it can assume.

### Assumptions

When Mathematica simplifies an expression it checks what we've told it to about the expression. It does that by looking at the value of the variable $Assumptions  $Assumptions

 True


This is the default value. But we can make it assume things for us. Let's assume that y satifies our ConditionalExpression . First we set the Assumptions :

 $Assumptions=y<.5   y<0.5  Now Mathematica will use these when solving:  xAndyRoots={x, y}/.Solve[polynomialInXandY == 0, {x, y}, Reals]//First//Simplify  Solve::svars: "Equations may not give solutions for all \"solve\" variables."  {-2-Sqrt[4 - y - 5 y^2 - 4 y^3],y}  And when we're done we simply reset the $Assumptions variable. We can also apply \$Assumptions to a single Simplify` expression or similar, but I will leave that to you to read up on.