# Party competition C h5

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

### WHAT IS IT?

This implements the "benchmark" model of party competition specified in Chapter 5 of Michael Laver and Ernest Sergenti's book, Party competition: an agent based model (Princeton University Press, 2012). A full description and analysis of the model can be found in this book and is not repeated here.

Party positions and voter ideal points are defined in two dimensions of policy/ideology, directly analogous to the dimensions used in other "spatial" models of political competition. The horizontal dimension might, for example, be seen as describing left-right economic policy positions; the vertical dimension might be seen as a liberal-conservative policy dimension on matters such as abortion, sexual orientation, euthanasia.

VOTERS always vote for the closest party. The preference structure of the voting population can be designed as if this is an aggregate of up to three subpopulations. (Only two are investigated by Laver and Sergenti and the default setting on the interface sets the size of the third subpopulation at zero). Voters in each subpopulation have normally distributed ideal points, and each subpopulation is characterized by: the number of voters it comprises; the standard deviation of the distribution of its voters' ideal points, and the means of this distribution on the x and y dimensions. All of these parameters can be set using the sliders in the _Population Designer_ panel near the bottom of the interface.

PARTY LEADERS compete with each other by offering policies to potential supporters. They use one of three _species_ of decision rule _ Sticker, Aggregator, Hunter _ to select a party policy position. These rules are described fully in Laver and Sergenti (2012) and implemented in the _party dynamics_ section of the code.

DYNAMICS OF PARTY COMPETITION. The baseline dynamics of the model iterate forever. (1) Voters support their closest party. (2) Given a profile of voter support for parties, leaders adapt party policy positions using their decision rule. (3) Go to 1.

The number of political parties in the benchmark runs in Laver and Sergenti is fixed exogenously. The number of parties and the decision rule used by each party are set on the interface. (In all subsequent models, the sets of surviving parties and decision rules they use are endogenous to model dynamics.)

### HOW TO USE IT

SETUP sets up parties, supporters and system parameters as specified above. GO starts and stops the simulation using current parameters.

(Hitting SETUP while GO is still pressed very occasionally causes an error depending where precisely the program is when setup is hit; this easily retrieved by unpressing GO and pressing SETUP again.)

RUNNING EXPERIMENTS. Laver and Sergenti designed computational benchmarking experiments, and report results of these, in Chapter 5 of their book. Although _production_ runs were executed on a high performance cluster, precisely equivalent smaller scale experiments can easily be run using Behavior Space. Sketch runs for all results reported in Laver and Sergenti were generated using Behavior Space on a normal laptop. Some sample behavior space experiments are included.

### WHAT TO PLAY WITH

Laver and Sergenti report results from carefully controlled computational experiments and only investigate electorate with two subpopulations. There are infinitely many alternative populations for you to explore using the population designer. There are also many parameterizations of the competitive environment, and the party birth regime, not explored by Laver and Sergenti. You may, for example, want to specify a parameterization of the model you feel corresponds to some real political system that interests you.

By far the most exciting and callenging way forward is to specify and program your own decision rule for party leaders. Just drop in your coded new rule as a procedure in the party dynamics section, add its name to the rule list, edit it in to the _adapt_ and _color-myself_ procedures, and add a reporter for your rule_s vote share to the interface. You_re good to go!

### CREDITS AND REFERENCES

Programmed by:

Michael Laver, Department of Politics, New York University

ml127@nyu.edu

Ernest Sergenti, The World Bank

esergenti@gmail.com

## Comments and Questions

