This example is taken from the book “*Complementarity Modeling in Energy Markets*.”

We have two firms *i* producing *q(i)*. The total production *Qtot* is then defined by adding up these two quantities. Because of say transmission capacity or available drilling riggs, there is a limit on the total production *Qtot*. The cost function of each firm is linear: *Cost(i) = γ(i)*q(i)*. The demand price *P* is determined by an inverse demand function of the form *P=α-β*Qtot*.

The two firms each face an optimization problem: maximize profit = revenue – cost. To combine the optimization problem of both agents we form the first-order conditions (KKT conditions) and combine these in one model. For details see the book.

A “scalar” model is given in the appendix of the book. The model does not use GAMS indexing so it is merely using GAMS as a calculator. Here is a GAMSified version:

$ontext Reference: Steven A. Gabriel, Antonio J. Conejo, J. David Fuller, Benjamin F. Hobbs, Carlos Ruiz Complementarity Modeling in Energy Markets Springer 2012 $offtext set i /firm1,firm2/; parameters gamma(i) 'unit cost' /firm1 1, firm2 2/ beta 'coefficient inverse demand function' /5/ alpha 'coefficient inverse demand function' /10/ Qmax 'upper limit on total quantity produced' / 1.06 / ; positive variables q(i) 'production at each firm' lambda_MAX 'dual of MaxQ constraint' P 'price' ; free variable Qtot 'total production: automatic positive -- q(i) is positive' ; equations FOCfirm(i) 'first-order conditions: derivative of lagrangian wrt q(i)' MaxQ 'max total production restriction' QDef 'definition of Qtot (total production)' Demand 'inverse demand function' ; FOCFirm(i).. 0 =g= P - beta*q(i) - gamma(i) - lambda_MAX; MaxQ.. Qmax =g= Qtot; QDef.. Qtot =e= sum(i, q(i)); Demand.. P =g= alpha - beta*Qtot; model problem2 / FOCfirm.q MaxQ.lambda_MAX QDef.QTot Demand.P /; solve problem2 using mcp; parameter results(*,*,*); $macro report(a) \ results(a, 'unit cost', i) = gamma(i); \ results(a, 'q', i) = q.l(i); \ results(a, 'q', 'total') = Qtot.l; \ results(a, 'q', 'max') = Qmax; \ results(a, 'p', 'total') = P.l; \ results(a, 'dual', 'max') = lambda_MAX.l; \ display results; report('base case') * experiments: * make firm 2 very expensive gamma('firm2') = 6; solve problem2 using mcp; report('firm2 expensive') * make firm 2 very cheap gamma('firm2') = .5; solve problem2 using mcp; report('firm2 cheap') |

The results look like:

---- 75 PARAMETER results firm1 firm2 total max base case .unit cost 1.000 2.000 |

Notes:

- In the base case the capacity constraints is binding and we have a dual.
- In the second case the capacity constraint is no longer binding and the dual is zero. Furthermore, firm 2 is too expensive to make it worthwhile to produce anything (the unit cost is larger than the price).
- If we make firm 2 very cheap we see that firm 1 stays in business. The capacity constraint effectively puts a floor on the price, and at this price firm 1 is still able to produce.
- In the model, both firms share a single dual λ in the FOC equation.
- This model is easily extended to more firms (no equations need to be changed), in which case we have a oligopoly.
- Qtot is a free variable and we match it to a =e= constraint. We could also make it a positive variable. In that case we could make QDef a =g= equation.