MTC Chapter 2 — The Aggregation Problem (Reswitching)¶
Part I · Week 1 · Seed 20260201
The Cambridge reswitching example: two techniques whose cost curves cross twice, so the cost-minimizing technique is not monotone in the interest rate. The switches occur at $r=50\%$ and $r=100\%$.
In [ ]:
import sys, os
sys.path.insert(0, r"/home/claude/mtc/mtc-course/downloads/engine_lib")
sys.path.insert(0, r"/home/claude/mtc/nbbuild")
from mtcplot import apply_style, MTC_RED, BRASS, SLATE, MTC_RED_LITE, MTC_RED_DARK
import matplotlib.pyplot as plt
import numpy as np
apply_style()
The cost curves and their two crossings¶
In [ ]:
from engines import mtc_engine_ch02 as e
cc = e.cost_curves(r_min=0, r_max=1.6, n=200)
fig, ax = plt.subplots()
ax.plot(cc["r"], cc["c_A"], color=MTC_RED, lw=2.2, label="$c_A(r)=7(1+r)^2$")
ax.plot(cc["r"], cc["c_B"], color=BRASS, lw=2.2, label="$c_B(r)=2(1+r)^3+6(1+r)$")
for sp in cc["switch_points"]:
ax.axvline(sp, color=SLATE, ls="--", lw=1)
ax.text(sp+0.01, 5, f"r={sp:g}", color=SLATE, rotation=90, va="bottom")
ax.set_xlabel("interest rate $r$"); ax.set_ylabel("cost of one unit at date 0")
ax.set_title("Reswitching: A cheaper, then B, then A again")
ax.legend()
plt.tight_layout(); plt.show()
print("switch points:", cc["switch_points"])
print("ordering at r=20/75/150%:", {r: e.cheaper_technique(r) for r in (0.2,0.75,1.5)})
The cost difference — two sign changes¶
The reversal is visible as $c_B-c_A$ crossing zero twice.
In [ ]:
rs = np.linspace(0, 1.6, 200)
diff = [e.cost_B(r)-e.cost_A(r) for r in rs]
fig, ax = plt.subplots()
ax.plot(rs, diff, color=MTC_RED, lw=2.2)
ax.fill_between(rs, diff, 0, where=[d<0 for d in diff], color=BRASS, alpha=0.3, label="B cheaper")
ax.axhline(0, color=SLATE, lw=0.9)
ax.set_xlabel("interest rate $r$"); ax.set_ylabel("$c_B - c_A$")
ax.set_title("Two sign changes: no scalar orders the techniques")
ax.legend()
plt.tight_layout(); plt.show()
Validation¶
Every number above is reproduced by the seeded engine; the checks below must all pass.
In [ ]:
from engines import mtc_engine_ch02 as _e
v = _e.validation_checks(); v.pop("_values", None)
for k, val in v.items():
print(f" {k}: {val}")
assert v["ALL_PASS"], "validation failed"
print("\nALL_PASS — matches notebook + workbook + API")