5 Introduction to Functions

As quoted in the Preface, a ☞ system ☜ is a framework or an organized structure with interconnected elements. What are these elements? And, what are the connections among them?

In our conception of a system, the elements are often called variables. However, to build a quantitative model, we need to operationalize the variables, as described in Chapter 1, that is, turn the conceptual variables into measurable quantities. (Note that some variables do not correspond to quantities but rather to words or other non-numerical labels. In the language of statistics, these are called ☞ categorical variables ☜. Our focus in this book is on the so-called ☞ quantitative variables ☜.)

A collection of variables becomes a system when we consider the connections among the variables, that is, how the variables interact with one another. To build a quantitative model of a system, we need to represent these relationships quantitatively.

Spotted a problem?
Help us fix it!

A standard practice, which we will use here, is to represent the connections in a system with ☞ functions ☜. A function is a mathematical concept, a mechanism that takes one or more ☞ input quantities ☜ and produces a corresponding ☞ output quantity ☜.1 In English, we might say that “[the output] is a function of [the inputs].” (In Chapters 12 and 13 we will meet another important way of representing some kinds of connections. An example is the relationship between velocity and distance travelled.

As an example of a function, consider the connections between temperature, humidity, and comfort. Temperature and humidity are both quantities, but comfort is subjective. It can refer to different perceptions —for instance, the postural comfort provided by a plush couch or the psychological comfort of spending time with friends or eating comfort foods. With respect to temperature and humidity, one operationalization of comfort is the “heat index” scale often presented in weather reports. The original version, presented by R.G. Steadman in 1979 as the “sultriness index” 2, is displayed in Fig 5. 1.

Figure 5. 1: The sultriness function. (Source: Assessment of sultriness, p. 862.) Note: Meteorologists measure the “dry bulb” temperature with an ordinary thermometer. In contrast, the “wet bulb” temperature measures evaporative cooling, operationalized by wrapping the thermometer with wet gauze.

The sultriness function takes two inputs: temperature and relative humidity. To find the output for given values of the inputs, look them up in the margins of the table and read off the corresponding value in the body of the table. For example, calling the function sultriness() and the inputs “DBT” (for dry bulb temperature) and RH (for relative humidity), the table shows that sultriness(DBT = 30\(^\circ\)C, RH = 80%) \(\rightarrow 37\).

5.1 Diagramming systems and their functions

As always, it can help to have a graphical image to draw on while thinking about systems and the quantities and functions that comprise them. Consider this diagram of the relationships in a household solar-panel system:

Spotted a problem?
Help us fix it!

graph LR
  A(Sun position)
  B(Cloudiness)
  A --> C[Production]
  B --> C
  
classDef exogenous fill:#fff,stroke-width:1px


class A exogenous
class B exogenous

Figure 5. 2: A diagram of a simple system. The quantities are named. A sharp-cornered box encloses a quantity that is the output from a function. The arrows impinging on the sharp-cornered box indicate inputs to each function.

Such diagrams show a quantity with a word or phrase, e.g., “Cloudiness.” The arrows pointing into the box surrounding the word indicate the source of the quantity. In Fig 5. 2, “production” is in a box with sharp corners, with arrows pointing in, signifying that “production” is the output of a function. The inputs to the function are at the tail-end of the arrows: “cloudiness” and “sun position.” Taken as a whole, the diagram says that electricity production is a function of the sun position and the amount of cloudiness.

The round-cornered boxes indicate that the enclosed quantity is ☞ exogenous ☜, that is, “coming from outside” the model. As such, we are not trying to account for the levels of cloudiness and sun position with the model; we are taking them as given. Quantities, like production that are accounted for in the model as the output of a function are called ☞ endogenous ☜ (“coming from inside” the model.)

The inputs to functions can be exogenous, endogenous, or a mix of both.

A diagram of a system, such as Fig 5. 2, helps display the big picture: what the components of the system are and how they are connected. For a modeler, this provides a roadmap for composing the functions needed for the model.

5.2 Inputs, arguments, and algorithms

A function is a machine for turning input values into an output. Real-world machines offer helpful intuition for constructing functions. To this end, consider a home bread-making machine. The machine performs several manipulations on the inputs: mixing, kneading, waiting for the dough to rise, and baking. In the language of functions, the description of these sequenced manipulations is called an ☞ algorithm ☜. While the machine is at work, it is ☞ executing the algorithm ☜. (An equivalent phrase is “☞ running the algorithm. ☜)

Spotted a problem?
Help us fix it!

In everyday use, the person operating the bread machine does not need to know the algorithm’s steps in detail. (Indeed, he or she is likely asleep while the machine works alone on a darkened kitchen counter.) So what does the person have to know to run the machine? Here are four basic tasks for the human:

  1. Plug in the machine.
  2. Add the inputs. For cooking, there is a specific term for the ingredients: ingredients.
  3. Press the RUN button.
  4. When the machine stops, take out the bread and make toast or a sandwich.

Let us focus on (2), the inputs. There are many kinds of bread, but they all have the same set of input types:

  • liquid—usually water, but sometimes beer or milk
  • fat—butter, olive oil, or egg
  • sweetener—sugar or honey
  • flavorings—salt, perhaps some herbs
  • flour—there are several types available
  • yeast

Notice that the words used for the inputs are general: liquid, fat, and flour. The human user provides specific values for these depending on the kind of bread desired.

If we were modeling the bread machine with a function, the user interface might look like this:

bread(liquid, fat, sweetner, flavorings, flour, yeast)

The ☞ function name ☜, bread() here, identifies which machine is to use.

The words used to identify the various inputs are called the ☞ arguments ☜ to the function. They are merely words. To use the function, you need to substitute the actual inputs for each word. For instance, for a one-pound loaf of honey bread, an ☞ invocation ☜ of the function would look like this:

bread(
  5.5 oz water,
  1.5 T butter,
  2 T honey,
  1 t salt,
  9.7 oz bread flour,
  1 t active dry yeast
)

There is an implicit division of labor in this interface. The bread() function says nothing about how to acquire or measure the ingredients.

As mentioned previously, the bread-machine user does not need to know anything about the algorithm. It is, however, critically important for the user to be able to determine whether the output is as intended. When it is not, troubleshooting is in order: check if the arguments were correct and, maybe, look inside the machine. This diagnostic process is called ☞ debugging ☜.

A valuable strategy for constructing a function is to divide the algorithm into simpler parts, each of which can be validated and modified independently. This strategy is called ☞ decomposition ☜ of the function. (In ☞ sec-basic-functions ☜ we will start to look at how to build functions, that is, the ☞ composition ☜ of functions from simpler parts.)

To illustrate decomposition, let us imagine some simpler functions used to build a bread-baking algorithm. For instance, the traditional process of baking bread looks like this:

  • blob <- dough(liquid, fat, sweetener, flavorings, flour, yeast)
  • loaf <- shape(blob, pan)
  • bread <- bake(loaf, temperature, time)

For each of the three functions, the inputs are listed between parentheses. The <- punctuation sign tells the algorithm to store each function’s output under a name. Then, as is typical in algorithms, the named output from a previous function can be used as input to another function.

Spotted a problem?
Help us fix it!

The dough() function is itself made from simpler components, the algorithm looking like this:

dough <- function(liquid, fat, sweetener, flavorings, flour, yeast) {
  stuff <- mix(liquid, fat, sweetener, flavorings, flour, yeast)
  wait(30 minutes)
  stuff <- knead(stuff)
  wait(15 minutes)
  stuff <- knead(stuff)
  wait(15 minutes)
  
  return(stuff) # hand back the output
}

5.3 What do you need to know about an algorithm?

In the modern world, many of the objects we use productively every day are so complicated that few people, if any, know exactly what is inside them. For example, telephoning a friend does not require knowing in detail how a phone works. Drivers typically do not know how a modern gasoline engine works. We can use these machines because they have a user interface that we know how to operate. Using the interface lets us confirm we are using it properly. For instance, confidence in a phone comes (in part) from the text messages sent and successfully received.

The same is true of functions. Using a function requires knowing what kinds of inputs it takes and observing what kind of output it produces. To illustrate, consider a problem faced by prospective home buyers: How much money can they borrow while keeping monthly house payments at an acceptable level?

The internet has apps that calculate monthly mortgage payments. Behind such apps is a function that takes three inputs: the amount borrowed (the principal), the annual interest rate on the loan, and the number of monthly payments needed to pay off the loan. The function’s output is the amount of the monthly payment. As an illustration, we have implemented the three-input function and provided an interface. Try it out in @chk-monthly-payment, where, at least initially, the arguments have been set to a $200,000 loan at 6 percent interest for a standard 30-year duration (360 months).

monthly_payment(principal, interest_rate, years)`

Typically, computer languages accept purely numerical inputs rather than a complete description of the quantity. So, the first input is 200000 rather than $200,000, the second is 7 rather than 7%, and the third is 30 rather than 30 years.

Spotted a problem?
Help us fix it!

What is needed to know to use this function successfully? Here is a list:

  1. The name of the function: monthly_payment().
  2. The order in which to provide the inputs: (principal, interest, years)
  3. The meaning of each input and the eventual output:
    1. principal: a numerical amount, the currency does not matter
    2. interest: a yearly interest rate
    3. years: the number of years
    4. Output: A numerical amount. The currency will be the same as that of the principal input.
  4. A way to check the function’s action and whether the user correctly works the interface. Such checking can take several forms. The simplest is a set of inputs and the eventual output from another, trusted source, as in Fig 5. 3
Figure 5. 3: A randomly selected mortgage payment calculator from the internet. The interface is different from the monthly_payment() function, with entry slots for house price and down payment rather than principal.

Another crucial aspect of successfully using the function is understanding how to apply it to address the actual question of interest. Recall that the motivating question was not “What is the monthly payment?” but “How much money can be borrowed while keeping monthly house payments at an acceptable level?” Monthly_payment() does not directly answer the question, but can be used as a tool to find the answer.

What about the algorithm? Does the user need to know that? Undeniably, being able to see and interpret the algorithm—which is, in this case, a formula—would enhance mastery of the subject. However, in practice, even algebraically skilled people who might understand a derivation of the formula and be able to translate it into computer code will need to check the results. Will AI help? Maybe eventually. However, the AI query I used, “How to calculate mortgage payment,” returned a formula with a fatal error.

Instead of focusing primarily on the algorithm, it is more helpful to use tools that translate the function’s output into a format that is more readily understood. The following section describes one such tool.

5.4 Slicing a function

In the slicing technique, we select a single argument for investigation. When a function has multiple arguments, we fix the values for all the others. To illustrate, let us look at the monthly payment function and how the payment depends on the interest rate. Common sense suggests that we examine the function’s output for different values of the interest rate. Picking up from the earlier example, we will set the principal to 200,000 and the years to 30. For instance, the following computer expressions direct the computer to calculate the monthly payment at each of three interest rates: 5% per year, 6% per year, and 7% per year.

The function outputs show that the higher the interest rate, the higher the monthly payment.

Spotted a problem?
Help us fix it!

We can dramatically reduce cognitive load while simultaneously examining a much larger set of interest-rate values using graphics. A suitable graphics mode for a function slice is the ☞ slice plot ☜, such as that in Fig 5. 4.

Figure 5. 4: A slice through the monthly_payment() function with respect to the interest_rate input. The other inputs are being held constant: principal at $200,000 and years at 30.

A trivial use for a slice plot is to look up the output value for a given input. For instance, when the input interest rate is 7.5 percent, the output value is 1400. To communicate with someone using a static display, such as print, the slice plot enables the reader to evaluate the function at the input value of interest to them. (In an interactive display, as here, it is just as effective to evaluate the function directly, as in @chk-three-interest-rates. Try that now, setting the interest rate to 7.5% to confirm.)

When it comes to quantitative reasoning, however, a slice plot has a much more important role: it helps us understand the relationship between the input and the output. More specifically, a slice plot characterizes the change in the output with respect to one of the inputs. (Section 2.6 introduced the phrase “with respect to.”)

Experience shows that a highly effective way to describe relationships is to use the vocabulary of rxf_definition(“shapes and progressions”)`. When reading the progression, start at the left-hand side of the graphic, as with text or music. Then move steadily to the right, observing the output as it changes. In the case of Fig 5. 4, the output value goes up when moving from left to right. Such a progression is said to be “increasing.” That is, as the input increases, the output increases as well.

The shape of the slice plot in Fig 5. 4 is, more or less, a straight line. This simple relationship shape is ubiquitous.

The relationship between output and years (Fig 5. 5) shows a different progression and shape.

Figure 5. 5: The relationship between the monthly payment and the mortgage’s duration in years. The slice holds fixed the principal and interest rate at $200,000 and 7.5% per year, respectively.

Reading, as always, from left to right, the progression is downward: the payment decreases as the duration of the loan increases. That makes sense. A homebuyer seeking to reduce the monthly payment can do so by obtaining a long-term loan.

Spotted a problem?
Help us fix it!

The shape is nonlinear: a curve. This particular type of curve decreases steeply for short-duration loans but has a shallow slope for long-duration loans. This shape has important implications for mortgages. Although a 30-year loan is conventional (in the US), the monthly payment would hardly go down if you extended it to 50 years.3 To put this in human, generational terms, the homebuyer who is encumbering his children and grandchildren with a 60-year mortgage is decreasing the monthly payment by a trivial amount. Economists often use the word ☞ marginal ☜ to refer to the rate of change—e.g. the ☞ slope ☜ of the graph—when the input is changed just a little. In this terminology, the homeowner suffers from “☞ diminishing marginal returns ☜” as the loan duration increases.

In later chapters, we will encounter a variety of shapes often seen in slice plots. Learning to recognize and name the most common shapes helps in thinking more clearly about the implications of each relationship.


New terms {

Footnotes

  1. Functions aren’t constrained to using quantities as inputs or to producing a quantity as an output. For instance, a function can take another function as an input, producing as output yet another function. We will touch on this briefly in Chapers 11, 12 and 13.↩︎

  2. R.G. Steadman “The Assessment of Sultriness”, Journal of Applied Metereology and Climatology. July 1979 pp. 861-873]↩︎

  3. At the time of this writing, proposals to offer 50-year mortgages are being proposed as a way to make housing more affordable.↩︎