import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import minimize, fsolveModule 10 — Edinburgh’s Legacy
From Moral Philosophy to Computational Economics
From Smith to Simulation: Computing the Ideas that Built Economics
The University of Edinburgh · School of Economics
Part I — The History
Full Circle
We began this course on the Royal Mile, in the Edinburgh of David Hume and Adam Smith. We end it there too — but with new eyes.
In the 1750s and 1760s, Hume and Smith were doing something radical. They were applying the methods of natural philosophy — careful observation, systematic reasoning, scepticism toward received authority — to the study of human society. Hume insisted that we can only know what we observe. Smith walked through pin factories and counted operations. They were empiricists about morality and commerce, at a time when most thinkers still reasoned from first principles handed down by Aristotle or the Church.
This was the Scottish Enlightenment’s great gift to economics: the conviction that society is a natural system, governed by regularities that can be discovered through evidence, not decreed by kings or philosophers. Every module in this course has been a chapter in the story of that conviction being tested, refined, extended, and sometimes overturned.
The Arc of the Course
Let us trace the intellectual journey we have taken:
Smith (Module 1) showed that decentralised markets, guided by self-interest and competition, can coordinate an entire economy without central planning — the invisible hand. We computed market equilibrium by finding the root of the excess demand function.
Ricardo and Malthus (Module 2) introduced the idea of limits to growth. Ricardo’s theory of rent showed how scarcity shapes distribution; Malthus warned that population growth could outstrip food production. We simulated Malthusian dynamics and the Ricardian model of diminishing returns.
Keynes (Module 3) shattered the classical confidence that markets always clear. In the Great Depression, millions were unemployed not because they refused to work but because demand had collapsed. We built the multiplier model and saw how fiscal policy could stabilise output.
Marx (Module 4) asked the question Smith’s admirers preferred to avoid: who benefits? His analysis of surplus value, capital accumulation, and the falling rate of profit put distribution at the centre of economics. We modelled the labour share under CES production and watched it decline as capital accumulated — just as the data show since 1980.
The Marginalists (Module 5) rebuilt economics from the ground up, replacing classes with individuals and labour theories of value with subjective utility. We derived demand curves from utility maximisation using scipy.optimize.
Solow (Module 6) gave us the modern theory of economic growth: capital accumulation, diminishing returns, and the centrality of technological progress. We simulated convergence to the steady state and explored the Solow residual.
Game Theory (Module 7) formalised strategic interaction — how rational agents behave when their payoffs depend on others’ choices. We computed Nash equilibria and explored the Prisoner’s Dilemma.
Lucas and Rational Expectations (Module 8) argued that economic agents are forward-looking and that policy works differently when people anticipate it. We modelled the Lucas critique and showed how expectations can be self-fulfilling.
Piketty (Module 9) brought inequality back to the centre of economics with the simple but devastating formula \(r > g\): when the return on capital exceeds the growth rate, wealth concentrates. We simulated wealth dynamics across generations.
The Frontier Today
Where does economics go from here? The frontier is vast and rapidly evolving:
Climate economics. William Nordhaus’s DICE model and its descendants attempt to integrate climate science with economic growth theory. The central question — how much should we sacrifice today to prevent future warming? — is fundamentally a question of discounting, distribution across generations, and uncertainty. It draws on Solow (growth), Piketty (distribution), and the marginalists (optimisation).
AI and automation. The “machinery question” that Ricardo and Marx debated in the 19th century has returned with extraordinary urgency. If artificial intelligence can substitute for human cognitive labour, what happens to wages, employment, and inequality? The CES production function from Module 4 — with its elasticity of substitution between capital and labour — is precisely the tool economists use to think about this.
Agent-based models. Instead of assuming a representative agent or solving for equilibrium analytically, agent-based models simulate millions of heterogeneous agents interacting in artificial economies. This is Smith’s invisible hand made literal: no one plans the outcome; it emerges from decentralised interaction. Edinburgh’s own research groups are active in this area.
Machine learning in economics. Causal inference, prediction, and high-dimensional data analysis are transforming empirical economics. The Scottish Enlightenment’s emphasis on evidence has never been more relevant — but now the “evidence” is terabytes of transaction data, satellite imagery, and social media text.
Edinburgh’s Continuing Contributions
The University of Edinburgh remains at the frontier. The School of Economics contributes to research on inequality, development, behavioural economics, and computational methods. The city that gave the world Hume’s scepticism and Smith’s invisible hand continues to shape how we understand economic life.
And the method remains the same: observe the world carefully, build models that formalise your intuition, test those models against data, and — when the evidence demands it — change your mind. That is the Scottish Enlightenment’s legacy to economics.
In this final module, we put that legacy to the test. We return to Smith’s invisible hand and ask: when does it work, and when does it fail?
Part II — The Computation
The Invisible Hand on Trial
Adam Smith’s central claim was that competitive markets, left to themselves, produce outcomes that are not merely tolerable but efficient — no rearrangement of resources could make everyone better off. This is formalised in the First Welfare Theorem: under certain conditions (perfect competition, no externalities, complete information), the market equilibrium is Pareto efficient.
But those conditions are demanding. In this module, we run three computational experiments that each violate one condition, and we watch the invisible hand fail. In each case, we compute the gap between what the market delivers and what society needs — and we identify the policy that closes that gap.
Setting Up
Model 1 — Externalities: The Polluting Factory
A factory on the Water of Leith produces cloth. Production generates pollution that harms downstream residents — fishermen, families, other businesses. The factory does not bear these costs. This is a negative externality: a cost imposed on third parties who are not part of the market transaction.
We model the market for cloth as follows:
- Private marginal cost (PMC): the cost to the factory of producing one more unit: \(PMC(Q) = 2 + 0.1Q\)
- External marginal cost (EMC): the pollution damage from one more unit: \(EMC(Q) = 0.05Q\)
- Social marginal cost (SMC): the true cost to society: \(SMC(Q) = PMC(Q) + EMC(Q) = 2 + 0.15Q\)
- Demand (marginal benefit): \(P(Q) = 20 - 0.2Q\)
The free market sets \(P = PMC\) (the factory ignores pollution). The social optimum sets \(P = SMC\) (society accounts for pollution). The gap between them is the market failure — and a Pigouvian tax equal to the external cost at the optimal quantity can correct it.
# Cost and demand functions
def demand(Q):
"""Inverse demand: price as a function of quantity."""
return 20 - 0.2 * Q
def PMC(Q):
"""Private marginal cost."""
return 2 + 0.1 * Q
def EMC(Q):
"""External marginal cost (pollution damage)."""
return 0.05 * Q
def SMC(Q):
"""Social marginal cost = private + external."""
return PMC(Q) + EMC(Q)
# Free-market equilibrium: demand = PMC
# 20 - 0.2Q = 2 + 0.1Q => 18 = 0.3Q => Q = 60
Q_market = fsolve(lambda Q: demand(Q) - PMC(Q), x0=30)[0]
P_market = demand(Q_market)
# Social optimum: demand = SMC
# 20 - 0.2Q = 2 + 0.15Q => 18 = 0.35Q => Q ≈ 51.43
Q_social = fsolve(lambda Q: demand(Q) - SMC(Q), x0=30)[0]
P_social = demand(Q_social)
# Pigouvian tax = EMC at the social optimum
pigouvian_tax = EMC(Q_social)
print("=== Model 1: Externality (Pollution) ===")
print(f"\nFree-market equilibrium:")
print(f" Q_market = {Q_market:.2f} units")
print(f" P_market = {P_market:.2f}")
print(f"\nSocial optimum:")
print(f" Q_social = {Q_social:.2f} units")
print(f" P_social = {P_social:.2f}")
print(f"\nOverproduction = {Q_market - Q_social:.2f} units")
print(f"Pigouvian tax = EMC(Q*) = {pigouvian_tax:.2f} per unit")
print(f"\nThe free market produces TOO MUCH because the factory ignores pollution costs.")# Visualise the externality
Q_range = np.linspace(0, 100, 300)
fig, ax = plt.subplots(figsize=(10, 6))
ax.plot(Q_range, demand(Q_range), color='steelblue', linewidth=2.5, label='Demand (Marginal Benefit)')
ax.plot(Q_range, PMC(Q_range), color='coral', linewidth=2.5, label='Private Marginal Cost (PMC)')
ax.plot(Q_range, SMC(Q_range), color='darkred', linewidth=2.5, linestyle='--', label='Social Marginal Cost (SMC)')
ax.plot(Q_range, EMC(Q_range), color='gray', linewidth=1.5, linestyle=':', label='External Cost (pollution)')
# Mark equilibria
ax.plot(Q_market, P_market, 'ko', markersize=10, zorder=5)
ax.annotate(f'Market equilibrium\nQ={Q_market:.0f}, P={P_market:.1f}',
xy=(Q_market, P_market), xytext=(Q_market + 8, P_market + 2),
fontsize=10, arrowprops=dict(arrowstyle='->', color='black'),
bbox=dict(boxstyle='round,pad=0.3', facecolor='lightyellow', edgecolor='gray'))
ax.plot(Q_social, P_social, 's', color='darkgreen', markersize=10, zorder=5)
ax.annotate(f'Social optimum\nQ={Q_social:.0f}, P={P_social:.1f}',
xy=(Q_social, P_social), xytext=(Q_social - 30, P_social + 3),
fontsize=10, arrowprops=dict(arrowstyle='->', color='darkgreen'),
bbox=dict(boxstyle='round,pad=0.3', facecolor='honeydew', edgecolor='darkgreen'))
# Shade the deadweight loss triangle
Q_dwl = np.linspace(Q_social, Q_market, 100)
ax.fill_between(Q_dwl, demand(Q_dwl), SMC(Q_dwl), alpha=0.25, color='red',
label='Deadweight loss from overproduction')
ax.set_xlabel('Quantity (Q)', fontsize=12)
ax.set_ylabel('Price / Cost', fontsize=12)
ax.set_title('Market Failure: Negative Externality (Pollution)', fontsize=13)
ax.legend(fontsize=9, loc='upper right')
ax.set_xlim(0, 100)
ax.set_ylim(0, 22)
ax.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
# Compute deadweight loss
# DWL = integral from Q_social to Q_market of (SMC - demand) dQ
# = area of triangle with base (Q_market - Q_social) and height (SMC(Q_market) - demand(Q_market))
# At Q_market: SMC = 2 + 0.15*60 = 11, demand = 20 - 0.2*60 = 8, so height = 11 - 8 = 3
# Wait — at Q_market, SMC > demand. The DWL is the triangle between SMC and demand from Q_social to Q_market.
DWL = 0.5 * (Q_market - Q_social) * (SMC(Q_market) - demand(Q_market))
print(f"Deadweight loss from the externality: {DWL:.2f}")
print(f"This is the cost to society of letting the market overproduce.")The shaded triangle is the deadweight loss — the net harm to society from overproduction. Every unit between \(Q_{\text{social}}\) and \(Q_{\text{market}}\) costs society more (SMC) than it benefits consumers (demand). The invisible hand, blind to pollution, gets the wrong answer.
A Pigouvian tax of \(\tau = EMC(Q^*)\) per unit shifts the private cost curve up to align with the social cost curve, restoring efficiency. Named after Arthur Pigou (1877–1959), a student of Alfred Marshall at Cambridge, this is the economist’s standard prescription for externalities.
Model 2 — Asymmetric Information: Akerlof’s Market for Lemons
In 1970, George Akerlof published “The Market for ‘Lemons’,” one of the most influential papers in economics. His insight: when sellers know more about product quality than buyers, markets can unravel.
Consider the used car market. Each car has a quality \(q\) drawn uniformly from \([0, 1]\). A seller values a car at \(q\) (they know its quality). A buyer values it at \(1.5q\) (buyers value cars more than sellers — there are gains from trade). But the buyer cannot observe \(q\) before purchase.
If buyers could observe quality, every car would trade at some price between \(q\) and \(1.5q\), and all trades would happen. But with asymmetric information, the buyer can only offer a price based on expected quality. Let’s see what happens.
def lemons_market(n_cars=10000, buyer_premium=1.5, seed=42):
"""
Simulate Akerlof's lemons market.
Each car has quality q ~ Uniform(0,1).
Seller values car at q.
Buyer values car at buyer_premium * q (but can't observe q).
We iterate: buyer offers price based on expected quality of
cars still on the market. Sellers with q > price withdraw.
Repeat until the market stabilises or collapses.
"""
rng = np.random.default_rng(seed)
qualities = rng.uniform(0, 1, n_cars)
on_market = np.ones(n_cars, dtype=bool) # all cars start on market
history = [] # track (round, price_offered, n_remaining, avg_quality)
for round_num in range(1, 51):
if on_market.sum() == 0:
break
# Buyer estimates average quality of cars on market
avg_q = qualities[on_market].mean()
# Buyer offers price = buyer_premium * expected quality
price_offered = buyer_premium * avg_q
history.append({
'round': round_num,
'price': price_offered,
'n_cars': on_market.sum(),
'avg_quality': avg_q
})
# Sellers with quality > price withdraw (they value their car more)
new_on_market = on_market & (qualities <= price_offered)
# Check for convergence
if np.array_equal(new_on_market, on_market):
break
on_market = new_on_market
return history, qualities, on_market
# Run the simulation
history, qualities, final_market = lemons_market()
print("=== Model 2: Akerlof's Market for Lemons ===")
print(f"\n{'Round':>5} {'Price':>8} {'Cars left':>10} {'Avg quality':>12}")
print("-" * 40)
for h in history:
print(f"{h['round']:>5} {h['price']:>8.3f} {h['n_cars']:>10} {h['avg_quality']:>12.3f}")
print(f"\nWith full information: all {len(qualities)} cars would trade (gains from trade on every car).")
print(f"With asymmetric information: only {final_market.sum()} cars trade.")
print(f"Average quality of traded cars: {qualities[final_market].mean():.3f}")
print(f"\nAdverse selection has driven high-quality cars out of the market.")
print(f"Only 'lemons' remain — the market has partially collapsed.")# Visualise the unravelling
rounds = [h['round'] for h in history]
prices = [h['price'] for h in history]
n_cars = [h['n_cars'] for h in history]
avg_qs = [h['avg_quality'] for h in history]
fig, axes = plt.subplots(1, 3, figsize=(15, 4.5))
axes[0].plot(rounds, prices, 'o-', color='coral', linewidth=2, markersize=5)
axes[0].set_xlabel('Round', fontsize=11)
axes[0].set_ylabel('Price offered', fontsize=11)
axes[0].set_title('Price Falls as Quality Drops', fontsize=12)
axes[0].grid(True, alpha=0.3)
axes[1].plot(rounds, n_cars, 'o-', color='steelblue', linewidth=2, markersize=5)
axes[1].set_xlabel('Round', fontsize=11)
axes[1].set_ylabel('Cars remaining', fontsize=11)
axes[1].set_title('Market Shrinks', fontsize=12)
axes[1].grid(True, alpha=0.3)
axes[2].plot(rounds, avg_qs, 'o-', color='seagreen', linewidth=2, markersize=5)
axes[2].set_xlabel('Round', fontsize=11)
axes[2].set_ylabel('Average quality', fontsize=11)
axes[2].set_title('Only Lemons Survive', fontsize=12)
axes[2].grid(True, alpha=0.3)
plt.suptitle("Akerlof's Adverse Selection: the Market Unravels", fontsize=14)
plt.tight_layout()
plt.show()
print("The death spiral: low price → good cars leave → quality drops → lower price → ...")
print("The invisible hand cannot work when one side of the market is blind.")Akerlof’s insight earned him the Nobel Prize in 2001. The practical consequences are everywhere: this is why used cars come with vehicle history reports (reducing information asymmetry), why health insurance markets can collapse without mandates, and why warranties and certifications exist. These are all institutional responses to a market failure that Smith’s framework could not anticipate.
Model 3 — Market Power: Monopoly vs Competition
Smith was a fierce critic of monopolies. He understood that when a single firm dominates a market, it restricts output and raises prices, harming consumers. Let us compute this precisely.
Consider a market with inverse demand \(P(Q) = 20 - 0.2Q\) and a constant marginal cost \(MC = 4\).
- Competitive equilibrium: many firms take the price as given and produce where \(P = MC\).
- Monopoly: a single firm chooses \(Q\) to maximise profit \(\pi = (P(Q) - MC) \cdot Q\).
The monopolist’s marginal revenue is \(MR(Q) = 20 - 0.4Q\) (the derivative of total revenue \(P(Q) \cdot Q = 20Q - 0.2Q^2\)). The monopolist sets \(MR = MC\).
# Monopoly vs Competition
MC = 4 # constant marginal cost
def inverse_demand(Q):
return 20 - 0.2 * Q
def marginal_revenue(Q):
return 20 - 0.4 * Q
def profit(Q):
"""Monopolist's profit."""
return (inverse_demand(Q) - MC) * Q
# Competitive equilibrium: P = MC
# 20 - 0.2Q = 4 => Q = 80
Q_comp = fsolve(lambda Q: inverse_demand(Q) - MC, x0=50)[0]
P_comp = inverse_demand(Q_comp)
# Monopoly: MR = MC
# 20 - 0.4Q = 4 => Q = 40
Q_mono = fsolve(lambda Q: marginal_revenue(Q) - MC, x0=30)[0]
P_mono = inverse_demand(Q_mono)
# Monopoly profit
profit_mono = profit(Q_mono)
# Deadweight loss: triangle between demand and MC from Q_mono to Q_comp
DWL_mono = 0.5 * (Q_comp - Q_mono) * (P_mono - MC)
# Consumer surplus under competition vs monopoly
CS_comp = 0.5 * (20 - P_comp) * Q_comp
CS_mono = 0.5 * (20 - P_mono) * Q_mono
print("=== Model 3: Monopoly vs Competition ===")
print(f"\nCompetitive equilibrium:")
print(f" Q = {Q_comp:.0f}, P = {P_comp:.0f}")
print(f" Consumer surplus = {CS_comp:.0f}")
print(f" Producer surplus = 0 (P = MC under perfect competition)")
print(f"\nMonopoly:")
print(f" Q = {Q_mono:.0f}, P = {P_mono:.0f}")
print(f" Consumer surplus = {CS_mono:.0f}")
print(f" Monopoly profit = {profit_mono:.0f}")
print(f"\nDeadweight loss from monopoly = {DWL_mono:.0f}")
print(f"\nThe monopolist restricts output by {Q_comp - Q_mono:.0f} units and raises price by {P_mono - P_comp:.0f}.")
print(f"Society loses {DWL_mono:.0f} in value that no one captures — pure waste.")# Visualise monopoly vs competition
Q_range = np.linspace(0, 100, 300)
fig, ax = plt.subplots(figsize=(10, 6))
ax.plot(Q_range, inverse_demand(Q_range), color='steelblue', linewidth=2.5, label='Demand')
ax.plot(Q_range, marginal_revenue(Q_range), color='steelblue', linewidth=2, linestyle='--', label='Marginal Revenue')
ax.axhline(MC, color='coral', linewidth=2.5, label=f'Marginal Cost = {MC}')
# Competitive equilibrium
ax.plot(Q_comp, P_comp, 'ko', markersize=10, zorder=5)
ax.annotate(f'Competitive\nQ={Q_comp:.0f}, P={P_comp:.0f}',
xy=(Q_comp, P_comp), xytext=(Q_comp + 5, P_comp + 2.5),
fontsize=10, arrowprops=dict(arrowstyle='->', color='black'),
bbox=dict(boxstyle='round,pad=0.3', facecolor='lightyellow', edgecolor='gray'))
# Monopoly equilibrium
ax.plot(Q_mono, P_mono, 's', color='darkred', markersize=10, zorder=5)
ax.annotate(f'Monopoly\nQ={Q_mono:.0f}, P={P_mono:.0f}',
xy=(Q_mono, P_mono), xytext=(Q_mono - 25, P_mono + 2),
fontsize=10, arrowprops=dict(arrowstyle='->', color='darkred'),
bbox=dict(boxstyle='round,pad=0.3', facecolor='mistyrose', edgecolor='darkred'))
# Shade deadweight loss
Q_dwl = np.linspace(Q_mono, Q_comp, 100)
ax.fill_between(Q_dwl, inverse_demand(Q_dwl), MC, alpha=0.25, color='red',
label=f'Deadweight loss = {DWL_mono:.0f}')
# Shade monopoly profit
ax.fill_between([0, Q_mono], P_mono, MC, alpha=0.15, color='orange',
label=f'Monopoly profit = {profit_mono:.0f}')
ax.set_xlabel('Quantity (Q)', fontsize=12)
ax.set_ylabel('Price / Cost', fontsize=12)
ax.set_title('Monopoly vs Perfect Competition', fontsize=13)
ax.legend(fontsize=9, loc='upper right')
ax.set_xlim(0, 105)
ax.set_ylim(0, 22)
ax.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
print("Smith warned about monopolies in 1776. Two and a half centuries later,")
print("the same logic drives antitrust enforcement against tech giants.")Synthesis: When Does the Invisible Hand Work?
We have now seen three ways the invisible hand can fail:
| Condition violated | Market failure | Result | Policy response |
|---|---|---|---|
| No externalities | Pollution | Overproduction | Pigouvian tax |
| Full information | Adverse selection (lemons) | Market collapse | Disclosure, warranties, mandates |
| Perfect competition | Monopoly | Underproduction, high prices | Antitrust, regulation |
Smith’s invisible hand works — under certain conditions. When those conditions hold (competitive markets, no external costs or benefits, full information), markets are efficient. But when they fail, the invisible hand points the wrong way, and that is where policy enters.
This is the mature view of economics that the course has built toward. Neither the libertarian fantasy (“markets always work”) nor the central-planning fantasy (“markets never work”) survives contact with computation. The question is always: which conditions hold here, and what happens when they don’t?
This is Hume’s scepticism made operational: don’t trust your assumptions — test them.
Part III — Exercises
Exercise 1 — Carbon Tax: Restoring Efficiency in a Polluted Market
A coal-fired power plant generates electricity but emits carbon dioxide. The market for electricity is described by:
- Inverse demand: \(P(Q) = 50 - 0.5Q\)
- Private marginal cost: \(PMC(Q) = 10 + 0.2Q\)
- External marginal damage (carbon emissions): \(EMD(Q) = 0.3Q\)
(a) Find the free-market equilibrium (where \(P = PMC\)) and the social optimum (where \(P = PMC + EMD\)). Compute both quantities and prices.
(b) Compute the optimal Pigouvian tax \(\tau^* = EMD(Q_{\text{social}})\). Verify that when the firm faces \(PMC(Q) + \tau^*\), the market equilibrium coincides with the social optimum.
(c) Compute the deadweight loss from the unregulated market (the area of the triangle between the demand curve and the social marginal cost curve, from \(Q_{\text{social}}\) to \(Q_{\text{market}}\)). This is the gain from imposing the carbon tax.
(d) Plot the demand curve, PMC, SMC, and the PMC + tax curve on one graph. Mark both equilibria. Shade the deadweight loss that the tax eliminates. Add a brief caption explaining what the graph shows.
# Your answer hereExercise 2 — Public Goods: The Free-Rider Problem
A public good (like a lighthouse, street lighting, or national defence) is non-excludable (you can’t stop anyone from using it) and non-rival (one person’s use doesn’t reduce another’s). This creates the free-rider problem: everyone wants the good to exist, but no one wants to pay for it.
Model: \(N = 10\) residents of a village each choose how much to contribute (\(g_i \geq 0\)) to a public good (a shared park). Total provision is \(G = \sum g_i\). Each resident’s payoff is:
\[u_i = (w - g_i) + \beta \sqrt{G}\]
where \(w = 100\) is their endowment, \((w - g_i)\) is private consumption, and \(\beta \sqrt{G}\) is the benefit from the public good (\(\beta = 20\)).
(a) Find the Nash equilibrium of the voluntary contribution game. Each player maximises \(u_i\) taking others’ contributions as given. Show that in equilibrium, each player contributes \(g_i^* = \frac{\beta^2}{4N^2}\) (derive this by setting \(\partial u_i / \partial g_i = 0\), noting \(\partial G / \partial g_i = 1\)). Compute total provision \(G^{NE}\).
(b) Find the social optimum. A social planner maximises \(\sum u_i\) by choosing a common contribution \(g\) for each player. Show that the optimal per-person contribution is \(g^{SO} = \frac{N \beta^2}{4}\) divided by… actually, derive it by setting \(\frac{\partial}{\partial g} \sum u_i = 0\). Compute total provision \(G^{SO}\).
(c) Compute the ratio \(G^{NE} / G^{SO}\). By what factor does the voluntary mechanism underprovide the public good? How does this ratio change with \(N\)?
(d) Plot total provision and total utility under both regimes as \(N\) varies from 2 to 50. Discuss: does the free-rider problem get better or worse as the group grows?
# Your answer hereExercise 3 — Reflection: One Economist, One Model
This is a combined writing and coding exercise.
(a) Choose one economist from the course (Smith, Ricardo, Malthus, Marx, Jevons/Walras/Marshall, Keynes, Solow, Nash, Lucas, Piketty, or Akerlof). In a markdown cell, write 150–250 words explaining their key idea and why it mattered.
(b) In a code cell, implement a simple computational model of that idea. It need not be complex — a supply-demand equilibrium, a growth simulation, a game-theoretic payoff matrix, a wealth accumulation loop — but it must produce a quantitative result or a plot.
(c) In another markdown cell, write 100–150 words discussing: what does your model capture about the economist’s idea, and what does it miss? Every model is a simplification — where does yours simplify too much?
(d) Connect your economist’s idea to one issue in the world today. How does the idea help us think about it? How might it mislead us?
# Your answer herePart IV — Quiz
Conceptual Questions
Q1. The First Welfare Theorem states that competitive equilibrium is Pareto efficient provided that:
- The government sets prices correctly
- There are no externalities, no market power, and complete information
- All consumers have identical preferences
- There are more buyers than sellers
Q2. A negative externality causes the free market to:
- Underproduce the good
- Overproduce the good
- Produce the efficient quantity but at the wrong price
- Produce nothing at all
Q3. In Akerlof’s lemons model, adverse selection occurs because:
- Buyers are irrational
- Sellers with high-quality goods withdraw when the price reflects average quality
- The government bans high-quality goods
- All goods are of identical quality
Q4. The Scottish Enlightenment’s most important contribution to economics was:
- The invention of double-entry bookkeeping
- The emphasis on empirical observation, scepticism, and systematic reasoning about society
- The development of central banking
- The abolition of tariffs
Q5. Which of the following is NOT a condition required for the invisible hand to produce efficient outcomes?
- Perfect competition (no firm has market power)
- No externalities
- Complete information
- All consumers must have equal income
Computational Questions
Q6. In our pollution model, demand is \(P = 20 - 0.2Q\), PMC is \(2 + 0.1Q\), and EMC is \(0.05Q\). The social optimum quantity is:
- \(Q = 60\) (set \(P = PMC\))
- \(Q \approx 51.4\) (set \(P = SMC\))
- \(Q = 100\) (set \(P = 0\))
- \(Q = 40\) (set \(MR = MC\))
Q7. A Pigouvian tax corrects an externality by:
- Banning the polluting activity
- Setting a tax equal to the external marginal cost at the socially optimal quantity
- Subsidising the polluter to reduce emissions
- Setting a tax equal to the firm’s total profit
Q8. A monopolist facing demand \(P = 20 - 0.2Q\) and \(MC = 4\) produces \(Q = 40\) and charges \(P = 12\). The competitive output would be \(Q = 80\) at \(P = 4\). The deadweight loss is:
- \((80 - 40) \times (12 - 4) / 2 = 160\)
- \((12 - 4) \times 40 = 320\)
- \((80 - 40) \times 12 = 480\)
- \((20 - 4) \times 80 / 2 = 640\)
Q9. In the voluntary contribution game for a public good with \(N\) players, as \(N\) increases the ratio of Nash equilibrium provision to the social optimum:
- Stays constant
- Increases (free-riding gets better)
- Decreases as \(1/N^2\) (free-riding gets worse)
- Equals 1 for all \(N\)
Q10. Across the course, the recurring computational method for finding equilibria has been:
- Machine learning
- Root-finding and optimisation (fsolve, minimize)
- Monte Carlo simulation
- Linear regression
Quiz Answers
Click to reveal answers
Q1. (b) The First Welfare Theorem requires competitive markets (no firm sets prices), no externalities (all costs and benefits are captured in market prices), and complete information (no adverse selection or moral hazard).
Q2. (b) A negative externality means the social cost exceeds the private cost. The market, responding only to private costs, produces more than the socially efficient quantity.
Q3. (b) When buyers cannot distinguish high- from low-quality goods, they offer a price reflecting average quality. Sellers of high-quality goods find this price too low and withdraw, reducing average quality further. This is the adverse selection spiral.
Q4. (b) Hume, Smith, and their contemporaries insisted on studying society through careful observation and systematic reasoning rather than appeals to authority, tradition, or pure theory. This empirical commitment became the foundation of modern social science.
Q5. (d) Income equality is not required for efficiency. The First Welfare Theorem says the equilibrium is Pareto efficient (no one can be made better off without making someone worse off) regardless of the distribution of income. Equity is a separate concern.
Q6. (b) The social optimum sets demand equal to social marginal cost: \(20 - 0.2Q = 2 + 0.15Q\), giving \(18 = 0.35Q\), so \(Q \approx 51.4\). The market equilibrium (ignoring externalities) would be \(Q = 60\).
Q7. (b) A Pigouvian tax is set equal to the marginal external cost evaluated at the socially optimal quantity. This “internalises the externality” by making the polluter face the full social cost of production.
Q8. (a) The deadweight loss is the area of the triangle between the demand curve and the marginal cost line, from the monopoly quantity to the competitive quantity: \(\frac{1}{2} \times (80 - 40) \times (12 - 4) = 160\).
Q9. (c) In the voluntary contribution game, Nash equilibrium provision is proportional to \(1/N\) while socially optimal provision is proportional to \(N\), so the ratio falls as \(1/N^2\). Larger groups face worse free-riding.
Q10. (b) Throughout the course, we have used fsolve (to find where excess demand equals zero) and minimize (to solve optimisation problems like utility maximisation). Root-finding and optimisation are the computational workhorses of economics.
Further Reading
- Akerlof, G. “The Market for ‘Lemons’” (QJE, 1970) — the paper that launched information economics.
- Pigou, A.C. The Economics of Welfare (1920) — the original treatment of externalities and corrective taxation.
- Nordhaus, W. The Climate Casino (2013) — climate economics for a general audience.
- Broadie, A. The Scottish Enlightenment: The Historical Age of the Historical Nation — the intellectual world that made economics possible.
- Heilbroner, R. The Worldly Philosophers — a magnificent tour through the lives and ideas of the great economists.
Coda
We began in 18th-century Edinburgh, with a retired professor of moral philosophy who believed that careful observation of how people actually behave could reveal the hidden order of commercial society. We end here, in the same city, having traced the arc of that idea through two and a half centuries.
Along the way we met economists who agreed with Smith and economists who opposed him, economists who formalised his intuitions and economists who demolished them. We met Ricardo’s iron laws and Keynes’s radical uncertainty, Marx’s class struggle and Nash’s strategic equilibrium, Solow’s growth engine and Piketty’s inequality trap. And in every case, we did what Smith himself would have done if he had had a laptop: we built a model, ran the numbers, and looked at what came out.
The models are simple. Real economies are not. But the point of a model is not to replicate reality — it is to isolate a mechanism, to make an idea precise enough to test. That is what computation gives us: not answers, but sharper questions.
Economics is unfinished. The great questions — why are some nations rich and others poor? how should we weigh the future against the present? can markets and justice coexist? — remain open. But the method is clear. Observe. Model. Compute. Test. Revise. It is the method of Hume and Smith, updated for an age of data and code.
“The real voyage of discovery consists not in seeking new landscapes, but in having new eyes.”
— Marcel Proust, In Search of Lost Time
…or in having new code.
End of course.