Quantity Games

with Linear Demand

Most introductory economics courses study optimal decision making by a single agent - be it a firm or a consumer.   
	In many economic situations, however, the optimal decision of one agent will depend on the decision of another agent.  Game theory is the study of optimal decion making by interacting agents.  In the games that follow, we will consider the optimal decisions made by an industry comprised of only two firms (duopoly).  Duopoly games belong to a broader class of microeconomics theory called Oligopoly.  Oligopolistic industries  lie somewhere between competitive industries and monopolies.  The key distinction between an oligopolistic industry and a competitive industry is that in an oligopoly individual firms possess market power.   
	In this lab, we study quantity games.  As the name implies, quantity games are games in which the two agents (firms) each choose a quantity to supply and allow the price to be determined endogenously by the market.  The two quantity games we will consider are a Cournot game and a Stackelberg game.  As you will see, the Cournot game is a simultaneous move game in which each firm chooses its own quantity before observing the other firm's quantity.  A slightly different game is the Stackelberg quantity leadership game.  The Stackelberg game is a two-stage, or sequential move, game in which the Stackelberg leader (assumed to be firm 1) chooses its quantity in the first stage.  In the second stage, the other firm (Stackelberg follower) chooses its own optimal output level having observed the Stackelberg leaders output choice.

This file (Combine.ma)contains the same material as the previous files (React.ma, Cournot.ma, and Stack.ma) but extends it to provide additional graphics and a comparative results section.  Many of the comments are from the React.ma are preserved in Cournot.ma so that each program can be clearly understood independant of the others.

General Setup

Mathematica notes are presented in this format.

Economic notes are in this format.

Setup for the problem.

Because we want to study the analytical solution to this simply problem, we need to tell Mathematica what the parameters (or constants) of the model are.  Everything else will be treated as a variable.  The semi-colons at the end of input lines suppress the display of output.

SetAttributes[a, Constant]   
SetAttributes[b, Constant]   
SetAttributes[c, Constant]

The Clear command tells Mathematica to wipe out any previous values associated with the listed variables.

Clear[a,b,c,temp1,temp2];   
Clear[Q,Q1,Q2,eqPr1,eqPr1,focPr1,focPr2,R2,pie1c,pie2c];

Next, we specify a functional form for the inverse market demand faced by the duopolists; in this case a linear function.

Price = a - b*Q ;

Collusive Solution

Our benchmark model for comparing our Cournot and Stackelberg outcomes is the collusive monopoly outcome.  In the collusive solution, the two firms agree to restrict market output to the monopoly level.  We assume that each produces one-half of this monopoly quantity.

eqPrM = ProfitM == Q(P[Q] - c) ;

eqPrM = Expand[%/. P[Q] -> Price]

focPrM = D[eqPrM, Q]

Qm = Simplify[Q/. Solve[focPrM,Q][[1]]]

Q1m = Qm/2

Q2m = Qm/2

Pmon = Simplify[Price /. Q -> Qm]

pie1m = Simplify[Q1m*(Pmon - c)]

pie2m =pie1m

General Setup for Quantity Games

Total market quantity (Q) is the sum of firm 1's qty (Q1) and firm 2's qty (Q2).

Q = Q1 + Q2 ;

Cournot Game

Similar to the model first ananlyzed by Cournot in 1838, this Cournot quantity game assumes that there are two firms producing identicle goods each at a per unit cost "c".  Because market price is a function of market output (as determined by the inverse demand function) each firm's profits depend on their output choice as well as the output of their competitor.  Therefore, the task of the two firms is to choose their levels of output without knowing the output of the other firm with certainty.  A Nash equilibrium for this game is a set of outputs in which each firm chooses its optimal level of output as a best response to the hypothesized output of its competitor, and each firm's beliefs about its competitor's output is correct.   
Because the Cournot game is a simultaneous move game, it does not matter whether we consider firm 1's or firm 2's optimization problem first.  However, to be consistent with the sequential move Stackelberg game (where order is important) we will consider firm 2's optimization problem first.

Firm 2's payoff is simply its profit.

Firm 2's profits are equal to the difference between the revenue from selling the quantity Q2 and the cost of selling this quantity.  Revenue is firm 2's own quantity (Q2) times market price which is a function of firm 2's own quantity as well as firm 1's quantity (i.e.: P[Q1,Q2]).  Firm 2's total cost of production is quantity Q2 times a constant unit cost c.

