# IranBargaining

No preview image

### 1 collaborator

Steven Kimbrough (Author)

### Tags

bargaining

"This is an example of an agent-based bargaining model."

Tagged by Steven Kimbrough about 8 years ago

group decision forecasting

"This is a particular model in the class of group decision forecasting models."

Tagged by Steven Kimbrough about 8 years ago

group decision prediction

Tagged by Steven Kimbrough about 8 years ago

Visible to everyone | Changeable by the author
Model was written in NetLogo 5.0.5 • Viewed 488 times • Downloaded 45 times • Run 0 times

## WHAT IS IT?

The IranBargaining NetLogo model implements group decision making models for an example discussed in:

Bueno de Mesquita, Bruce. "Forecasting Policy Decisions: An Expected Utility
Approach to Post-Khomeini Iran" PS, vol. 17, No. 2 (spring 1984), pp. 226-236.
Available from JSTOR: http://www.jstor.org/stable/418786.


The Bueno de Mesquita paper does not specify the decision models actually employed to make the predictions reported in the paper. A good conjecture is some form of generalized voting model, which is what we explore here in the IranBargaining model.

In addition to merely implementing conjectured decision models, the IranBargaining NetLogo model provides three post-solution analysis features, which can be used for analyzing the decision models. Moreover, the IranBargaining model is generic in the sense that it can be used for group decision prediction (GDP) problems that are similar to Bueno de Mesquita's formulation of the Iranian decision problem.

## BACKGROUND

Bueno de Mesquita (1984) provides a well-known instance of using voting models to forecast negotiated outcomes. We are, of course, aware of controversy attached to this paper; resolving this controversy is well beyond the scope of this NetLogo model. Instead, we present (Bueno de Mesquita 1984) as an example (a particularly accessible example) of how modeling can be, and in fact is, used to provide insight on the important area of forecasting negotiation outcomes.

Published during the Iran-Iraq War (1980-1988; aka the First Persian Gulf War) and seeking to model decision making on the Iranian side, the paper identifies 27 agents of interest (which he calls groups), of which 18 are actually used in his model to predict the position eventually arrived at by these agents.

Each of the agents is given a two or three letter abbreviation for its name, e.g., SC for Supreme Court, LCR for Lower Class Rural Peasants; see Table 1 in (Bueno de Mesquita 1984) for the full listing. We use these abbreviations in the input data file for the case (BuenodeMesquita1984.txt) to identify the agents in the models; for the purpose of our explanation the true identity of these agents is not important. In his paper Bueno de Mesquita forecasted that the war would continue but in a more economical fashion with the hardliners of MON, TMC and QUM sidelined. In the end, the fighting on the battlefield ended only in August 1988 with Resolution 598, a UN-brokered ceasefire, but the hostilities continued into the peace-negotiating chamber until a peace was finally signed in 1990.

In line with our description of how agents hold opinions, (Bueno de Mesquita 1984) assigns three numeric data values to each agent. He calls them issue position, salience, and influence. These map to our introduced terminology. What we call exercised power will be modeled as the product of the influence and salience values from Bueno de Mesquita's data.

## POST-SOLUTION ANLAYSIS

It is a commonplace among modelers that the real work for decision making begins after a model has been conceived, designed, implemented, tested, validated, and exercised to obtain a solution. The term post-solution analysis refers to what is done during this phase of the modeling life-cycle. See the accompanying paper/chapter for a general discussion.

The IranBargaining model implements three very general capabilities for post-solution analysis. What-if is the first of these capabilities.

Using the what-if features of the NetLogo model the user may change one or more parameter values and then execute an associated model to see what the effect is of the change(s). If, for example, we change the influence value of agent JC from its default value of 11.3 to 24.9 and execute model 1, we will see that the position predicted of the group changed from PRE to JC. The increase in JC's influence has been sufficient to alter the outcome of the group's deliberations, according to the model.

Second, a form of individual exploration analysis is supported in the IranBargaining Netlogo model with the code associated with the "Individual exploration" button, labeled (6) in the display.

Try executing individual exploration on model 1 with an exploration range of 177 percent on the salience values for the 18 agents. The meaning of the resulting output, shown in white lettering on a black background in the view, is as follows. The left-hand column of the output arrays the short names of the 18 agents in the data for model 1. The order is in their position values, increasing downwards. So UMC has the smallest position value and QUM the largest. The values in the right-hand column are the decisions reached by the model when the corresponding agent in the left-hand column has its salience score enlarged by 177 percent. For example, for REV in the left-hand column, we find JC in the right-hand column. This means that if we keep the input data (perhaps as changed by what-if operations) constant, but increase the salience value for REV by 177 percent, then the group is predicted to resolve its decision by choosing the JC position. If, for example, we set the exploration range to 177 percent on the salience values for the 18 agents we get a report whose meaning is as follows. For each of the 18 positions we see the decision reached by the model when the corresponding agent has its salience score enlarged by 177 percent. For example, for REV, we find JC is the new decision. This means that if we keep the input data (perhaps as changed by what-if operations) constant, but increase the salience value for REV by 177 percent, then the group is predicted to resolve its decision by choosing the JC position.

Overall, what the NetLogo model model is telling us here is that even with such a large change PRE still occurs most often. However, there are several cases in which it is altered. Note that the output reported contains information from 18 distinct solutions of model 1. This is valuable not only for saving analyst time by avoiding a one-a-time what-if analysis; it also presents a higher-level pattern for viewing by the analyst and decision makers. This is a simple instance of application of the principle of solution pluralism for post-solution analysis.

In individual exploration we systematically make changes to one variable at a time and observe the behavior of the model. In group sampling exploration we randomly change a number of variables at once and record the behavior of the model. We repeat this process a large number of times and observe the distribution or pattern of behavior of the model.

A form of group sampling exploration analysis is supported in the IranBargaining NetLogo model. with the code associated with the "Group sampling exploration" button, labeled (7b) on the Interface tab. Try executing group sampling exploration on model 1 with an exploration range of plus or minus 75 percent on the salience values for the 18 agents. For example, if we set the exploration range to plus or minus 75 percent on the salience values for the 18 agents we can get a report of the consequences.

The meaning of the report, shown in white lettering on a black background in the view, is as follows. The left-hand column of the output arrays the short names of the 18 agents in the data for model 1. The order is in their position values, increasing downwards. So UMC has the smallest position value and QUM the largest. The values in the right-hand column are the number of times the decisions reached by the model for the corresponding agent position in the left-hand column. This is under perturbation of the salience values in which the salience value for every agent is randomly perturbed in its $\pm$75 percent range and model 1 is executed to predict an outcome. For example, for REV in the left-hand column, we find 2 in the right-hand column. This means that in 10,000 trials (see "NumTrials" on the Interface, labeled (7a)) exactly 2 produced joint salience values resulting in a predicted position of REV as the outcome.

Overall, what the NetLogo model model is telling us here is that even with such a large change PRE still occurs about 70 percent of the time. However, there is definitely a distribution of outcomes. JC will occur about 20 percent of the time and the other outcomes are concentrated on the high side (lower in the display) of the PRE position (i.e., favoring vigorously pursuing the war).

## RELATED MODELS

Here are helpful files/tutorials from the NetLogo models library: File Input Example File Output Example

## INPUT FILE FORMAT

Here is a valid input file for this model. In fact it contains the data extracted from the Bueno de Mesquita 1984 article that is used as the default data with "load-default-data".

Bueno d Mesquita article PS, vol. 17, No. 2 (spring 1984), pp. 226-236.
"Agent" "Position" "Salience" "Influence"
"UMC" 0.0 0.8 1.1
"TEC" 0.0 2.5 0.6
"MCR" 2.1 2.5 0.9
"SOV" 3.0 10.3 0.6
"PM" 4.7 6.8 9.0
"BAZ" 5.1 0.8 5.6
"REV" 5.1 8.5 12.4
"JC" 5.1 10.3 11.3
"PRE" 6.4 10.3 10.7
"UP" 7.3 2.5 4.5
"LCR" 7.3 3.4 4.5
"KUR" 8.6 4.3 2.3
"COM" 9.8 8.5 11.8
"SC" 11.1 6.0 4.5
"CG" 11.1 4.3 9.0
"MON" 12.4 9.4 0.1
"TMC" 12.4 9.4 3.4
"QUM" 12.4 9.4 4.5


Points arising:

1. The first line should not be empty. It can be as long as you wish.
2. The second line should be exactly as shown here.
3. The third line begins the actual data. You should follow the format shown:
1. Four items per line, separated by spaces.
2. The first item should be a string in quotes.
3. Items 2 through 4 should be numbers
4. All items should be separated by spaces.
4. Do not start a new (empty) line after the last data line.
5. You may have as many data lines as you wish. However, the world and its view are currently configured to have no more than 18 data lines. If you need more, you will need to adjust the world and its view.

## HOW TO CITE

If you mention this model in a publication, we ask that you include these citations for the model itself and for the NetLogo software:

• Kimbrough, Steven O. (2014). NetLogo Iran Bargaining model. University of Pennsylvania, Philadelphia, PA. IranBargaining.nlogo

Copyright 2014 Steven O. Kimbrough.

This work is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 3.0 License. To view a copy of this license, visit http://creativecommons.org/licenses/by-nc-sa/3.0/ or send a letter to Creative Commons, 559 Nathan Abbott Way, Stanford, California 94305, USA.

Support for this model, in part, was provided by KAPSARC, http://www.kapsarc.org. We gratefully acknowledge the support.

Version: $Id: IranBargaining.nlogo 4264 2014-07-20 21:45:22Z sok$.

## Comments and Questions

Click to Run Model

extensions [matrix]
globals [input-data agents data-matrix data-row-list
exercised-powers saliences positions influences
positions-normalized
weighted-median weighted-median-position
apa-table
agent-max parameter-list
p1 p2 ; mnemononic for parameter 1, parameter 2; dummies
]

;; This procedure is being depricated so that a single Netlogo
;; file can be uploaded to the Modeling Commons.
;  ifelse ( file-exists? "BuenodeMesquita1984.txt" )
;  [
;  set input-data []
;  ;; This opens the file, so we can use it.
;  file-open "BuenodeMesquita1984.txt"
;  while [ not file-at-end? ]
;  [
;  ]
;  ;show input-data
;  file-close
;  make-data-structures
;  ]
;  [user-message "There is no BuenodeMesquita1984.txt file in current directory!" ]
;end

let default-data [["Agent" "Position" "Salience" "Influence"] ["UMC" 0 0.8 1.1] ["TEC" 0 2.5 0.6] ["MCR" 2.1 2.5 0.9] ["SOV" 3 10.3 0.6] ["PM" 4.7 6.8 9] ["BAZ" 5.1 0.8 5.6] ["REV" 5.1 8.5 12.4] ["JC" 5.1 10.3 11.3] ["PRE" 6.4 10.3 10.7] ["UP" 7.3 2.5 4.5] ["LCR" 7.3 3.4 4.5] ["KUR" 8.6 4.3 2.3] ["COM" 9.8 8.5 11.8] ["SC" 11.1 6 4.5] ["CG" 11.1 4.3 9] ["MON" 12.4 9.4 0.1] ["TMC" 12.4 9.4 3.4] ["QUM" 12.4 9.4 4.5]]
set input-data default-data
make-data-structures
end

;; This procedure does the same thing as the above one, except it lets the user choose
;; the file to load from.  Note that we need to check that it isn't false.  This because
;; it will return false if the user cancels the file dialog.  There is currently only
;; one file to load from, but you can create your own using the function save-patch-data
;; near the bottom which saves all the current patches into a file.

let file user-file

if ( file != false )
[
set input-data []
file-open file
while [ not file-at-end? ]

file-close
make-data-structures
]
end

to show-input-data
ifelse ( is-list? input-data )
[ clear-output
foreach input-data [ output-print ? ]]
[ user-message "You need to load in patch data first!" ]
end

to show-current-data
ifelse ( is-list? agents )
[ clear-output
output-print (word "Agent Position Salience Influence")
output-print "-------------------------------------"
foreach n-values length agents [?] [ output-print (word item ? agents " " item ? positions " " item ? saliences " " item ? influences)]]
[ user-message "You need to load in data first!" ]
end

to model-report
ifelse ( is-list? input-data )
[ clear-output
foreach input-data [ output-print ? ]
;; Now do the report on the selected model.
if model = 1 [
user-message "Valid model! Will run report."
model1
]
if model = 2 [
user-message "Valid model! Will run report."
model2
]
]
[ user-message "You need to load in input data first!" ]
end

