Monopoly Probe and Adjust

No preview image

1 collaborator

Default-person Steven Kimbrough (Author)

Tags

"probe and adjust" 

Tagged by Steven Kimbrough over 8 years ago

markets 

Tagged by Steven Kimbrough over 8 years ago

monopoly 

Tagged by Steven Kimbrough over 8 years ago

Visible to everyone | Changeable by the author
Model was written in NetLogo 5.0.3 • Viewed 425 times • Downloaded 36 times • Run 0 times
Download the 'Monopoly Probe and Adjust' modelDownload this modelEmbed this model

Do you have questions or comments about this model? Ask them here! (You'll first need to log in.)


WHAT IS IT?

This model explores how a monopolist might discover the "monopoly quantity" (the quantity that maximizes profit for the monopolist agent) in the face of, here, a linear demand function.

Quantity is being adjusted and quantity is a continuous variable. This program uses what I call a "Probe and Adjust" model, and a very simple one at that. The agent begins with a current value, here currentQuantity, set by initialQuanity in the Interface tab. Play is organized by epochs, each containing a number of episodes. In each episode, the agent probes its market by offering a quantity in the range [currentQuantity - delta, currentQuantity + delta]. The agent records the revenue it gets form the probe, classifying the revenue as coming from a quantity offered that is either above or below the currentQuantity. When the epoch is over (a number of episodes, set by epochLength in the Interface tab), the agent determines whether on average it did better by offering more than the currentQuantity or less. Depending on the results, it increases its currentQuantity by epsilon or decreases it by epsilon. Then a new epoch begins. Both delta and epsilon are set in the Interface. The key point about this model is that the agent does not have access to the demand function, except as it responds to probing.

Introductory textbooks in microeconomics will tell the story roughly as follows. Suppose, for the sake of simplicity that the product in question can be produced at 0 cost. (Extensions of the model can be made for non-zero costs. The results will not be terribly sensitive to this.) The market's demand, Q (think: quantity demanded), for our product is a linear function of its price, P:

(1) Q(P) = Q = c - b*P

Here, c is a constant, representing the quantity demanded when price is 0 and, since we are linear, the price point at which demand disappears when the price is too high (when b*P = c). Rearranging (1) we get:

(2) P(Q) = P = a - dSlope*Q

where a = c/b and dSlope = 1/b. (We assume that dSlope > 0, so -dSlope < 0.)

The profit, pi, made by the monopolist is PQ (since the cost of production is 0, we need only account for revenue, which is defined here as PQ).

(3) pi = PQ = (a - dSlopeQ)Q = aQ - dSlopeQ*2

The monopolist will seek to maximize pi, which can be done by a simple exercise with the calculus.

(4) dpi/dQ = a - 2dSlopeQ

Setting a - 2dSlopeQ to zero and solving for Q yields

(5) Q = a/(2*dSlope)

So Q in (5) is Q*, the optimal quantity for the monopolist to put on the market.

(Checking that d2 pi/dQ2 = -2*dSlope < 0 verifies that we indeed have found a maximum.)

See, for example, IntermediateMicroeconomics:AModernApproach, 6th ed., by Hal. R. Varian. I draw explicitly on MicroeconomicTheory, 2nd ed., 1978, The Dryden Press, Hinsdale, Illinois, by Walter Nicholson. See "Appendix to Chapter 13: Models of Interdependent Output Decisions," pp. 389-398. Nicholson's is the more advanced text. My treatment generalizes his discussion. Kreps's _ACourseinMicroeconomicTheory, 1990, is excellent and more advanced.

HOW IT WORKS

The program variable slope corresponds to slope in equation (2). A slider on the Interface sets its value. The program variable qIBase (quantity-intercept, basic or initial) is the value of Q (quantity) at which P (price) equals 0. A slider on the Interface sets its value. See equation (2). So, a = dSlope*qIBase.

Put slightly differently, the demand function can be expressed as

Price(Quantity) = Price = priceIntercept - (dSlope * Quantity)

From the Interface tab we are given at initialization:

dSlope

and

qIBase

qIBase is the initial value of quantityIntercept. The program uses dSlope and qIBase to solve for priceIntercept, since:

0 = priceIntercept - (dSlope * quantityIntercept)

This gives us priceIntercept and dSlope, from which we can compute Price given a Quantity via the above equation, reproduced here:

Price(Quantity) = Price = priceIntercept - (dSlope * Quantity)

(Note on notation: Price and Quantity are variables, priceIntercept and dSlope are constants.)

Play is organized by epochs. There is a series of probes by the monopolist within each epoch, one probe per episode (market transaction). When the number of probes (episodes) is large enough (>= epochLength), the epoch concludes, adjustments are made, and a new epoch begins.

HOW TO USE IT

random-as is an On-Off switch. When it is off, the demand curve is set and fixed throughout the run, determined by q-i (initial quantity intercept) and slope. When random-as is on, then at the beginning of each probe (play) in an episode, quantity-intercept is randomly perturbed. There are two ways this might be done.

First, if the On-Off switch for random-walk-as is on, quantity-intercept is randomly reset uniformly between the current value of quantity-intercept plus a-delta and the current value of quantity-intercept minus a-delta. Second, if the On-Off switch for random-walk-as is off, quantity-intercept is randomly reset uniformly between the current value of q-i plus a-delta and the current value of q-i minus a-delta. In either case, the value for price-intercept is recalculated/reset, as are m-quantity and m-price.

RUNNING THE MODEL

On the Interface tab, click the setup button, then click the go button. The model will run until you click the go button again to stop it.

The Interface tab offers a number of sliders and switches for setting run parameter values.

initialQuantity

Sets the base, or anchor, quantity the monopolist agent uses during its first episode. As in all episodes, the agent has a base value for quantity and it probes by offering to the market quantities that are somewhat above or below this base quantity.

episodeLength

Sets the number of samples the monopolist agent takes before considering an adjustment of its base quantity value. The agent samples until the number of samples is greater than or equal to episodeLength. Then the agent adjusts its base quantity and a new episode begins.

daRandomSeed

Picking an item with this chooser determines how the random number generator is to be initialized for the run. Picking "system clock" lets NetLogo do the initialization. This will result in a different random number stream for each run. Picking a number results in the random number generated with that number, resulting in an identical random number stream for each run. This is useful for comparison and communication purposes. Also, note that the chooser is user-editable, so it it possible to add and delete entries.

random-as, random-walk-as

Price = a - dSlope*Quanity. dSlope is set by the interface slider:

dSlope

and a is the price intercept for the demand function (the value of the demand function when Quantity = 0. The initial value of the quantity intercept (the value of Quantity when Price = 0) is set with the Interface tab slider

qIBase

At initialization (in setup) qIBase is read into the program variable quantityIntercept.

aDelta

When random-as is on and random-walk-as is off, quantityIntercept is randomly changed each period by uniformly drawing in [quantityIntercept - aDelta, quantityIntercept + aDelta].

When both random-as is on and random-walk-as is on, quantityIntercept is randomly change each period as follows:

quantityIntercept(t+1) = U[-aDelta, aDelta] + quantityIntercept(t)

THINGS TO NOTICE

This section could give some ideas of things for the user to notice while running the model.

/* here, I need to say more */

THINGS TO TRY

Leave debug-switch off.

1) Simple example.

delta 3.0
epsilon 1.0
q-i 200
slope 2.0
fine-grained ON
initialQuantity 115.0
random-as Off
a-delta -
random-walk-as -
repeated-sampling Off

Quickly finds the static optimum quantity and bounces around, a little above and below. Experiment with reducing epsilon. Once the agent gets in the neighborhood of the static optimum, reduce epsilon, say to 0.1. The agent, of course, doesn't know the demand function. Is there a way the agent could sense that epsilon is too big (or too small)? Yes!

2) Random walk example

