# 7. Introduction to Supply and Demand#

## 7.1. Overview#

This lecture is about some models of equilibrium prices and quantities, one of the main topics of elementary microeconomics.

Throughout the lecture, we focus on models with one good and one price.

In a subsequent lecture we will investigate settings with many goods.

Key infrastructure concepts that we’ll encounter in this lecture are

inverse demand curves

inverse supply curves

consumer surplus

producer surplus

social welfare as the sum of consumer and producer surpluses

relationship between equilibrium quantity and social welfare optimum

Throughout the lectures, we’ll assume that inverse demand and supply curves are **affine** functions of quantity.

(“Affine” means “linear plus a constant” and here is a nice discussion about it.)

We’ll also assume affine inverse supply and demand functions when we study models with multiple consumption goods in our subsequent lecture.

We do this in order to simplify the exposition and enable us to use just a few tools from linear algebra, namely, matrix multiplication and matrix inversion.

In our exposition we will use the following imports.

```
import numpy as np
import matplotlib.pyplot as plt
```

## 7.2. Supply and demand#

We study a market for a single good in which buyers and sellers exchange a quantity \(q\) for a price \(p\).

Quantity \(q\) and price \(p\) are both scalars.

We assume that inverse demand and supply curves for the good are:

We call them inverse demand and supply curves because price is on the left side of the equation rather than on the right side as it would be in a direct demand or supply function.

Here is a class that stores parameters for our single good market, as well as implementing the inverse demand and supply curves.

```
class Market:
def __init__(self,
d_0=1.0, # demand intercept
d_1=0.6, # demand slope
s_0=0.1, # supply intercept
s_1=0.4): # supply slope
self.d_0, self.d_1 = d_0, d_1
self.s_0, self.s_1 = s_0, s_1
def inverse_demand(self, q):
return self.d_0 - self.d_1 * q
def inverse_supply(self, q):
return self.s_0 + self.s_1 * q
```

Let’s create an instance.

```
market = Market()
```

Here is a plot of these two functions using `market`

.

## Show code cell source

```
market = Market()
grid_min, grid_max, grid_size = 0, 1.5, 200
q_grid = np.linspace(grid_min, grid_max, grid_size)
supply_curve = market.inverse_supply(q_grid)
demand_curve = market.inverse_demand(q_grid)
fig, ax = plt.subplots()
ax.plot(q_grid, supply_curve, label='supply')
ax.plot(q_grid, demand_curve, label='demand')
ax.legend(loc='upper center', frameon=False)
ax.set_ylim(0, 1.2)
ax.set_xticks((0, 1))
ax.set_yticks((0, 1))
ax.set_xlabel('quantity')
ax.set_ylabel('price')
plt.show()
```

In the above graph, an **equilibrium** price-quantity pair occurs at the intersection of the supply and demand curves.

### 7.2.1. Consumer surplus#

Let a quantity \(q\) be given and let \(p := d_0 - d_1 q\) be the corresponding price on the inverse demand curve.

We define **consumer surplus** \(S_c(q)\) as the area under an inverse demand
curve minus \(p q\):

The next figure illustrates

## Show code cell source

```
q = 1.25
p = market.inverse_demand(q)
ps = np.ones_like(q_grid) * p
fig, ax = plt.subplots()
ax.plot(q_grid, demand_curve, label='demand')
ax.fill_between(q_grid[q_grid <= q],
demand_curve[q_grid <= q],
ps[q_grid <= q],
label='consumer surplus',
color='#EED1CF')
ax.vlines(q, 0, p, linestyle="dashed", color='black', alpha=0.7)
ax.hlines(p, 0, q, linestyle="dashed", color='black', alpha=0.7)
ax.legend(loc='upper center', frameon=False)
ax.set_ylim(0, 1.2)
ax.set_xticks((q,))
ax.set_xticklabels(("$q$",))
ax.set_yticks((p,))
ax.set_yticklabels(("$p$",))
ax.set_xlabel('quantity')
ax.set_ylabel('price')
plt.show()
```