to get-agent-list
ifelse ( is-list? input-data )
[ clear-output
set agents []
foreach input-data [ set agents lput item 0 ? agents ]
;; Now do the report on the selected model.
set agents but-first agents
;show agents
]
[ user-message "You need to load in input data first!" ]
end

to make-row-list
;; Of the input-data
ifelse ( is-list? input-data )
[ clear-output
set data-row-list []
foreach input-data [ set data-row-list lput but-first ? data-row-list ]
set data-row-list but-first data-row-list
;output-show data-row-list
]
[ user-message "You need to load in input data first!" ]
end

to make-data-array
make-row-list
set data-matrix matrix:from-row-list data-row-list
end

to make-data-structures
get-agent-list
make-data-array
;; The following all report lists, not matrices.
;; Of course the lists can be easily converted to matrices as needed.
set positions matrix:get-column data-matrix 0
set saliences matrix:get-column data-matrix 1
set influences matrix:get-column data-matrix 2
;; Now normalize the positions
;  set positions-normalized []
;  let damax max positions
;  let damin min positions
;  foreach positions [
;   set positions-normalized lput ((? - damin) / (damax - damin)) positions-normalized
;  ]
set positions-normalized normalize-list (positions)
set agent-max  length agents - 1
end

to-report normalize-list [to-normalize]
let normalized []
let damax max to-normalize
let damin min to-normalize
foreach to-normalize [
set normalized lput ((? - damin) / (damax - damin)) normalized
]
report normalized
end

to model1
clear-output
output-print "Results from model 1"
make-exercised-powers
make-weighted-median-position
output-print (word "Weighted median value: " (round (100 * weighted-median) / 100))
output-print (word "Weighted median position: " weighted-median-position)
end

to model2
clear-output
output-print "Results from model 2"
let row-sums-list model2prediction (positions)
;let row-sums matrix:from-column-list (list agents row-sums-list)
output-print "The group attractiveness sums are:"
foreach n-values length agents [?] [
output-print (word item ? agents " " ((round (100 * item ? row-sums-list)) / 100 ) ) ; matrix:pretty-print-text row-sums
]
output-print "The maximum attractiveness sum is:"
output-print max row-sums-list
end

to make-exercised-powers
ifelse ( is-list? input-data )
[ let s matrix:from-column-list (list saliences)
let i matrix:from-column-list (list influences)
set exercised-powers matrix:times-element-wise s i
;; exercised-powers is now a matrix.
;; Convert it to a list
set exercised-powers first matrix:to-column-list exercised-powers
]
[ user-message "You need to load in input data first!" ]
end

to-report get-exercised-powers [s i]
;; s ~ saliences
;; i ~ influences
let ss matrix:from-column-list (list s)
let ii matrix:from-column-list (list i)
let ep matrix:times-element-wise ss ii
;; exercised-powers is now a matrix.
;; Convert it to a list
let eplist first matrix:to-column-list ep
;show eplist
report eplist
end

to make-weighted-median-position
ifelse (exercised-powers = 0)
[user-message "You need to create exercised-powers first! Use: make-exercised-powers"]
[set weighted-median (sum exercised-powers) / 2
let sofar 0
let found []
foreach exercised-powers [
set sofar sofar + ?
ifelse sofar <= weighted-median
[set found lput 0 found]
[set found lput 1 found]
]
;show found
let pos position 1 found
set weighted-median-position item pos agents
;show weighted-median-position
]
end

to-report get-weighted-median-position [expow]
let wt-median (sum expow) / 2
let sofar 0
let found []
foreach expow [
set sofar sofar + ?
ifelse sofar <= wt-median
[set found lput 0 found]
[set found lput 1 found]
]
;show found
let pos position 1 found
report item pos agents
end

to test
;  set bob matrix:from-column-list (list agents)
;  show bob
let bobw (list 1 2 3 "not bob")
let carol bobw
set carol lput 4 carol
set bobw fput 19 bobw
show carol
show bobw
end

to display-agents
let start (length agents) + 1
foreach agents [
ask patch 1 start [set plabel ?]
set start (start - 1)
]
end

