IranBargaining
Do you have questions or comments about this model? Ask them here! (You'll first need to log in.)
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:
- The first line should not be empty. It can be as long as you wish.
- The second line should be exactly as shown here.
- The third line begins the actual data. You should follow the format shown:
- Four items per line, separated by spaces.
- The first item should be a string in quotes.
- Items 2 through 4 should be numbers
- All items should be separated by spaces.
- Do not start a new (empty) line after the last data line.
- 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 AND LICENSE
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.
Commercial licenses are also available. To inquire about commercial licenses, please contact Steven O. Kimbrough at kimbrough@wharton.upenn.edu.
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
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. ;to load-input-data ; ifelse ( file-exists? "BuenodeMesquita1984.txt" ) ; [ ; set input-data [] ; ;; This opens the file, so we can use it. ; file-open "BuenodeMesquita1984.txt" ; let file-header file-read-line ; show file-header ; while [ not file-at-end? ] ; [ ; set input-data sentence input-data (list (list file-read file-read file-read file-read)) ; ] ; ;show input-data ; file-close ; make-data-structures ; ] ; [user-message "There is no BuenodeMesquita1984.txt file in current directory!" ] ;end to load-default-data 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. to load-own-input-data let file user-file if ( file != false ) [ set input-data [] file-open file let file-header file-read-line show file-header while [ not file-at-end? ] [ set input-data sentence input-data (list (list file-read file-read file-read file-read)) ] user-message "File loading complete!" 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) add-sample-count (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) add-sample-count (new-outcome) ] ; 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) add-sample-count (new-outcome) ] ; end of repeat numtrials end to add-sample-count [outcome] 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 over 10 years ago by Steven Kimbrough.
Attached files
No files
This model does not have any ancestors.
This model does not have any descendants.