eqPr2 = Profit2 == Q2(P[Q1,Q2] - c) ;

Because a linear inverse demand function is given, we want to replace the general form of the price function with the linear demand given above (Price = a - bQ).

In Mathematica % refers to the last result generated (ie: %% uses the 2nd to last result generated) and /. is the replacement identifier.  So below, we take the original profit equation (defined above) and replace the general form of our demand equation P[Q1,Q2] with our explicit linear inverse demand equation "Price" which is specified above.

eqPr2 = Expand[%/. P[Q1,Q2] -> Price]

To find firm 2's profit maximizing quantity define a new equation focPr2 (firm 2's first order condition) to be the derivative (D[ ]) of firm 2's profit (payoff) function with respect to its choice of its own quantity Q2.

focPr2 = D[eqPr2, Q2]

Use the Mathematica Solve statement to solve the first order condition for Q2 and name the output temp2.  It is helpful to note that the output from a solve statement is a list of solutions.  Consequently, temp2 is the name of the list of solutions.  In the case below, the list temp2 has only one solution and therefore a single element.

temp2 = Solve[focPr2, Q2]

It is clear from the first order condition above that firm 2's optimal choice of Q2 will depend on firm 1's optimal choice Q1.  This is the key to game theoretic problems; each party must consider what the other parties will do.  Because firm 2's choice of Q2 is a function of firm 1's choice Q1, we call the expression above firm 2's Best Response or Reaction Function.  As its name implies, this function dictates how firm 2 chooses Q2 as a best response (or in reaction) to firm 1's choice Q1.  In the simply linear case, we can solve for firm 2's best response quantity (R2[Q1]) explicitly.

Note: In the next line of code, we create an expression called React2 (firm 2's reaction function) that represents firm 2's optimal response (R2[Q1]) to firm 1's quantity choice Q1.  The right hand side of this expression is simply the solution for Q2 that we found above.  In other words, R2[Q1] is equal to Q2 where Q2 is replaced ( /. ) by the first solution ( [[1]] ) from the output list "temp2".  R2[Q1] is just another name for Q2 that reflects the fact that this quantity is chosen in response to Q1.

React2 = R2[Q1] == Q2 /. temp2[[1]]

Firm 1's payoff is simply its profit.

In the simultaneous move Cournot game, firm 1 solves for its own Best Response quantity in the same manner as firm 2 has.   
Firm 1's profits are equal to the difference between the revenue from selling its own quantity Q1 and the cost of selling this quantity.

eqPr1 = Profit1 == Q1*(P[Q1,Q2]-c) ;

Once again, because a linear demand function is given, we replace the general form of the price function with the linear demand given above (Price = a - bQ).

eqPr1 = Expand[%/. P[Q1,Q2] -> Price]

To find firm 1's profit maximizing quantity define a new equation focPr1 (firm 1's first order condition) to be the derivative (D[ ]) of firm 1's profit (payoff) function with respect to its choice of its own quantity Q1.

focPr1 = D[eqPr1, Q1]

Use the Mathematica Solve statement to solve the first order condition for Q1 and name the output temp1.

temp1 = Solve[focPr1, Q1];

Note: We name the function relating firm 1's optimal response (R1[Q2]) to firm 2's quantity choice "React1".

React1 = R1[Q2] == Simplify[Q1 /. temp1[[1]]]

Solution to the simply Cournot Game.

At this point we have the reaction functions (or best response functions) for both of the Cournot firms.  Each of these functions specifies how the firm will choose its optimal quantity in response to the quantity choice of the other firm.  If we knew firm 1's choice of Q1 we could solve firm two's reaction function for its optimal choice of Q2.  Similarly, if we knew firm 2's choice Q2 we could solve firm one's reaction function for its optimal choice of Q1.  The difficulty with the Cournot game is that the players simultaneously choose their respective quantities.  Therefore, the solution to the simultaneous move Cournot game is found by solving both firms' reaction functions simultaneously for the quantities Q1 and Q2.  Intuitively, the solution to the Counot game has each firm choosing its best response quantity in reaction to the hypothesized quantity of the other firm.