delta 3.0
epsilon 2.0
q-i 200
slope 2.0
fine-grained ON
initialQuantity 100
random-as On, random-seed 17
a-delta 0.9
random-walk-as On
repeated-sampling Off

EXTENDING THE MODEL

This section could give some ideas of things to add or change in the procedures tab to make the model more complicated, detailed, accurate, etc.

NETLOGO FEATURES

This section could point out any especially interesting or unusual features of NetLogo that the model makes use of, particularly in the Procedures tab. It might also point out places where workarounds were needed because of missing features.

RELATED MODELS

This section could give the names of models in the NetLogo Models Library or elsewhere which are of related interest.

CREDITS AND REFERENCES

This model was created and written by Steven O. Kimbrough: kimbrough at wharton.upenn.edu and http://opim-sky.wharton.upenn.edu/~sok/. The model is
freely downloadable at:
http://opim-sky.wharton.upenn.edu/~sok/agebook/applications/nlogo/monopolyProbeAndAdjust.nlogo

Please give me credit if you use this model or program.

To refer to this model in academic publications, please use: Kimbrough, Steven O. (2007). Monopoly Probe and Adjust
model. http://opim-sky.wharton.upenn.edu/~sok/agebook/applications/nlogo/monopolyProbeAndAdjust.nlogo University of Pennsylvania, Philadelphia, PA 19004, USA.
In other publications, please use: Copyright 2007 Steven O. Kimbrough. All
rights reserved.