;;____________________________ ; ;; SETUP AND HOUSEKEEPING ;;____________________________ breed [ parties party ] globals [ cycle total-votes max-voteshare ; largest vote share on any patch mean-voterx ; mean voter x-coordinate mean-votery ; mean voter y-coordinate mean-eccentricity ; mean Euclidean distance of parties from (mean-voterx, mean-votery) largest-party ; "who" of largest party voter-misery ; mean quadratic Euclidean voter distance from closest party enp ; effective number of parties = 1/(sum of squared party vote shares) party-number ; party number tickcycle ; with aggregator runs: records cycle for the calculate-party-variance procedure position-list ; with aggregator runs: list of the x & y coordinates of the party positions old-position-list ; with aggregator runs: list of the x & y coordinates of the party positions from the previous tick tot-var ; with aggregator runs: total variance for the x & y coordinates between position-list & old-position-list var-stop ; with aggregator runs: stops program when 1 ] parties-own [ mysize ; current party size old-mysize ; party's size previous tick my-rule ; party's decision rule eccentricity ; party's Euclidean distance from (mean-voterx, mean-votery) ] patches-own [ votes ; number of voters on patch vote-share ; proportion of total voters on patch closest-party ; party with smallest Euclidean distance from patch ] to setup clear-all create-parties n-parties set party-number n-values 12 [?] foreach party-number [ if ?1 >= n-parties [set party-number replace-item ?1 party-number 0] ] set position-list n-values 24 [0] set tickcycle 0 set tot-var 10 set var-stop 0 ask parties [set heading random-float 360 jump random-float 30] ; create n parties and set their positions as a random draw from a bivariate normal with mean 0 and std. dev. 10 ask parties [set color lime set size 1.5] ask parties [update-rule] ask parties [set old-mysize 0] ; ask each party to display itself as large and lime green, and to read its decision rule from the interface ask patches [ let x1 (pxcor - x-mean1) / sd-1 let y1 (pycor - y-mean1) / sd-1 set votes votes1 * exp (-0.5 * ( x1 ^ 2 + y1 ^ 2)) / (2 * pi * sd-1 ^ 2) ;; votes1, x_mean1, y_mean1, sd_1 = votes, mean and standard deviation of subpopulation 1, read from interface ;; each patch's votes arising from subpopulation 1 = votes1 * bivariate normal density with mean1, sd_1, rho = 0 let x2 (pxcor - x-mean2) / sd-2 let y2 (pycor - y-mean2) / sd-2 set votes votes + votes2 * exp (-0.5 * ( x2 ^ 2 + y2 ^ 2)) / (2 * pi * sd-2 ^ 2) ;; add votes to each patch from subpopulation 2, calculated as above let x3 (pxcor - x-mean3) / sd-3 let y3 (pycor - y-mean3) / sd-3 set votes votes + votes3 * exp (-0.5 * ( x3 ^ 2 + y3 ^ 2)) / (2 * pi * sd-3 ^ 2) ;; add votes to each patch from subpopulation 3, calculated as above ] set total-votes sum [ votes ] of patches type "Total votes at all locations = " type round(total-votes) ;; add total of votes on all patches and output this to the command window ask patches [set vote-share votes / total-votes] ;calculate each patch's vote share set mean-voterx sum [ pxcor * vote-share ] of patches set mean-votery sum [ pycor * vote-share ] of patches type " Mean voter x = " type round(mean-voterx) type " Mean voter y = " print round(mean-votery) ;; calculate center (mean) of voter distribution on each dimension as sum of (patch positions weighted by vote share) ;; output this to the command window set max-voteshare max [ vote-share ] of patches ask patches [set pcolor scale-color red vote-share 0 max-voteshare ] ;; color patches red with density proportional to vote shares update-support end to update-rule if ( who = 0 ) [set my-rule party0-rule] if ( who = 1 ) [set my-rule party1-rule] if ( who = 2 ) [set my-rule party2-rule] if ( who = 3 ) [set my-rule party3-rule] if ( who = 4 ) [set my-rule party4-rule] if ( who = 5 ) [set my-rule party5-rule] if ( who = 6 ) [set my-rule party6-rule] if ( who = 7 ) [set my-rule party7-rule] if ( who = 8 ) [set my-rule party8-rule] if ( who = 9 ) [set my-rule party9-rule] if ( who = 10 ) [set my-rule party10-rule] if ( who = 11 ) [set my-rule party11-rule] ;parties read their decision rules off choice buttons on the interface end ;;____________________________ ; ;; PARTY DYNAMICS ;;____________________________ to hunt ifelse (mysize > old-mysize) [jump 1] [set heading heading + 90 + random-float 180 jump 1] ;;hunter makes a move of size 1 in same direction as previous move if this increased party support ;;NB the NetLogo command FORWARD is limited to a maximum of a unit move per tick ;;JUMP is needed for larger than unit moves ;;else reverses direction and makes a move of size 1 in on a heading chosen from the 180 degree arc now faced set old-mysize mysize ;;remember party size for next cycle - note that "go" calls "update-support" BEFORE asking hunters to "hunt" end to aggregate if (mysize > 0) [ set xcor (sum [votes * pxcor] of patches with [closest-party = myself] / mysize) set ycor (sum [votes * pycor] of patches with [closest-party = myself] / mysize) ] ;;set party x, y positions at the mean x, y positions of party members ;;maintain current position if zero supporters end to predate if (mysize < [mysize] of largest-party) [face largest-party jump 1] ;;predator identifies the largest party and makes a move of size 1 towards it end ;;____________________________ ; ;; MAIN CONTROL SUBROUTINES ;;____________________________ to update-support ask patches [set closest-party min-one-of parties [distance myself]] ;;patches find their closest party ask parties [set mysize sum [votes] of patches with [closest-party = myself]] ;;each party sums the votes on patches for which it is the closest party set largest-party max-one-of parties [mysize] ;;find the largest party end to measure-misery set voter-misery sum [((distance closest-party ^ 2) / 100) * votes] of patches / total-votes end to measure-eccentricity ask parties [set eccentricity sqrt ((xcor - mean-voterx) ^ 2 + (ycor - mean-votery) ^ 2) / 10] ;;calculate each party's eccentricity, its Euclidean distance from the center of the voter distribution set mean-eccentricity sum [eccentricity] of parties / n-parties ;;calculate the mean eccentricity of all parties in the system end to adapt if (my-rule = "hunter") [hunt] if (my-rule = "aggregator") [aggregate] if (my-rule = "predator") [predate] ;;NB stickers do nothing end to calculate-party-variance ;;used in all-Aggregator runs to stop the program when all parties stop moving set tickcycle tickcycle + 1 if (tickcycle = 10) [ set old-position-list position-list (foreach n-values 12 [? * 2] party-number [ set position-list replace-item ?1 position-list [xcor] of turtle (item ?2 party-number) ]) (foreach n-values 12 [? * 2 + 1] party-number [ set position-list replace-item ?1 position-list [ycor] of turtle (item ?2 party-number) ]) set tot-var 0 ( foreach old-position-list position-list [ set tot-var tot-var + (?2 - ?1) ^ 2 ] ) if (tot-var < .1) [ set var-stop 1 ] set tickcycle 0 ] end ;;____________________________ ; ;; MAIN CONTROL ROUTINE ;;____________________________ to go ifelse (party0-rule = "aggregator") ; with aggregator runs: use the calculate-party-variance procedure and var-stop check ; the program stops when the parties stop moving and the system is in stationary state ; NB in benchmark runs all parties are set to use the same rule [ ask parties [adapt] update-support set enp (total-votes ^ 2) / (sum [mysize ^ 2] of parties) measure-eccentricity measure-misery calculate-party-variance set cycle cycle + 1 if (var-stop = 1) [stop] ] [ ask parties [adapt] update-support set enp (total-votes ^ 2) / (sum [mysize ^ 2] of parties) measure-eccentricity measure-misery set cycle cycle + 1 ] end

There is only one version of this model, created about 7 years ago by Michael Laver.

## Attached files

No files

This model does not have any ancestors.

This model does not have any descendants.