Functions
As previously explained, functions are mathematical objects that generally take in some input and produce a desired output. A function is therefore often considered as a mapping of one mathematical object to another. When a function receives an input and subsequently produces an output, the concept of relation can also be used, which emphasizes the relationship between the set of possible inputs and that of possible outputs that is established by the function itself.
A function is typically denoted by the lowercase letter f with parentheses, which surround an input that f takes in. This symbol, f(x), also denotes the output that f produces when taking in x as input. For example, let's say the function f that outputs the square of its input; f can be denoted as f(x) = x2.
We see that the syntax for declaring a function in Python also follows this convention. For example, to declare the same squaring function in Python, the code would look like the following:
def f(x):
return x ** 2
And when we would like to obtain the value of f with a number as its input, we simply say that we call f on the input. For example:
print(f(2))
print(f(-3))
This code will print out 4 and 9, respectively. As we also know, the value returned from a function can also be stored in a variable via assignment.
One of the most important characteristics of a function is the fact that no input can be mapped to different outputs. Once an input x has been associated with a corresponding output f(x), that output is deterministic and cannot have more than one possible value. On the other hand, it is entirely possible that multiple inputs can be mapped to the same output. In other words, multiple values of x can cause f(x) to be a common value.
It is also possible that a function does not have to take in any input, nor does it necessarily need to produce any output. For instance, in the context of programming, a function whose job is to read and return the data included in a specific file does not need to take in any input. Another example would be a function that updates the value of a global variable, in which case it is not required to return anything. That said, these functions can be considered to belong to a specific subset of general functions, so our discussions will still revolve around functions with inputs and outputs.
In this upcoming subsection, let's consider a number of common types of functions in mathematics and programming.
Common Functions
While each function is unique in its own way, there are a number of special classifications, or families, of functions that we need to be aware of. These are constant, linear, polynomial, logarithmic, and exponential functions, which are summarized in the following table:
Take a moment to consider the third column of our table, which contains the plots of sample functions belonging to each of the function families that are listed. We will go further into the theoretical details of the plot of a function later on in this section, but for now, we see that each family of functions gives us a unique style of graph; in fact, the identification of functions from their plots is the topic of our upcoming exercise.
Note that constant and linear functions are actually subsets of the polynomial function family (when the coefficients for larger powers of x are all zeros). Another interesting fact you may have already noticed is that the input of a logarithmic function has to be positive, which is why its plot does not extend past the left side of the y axis. Conversely, the output of an exponential function (given that the constant is positive) is always positive; correspondingly, its graph stays above the x axis. These points directly transition us to our next topic: the domain and range of a function.
Domain and Range
The domain and the range are two essential concepts in the context of functions. The domain of a function denotes the set of all possible inputs that the function takes in, while the range specifies the set of all possible outputs.
Most of the time, the domain and range of a given function can be identified by considering its formulaic expression. For example, a linear function, f(x) = mx + c, takes in any real-valued x to produce a real-valued mx + c, so both its domain and range are the set of real numbers, R. The quadratic function f(x) = x2, on the other hand, only produces non-negative outputs, so its range is the set of non-negative real numbers.
The domain and range of a function can also be examined using its plot. Consider the plot of a function with a single input and a single output: its domain corresponds to the projection of the plot onto the x axis; similarly, the range is obtained when the plot is projected onto the y axis. This is why we can claim that the domain of the logarithmic function f(x) = ln(x), whose plot is included in the table from the previous section, is the set of positive numbers. Conversely, the range of the exponential function f(x) = ex is the set of positive numbers as well.
Overall, the domain and range of a function are dependent on the form of the function itself and can be highly informative regarding various behaviors of the function. One of these behaviors that is often of interest is the root of a function, which we will discuss in the next subsection.
Function Roots and Equations
A root of a function is a value belonging to its domain that makes the output equal to zero. Again, which value the root of a function takes is highly dependent on the function itself. Still using the examples that are included in the preceding table, Figure 4.1, we see that f(x) = mx + c accepts the unique root of x = - c / m if m is non-zero, while f(x) = ln(x) has the unique root of x = 1. Some functions might have more than one root: f(x) = x2 - 3x + 2 has x = 1 and x = 2 as its roots, while f(x) = 0 (whose plot corresponds to the x axis) accepts all values of x as its roots. Finally, if the range of a function does not include 0, then the function itself does not have any root; examples of this include f(x) = ex, f(x) = x2 + 1, and f(x) = 3.
The process of finding all roots of a function f(x) is equivalent to solving the equation f(x) = 0. The term equation here denotes the fact that we have two separate quantities, f(x) and 0, that are equal to each other in the mathematical expression. Solving equations is arguably one of the most central tasks in mathematics, and there are multiple techniques for doing so that apply to specific equation types.
We are only introducing the concept of equations here as part of the topic of functions, and we will come back to it later in this chapter. For now, we will move on to the last important component of a function: plots.
The Plot of a Function
In the earlier examples, the plot of a function is a visual representation of the behavior of the output, with respect to the input of the function. Specifically, with a function plot, we aim to examine how the output changes across the function range as the input of the function changes across its domain.
In the context of programming, the plot of a function can be produced by connecting the scatter points corresponding to the inpidual values of a function over a set of fine-grained evenly spaced values on the x axis. For example, say we would like to visualize the plot of the function f(x) = x + 1 between -10 and 10, we would first declare the corresponding evenly spaced values of x using NumPy:
x = np.linspace(-10, 10, 1000)
This NumPy function generates an array of 1,000 evenly spaced numbers between -10 and 10, which is illustrated by the output of x:
The plot can then be generated using the plot() function from Matplotlib:
plt.plot(x, x + 1)
plt.show()
Remember that due to vectorization, the expression x + 1 will compute an array of the same size as x, whose elements are the elements of x with 1 added to each. This is a great feature of the Python language, or more specifically, the NumPy library, that allows us to quickly generate the points that make up the graph of a function.
This code should produce the following visualization:
The same logic can be applied to different forms of functions. We will come back to this process during our next exercise. For now, let's return to our theoretical discussion.
The plot of a function is a direct visualization of its formulaic expression and contains all of the information we need to know about that function. In particular, we have already argued that a function plot can help us identify the domain and range of the function. Furthermore, given a graph, we can even determine whether that graph is a plot of a valid function. This is done with the vertical line test, which dictates the following.
Given a graph on a two-dimensional plane, if, for every vertical line (every line that is parallel to the y axis), the graph has more than one intersection, then it is not the plot of a valid function. This is a direct corollary of the requirement of a function that we stated earlier: one single input cannot be mapped to more than one output. If a graph did have at least two intersections with a vertical line, that would mean a point on the x axis could be mapped to at least two points on the y axis, which would necessarily mean that this is not a plot of a function.
For example, consider the following graph of the unit circle (whose center is O(0, 0) and radius is equal to 1), which fails the vertical line test, illustrated by the red line:
This is to say that the unit circle is, in fact, not the plot of a function with respect to the two-dimensional plane that we are considering.
This topic also marks the end of our introduction to the definition of functions. Before we move on to the next section, let's go through an exercise that aims to solidify all the concepts that we have learned so far.
Exercise 4.01: Function Identification from Plots
In this exercise, we will practice the skill of analyzing the behavior of a function given its plot. This process will allow us to combine various topics that we have mentioned previously, as well as understand the connection between the behavior of a function and its plot.
For each of the following graphs:
- Determine whether it corresponds to a function and if so, go on to the next step.
- Identify the domain, the range, and the formula of the function (hint: use the labeled ticks).
- Determine whether the function has at least one root.
- Reproduce the plot using Python (the axes and their arrows are not necessary).
- Horizontal line:
The graph does correspond to a function. The function is f(x) = 2, the domain is the set of real numbers, and the range is {2}. The function does not have any root.
The following code can be used to reproduce the plot:
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(-5, 5, 1000)
plt.plot(
x, # evenly spaced numbers in the x-axis
np.ones(1000) * 2 # all 2s in the y-axis
)
plt.show()
- Rotated quadratic curve:
The graph does not correspond to a function since it fails the vertical line test.
- Straight line:
The graph corresponds to the plot of the function f(x) = x. Both the domain and the range of this function are a set of real-valued numbers. The function has one root: x = 0.
The following code can be used to reproduce the plot (using the same x variable as in the solution to Horizontal line):
plt.plot(x, x)
plt.show()
- Quadratic curve:
The graph corresponds to the plot of the function f(x) = x2. The domain of the function is the set of all real numbers, while the range is the set of non-negative numbers. The function also has one root: x = 0.
The following code can be used to reproduce the plot (thanks to vectorization for NumPy arrays):
plt.plot(x, x ** 2)
plt.show()
Through this quick exercise, we have solidified our understanding of functions and a number of relevant concepts, including the domain, the range, the vertical line test, and the process of plotting a graph using Python.
Note
To access the source code for this specific section, please refer to https://packt.live/2YRMZhL.
You can also run this example online at https://packt.live/2YSBgj2.
In the next section, we will discuss the transformation of functions.