to individual-exp [x-percent variable]
clear-patches
display-agents
if (model = 1) [
let hold-values []
if runresult variable = saliences
[ ;; So we fix influences and vary saliences
;;
;; First we modify the salience value for the agent.
;; Then we get the exercised power for the agent.
;; Then we get the weighted median position for the group,
;; and append it to hold-values.
;; Then we reset the salience value for the agent.
;; We continue this way until all agents have been processed.
;; The we print out the hold-values list.
foreach n-values length agents [?]
[
;; ok, once through
let temp runresult variable
;show temp
let target-value item ? temp
;show target-value
let factor (1 + (x-percent / 100)) ;1.1
;show (word "factor = " factor)
let new-value (target-value * factor)
;show new-value
set temp replace-item ? temp new-value
;show runresult variable
;show temp
;; OK, now get the new exercised powers
let ex-powers get-exercised-powers(temp)(influences)
;show ex-powers
;; Now get the weighted median position for the group,
;; and append it to hold-values.
set hold-values lput get-weighted-median-position(ex-powers) hold-values
]
] ; end of if runresult variable = saliences
if runresult variable = influences
[ foreach n-values length agents [?]
[
;; ok, once through
let temp runresult variable
;show temp
let target-value item ? temp
;show target-value
let factor (1 + (x-percent / 100)) ;1.1
;show (word "factor = " factor)
let new-value (target-value * factor)
;show new-value
set temp replace-item ? temp new-value
;show runresult variable
;show temp
;; OK, now get the new exercised powers
let ex-powers get-exercised-powers(saliences)(temp)
;show ex-powers
;; Now get the weighted median position for the group,
;; and append it to hold-values.
set hold-values lput get-weighted-median-position(ex-powers) hold-values
]

]
paint-values(hold-values)(3)
if runresult variable = positions
[user-message "Positions are not relevant to this model for post-solution analysis."]
] ; end of if (model = 1)
;; Now, the next model, model 2.
if (model = 2) [
;; A more complicated model.
;; We begin by constructing the APA table (agent position attractiveness)
;; This table is n by n where n is the number of agents = number of postions.
;; We'll make it with a matrix, initially of 0s
;    let dasize length agents
;    set apa-table matrix:make-constant dasize dasize 0
;    foreach n-values dasize [?]
;    [let row ?
;     foreach n-values dasize [?]
;      [let col ?
;       let row-position item row positions-normalized
;       let theta item col positions-normalized
;       matrix:set apa-table row col 1 - abs(row-position - theta)
;      ]
;    ]
;print matrix:pretty-print-text apa-table
;; Now, get the row sums.
let row-sums-list model2prediction (positions)
;    let row-sums matrix:from-column-list (list agents row-sums-list)
;    print matrix:pretty-print-text row-sums
;    print max row-sums-list
let hold-values-model2 []
if runresult variable = positions
[ ;; So we fix influences and vary saliences
;;
;; First we modify the salience value for the agent.
;; Then we get the exercised power for the agent.
;; Then we get the weighted median position for the group,
;; and append it to hold-values.
;; Then we reset the salience value for the agent.
;; We continue this way until all agents have been processed.
;; The we print out the hold-values list.
foreach n-values length agents [?]
[
;; ok, once through
let temp runresult variable
;show temp
let target-value item ? temp
;show target-value
let factor (1 + (x-percent / 100)) ;1.1
;show (word "factor = " factor)
let new-value (target-value * factor)
;show new-value
set temp replace-item ? temp new-value
;show runresult variable
;show temp
;; OK, now get the new exercised powers
let row-sums-list-new model2prediction (temp)
;show ex-powers
;; Now get the weighted median position for the group,
;; and append it to hold-values.
set hold-values-model2 lput (item (position (max row-sums-list-new) row-sums-list-new) agents) hold-values-model2
]
paint-values(hold-values-model2)(3)
] ; end of if runresult variable = positions
if runresult variable = saliences
[user-message "Saliences are not relevant to this model."]
if runresult variable = influences
[user-message "Influences are not relevant to this model."]
] ; end of if (model = 2)
end

to-report model2prediction [thepositions]
;; First, normalize the positions
let thepositions-normalized normalize-list (thepositions)
let dasize length agents
set apa-table matrix:make-constant dasize dasize 0
foreach n-values dasize [?]
[let row ?
foreach n-values dasize [?]
[let col ?
let row-position item row thepositions-normalized
let theta item col thepositions-normalized
matrix:set apa-table row col 1 - abs(row-position - theta)
]
]
;; Now, get the row sums.
let row-sums []
foreach n-values dasize [?]
[set row-sums (lput sum matrix:get-row apa-table ? row-sums)]
;; Now we have to find the max and get the associated position.
;; Complicating this is the possibility of ties.
;; I think the best thing to do is to report the whole thing,
;; as follows.
;let max-row-sum-value max row-sums
report row-sums
;report apa-table
end