The Solve statement is used to simultaneously solve the two reaction functions which we have called React1 and React2 for the optimal quantities Q1 and Q2.  NOTE: Before solving these simultaneous equations, it is necessary to first rename firm 1's best response quantity, R1[Q2], to be Q1 and to rename firm 2's best response quantity, R2[Q1], to be Q2.

cournotQ = Simplify[   
	      Solve[{React1 /. R1[Q2] -> Q1,   
		     React2 /. R2[Q1] -> Q2},   
		    {Q1, Q2}]]

Because we eventually want to compare the results from this Cournot game to the results form a Stackelberg game, we rename the optimal outputs for firms one and two from the Cournot game to be Q1c and Q2c respectively.

In Mathematica this is accomplished be creating a new variable Q1c that is equal to Q1 where Q1 is replaced ( /. ) with its first solution value ( [[1]] ) from the previous line of output ( % ).  Similarly, the new variable Q2c is set equal to Q2 where Q2 is replaced ( /. ) with its first solution value ( [[1]] ) from the second to last line of output ( %% ) .

Q1c = Q1 /.%[[1]] ;

Q2c = Q2 /.%%[[1]] ;

The resulting market quantity and market price for the Cournot game are calculated by substituting the firms' optimal quantities into the quantity and price equations.

Note: In the next two input lines we replacing a list of variables (not a single variable substitution).  The Mathematica syntax requires that, following the replacement  switch ( /. ), your list of replacements be enclosed in brackets, { }, and that the individual substitutions be separated by commas.

Qcour = Q /.{Q1 -> Q1c, Q2 -> Q2c}

Pcour = Simplify[Price /.{Q1 -> Q1c, Q2 -> Q2c}]

The profits from playing the Cournot Game to firm 1 and firm 2 respectively are:

pie1c = Simplify[Q1c*(Pcour - c)]

pie2c = Simplify[Q2c*(Pcour - c)]

SENSATIVITY ANALYSIS: This 3-D plot shows sensativity of Cournot firm profits to the parameters of the market demand function.

Pieplot = Plot3D[pie2c /. c -> .005, {a, .1, 2}, {b, .001, .01},   
         ViewPoint -> {3.4,2.4,2},AxesLabel -> { a, b, Qty}]

Stackelberg Quantity Game

Stackelberg quantity games are similar to Cournot games in that both are quantity competitions.  In the Stackelberg game, however, firms do not choose quantities simultaneously.  Instead, a dominant firm (or Stackelberg leader) moves first by choosing its level of output in the first stage.  After observing the leader's move the other firm chooses its best response output in the second stage.  As we will see, the sequential play will require a different methodology and produces different results than those of the simultaneous move Cournot game.

Setup for the problem.

Clear[a,b,c,temp1,temp2];   
Clear[Q1,Q2,eqPr1,eqPr1,focPr1,focPr2,R2,pie1s,pie2s];

Firm 2: the Stackelberg follower

As is typical with sequential games, we will solve the Stackelberg game backwards.  Thus we begin to solve the problem by characterizing how the Stackelberg follower (firm 2) will respond to the Stackelberg leader's choice of quantity.

eqPr2 = Profit2 == Q2*(P[Q1,Q2]-c)

eqPr2 = Expand[%/. P[Q1,Q2] -> Price]

