Skip to content

Commit 8ca18df

Browse files
Tom's Dec 24 afternoon edits
1 parent e6de7d8 commit 8ca18df

File tree

3 files changed

+74
-42
lines changed

3 files changed

+74
-42
lines changed

lectures/_static/quant-econ.bib

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@
66
@techreport{boerma2023composite,
77
title={Composite sorting},
88
author={Boerma, Job and Tsyvinski, Aleh and Wang, Ruodu and Zhang, Zhenyuan},
9-
year={2023},
10-
institution={National Bureau of Economic Research}
9+
year={2024},
10+
institution={University of Wisconsin}
1111
}
1212

1313
@article{delon2011minimum,

lectures/calvo.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,7 @@ where $\beta \in (0,1)$ is a discount factor.
291291
292292
```{note}
293293
We define $ r(x_t,\mu_t) := - s(\theta_t, \mu_t) $ as we do in order to represent the government's **maximum** problem in terms of our Python code for solving linear quadratic discounted dynamic programs.
294-
In earlier quantecon lectures, we formulated these as **loss minimization** problems.
294+
In [first LQ control lecture](https://python-intro.quantecon.org/lqcontrol.html) and some other quantecon lectures, we formulated these as **loss minimization** problems.
295295
```
296296
297297
The government's time $t$ continuation value $v_t$ is

lectures/match_transport.md

Lines changed: 71 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -15,30 +15,30 @@ kernelspec:
1515

1616
+++
1717

18-
## Introduction
18+
## Overview
1919

20-
This lecture presents Python code for solving **composite sorting** problems of the kind
21-
studied in *Composite Sorting* by Job Boerma, Aleh Tsyvinski, Ruodo Wang,
22-
and Zhenyuan Zhang {cite}`boerma2023composite`.
20+
This lecture describes how Job Boerma, Aleh Tsyvinski, Ruodo Wang,
21+
and Zhenyuan Zhang {cite}`boerma2023composite` used optimal transport theory to formulate and solve an equilibrium of a model in which wages and allocations of workers across jobs adjust to match measures of different types with measures of different types of occupations.
2322

24-
In this lecture, we will use the following imports
23+
Production technologies allow firms to affect shape costs of mismatch with the consequence
24+
that costs of mismatch can be concave.
2525

26-
```{code-cell} ipython3
27-
import numpy as np
28-
from scipy.optimize import linprog
29-
from itertools import chain
30-
import pandas as pd
31-
from collections import namedtuple
26+
That means that it possible that equilibrium there is neither **positive assortive** nor **negative assorting** matching, an outcome that {cite}`boerma2023composite` call **composite assortive** matching.
27+
28+
In such an equilibrium with composite matching, for example, identical workers can sort into different occupations, some positively and some negatively.
29+
30+
{cite}`boerma2023composite`
31+
show how this can generate distinct distributions of labor earnings within and across occupations.
32+
33+
34+
This lecture describes the {cite}`boerma2023composite` model and presents Python code for computing equilibria.
35+
36+
It then applies the code to their model of labor markets.
37+
38+
As with our earlier lecture on optimal transport (https://python.quantecon.org/opt_transport.html), a key tool will be **linear programming**.
3239

3340

34-
import matplotlib.pyplot as plt
35-
import matplotlib.patches as patches
36-
from matplotlib.ticker import MaxNLocator
37-
from matplotlib import cm
38-
from matplotlib.colors import Normalize
39-
```
4041

41-
+++ {"user_expressions": []}
4242

4343
## Setup
4444

@@ -49,7 +49,7 @@ For each $x \in X,$ let a positive integer $n_x$ be the number of agents of typ
4949

5050
Similarly, let a positive integer $m_y$ be the agents of agents of type $y \in Y$.
5151

52-
We will refer to these two measures as *marginals*.
52+
We refer to these two measures as *marginals*.
5353

5454
We assume that
5555

@@ -73,15 +73,15 @@ $$
7373
Given our discreteness assumptions about $n$ and $m$, the problem admits an integer solution $\mu \in \mathbb{Z}_+^{X \times Y}$, i.e. $\mu_{xy}$ is a non-negative integer for each $x\in X, y\in Y$.
7474

7575

76-
In this notebook, we will focus on integer solutions of the problem.
76+
We will study integer solutions.
7777

78-
Two points on the integer assumption are worth mentioning:
78+
Two points about restricting ourselves to integer solutions are worth mentioning:
7979

8080
* it is without loss of generality for computational purposes, since every problem with float marginals can be transformed into an equivalent problem with integer marginals;
81-
* arguments below work for arbitrary real marginals from a mathematical standpoint, but some of the implementations will fail to work with float arithmetic.
81+
* although the mathematical structure that we present actually wors for arbitrary real marginals, some of our Python implementations would fail to work with float arithmetic.
8282

8383

84-
Our focus in this notebook is a specific instance of the optimal transport problem:
84+
We focus on a specific instance of an optimal transport problem:
8585

8686
We assume that $X$ and $Y$ are finite subsets of $\mathbb{R}$ and that the cost function satisfies $c_{xy} = h(|x - y|)$ for all $x,y \in \mathbb{R},$ for an $h: \mathbb{R}_+ \rightarrow \mathbb{R}_+$ that is **strictly concave** and **strictly increasing** and **grounded** (i.e., $h(0)=0$).
8787

@@ -112,7 +112,29 @@ $$
112112
\end{aligned}
113113
$$
114114

115-
The following class takes as inputs sets of types $X,Y \subset \mathbb{R},$ marginals $n, m $ with positive integer entries such that $\sum_{x \in X} n_x = \sum_{y \in Y} m_y $ and cost parameter $\zeta>1$.
115+
116+
Let's start setting up some Python code.
117+
118+
We use the following imports:
119+
120+
```{code-cell} ipython3
121+
import numpy as np
122+
from scipy.optimize import linprog
123+
from itertools import chain
124+
import pandas as pd
125+
from collections import namedtuple
126+
127+
128+
import matplotlib.pyplot as plt
129+
import matplotlib.patches as patches
130+
from matplotlib.ticker import MaxNLocator
131+
from matplotlib import cm
132+
from matplotlib.colors import Normalize
133+
```
134+
135+
+++ {"user_expressions": []}
136+
137+
The following Python class takes as inputs sets of types $X,Y \subset \mathbb{R},$ marginals $n, m $ with positive integer entries such that $\sum_{x \in X} n_x = \sum_{y \in Y} m_y $ and cost parameter $\zeta>1$.
116138

117139

118140
The cost function is stored as an $|X| \times |Y|$ matrix with $(x,y)$-entry equal to $|x-y|^{1/\zeta},$ i.e., the cost of matching an agent of type $x \in X$ with an agent of type $y \in Y.$
@@ -843,7 +865,7 @@ print(V_i_j.round(2)[:min(10, V_i_j.shape[0]),
843865

844866
Having computed the value function, we can proceed to compute the optimal matching as the *policy* that attains the value function that solves the Bellman equation (*policy evaluation*).
845867

846-
Specifically, we start from agent $1$ and match it with the $k$ that achieves the minimum in the equation associated with $V_{1,2N_\ell};$
868+
We start from agent $1$ and match it with the $k$ that achieves the minimum in the equation associated with $V_{1,2N_\ell}.$
847869

848870
Then we store segments $[2,k-1]$ and $[k+1,2N_\ell]$ (if not empty).
849871

@@ -960,7 +982,7 @@ example_off_diag.plot_layer_matching(layer_example, matching_layer)
960982

961983
+++ {"user_expressions": []}
962984

963-
We will now present two key results in the context of OT with concave type costs.
985+
We now present two key results in the context of OT with concave type costs.
964986

965987
We refer {cite}`boerma2023composite` and {cite}`delon2011minimum` for proofs.
966988

@@ -1046,7 +1068,7 @@ print(f"Difference with previous Bellman equations: \
10461068

10471069
+++ {"user_expressions": []}
10481070

1049-
Thanks to the results in this section, we can actually compute the optimal matching within the layer cuncurrently to the computation of the value function, rather than afterwards.
1071+
We can actually compute the optimal matching within the layer simultaneously with computing the value function, rather than sequentially.
10501072

10511073
The key idea is that, if at some step of the computation of the values the left branch of the minimum above achieves the minimum, say $V_{ij}= c_{ij} + V_{i+1,j-1},$ then $(i,j)$ are optimally matched on $[i,j]$ and by the theorem above we get that a matching on $[i+1,j-1]$ which achieves $ V_{i+1,j-1}$ belongs to an optimal matching on the whole layer (since it is covered by the arc $(i,j)$ in $[i,j]$).
10521074

@@ -1147,7 +1169,7 @@ The following method assembles our components in order to solve the primal prob
11471169

11481170
First, if matches are perfect pairs, we store the on-diagonal matching and create an off-diagonal instance with the residual marginals.
11491171

1150-
Then, we compute the set of layers of the residual distributions.
1172+
Then we compute the set of layers of the residual distributions.
11511173

11521174
Finally, we solve each layer and put together matchings within each layer with the on-diagonal matchings.
11531175

@@ -1360,7 +1382,7 @@ print(f"Value (DSS): {(matching_DSS * example_pb.cost_x_y).sum()}")
13601382
## Examples
13611383
### Example 1
13621384

1363-
In this notebook we study optimal transport problems on the real line with cost $c(x,y)= h(|x-y|)$ for a strictly concave and increasing function $h: \mathbb{R}_+ \rightarrow \mathbb{R}_+.$
1385+
We study optimal transport problems on the real line with cost $c(x,y)= h(|x-y|)$ for a strictly concave and increasing function $h: \mathbb{R}_+ \rightarrow \mathbb{R}_+.$
13641386

13651387
The outcome is called *composite sorting*.
13661388

@@ -1477,7 +1499,7 @@ example_1.plot_matching(matching_NAM, title = 'NAM',
14771499

14781500
+++ {"user_expressions": []}
14791501

1480-
Finally, notice that the the **Monge problem** cost function $|x-y|$ equals the limit of composite sorting cost $|x-y|^{1/\zeta}$ as $\zeta \downarrow 1$ and also the limit of $|x-y|^p$ as $p \downarrow 1.$
1502+
Finally, notice that the **Monge problem** cost function $|x-y|$ equals the limit of the composite sorting cost $|x-y|^{1/\zeta}$ as $\zeta \downarrow 1$ and also the limit of $|x-y|^p$ as $p \downarrow 1.$
14811503

14821504
Evidently, the Monge problem is solved by both the PAM and the composite sorting assignment that arises for $\zeta \downarrow 1.$
14831505

@@ -1573,11 +1595,11 @@ example_2.plot_matching(matching_NAM, title = 'NAM',
15731595

15741596
+++ {"user_expressions": []}
15751597

1576-
### Example 3 : from the paper
1598+
### Example 3
15771599

15781600
+++ {"user_expressions": []}
15791601

1580-
Boerma et al. provide the following example.
1602+
{cite}`boerma2023composite` provide the following example.
15811603

15821604
There are four agents per side and three types per side (so the problem is not unitary, as opposed to the examples above).
15831605

@@ -1622,7 +1644,7 @@ example_3.plot_matching(matching_NAM, title = 'NAM',
16221644

16231645
+++ {"user_expressions": []}
16241646

1625-
Let us recall our formulation
1647+
Let's recall the formulation
16261648

16271649
$$
16281650
\begin{aligned}
@@ -1647,7 +1669,11 @@ where $(\phi , \psi) $ are dual variables, which can be interpreted as shadow co
16471669
Since the dual is feasible and bounded, $V_P = V_D$ (*strong duality* prevails).
16481670

16491671

1650-
Assume now that $y_{xy} = \alpha_x + \gamma_y - c_{xy}$ is the output generated by matching $x$ and $y.$ It includes the sum of $x$ and $y$ specific amenities/outputs minus the cost $c_{xy}.$ Then, we have can formulate the following problem and its dual
1672+
Assume now that $y_{xy} = \alpha_x + \gamma_y - c_{xy}$ is the output generated by matching $x$ and $y.$
1673+
1674+
It includes the sum of $x$ and $y$ specific amenities/outputs minus the cost $c_{xy}.$
1675+
1676+
Then we can formulate the following problem and its dual
16511677

16521678
$$
16531679
\begin{aligned}
@@ -1902,7 +1928,7 @@ As already mentioned, the algorithm starts from the matched pairs $(x_0,y_0)$ wi
19021928

19031929

19041930

1905-
Then, the algorithm proceeds iterarively by processing any matched pair whose subpairs have already been processed.
1931+
The algorithm then proceeds sequentially by processing any matched pair whose subpairs have already been processed.
19061932

19071933
After picking any such matched pair $(x_0,y_0)$, the dual variables already computed for the processed subpairs need to be made "comparable".
19081934

@@ -2148,7 +2174,7 @@ print('Value of primal solution: ', (assignment * exam_assign.cost_x_y).sum())
21482174

21492175
+++ {"user_expressions": []}
21502176

2151-
## Empirical application
2177+
## Application
21522178

21532179
+++ {"user_expressions": []}
21542180

@@ -2164,7 +2190,11 @@ The occupation of each individual consists of a Standard Occupational Classifica
21642190

21652191
There are 497 codes in total.
21662192

2167-
We consider only employed (civilian) individuals with ages between 25 and 60 from 2010 to 2017. To visualize log-wage dispersion, we group the individuals by occupation and compute the mean and standard deviation of the wages within each occupation. Then, we sort the occupations by average log-earnings within each occupation.
2193+
We consider only employed (civilian) individuals with ages between 25 and 60 from 2010 to 2017.
2194+
2195+
To visualize log-wage dispersion, we group the individuals by occupation and compute the mean and standard deviation of the wages within each occupation.
2196+
2197+
Then we sort occupations by average log-earnings within each occupation.
21682198

21692199
The resulting dataset is included in the dataset `acs_data_summary.csv`
21702200

@@ -2382,7 +2412,9 @@ model_OD_1980.plot_matching(matching_OD_1980,
23822412

23832413
+++ {"user_expressions": []}
23842414

2385-
From the optimal matching we compute and visualize the hierarchies. Then, we find the dual solution $(\phi,\psi)$ and compute the wages as $w_x = g(x) - \phi_x,$ assuming that the type-specific productivity of type $x$ is $g(x) = x$.
2415+
From the optimal matching we compute and visualize the hierarchies.
2416+
2417+
We then find the dual solution $(\phi,\psi)$ and compute the wages as $w_x = g(x) - \phi_x,$ assuming that the type-specific productivity of type $x$ is $g(x) = x$.
23862418

23872419
```{code-cell} ipython3
23882420
# Find subpairs and plot hierarchies
@@ -2414,7 +2446,7 @@ wage_worker_x_1980 = model_1980.X_types - ϕ_worker_x_1980
24142446

24152447
+++ {"user_expressions": []}
24162448

2417-
Let us plot the average wages and wage dispersion generated by the model.
2449+
Let's plot average wages and wage dispersion generated by the model.
24182450

24192451
```{code-cell} ipython3
24202452
def plot_wages_application(wages):

0 commit comments

Comments
 (0)