$Id: MonopolyProbeAndAdjust.nlogo 4082 2014-03-20 00:40:40Z sok $

Comments and Questions

Please start the discussion about this model! (You'll first need to log in.)

Click to Run Model

globals [pstar current-price price-intercept m-price epochOver
         up-data down-data total-revenue probe-count ;episodeLength 
         quantityIntercept
         up-prices down-prices ;monop-prices 
         monop-quantities
         m-up-prices m-dn-prices m-up-revs m-dn-revs
         up-as down-as currentQuantity m-quantity initial-m-quantity initial-m-price initial-price
         version ; CVS (or Subversion) version string
         ]

to setup
set version "$Id: MonopolyProbeAndAdjust.nlogo 4082 2014-03-20 00:40:40Z sok $"
if (daRandomSeed != "system clock")
  [random-seed daRandomSeed]
  
set  quantityIntercept qIBase

set currentQuantity initialQuantity

set price-intercept daPriceIntercept(quantityIntercept)(dSlope)
set current-price (price-intercept - (dSlope * initialQuantity))
set initial-price current-price
set m-quantity daMQuantity ; (price-intercept / ( 2 * slope)) ; set the monopoly quantity
set initial-m-quantity m-quantity
set initial-m-price (price-intercept - (dSlope * initial-m-quantity))

set m-price getMPrice(price-intercept)(dSlope)(m-quantity)
clear-all-plots
plot-quantity-price(current-price)
set epochOver false
set up-data []
set up-prices []
set down-data []
set down-prices []
set monop-quantities []
set m-up-prices []
set m-dn-prices []
set m-up-revs []
set m-dn-revs []
set up-as []
set down-as []
set total-revenue 0
set probe-count 0
end 

to go
let probe 0
  let myRevenue 0
  
while [not epochOver]
[ 
; If random-as, that is if a in the demand function, = a + b*p, is to be be set 
; via random walk, then
; figure out the new demand curve.
if (random-as)
  [ 
   ifelse (random-walk-as)
   [set quantityIntercept (random-float 2 * aDelta) - aDelta + quantityIntercept]
   [set quantityIntercept (random-float 2 * aDelta) - aDelta + qIBase] ;quantityIntercept
  set price-intercept daPriceIntercept(quantityIntercept)(dSlope) ; quantityIntercept * slope
  set m-quantity daMQuantity ; quantityIntercept / (2 * slope) 
  set m-price getMPrice(price-intercept)(dSlope)(m-quantity)
  ] ; end of if (random-as)

; repeated-sampling. If On, our new probe is currentQuantity plus or minus delta.
; If Off, our new probe ranges uniformly between currentQuantity plus and minus delta.
ifelse (repeated-sampling) 
[set probe (random-float 1)
 ifelse (probe <= 0.5)
   [set probe currentQuantity - delta]
   [set probe currentQuantity + delta]] ; end of if in ifelse(repeated-sampling)
[set probe (random-float 2 * delta) - delta + currentQuantity] ; end of ifelse repeated-sampling


 set current-price (price-intercept - (dSlope * probe))
 set probe-count probe-count + 1
 set myRevenue daRevenue(probe)
 set total-revenue total-revenue + myRevenue ; daRevenue(probe)  
 ifelse (probe >= currentQuantity) 
   [set up-data lput myRevenue up-data]   
   [set down-data lput myRevenue down-data]
   
 if (fine-grained)
   [plot-quantities(currentQuantity)(m-quantity)]
 
; if (length up-data > episodeLength and length down-data > episodeLength)
 if (length up-data + length down-data >= epochLength)
   [set epochOver true]
   
] ; end of do while 

if (epochOver)
[ifelse (mean up-data >= mean down-data) 
  [set currentQuantity (currentQuantity + epsilon)]
  [set currentQuantity (currentQuantity - epsilon)]
 
  if (not fine-grained)
    [plot-quantities(currentQuantity)(m-quantity)]
  
  set epochOver false
  set up-data []
  set down-data []

  ] ; end of if(epochOver)
end 

to plot-quantity-price [daPrice]
set-current-plot "quantity-price"
clear-plot
set-plot-y-range 0 price-intercept 
set-plot-x-range 0 quantityIntercept 
set-current-plot-pen "Demand Curve"
plot-pen-up
plotxy 0 price-intercept
plot-pen-down
plotxy quantityIntercept 0
set-current-plot-pen "Monopoly Quantity"
plot-pen-up
plotxy m-quantity 0
plot-pen-down
plotxy m-quantity m-price
set-current-plot-pen "Monopoly Price"
plot-pen-up
plotxy 0 m-price
plot-pen-down
plotxy m-quantity m-price
end 

to-report daRevenue [daQuantity] ; [daPrice]
  let daPrice 0
  
  set daPrice (price-intercept - (dSlope * daQuantity))
  report daPrice * daQuantity
end 

to-report daPriceIntercept [q-intercept daSlope]
  set price-intercept (q-intercept * daSlope) 
  report price-intercept
end 

to-report daMQuantity
  set m-quantity (price-intercept / ( 2 * dSlope))
  report m-quantity
end 

to-report getMPrice [da-price-intercept da-slope da-m-quantity]
  report (da-price-intercept - (da-slope * da-m-quantity)) 
end 

to plot-quantities [daQuantity mono-quant]
set-current-plot "Monopoly and Current Quantities"
set-current-plot-pen "Agent's Quantity"
plot daQuantity 
set-current-plot-pen "Monopoly Quantity"
plot mono-quant 
end 

to debug
let probe 0
  
if (random-as)
  [ set quantityIntercept (random-float 2 * aDelta) - aDelta + qIBase ;quantityIntercept
  set price-intercept quantityIntercept / dSlope
  set m-price quantityIntercept / (2 * dSlope)
  ;set monop-prices lput m-price monop-prices
  ] ; if of if (random-as)
set probe (random-float 2 * delta) - delta + current-price
show (word "a = "  quantityIntercept)
show (word "price intercept = "  price-intercept)
show (word "dSlope = "  dSlope)
show (word "monopoly price = "  m-price)
show (word "monopoly demand = "  (quantityIntercept - dSlope * m-price) )
show (word "monopoly revenue = "  daRevenue(m-price) )
show (word "current-price = "  current-price)
show (word "probe = "  probe)
show (word "probe revenue = "  daRevenue(probe))
end 

There is only one version of this model, created over 8 years ago by Steven Kimbrough.

Attached files

No files

This model does not have any ancestors.

This model does not have any descendants.