To illustrate implementation of the collocation method for implicit function problems, consider the example of Cournot oligopoly. In the standard microeconomic model of the firm, the firm maximizes profit by equating marginal revenue to marginal cost (MC). An oligopolistic firm, recognizing that its actions affect price, takes the marginal revenue to be $p + q\frac{dp}{dq}$, where $p$ is price, $q$ is quantity produced, and $\frac{dp}{dq}$ is the marginal impact of output on market price. The Cournot assumption is that the firm acts as if any change in its output will be unmatched by its competitors. This implies that

\begin{equation} \frac{dp}{dq} = \frac{1}{D'(p)} \end{equation}where $D(p)$ is the market demand curve.

Suppose we wish to derive the effective supply function for the firm, which specifies the quantity $q = S(p)$ it will supply at any price. The firm's effective supply function is characterized by the functional equation

\begin{equation} p + \frac{S(p)}{D'(p)} - MC(S(p)) = 0 \end{equation}for all positive prices $p$. In simple cases, this function can be found explicitly. However, in more complicated cases, no explicit solution exists.

In [1]:

```
from demos.setup import np, plt, demo
from compecon import BasisChebyshev, NLP, nodeunif
%matplotlib inline
```

Here, the demand elasticity and the marginal cost function parameter are

In [2]:

```
alpha = 1.0
eta = 3.5
```

A degree-25 Chebychev basis on the interval [0.5, 3.0] is selected; also, the associated collocation nodes `p`

are computed.

In [3]:

```
n = 21
a = 0.5
b = 2.0
S = BasisChebyshev(n, a, b, labels=['price'], l=['supply'])
p = S.nodes
```

Suppose, for example, that

\begin{equation} D(p) = p^{-\eta} \quad\text{and}\quad MC(q) = \alpha\sqrt{q} + q^2 \end{equation}Then the functional equation to be solved for S(p),

\begin{equation} \left[p - \frac{S(p)p^{\eta+1}}{\eta}\right] -\left[\alpha\sqrt{S(p)} + S(p)^2\right] = 0 \end{equation}has no known closed-form solution.

In [4]:

```
def resid(c):
S.c = c # update interpolation coefficients
q = S(p) # compute quantity supplied at price nodes
return p - q * (p ** (eta+1) / eta) - alpha * np.sqrt(q) - q ** 2
```

`resid`

only takes one argument. The other parameters (`Q`

, `p`

, `eta`

, `alpha`

) should be declared as such in the main script, were Python's scoping rules will find them.

Class `NLP`

defines nonlinear problems. It can be used to solve `resid`

by Broyden's method.

In [5]:

```
c0 = np.zeros(n) # set initial guess for coefficients
c0[0] = 1
cournot = NLP(resid)
S.c = cournot.broyden(c0, tol=1e-12)
```

In [6]:

```
pplot = nodeunif(501, a, b)
splot = S(pplot)
dplot = pplot ** -eta
demo.figure('Cournot Effective Firm Supply Function',
'Quantity', 'Price', [0, 4], [0.5, 2])
plt.plot(5 * splot, pplot, dplot, pplot)
plt.legend(('Supply','Demand'))
```

Out[6]:

Notice that `resid`

does not take explicit parameters, so to evaluate it when prices are `pplot`

we need to assign `p = pplot`

.

In [7]:

```
p = pplot
rplot = resid(S.c)
demo.figure('Residual Function for Cournot Problem',
'Quantity', 'Residual')
plt.hlines(0, a, b, 'k', '--', lw=2)
plt.plot(pplot, rplot)
```

Out[7]:

In [8]:

```
m = np.array([1, 3, 5, 10, 15, 20])
demo.figure('Industry Supply and Demand Functions',
'Quantity', 'Price', [0, 13])
plt.plot(np.outer(splot, m), pplot, dplot, pplot)
plt.legend(['m=1', 'm=3', 'm=5', 'm=10', 'm=15', 'm=20'])
```

Out[8]:

In [9]:

```
pp = (b + a) / 2
dp = (b - a) / 2
m = np.arange(1, 26)
for i in range(50):
dp /= 2
pp = pp - np.sign(S(pp) * m - pp ** (-eta)) * dp
demo.figure('Cournot Equilibrium Price as Function of Industry Size',
'Number of Firms', 'Price')
plt.plot(m, pp)
```

Out[9]: