In this lab, we will practice our knowledge of derivatives. Remember that our key formula for derivatives, is
- Learn how to represent linear and nonlinear functions in code.
- Then because our calculation of a derivative relies on seeing the output at an initial value and the output at that value plus delta x, we need an
output_at
function. - Then we will be able to code the
$\Delta f$ function that sees the change in output between the initial x and that initial x plus the$\Delta x$ - Finally, we will calculate the derivative at a given x value,
derivative_at
.
For this first section, you should be able to answer all of the question with an understanding of our definition of a derivative:
- Our intuitive explanation that a derivative is the instantaneous rate of change of a function
- Our mathematical definition is that
We are about to learn to take the derivative of a function in code. But before doing so, we need to learn how to express any kind of function in code. This way when we finally write our functions for calculating the derivative, we can use them with both linear and nonlinear functions.
For example, we want to write the function $f(x) = 2x^2 + 4x - 10 $ in a way that allows us to easily determine the exponent of each term.
This is our technique: write the formula as a list of tuples.
A tuple is a list whose elements cannot be reassigned. But everything else, for our purposes, is the same.
tuple = (7, 3)
tuple[0] # 7
tuple[1] # 3
We get a TyperError if we try to reassign the tuple's elements.
tuple[0] = 7
# TypeError: 'tuple' object does not support item assignment
Take the following function as an example:
Here it is as a list of tuples:
four_x_squared_plus_four_x_minus_ten = [(4, 2), (4, 1), (-10, 0)]
So each tuple in the list represents a different term in the function. The first element of the tuple is the term's constant and the second element of the tuple is the term's exponent. Thus (4, 2)
and (-10, 0)
because
We'll refer to this list of tuples as "list of terms", or
list_of_terms
.
Ok, so give this a shot. Write $ f(x) = 4x^3 + 11x^2 $ as a list of terms. Assign it to the variable four_x_cubed_plus_eleven_x_squared
.
four_x_cubed_plus_eleven_x_squared = [(4, 3), (11, 2)]
Now that we can represent a function in code, let's write a Python function called term_output
that can evaluate what a single term equals at a value of
- For example, when
$x = 2$ , the term$3x^2 = 3*2^2 = 12 $ . - So we represent
$3x^2$ in code as(3, 2)
, and: -
term_output((3, 2), 2)
should return 12
def term_output(term, input_value):
pass
term_output((3, 2), 2) # 12
Hint: To raise a number to an exponent in python, like 3^2 use the double star, as in:
3**2 # 9
Now write a function called output_at
, when passed a list_of_terms
and a value of
- For example, we'll use
output_at
to calculate$f(x) = 3x^2 - 11$ .- Then
output_at([(3, 2), (-11, 0)], 2)
should return$f(2) = 3*2^2 - 11 = 1$
def output_at(list_of_terms, x_value):
pass
three_x_squared_minus_eleven = [(3, 2), (-11, 0)]
output_at(three_x_squared_minus_eleven, 2) # 1
output_at(three_x_squared_minus_eleven, 3) # 16
Now we can use our output_at
function to display our function graphically. We simply declare a list of x_values
and then calculate output_at
for each of the x_values
.
import plotly
from plotly.offline import iplot, init_notebook_mode
init_notebook_mode(connected=True)
from graph import plot, trace_values
x_values = list(range(-30, 30, 1))
y_values = list(map(lambda x: output_at(three_x_squared_minus_eleven, x),x_values))
three_x_squared_minus_eleven_trace = trace_values(x_values, y_values, mode = 'lines')
plot([three_x_squared_minus_eleven_trace], {'title': '3x^2 - 11'})
Let's start with a function,
four_x_plus_fifteen = [(4, 1), (15, 0)]
We can plot the function by calculating outputs at a range of x values. Note that we use our output_at
function to calculate the output at each individual x value.
import plotly
from plotly.offline import iplot, init_notebook_mode
init_notebook_mode(connected=True)
from graph import plot, trace_values, build_layout
x_values = list(range(0, 6))
# layout = build_layout(y_axis = {'range': [0, 35]})
four_x_plus_fifteen_values = list(map(lambda x: output_at(four_x_plus_fifteen, x),x_values))
four_x_plus_fifteen_trace = trace_values(x_values, four_x_plus_fifteen_values, mode = 'lines')
plot([four_x_plus_fifteen_trace])
Ok, time for what we are here for, derivatives. Remember that the derivative is the instantaneous rate of change of a function, and is expressed as:
We can see from the formula above that delta_f
that, given a list_of_terms
, an x_value
, and a value
Hint Don't forget about the
output_at
function. Theoutput_at
function takes a list of terms and an$x$ value and returns the corresponding output. So reallyoutput_at
is equivalent to$f(x)$ , provided a function and a value of x.
four_x_plus_fifteen = [(4, 1), (15, 0)]
def delta_f(list_of_terms, x_value, delta_x):
pass
delta_f(four_x_plus_fifteen, 2, 1) # 4
So for
Let's show
def delta_f_trace(list_of_terms, x_value, delta_x):
initial_f_value = output_at(list_of_terms, x_value)
delta_f_value = delta_f(list_of_terms, x_value, delta_x)
if initial_f_value and delta_f_value:
trace = trace_values(x_values=[x_value + delta_x, x_value + delta_x],
y_values=[initial_f_value, initial_f_value + delta_f_value], mode = 'lines',
name = 'delta f = ' + str(delta_x))
return trace
trace_delta_f_four_x_plus_fifteen = delta_f_trace(four_x_plus_fifteen, 2, 1)
Let's add another function that shows the delta x.
def delta_x_trace(list_of_terms, x_value, delta_x):
initial_f_value = output_at(list_of_terms, x_value)
if initial_f_value:
trace = trace_values(x_values=[x_value, x_value + delta_x],
y_values=[initial_f_value, initial_f_value], mode = 'lines',
name = 'delta x = ' + str(delta_x))
return trace
from graph import plot, trace_values
trace_delta_x_four_x_plus_fifteen = delta_x_trace(four_x_plus_fifteen, 2, 1)
if four_x_plus_fifteen_trace and trace_delta_f_four_x_plus_fifteen and trace_delta_x_four_x_plus_fifteen:
plot([four_x_plus_fifteen_trace, trace_delta_f_four_x_plus_fifteen, trace_delta_x_four_x_plus_fifteen], {'title': '4x + 15'})
Write a function, derivative_at
that calculates list_of_terms
, an x_value
for the value of delta_x
, which represents
Let's try this for
def derivative_of(list_of_terms, x_value, delta_x):
pass
derivative_of(four_x_plus_fifteen, 3, 2) # 4.0
Ok, now that we have written a Python function that allows us to plot our list of terms, we can write a function that called derivative_trace
that shows the rate of change, or slope, for the function between initial x and initial x plus delta x. We'll walk you through this one.
def derivative_trace(list_of_terms, x_value, line_length = 4, delta_x = .01):
derivative_at = derivative_of(list_of_terms, x_value, delta_x)
y = output_at(list_of_terms, x_value)
if derivative_at and y:
x_minus = x_value - line_length/2
x_plus = x_value + line_length/2
y_minus = y - derivative_at * line_length/2
y_plus = y + derivative_at * line_length/2
return trace_values([x_minus, x_value, x_plus],[y_minus, y, y_plus], name = "f' (x) = " + str(derivative_at), mode = 'lines')
Our
derivative_trace
function takes as argumentslist_of_terms
,x_value
, which is where our line should be tangent to our function,line_length
as the length of our tangent line, anddelta_x
which is our$\Delta x$ .
The return value of
derivative_trace
is a dictionary that represents tangent line at that values of$x$ . It uses thederivative_of
function you wrote above to calculate the slope of the tangent line. Once the slope of the tangent is calculated, we stretch out this tangent line by theline_length
provided. The beginning x value is just the midpoint minus theline_length/2
and the ending$x$ value is midpoint plus theline_length/2
. Then we calculate our$y$ endpoints by starting at the$y$ along the function, and having them ending atline_length/2*slope
in either direction.
tangent_line_four_x_plus_fifteen = derivative_trace(four_x_plus_fifteen, 2, line_length = 4, delta_x = .01)
tangent_line_four_x_plus_fifteen
Now we provide a function that simply returns all three of these traces.
def delta_traces(list_of_terms, x_value, line_length = 4, delta_x = .01):
tangent = derivative_trace(list_of_terms, x_value, line_length, delta_x)
delta_f_line = delta_f_trace(list_of_terms, x_value, delta_x)
delta_x_line = delta_x_trace(list_of_terms, x_value, delta_x)
return [tangent, delta_f_line, delta_x_line]
Below we can plot our trace of the function as well
delta_x = 1
# derivative_traces(list_of_terms, x_value, line_length = 4, delta_x = .01)
three_x_plus_tangents = delta_traces(four_x_plus_fifteen, 2, line_length= 2*1, delta_x = delta_x)
# only plot the list of traces, if three_x_plus_tangents, does not look like [None, None, None]
if list(filter(None.__ne__, three_x_plus_tangents)):
plot([four_x_plus_fifteen_trace, *three_x_plus_tangents])
So that function highlights the rate of change is moving at precisely the point x = 2. Sometimes it is useful to see how the derivative is changing across all x values. With linear functions we know that our function is always changing by the same rate, and therefore the rate of change is constant. Let's write functions that allow us to see the function, and the derivative side by side.
from graph import make_subplots, trace_values, plot_figure
def function_values_trace(list_of_terms, x_values):
function_values = list(map(lambda x: output_at(list_of_terms, x),x_values))
return trace_values(x_values, function_values, mode = 'lines')
def derivative_values_trace(list_of_terms, x_values, delta_x):
derivative_values = list(map(lambda x: derivative_of(list_of_terms, x, delta_x), x_values))
return trace_values(x_values, derivative_values, mode = 'lines')
def function_and_derivative_trace(list_of_terms, x_values, delta_x):
traced_function = function_values_trace(list_of_terms, x_values)
traced_derivative = derivative_values_trace(list_of_terms, x_values, delta_x)
return make_subplots([traced_function], [traced_derivative])
four_x_plus_fifteen_function_and_derivative = function_and_derivative_trace(four_x_plus_fifteen, list(range(0, 7)), 1)
plot_figure(four_x_plus_fifteen_function_and_derivative)
In this section, we coded out our function for calculating and plotting the derivative. We started with seeing how we can represent different types of functions. Then we moved onto writing the output_at
function which evaluates a provided function at a value of x. We calculated delta_f
by subtracting the output at initial x value from the output at that initial x plus delta x. After calculating delta_f
, we moved onto our derivative_at
function, which simply divided delta_f
from delta_x
.
In the final section, we introduced some new functions, delta_f_trace
and delta_x_trace
that plot our deltas on the graph. Then we introduced the derivative_trace
function that shows the rate of change, or slope, for the function between initial x and initial x plus delta x.