Equilibrium pricing

Alfred Galichon (NYU+ScPo)

'math+econ+code' masterclass series

With python code examples

© 2018-2023 by Alfred Galichon. Past and present support from NSF grant DMS-1716489, ERC grant CoG-866274 are acknowledged, as well as inputs from contributors listed here.

If you reuse material from this masterclass, please cite as:
Alfred Galichon, 'math+econ+code' masterclass series. https://github.com/math-econ-code/mec_equil

References

Textbooks

Papers

Getting started

See slides D1a_getting-started.pdf.

Generating demand and supply data

The pickup spots

For each $z \in \{0,...,n-1\}$, we define $h_z$ and $v_z$ the coordinates (horizontal and vertical) of $z$.

Generating supply

For each driver $i$, we shall generate the position (horizontal and vertical coordinates), the concavity of preferences $\tau_i$, and $\lambda_i$ the value of $i$'s time.

Generating demand

For each passenger $j$, we shall generate the position (horizontal and vertical coordinates), elasticity of price-time substitution $\sigma_j$, and the valuation of $j$'s time $\epsilon_j$.

The average speed walking is $4$ km/h and driving is $25$ km/h. Let's compute the time $T_{iz}$ that it takes driver each driver $i$ to drive to pickup at each $z$.

Now let's compute the supply. The utility that each driver $i$ have for each option $z$ is $$u_{iz}\left( p_z,\varepsilon \right) =p_{z}^{1-\tau _{i}}-\lambda _{i}T_{iz},$$ and the option that driver $i$ has for the exit option is $0$. We have $$s_z(p_z) = \sum_i 1{\{ z = argmax_{z^\prime} (u_{iz^\prime}(p_z)) \}}.$$

We now compute the demand. The cost that each passenger $j$ has for each option $z$, which is given by $$c_{jz}\left( p_{z}\right) =\left( p_{z}^{1-\frac{1}{% \sigma _{j}}}+\left( \epsilon _{j}T_{jz}\right) ^{1-\frac{1}{\sigma _{j}}% }\right) ^{\frac{\sigma _{j}}{\sigma _{j}-1}},$$ and the cost associated with the exit option is $\eta_j$. Similar to above, we have $$d_z(p_z) = \sum_j 1{\{ z = argmin_{z^\prime} (v_{jz^\prime}(p_z)) \}}.$$

Smoothed supply and demand

Actually, we would like to have a smooth approximation of supply and demand. Thus set $$s^{smooth}_z(p_z,T) = \sum_i \frac {e^{\frac {u_{iz}} {T} }} {\sum_{z^\prime} e^{\frac {c_{iz^\prime}} {T} }},$$ and $$d^{smooth}_z(p_z,T) = \sum_j \frac {e^{\frac {-c_{jz}} {T} }} {\sum_{z^\prime} e^{\frac {-c_{jz^\prime}} {T} }}.$$ Note (math exercise!) that as $T \to 0$, we tend to the previous functions $s$ and $d$.

Setting up the EquilibriumProblem class

We are now in a good place to create a Python class, with all the data that will be useful.

Equilibrium computation

We now would like to construct a toolbox to solve the equilibrium problem $$Q(p)=q.$$ We will see two related basic methods, the Gauss-Seidel algorithm and the Jacobi algorithm. Both of them are based ont the notion of coordinate updating.

Building coordinate update functions

To start with, we need to introduce a coordinate update function, denoted $cu^z(p),$ such that $$Q_z(cu^z_z(p),p_{-z})=q_z\\ cu^z_{-z}(p)=p_{-z} $$ so that $cu^z_z$ finds the equilibrium price in the market for $z$, provided all the other are markets are at equilibrium.

Above, self is intended to be an object of EquilibriumProblem class. We can just add the method cu to that class.

Gauss-Seidel vs Jacobi algorithms

The Gauss-Seidel algorithm consists of setting $p^t$ such that

$ p^1: Q_1(p^1_1,p^0_{-1})=q_1 , p^1_{-1} = p^0_{-1} \\ p^2: Q_2(p^2_2,p^1_{-2})=q_2, p^2_{-2} = p^1_{-2} \\ ... \\ p^Z: Q_z (p^Z_Z,p^{Z-1}_{-Z})=q_Z, p^Z_{-Z} = p^{Z-1}_{-Z} \\ p^{Z+1}: Q_{1} (p^{Z+1}_1,p^{Z}_{-1}) = q_1, p^{Z+1}_{-1} = p^{Z+1}_{-1} \\ ... $

In other words, one full iteration of the Gauss-Seidel algorithm amounts to iterating the map

$f^{GS}(p)=(cu^1(p),cu^2\circ cu^1(p),...,cu^Z\circ cu^{Z-1}\circ ... \circ cu^1(p)),$

which we now implement.

The Jacobi algorithm consists of setting $p^t$ such that

$ Q_1(p^1_1,p^0_{-1}) = q_1 \\ Q_2(p^1_2,p^0_{-2}) = q_2 \\ ... \\ Q_z (p^1_Z,p^0_{-Z}) = q_Z \\ Q_{1} (p^2_1,p^1_{-1}) = q_1\\ ... $

In other words, one full iteration of the Gauss-Seidel algorithm amounts to

$f^{J}(p)=(cu^1(p),cu^2(p),...,cu^Z(p)).$

Let's implement $f^J$:

The first five steps of the Gauss-Seidel algorithm will therefore be:

The first five steps of the Jacobi algorithm will therefore be:

Compared with Gauss-Seidel above, Jacobi does not make use of all the relevant information (i.e. latest price update) at a given point in time. But its structure makes it more naturally suited for parallelization -- we will return to that.

Let's provide a solve method to EquilibriumProblem which computes both Gauss-Seidel and Jacobi.

Convergence of the Gauss-Seidel and Jacobi algorithms

See the basics in slides D1.1_mathematical-results.pdf.

More on convergence will require Perron-Froebenius theory, which will be discussed in Advanced Lecture AL1.

Parallel implementation

Parallel implementation on the Cloud will be addressed in Advanced Lecture AL5.