to paint-values [value-list column]
let start (length agents) + 1
foreach value-list [
ask patch column start [set plabel ?]
set start (start - 1)
]
end

to group-sampling-exploration [x-percent variable]
clear-patches
display-agents
;; set the outcome counts to 0
foreach n-values length agents [?] [
ask patch 5 (length agents + 1 - ?) [set plabel 0]
]

if (model = 1) [
if runresult variable = saliences
[runresults-saliences-model1 (x-percent) ] ; end of if runresult variable = saliences
;; Ok, now do influences
if runresult variable = influences
[runresults-influences-model1 (x-percent) ] ; end of if runresult variable = influences
if runresult variable = positions
[user-message "Positions do not apply for post-solution exploration in model 1."]

] ; end of if (model = 1)

;; Now model 2. key is: model2prediction (positions)
if (model = 2) [
if runresult variable = positions
[runresults-positions-model2 (x-percent)] ; end of if runresult variable = positions
if runresult variable = influences
[user-message "Influences do not apply for post-solution exploration in model 2."]
if runresult variable = saliences
[user-message "Saliences do not apply for post-solution exploration in model 2."]
] ; end of if (model = 2)
end

to runresults-positions-model2 [x-percent]
repeat runresult numtrials [
;; Copy positions to a new variable,new-values-positions
let new-values-positions positions
;; Modify all of the positions randomly, uniformly in
;; plus/minus x-percent/100.
foreach n-values length agents [?] [
let upper item ? new-values-positions * (1 + (abs(x-percent) / 100))
let lower max (list 0 (item ? new-values-positions * (1 - (abs(x-percent) / 100))))
let new-value random-float (upper - lower)
set new-value (lower + new-value)
set new-values-positions replace-item ? new-values-positions new-value
]
;; Solve the model, yielding a list of the summed position evaluations.
let summed-position-evaluations model2prediction (new-values-positions)
;; Now we need to get the location of the first maximum value.
; set hold-values-model2 lput (item (position (max row-sums-list-new) row-sums-list-new) agents) hold-values-model2
let new-position-index position (max summed-position-evaluations) summed-position-evaluations
let new-position item new-position-index agents
;print (word "New outcome is " new-position)
] ; end of repeat runresult numtrials
end

to runresults-saliences-model1 [x-percent ]
repeat runresult numtrials [
;; First we modify the salience values for every agent.
let new-values-saliences saliences
foreach n-values length agents [?] [
let upper item ? new-values-saliences * (1 + (abs(x-percent) / 100))
let lower max (list 0 (item ? new-values-saliences * (1 - (abs(x-percent) / 100))))
let new-value random-float (upper - lower)
set new-value (lower + new-value)
set new-values-saliences replace-item ? new-values-saliences new-value
]
;; Ok, now we solve the model to get the predicted position
;; OK, now get the new exercised powers
let ex-powers get-exercised-powers(new-values-saliences)(influences)
;; new-outcome refers to the agent (a string)
let new-outcome get-weighted-median-position(ex-powers)
] ; end of repeat runresult
end

to runresults-influences-model1 [x-percent]
repeat runresult numtrials [
;; First we modify the salience values for every agent.
let new-values-influences influences
foreach n-values length agents [?] [
let upper item ? new-values-influences * (1 + (abs(x-percent) / 100))
let lower max (list 0 (item ? new-values-influences * (1 - (abs(x-percent) / 100))))
let new-value random-float (upper - lower)
set new-value (lower + new-value)
set new-values-influences replace-item ? new-values-influences new-value
]
;; Ok, now we solve the model to get the predicted position
;; OK, now get the new exercised powers
let ex-powers get-exercised-powers(saliences) (new-values-influences)
;; new-outcome refers to the agent (a string)
let new-outcome get-weighted-median-position(ex-powers)
] ; end of repeat numtrials
end

let new-agent position outcome agents
let x-index 5
let y-index (length agents + 1 - new-agent)
ask patch x-index y-index [set plabel (plabel + 1)]
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.