```python
%matplotlib inline
```


```python
import sympy
import numpy as np
import matplotlib.pyplot as plt
import math
```

## Generalizing the Plotting Function
Let's now use the power of Python to generalize the code we created to plot. In Python, you can pass functions as parameters to other functions. We'll utilize this to pass the math function that we're going to plot.

Note: We can also pass *lambda expressions* (anonymous functions) like this: 
```python
lambda x: x + 2```
This is a shorter way to write
```python
def some_anonymous_function(x):
    return x + 2
```

We'll also need a range of x values. We may also provide other optional parameters which will help set up our plot. These may include titles, legends, colors, fonts, etc. Let's stick to the basics now.

Write a Python function which takes another function, x range and number of points, and plots the function graph by evaluating it at every point.

**BIG hint:** If you want to use not only `numpy` functions for `f` but any one function, a very useful (and easy) thing to do, is to vectorize the function `f` (e.g. to allow it to be used with `numpy` broadcasting):
```python
f_vectorized = np.vectorize(f)
y = f_vectorized(x)
```


```python
def plot_math_function(f, min_x, max_x, num_points):
    f_vectorized = np.vectorize(f)
    x = np.linspace(min_x, max_x, num_points)
    y = f_vectorized(x)
    plt.plot(x, y)
    plt.show()
```


```python
plot_math_function(lambda x: 2 * x + 3, -3, 5, 1000)
plot_math_function(lambda x: -x + 8, -1, 10, 1000)
plot_math_function(lambda x: x**2 - x - 2, -3, 4, 1000)
plot_math_function(lambda x: np.sin(x), -np.pi, np.pi, 1000)
plot_math_function(lambda x: np.sin(x) / x, -4 * np.pi, 4 * np.pi, 1000)
```

## Solving Equations Graphically
Now that we have a general plotting function, we can use it for more interesting things. Sometimes we don't need to know what the exact solution is, just to see where it lies. We can do this by plotting the two functions around the "=" sign ans seeing where they intersect. Take, for example, the equation $2x + 3 = 0$. The two functions are $f(x) = 2x + 3$ and $g(x) = 0$. Since they should be equal, the point of their intersection is the solution of the given equation. We don't need to bother marking the point of intersection right now, just showing the functions.

To do this, we'll need to improve our plotting function yet once. This time we'll need to take multiple functions and plot them all on the same graph. Note that we still need to provide the $[x_{min}; x_{max}]$ range and it's going to be the same for all functions.

```python
vectorized_fs = [np.vectorize(f) for f in functions]
ys = [vectorized_f(x) for vectorized_f in vectorized_fs]
```


```python
def plot_math_functions(functions, min_x, max_x, num_points):
    fs_vectorized = [np.vectorize(f) for f in functions]
    x = np.linspace(min_x, max_x, num_points)
    ys = [vectorized_f(x) for vectorized_f in fs_vectorized]
    
    for y in ys:
        plt.plot(x, y)
    plt.show()
```


```python
plot_math_functions([lambda x: 2 * x + 3, lambda x: 0], -3, 5, 1000)
plot_math_functions([lambda x: 3 * x**2 - 2 * x + 5, lambda x: 3 * x + 7], -2, 3, 1000)
```

This is also a way to plot the solutions of systems of equation, like the one we solved last time. Let's actually try it.


```python
plot_math_functions([lambda x: (-4 * x + 7) / 3, lambda x: (-3 * x + 8) / 5, lambda x: (-x - 1) / -2], -1, 4, 1000)
```

1d3bf920c55dc61339adc1f3c069dd622c1211fe
ipynb
Jupyter Notebook
math/linear-algebra/plotting-function.ipynb
VGGeorgiev/ml-playground
65dc329d325ccdf40e021b0cb0c8fd1f4cfacc9e
MIT
2019-04-07T23:19:29.000Z
2019-04-07T23:19:29.000Z
math/linear-algebra/plotting-function.ipynb
VladiGGeorgiev/ml-playground
65dc329d325ccdf40e021b0cb0c8fd1f4cfacc9e
MIT
math/linear-algebra/plotting-function.ipynb
VladiGGeorgiev/ml-playground
65dc329d325ccdf40e021b0cb0c8fd1f4cfacc9e
MIT
Qwen/Qwen-72B
1. YES
2. YES