# Monopoly Probe and Adjust

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 P*Q (since the cost of production is 0, we need only account for revenue, which is defined here as P*Q).

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

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

(4) dpi/dQ = a - 2*dSlope*Q

Setting a - 2*dSlope*Q 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 d**2 pi/dQ**2 = -2*dSlope < 0 verifies that we indeed have found a maximum.)

See, for example, *Intermediate*Microeconomics:*A*Modern*Approach*, 6th ed., by Hal. R. Varian. I draw explicitly on *Microeconomic*Theory*, 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 _A*Course*in*Microeconomic*Theory*, 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

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 about 8 years ago by Steven Kimbrough.

## Attached files

No files

This model does not have any ancestors.

This model does not have any descendants.