$$
\huge \text{Deriving the Quadratic Formula with SymPy}\\
\large \text{Andrew Ribeiro}\\
\text{December 2017}
$$


```python
import sympy as sp
from IPython.display import display
sp.init_printing(order="lex",use_latex='mathjax')
```

Quadratic equations are of the form: 

$$ ax^2 + bx^1 + cx^0 = ax^2 + bx + c = 0$$

Where $a,b,c$ are coeficients. The coeficients can be integers, real numbers, or imaginary numbers. We know from the quadratic formula that such equations can be solved for x by completing the square. In this exercise we will use SymPy to help us derive the quadratic formula. Let's first define some symbols we will use in our symbolic calculations. 


```python
a,b,c = sp.symbols("a b c")
z,k = sp.symbols("z k")
x = sp.symbols("x")
```

Now we can easily represent the quadratic equation.


```python
lhs = a*x**2 + b*x + c
rhs = 0 
quadraticEqn = sp.Eq(lhs,rhs)
quadraticEqn
```




$$a x^{2} + b x + c = 0$$



## Completing the square 

Before we start our derivation, let's talk about completing the square. Say we have binomial rased to a power. 


```python
f =(a+b)**2
f
```




$$\left(a + b\right)^{2}$$



If we expand this we get the form: 


```python
fExp = f.expand()
fExp
```




$$a^{2} + 2 a b + b^{2}$$



Going from this expanded form back to the binomial is called *factoring.*


```python
fExp.factor()
```




$$\left(a + b\right)^{2}$$



We use SymPy to define a function for completing the square of a symbolic polynomial. This will work for different types of polynomials, but in the case of a quadratic, this works by solving for $z$ and $k$: 

$$
ax^2 + bx + c = (x+z)^2 + k \\
ax^2 + bx + c - (x+z)^2 + k = 0
$$


```python
def completeSquare(poly):
    z,k = sp.symbols("z k")
    completedSquareForm = (x+z)**2+k
    sol = sp.solve(poly-completedSquareForm,[z,k])
    squareRes = sp.Pow(x+sol[0][0],2,evaluate=False)
    constantRes = sol[0][1]
    return squareRes + constantRes

```

Consider the following polynomial, which is not a perfect square. 


```python
poly1 = x**2 + 10*x + 28
poly1
```




$$x^{2} + 10 x + 28$$



If we try to factor this with SymPy it will throw up its hands and do nothing because it cannot be factored. 


```python
poly1.factor()
```




$$x^{2} + 10 x + 28$$



We still can, however, complete the square. 


```python
completedSquareForm = (x+b)**2+c
poly1Eqn = sp.Eq(poly1,completedSquareForm)
poly1Eqn
```




$$x^{2} + 10 x + 28 = c + \left(b + x\right)^{2}$$




```python
sol = sp.solve(poly1 - completedSquareForm,[b,c])
sp.Eq(poly1Eqn,completeSquare(poly1))
```




$$x^{2} + 10 x + 28 = c + \left(b + x\right)^{2} = \left(x + 5\right)^{2} + 3$$



Now consider a polynomial which is a perfect square. 


```python
poly2 = ((x+5)**2).expand()
poly2
```




$$x^{2} + 10 x + 25$$



Factoring now works, but we can also complete the square with $c=0$


```python
poly2.factor()
```




$$\left(x + 5\right)^{2}$$




```python
completeSquare(poly2)
```




$$\left(x + 5\right)^{2}$$



We will use this function below to help us derive the quadratic formula. 

## Using the completion of the square to derive the quadratic formula


```python
quadApart = (quadraticEqn/a).apart(a)
quadApart
```




$$x^{2} + \frac{1}{a} \left(b x + c\right)$$




```python
expanded = quadApart.expand()
lhs = expanded
lhs
```




$$x^{2} + \frac{b x}{a} + \frac{c}{a}$$



Subtract both sides by $\large \frac{c}{a}$


```python
lhs = lhs - c/a
rhs = rhs - c/a
sp.Eq(lhs,rhs)
```




$$x^{2} + \frac{b x}{a} = - \frac{c}{a}$$



We would now like to know what term we must add to both sides of the equation such that we can complete the square of the left hand side so we can isolate x. We know from previous results that it is:

$$ 
\begin{align}
\large \left( \frac{b}{2a} \right)^2 = \frac{b^2}{4a^2}
\end{align}
$$

But let's derive this using sympy. To do this we will need to solve the following equation for $z$. We can also solve for $k$ to get the completed square, but we will derive this later.  

$$
\large x^2+\frac{b}{a}x+z = \left( x+k \right)^2
$$

Subtracting the right hand side from both sides will put this in a form SymPy favors for solving:

$$
\large x^2+\frac{b}{a}x+z - \left( x+k \right)^2 = 0
$$


```python
solvingForZK = sp.solve(lhs+z -(x+k)**2,z,k)
print("Z:")
# Sympy automatically applies the square. 
display(solvingForZK[0][0])
print("K:")
display(solvingForZK[0][1])
```

    Z:



$$\frac{b^{2}}{4 a^{2}}$$


    K:



$$\frac{b}{2 a}$$


Thus we see if we'd like to write the left hand side of our equation as a square, we need to add $ \left( \frac{b}{2a} \right)^2$ to both sides of our equation.


```python
completingSquareTerm = sp.Pow((b/(2*a)),2,evaluate=False)
nLhs = lhs + completingSquareTerm
nRhs = rhs + completingSquareTerm
sp.Eq(nLhs,nRhs)
```




$$x^{2} + \left(\frac{b}{2 a}\right)^{2} + \frac{b x}{a} = \left(\frac{b}{2 a}\right)^{2} - \frac{c}{a}$$



We can use the function we defined above to complete the square of the left hand side.


```python
nLhs = completeSquare(nLhs)
nLhs
```




$$\left(x + \frac{b}{2 a}\right)^{2}$$



As we see, $\frac{b}{2a}$ is the $k$ we computed before. We now have: 


```python
sp.Eq(nLhs,nRhs)
```




$$\left(x + \frac{b}{2 a}\right)^{2} = \left(\frac{b}{2 a}\right)^{2} - \frac{c}{a}$$



We have finally found a form where we can isolate $x$! The remainder of the derivation is just a simple matter of rearanging terms. 

We need to get the right hand side into a form easier for sympy to work with later. This requires a little wizardry with polynomial manipulation module. We could have done this operation on one line, but I will show the steps here. 

We first factor. 


```python
nRhs = nRhs.factor()
nRhs
```




$$- \frac{1}{4 a^{2}} \left(4 a c - b^{2}\right)$$



As you see this gives us a strange form. We can resolve this by expanding, then bringing the terms together again. 


```python
nRhs = nRhs.expand()
nRhs
```




$$- \frac{c}{a} + \frac{b^{2}}{4 a^{2}}$$




```python
nRhs = nRhs.together()
nRhs
```




$$\frac{1}{4 a^{2}} \left(- 4 a c + b^{2}\right)$$



We now square both sides. 

Since we did not define our symbol type, sympy will not apply the square root because it does not always hold for all types of numbers that $\sqrt{x^2} = x^2$; however we can force it to make this assumption with a utility function called powdnest.


```python
nLhs = sp.powdenest(sp.sqrt(nLhs),force=True)
nRhs = sp.powdenest(sp.sqrt(nRhs),force=True)
sp.Eq(nLhs,nRhs)
```




$$x + \frac{b}{2 a} = \frac{1}{2 a} \sqrt{- 4 a c + b^{2}}$$



Now we subtract $\frac{b}{2a}$ from both sides. 


```python
nLhs = nLhs - b/(2*a)
nRhs = nRhs - b/(2*a)
sp.Eq(nLhs,nRhs)
```




$$x = - \frac{b}{2 a} + \frac{1}{2 a} \sqrt{- 4 a c + b^{2}}$$



We simplify the right hand side and get our familiar quadratic equation. 


```python
sp.Eq(x,nRhs.simplify())
```




$$x = \frac{1}{2 a} \left(- b + \sqrt{- 4 a c + b^{2}}\right)$$



As you can see, there is no $\pm$ we are accustom to seeing. There is obviously no plus or minus operator inherent in mathematics. We would have introduced this when we took the square root of both sides because the square of $x$ could either be positive or negative. 

2e40cac7d3ce6712fb632ff9f04de9f7f1adb76f
ipynb
Jupyter Notebook
Notebooks/Exercise - Deriving the Quadratic Formula with SymPy.ipynb
Andrewnetwork/WorkshopScipy
739d24b9078fffb84408e7877862618d88d947dc
MIT
2017-12-16T20:50:07.000Z
2021-11-08T13:05:57.000Z
Notebooks/Exercise - Deriving the Quadratic Formula with SymPy.ipynb
Andrewnetwork/WorkshopScipy
739d24b9078fffb84408e7877862618d88d947dc
MIT
2017-12-17T06:10:28.000Z
2018-11-14T15:50:10.000Z
Notebooks/Exercise - Deriving the Quadratic Formula with SymPy.ipynb
Andrewnetwork/WorkshopScipy
739d24b9078fffb84408e7877862618d88d947dc
MIT
2017-12-06T20:40:09.000Z
2019-06-01T11:33:57.000Z
Qwen/Qwen-72B
1. YES
2. YES