Consumer surplus provides a measure of total consumer welfare at quantity \(q\).

The idea is that the inverse demand curve \(d_0 - d_1 q\) shows a consumer’s willingness to pay for an additional increment of the good at a given quantity \(q\).

The difference between willingness to pay and the actual price is consumer surplus.

The value \(S_c(q)\) is the “sum” (i.e., integral) of these surpluses when the total quantity purchased is \(q\) and the purchase price is \(p\).

Evaluating the integral in the definition of consumer surplus (7.1) gives

### 7.2.2. Producer surplus#

Let a quantity \(q\) be given and let \(p := s_0 + s_1 q\) be the corresponding price on the inverse supply curve.

We define **producer surplus** as \(p q\) minus the area under an inverse supply curve

The next figure illustrates

## Show code cell source

```
q = 0.75
p = market.inverse_supply(q)
ps = np.ones_like(q_grid) * p
fig, ax = plt.subplots()
ax.plot(q_grid, supply_curve, label='supply')
ax.fill_between(q_grid[q_grid <= q],
supply_curve[q_grid <= q],
ps[q_grid <= q],
label='producer surplus',
color='#E6E6F5')
ax.vlines(q, 0, p, linestyle="dashed", color='black', alpha=0.7)
ax.hlines(p, 0, q, linestyle="dashed", color='black', alpha=0.7)
ax.legend(loc='upper center', frameon=False)
ax.set_ylim(0, 1.2)
ax.set_xticks((q,))
ax.set_xticklabels(("$q$",))
ax.set_yticks((p,))
ax.set_yticklabels(("$p$",))
ax.set_xlabel('quantity')
ax.set_ylabel('price')
plt.show()
```

Producer surplus measures total producer welfare at quantity \(q\)

The idea is similar to that of consumer surplus.

The inverse supply curve \(s_0 + s_1 q\) shows the price at which producers are prepared to sell, given quantity \(q\).

The difference between willingness to sell and the actual price is producer surplus.

The value \(S_p(q)\) is the integral of these surpluses.

Evaluating the integral in the definition of producer surplus (7.2) gives

### 7.2.4. Competitive equilibrium#

Instead of equating quantities supplied and demanded, we can accomplish the same thing by equating demand price to supply price:

If we solve the equation defined by the second equality in the above line for \(q\), we obtain

This is the competitive equilibrium quantity.

Observe that the equilibrium quantity equals the same \(q\) given by equation (7.3).

The outcome that the quantity determined by equation (7.3) equates
supply to demand brings us a **key finding:**

a competitive equilibrium quantity maximizes our welfare criterion

This is a version of the first fundamental welfare theorem,

It also brings a useful **competitive equilibrium computation strategy:**

after solving the welfare problem for an optimal quantity, we can read a competitive equilibrium price from either supply price or demand price at the competitive equilibrium quantity

## 7.3. Generalizations#

In a later lecture, we’ll derive generalizations of the above demand and supply curves from other objects.

Our generalizations will extend the preceding analysis of a market for a single good to the analysis of \(n\) simultaneous markets in \(n\) goods.

In addition

we’ll derive

**demand curves**from a consumer problem that maximizes a**utility function**subject to a**budget constraint**.we’ll derive

**supply curves**from the problem of a producer who is price taker and maximizes his profits minus total costs that are described by a**cost function**.

## 7.4. Exercises#

Suppose now that the inverse demand and supply curves are modified to take the form

All parameters are positive, as before.

Define a new `Market`

class that holds the same parameter values as before by
changing the `inverse_demand`

and `inverse_supply`

methods to
match these new definitions.

Using the class, plot the inverse demand and supply curves \(i_d\) and \(i_s\)

Solution to Exercise 7.1

```
class Market:
def __init__(self,
d_0=1.0, # demand intercept
d_1=0.6, # demand slope
s_0=0.1, # supply intercept
s_1=0.4): # supply slope
self.d_0, self.d_1 = d_0, d_1
self.s_0, self.s_1 = s_0, s_1
def inverse_demand(self, q):
return self.d_0 - self.d_1 * q**0.6
def inverse_supply(self, q):
return self.s_0 + self.s_1 * q**1.8
```

Let’s create an instance.

```
market = Market()
```

Here is a plot of inverse supply and demand.

## Show code cell source

```
grid_min, grid_max, grid_size = 0, 1.5, 200
q_grid = np.linspace(grid_min, grid_max, grid_size)
supply_curve = market.inverse_supply(q_grid)
demand_curve = market.inverse_demand(q_grid)
fig, ax = plt.subplots()
ax.plot(q_grid, supply_curve, label='supply')
ax.plot(q_grid, demand_curve, label='demand')
ax.legend(loc='upper center', frameon=False)
ax.set_ylim(0, 1.2)
ax.set_xticks((0, 1))
ax.set_yticks((0, 1))
ax.set_xlabel('quantity')
ax.set_ylabel('price')
plt.show()
```

As before, consumer surplus at \(q\) is the area under the demand curve minus price times quantity:

Here \(p\) is set to \(i_d(q)\)

Producer surplus is price times quantity minus the area under the inverse supply curve:

Here \(p\) is set to \(i_s(q)\).

Social welfare is the sum of consumer and producer surplus under the assumption that the price is the same for buyers and sellers:

Solve the integrals and write a function to compute this quantity numerically at given \(q\).

Plot welfare as a function of \(q\).

Solution to Exercise 7.2

Solving the integrals gives

Here’s a Python function that computes this value:

```
def W(q, market):
# Unpack
d_0, d_1 = market.d_0, market.d_1
s_0, s_1 = market.s_0, market.s_1
# Compute and return welfare
S_c = d_0 * q - d_1 * q**1.6 / 1.6
S_p = s_0 * q + s_1 * q**2.8 / 2.8
return S_c - S_p
```

The next figure plots welfare as a function of \(q\).

Due to nonlinearities, the new welfare function is not easy to maximize with pencil and paper.

Maximize it using `scipy.optimize.minimize_scalar`

instead.

Solution to Exercise 7.3

```
from scipy.optimize import minimize_scalar
def objective(q):
return -W(q, market)
result = minimize_scalar(objective, bounds=(0, 10))
print(result.message)
```

```
Solution found.
```

```
maximizing_q = result.x
print(f"{maximizing_q: .5f}")
```

```
0.90564
```

Now compute the equilibrium quantity by finding the price that equates supply and demand.

You can do this numerically by finding the root of the excess demand function

You can use `scipy.optimize.newton`

to compute the root.

Initialize `newton`

with a starting guess somewhere close to 1.0.

(Similar initial conditions will give the same result.)

You should find that the equilibrium price agrees with the welfare maximizing price, in line with the first fundamental welfare theorem.

Solution to Exercise 7.4

```
from scipy.optimize import newton
def excess_demand(q):
return market.inverse_demand(q) - market.inverse_supply(q)
equilibrium_q = newton(excess_demand, 0.99)
print(f"{equilibrium_q: .5f}")
```

```
0.90564
```

## 7.2.3. Social welfare#

Sometimes economists measure social welfare by a

welfare criterionthat equals consumer surplus plus producer surplus, assuming that consumers and producers pay the same price:Evaluating the integrals gives

Here is a Python function that evaluates this social welfare at a given quantity \(q\) and a fixed set of parameters.

The next figure plots welfare as a function of \(q\).

## Show code cell source Hide code cell source

Let’s now give a social planner the task of maximizing social welfare.

To compute a quantity that maximizes the welfare criterion, we differentiate \(W\) with respect to \(q\) and then set the derivative to zero.

Solving for \(q\) yields

Let’s remember the quantity \(q\) given by equation (7.3) that a social planner would choose to maximize consumer surplus plus producer surplus.

We’ll compare it to the quantity that emerges in a competitive equilibrium that equates supply to demand.