In Mathematica % refers to the last result generated (ie: %% uses the 2nd to last result generated) and /. is the replacement identifier.  So here we take the original profit equation and replace the general form of our demand equation P[Q1,Q2] with our explicit linear demand equation Price.   
In the next line of code, we define a new equation focPr2 (firm 2's foc) to be the derivative (D[ ]) of firm 2's profit (payoff) function with respect to its choice of its own quantity Q2.

focPr2 = D[eqPr2, Q2]

In the simply linear case, we can solve for firm 2's best response quatity explicitly as a function of firm 1's quantity choice.

temp2 = Solve[focPr2, Q2]

React2 = R2[Q1] == Simplify[Q2 /. temp2[[1]]]

Note:  This is the same reaction function that we found for firm 2 in the Cournot game.  In the Stackelberg problem there is on important caveate:  Recall from the Cournot game that R2[Q1] was interpreted as firm 2's best response to firm 1's anticipated output Q1.  In the Stackelberg game, firm 2 knows Q1 for certain since it observed Q1 at the end of stage 1.  Therefore, firm 2 will respond to firm 1's observed output Q1 by producing:

Q2s = Simplify[R2[Q1] /.Solve[React2, R2[Q1]][[1]]]

Firm 1: the Stackelberg leader

eqPr1 = pie1s == Q1*(P[Q1,Q2]-c)

eqPr1 = %/. P[Q1,Q2] -> Price

Because firm 1 can solve for firm 2's best response quantity as well as firm 2 can, firm 1 will anticipate firm 2's reaction to any choice of Q1.  Thus firm 1 solves the following:

eqPr1 = Simplify[%/. Q2 ->Q2s]

focPr1 = Simplify[D[eqPr1, Q1]]

Solution to the simply Stackelberg Game.

The solution to the Stackelberg game has the Stackelberg leader (firm 1) choosing its optimal quantity:

Q1s = Simplify[Q1 /.Solve[focPr1, Q1][[1]]]

Firm 2 (the follower) takes firm 1's quantity choice as given and reacts by choosing:

Q2s = Simplify[Q2s /. Q1 ->Q1s]

The resulting market quantity and market price are calculated by substituting the firms' optimal quantities into the quantity and price equations.

Qstack = Q /. {Q1 -> Q1s, Q2 -> Q2s}

Pstack = Simplify[Price /. Q -> %]

The profits from playing the Stackelberg Game to firm 1 and firm 2 respectively are:

pie1s = Simplify[Q1s*(% - c)]

pie2s = Simplify[Q2s*(%% - c)]

Comparing the Cournot & Stackelberg Outcomes

Price and Output Comparisons.

Market output of the Cournot game differs from the Collusive outcome by the following percentage:

sizeQc = N[(Qcour/Qm-1)*100]

Firm 1's output from the Cournot game differs from the Collusive outcome by the following percentage:

sizeQ1c = N[(Q1c/Q1m-1)*100]

Firm 2's output from the Cournot game differs from the Collusive outcome by the following percentage:

sizeQ2c = N[(Q2c/Q2m-1)*100]

Market output of the Stackelberg game differs from the Collusive outcome by the following percentage:

sizeQs = N[(Qstack/Qm-1)*100]

Firm 1's output from the Stackelberg game differs from the Collusive outcome by the following percentage:

sizeQ1s = N[(Q1s/Q1m-1)*100]

Firm 2's output from the Stackelberg game differs from the Collusive outcome by the following percentage:

sizeQ2s = N[(Q2s/Q2m-1)*100]

Firm 1's profits from the Cournot game differ from its Collusive profits by the following percentage:

sizePie1c = N[(pie1c/pie1m-1)*100]

Firm 2's profits from the Cournot game differ from its Collusive profits by the following percentage:

sizePie2c = N[(pie2c/pie2m-1)*100]

Firm 1's profits from the Stackelberg game differ from its Collusive profits by the following percentage:

sizePies = N[((pie1s + pie2s)/(2*pie1m)-1)*100]

Firm 1's profits from the Stackelberg game differ from its Collusive profits by the following percentage:

sizePie1s = N[(pie1s/pie1m-1)*100]

Firm 2's profits from the Stackelberg game differ from its Collusive profits by the following percentage:

sizePie2s = N[(pie2s/pie2m-1)*100]

The output results above can also be represented graphically with pie charts.

Clear[a,b,c];   
Clear[Q1,Q2,eqPr1,eqPr1,focPr1,focPr2,R2];   
a = 0.43714 ;   
b = 0.00257 ;   
c = 0.005   ;   
QmQs_Ratio = .4*(Qm)/(Q1s + Q2s);  
QcQs_Ratio = .4*(Q1c + Q2c)/(Q1s + Q2s);

Show[Graphics[  
	{Text["Cournot", {0,.5}],   
	{RGBColor[0,0,1],   
	  Disk[{0,0},% ,{0,Q1c/(Q1c +Q2c)*360 Degree}]   
	},   
	 {RGBColor[1,1,1],   
	  Disk[{0,0},% ,{180 Degree,360 Degree}]   
	},   
	 Circle[{0,0},% ],   
	   
	Text["Collusive", {2,.5}],   
	{RGBColor[0,0,1],   
	  Disk[{2,0},%%,{0,180 Degree}]   
	},   
	 {RGBColor[1,1,1],   
	  Disk[{2,0},%%,{180 Degree,360 Degree}]   
	},   
 	 Circle[{2,0},%%],  
  
	Text["Stackelberg", {1,.5}],   
	{RGBColor[0,0,1],   
	  Disk[{1,0},.4,{0,Q1s/(Q1s +Q2s)*360 Degree}]   
	},   
	 {RGBColor[1,1,1],   
	  Disk[{1,0},.4,{Q1s/(Q1s +Q2s)*360 Degree,360 Degree}]   
	},   
 	 Circle[{1,0},.4]   
	}], AspectRatio -> Automatic, PlotLabel ->   
	FontForm["OUTPUT: firm 1 = Blue", {"Helvetica-Bold",12}]]

PieM_Ratio = (2*pie1m)/(pie1s + pie2s);  
PieC_Ratio = (pie1c + pie2c)/(pie1s + pie2s);

Show[Graphics[   
	{Text["Cournot", {0,2}],   
	{RGBColor[0,1,0],   
	  Disk[{0,0},% ,{0,pie1c/(pie1c +pie2c)*360 Degree}]   
	},   
	 {RGBColor[1,1,1],   
	  Disk[{0,0},% ,{180 Degree,360 Degree}]   
	},   
	 Circle[{0,0},% ],   
	   
	Text["Collusive", {6,2}],   
	{RGBColor[0,1,0],   
	  Disk[{6,0},%%,{0,180 Degree}]   
	},   
	 {RGBColor[1,1,1],   
	  Disk[{6,0},%%,{180 Degree,360 Degree}]   
	},   
 	 Circle[{6,0},%%],  
  
	Text["Stackelberg", {3,2}],   
	{RGBColor[0,1,0],   
	  Disk[{3,0},1.0,{0,pie1s/(pie1s +pie2s)*360 Degree}]   
	},   
	 {RGBColor[1,1,1],   
	  Disk[{3,0},1.0,{pie1s/(pie1s +pie2s)*360 Degree,360 Degree}]   
	},   
 	 Circle[{3,0},1.0]   
	}], AspectRatio -> Automatic, PlotLabel ->   
	FontForm["Profit: firm 1 = green", {"Helvetica-Bold",12}]]

Graphical Representation of Cournot/Stackelberg Games

Isoprofit Curves:

eqPr1c = Simplify[Q2 /. Solve[   
	pie1c == Q1*(P[Q1,Q2]-c) /. P[Q1,Q2] -> Price, Q2][[1]]] ;

eqPr2ca = Simplify[Q2 /. Solve[pie2c == Q2*(P[Q1,Q2]-c)    
	  /. P[Q1,Q2] -> Price, Q2][[1]]] ;

eqPr2cb = Simplify[Q2 /. Solve[pie2c == Q2*(P[Q1,Q2]-c)    
	  /. P[Q1,Q2] -> Price, Q2][[2]]] ;

eqPr1s = Simplify[Q2 /. Solve[pie1s == Q1*(P[Q1,Q2]-c)    
	 /. P[Q1,Q2] -> Price, Q2][[1]]] ;

eqPr2sa = Simplify[Q2 /. Solve[pie2s == Q2*(P[Q1,Q2]-c)    
	 /. P[Q1,Q2] -> Price, Q2][[1]]] ;

eqPr2sb = Simplify[Q2 /. Solve[pie2s == Q2*(P[Q1,Q2]-c)    
	 /. P[Q1,Q2] -> Price, Q2][[2]]] ;

isoPlot = Plot[   
	{eqPr1c,eqPr1s,eqPr2ca,eqPr2cb,eqPr2sa,eqPr2sb},   
	{Q1, .01, (a-c)/b},  
	PlotRange -> {0, (a-c)/b},  
	AxesLabel->{"Q1","Q2"}  
	]

Reaction Curves:

Solve[React2,R2[Q1]]

Solve[React1 /. R1[Q2] -> Q1, Q2][[1]]

reactPlot = Plot[   
	{R2[Q1] /.%%[[1]], Q2  /. %[[1]]},   
	{Q1, 0, (a-c)/b},   
	PlotRange -> {0, (a-c)/b},   
	PlotStyle->{{RGBColor[0,0,1],Thickness[0.001]},   
		    {RGBColor[1,0,0],Thickness[0.001]}},   
	AxesLabel->{"Q1","Q2"},   
	PlotLabel->"Reaction Curves"]

Complete Graphic:

Show[isoPlot, reactPlot]

a =.   
b =.   
c =.