Party competition C h5

No preview image

1 collaborator

Ml%20photo Michael Laver (Author)



Tagged by Didier Ruedin over 10 years ago


Tagged by Michael Laver about 12 years ago

Part of project 'Party competition'
Visible to everyone | Changeable by everyone
Model was written in NetLogo 4.1.1 • Viewed 1123 times • Downloaded 74 times • Run 0 times
Download the 'Party competition C h5' modelDownload this modelEmbed this model

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


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.)


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.


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!


Programmed by:

Michael Laver, Department of Politics, New York University

Ernest Sergenti, The World Bank

Comments and Questions

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

Click to Run Model


breed [ parties party ]

globals [
  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
  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

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


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"

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

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


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

to measure-misery
 set voter-misery sum [((distance closest-party ^ 2) / 100) * votes] of patches / total-votes

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

to adapt
  if (my-rule = "hunter") [hunt]
  if (my-rule = "aggregator") [aggregate]
  if (my-rule = "predator") [predate]
   ;;NB stickers do nothing

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


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]
    set enp (total-votes ^ 2) / (sum [mysize ^ 2] of parties)
    set cycle cycle + 1
    if (var-stop = 1) [stop]
    ask parties [adapt]
    set enp (total-votes ^ 2) / (sum [mysize ^ 2] of parties)
    set cycle cycle + 1

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

Attached files

No files

This model does not have any ancestors.

This model does not have any descendants.