Plurality Versus Approval voting - An elaborate spatial model for voting systems - Online version

Plurality Versus Approval voting - An elaborate spatial model for voting systems - Online version preview image

1 collaborator

Default-person Teun de Bilde (Author)

Tags

(This model has yet to be categorized with any tags)
Visible to everyone | Changeable by everyone
Model was written in NetLogo 6.2.2 • Viewed 82 times • Downloaded 4 times • Run 0 times
Download the 'Plurality Versus Approval voting - An elaborate spatial model for voting systems - Online version' modelDownload this modelEmbed this model

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


Comments and Questions

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

Click to Run Model

extensions[array view2.5d ]


globals[recursive-length last-approval-mean total-number-of-votes winner progress total-loyal-votes accuracy total-number-of-voters total-number-of-parties done cabinet prime-minister disproportionality bayesian-regret highest-sat satisfaction-list cabinet-mean unique-cabinets  average-utility]
breed[voters voter]
breed[parties party]
voters-own[approval-cutoff age preference-array strategize  christian utility approval-colorer ballot education populist]
parties-own[name primary-party-color secundary-party-color frontrunner votes seats loyalty-seats actual-seats party-utility utility-seats]

to setup
  clear-all
  initialize-preset
  set progress 0
  set-current-directory path
  ask patches[set pcolor white]
  initialize-parties
  actual-election-plot
  create-population
  vote
  update-election-results
  if(display-median = true)
  [
    plot-left-right
    plot-progressive-conservative
  ]

  if (view3d = true)
  [
    display-3d

  ]
end 
;the modelling commons really needs this for some reason

to go
end 

to initialize-preset
  if (presets = "Most accurate plurality setting" )
  [
    set percent-strategizing 0.27
    set maximum-noise 0.4
    set christianity-percentage 0.1
    set nonchristians-likelihood-to-CDA 0.61
    set christians-likelihood-to-CDA 0.72
    set possibility-populist-high-education 0.08
    set possibility-populist-low-education 0.15
    set party-loyalty true
  ]
  if (presets = "Most accurate approval setting(based on assumption)")
  [
    set percent-strategizing 0.27
    set maximum-noise 0
    set christianity-percentage 0.1
    set nonchristians-likelihood-to-CDA 0.61
    set christians-likelihood-to-CDA 0.72
    set possibility-populist-high-education 0.08
    set possibility-populist-low-education 0.15
    set party-loyalty false
    set use-approval-mean true
  ]
  if (presets = "Clear 3D view (no noise)")
  [
    set view3d true
    set maximum-noise 0
  ]
  if (presets = "All display options on")
  [
    set overlay true
    set display-median true
    set view3d true
    set display-strategy-in-graph true
    set show-approval-ballots true
  ]

  if (presets = "All display options off")
  [
    set overlay false
    set display-median false
    set view3d false
    set display-strategy-in-graph false
    set show-approval-ballots false
  ]
end 

to display-3d
  let temp-utility 0
  let temp-color 0
  ask voters with [approval-colorer = true]
  [
    if any? (voters-on patch-here) with [approval-colorer != true]
    [
      ask (voters-on patch-here) with [approval-colorer != true]
      [
        set temp-utility utility
        set temp-color color
      ]
    ]
    if( show-approval-ballots = false) [set color temp-color]
    set utility temp-utility
  ]
  view2.5d:turtle-view "3d-view-utility" voters [ the-voter -> [utility] of the-voter ]
  view2.5d:set-observer-distance "3d-view-utility" 40
  view2.5d:set-z-scale "3d-view-utility" 250
  view2.5d:set-observer-angles "3d-view-utility" 250 300
  view2.5d:set-turtle-stem-thickness "3d-view-utility" .001


  view2.5d:set-turtle-stem-color "3d-view-utility" [ 0 ]
end 

to initialize-parties

  let party-values [[ "Volt" -5 88 113 9.9 0 54.2 0 3]["D66" -5 70 65 9.9 19 42.8 0 24]["Bij1" -100 85 0 46 0 54.2 0 1]["PVDD" -100 65 61 9.9 5 35 0 6]["50+" -20 -13 114 9.9 4 54.2 0 2]["SP" -100 40 15 9.9 14 46.2 0 9]["GL" -70 68 15 65 14 49.3 0 8]["PVdA" -65 50 15 9.9 9 53.5 0 9]["DENK" -70 40 86 9.9 3 54.2 0 3]["CU" -20 15 105 85 5 55.9 1 5]["CDA" 5 -25 65 9.9 19 46.6 0.5 15]["PVV" -15 -75  15 95 20 74.9 0 17]["SGP" 35 -48 25 9.9 3 73 1 3]["VVD" 55 -20 25 105 33 54.2 0 34]["JA21" 60 -57 102 14 0 54.2 0 3]["FVD" 70 -75 13 9.9 2 34.8 0 8]]
  let frontrunnerlist read-from-string frontrunners

  set total-number-of-parties length party-values
  let loyal-votes-last-round  n-values total-number-of-parties [0]
  let counter 0





  set counter 0
  foreach party-values
  [
    [current-party] ->
    create-parties 1
    [
      ;set x and y coordinates from the party values
      set xcor item 1 current-party * 2
      set ycor item 2 current-party * 2

      ;sets the party name, the primary party color and the secundary party color
      set name item 0 current-party
      set primary-party-color item 4 current-party
      set secundary-party-color item 3 current-party

      ;visualizes above settings on the map
      set color primary-party-color
      ask [neighbors] of patch-here [ set pcolor [secundary-party-color] of myself]
      set plabel name
      set plabel-color black

      set frontrunner false
      ;applies a frontrunner value if given by user
      if ( member? name read-from-string frontrunners)
      [
        set frontrunner true
        set plabel-color red
      ]
      set actual-seats item 8 current-party


      set loyalty-seats item 5 current-party * (item 6 current-party / 100)

      set total-loyal-votes total-loyal-votes + loyalty-seats

    ]
  ]

  ;set a coloring for smallest distance to party for each patch
  if (overlay = true)
  [
    ask patches with [pcolor = white]
    [
      let current-party min-one-of parties[distance myself]
      ifelse ([primary-party-color] of current-party = 9.9)
      [
        set pcolor [secundary-party-color] of current-party + 2.5
      ]
      [
        set pcolor [primary-party-color] of current-party + 2.5
      ]
    ]
  ]
  ;display axis
  ask patches with [pxcor = 0 or pycor = 0]
  [
    ifelse (overlay = true)
    [
      set pcolor white
    ]
    [
      set pcolor blue
    ]
  ]
end 

to create-population

 ; as i can not upload files to commons, the if statement is leftover code. contact me if you want the complete zip file
  if(population = "random" )
  [
    create-voters number-random-voters
    [
      ; this makes sure that voters are distributed realistically, as left-conservative is rarer than left progressive,
      ; and right-progressive rarer than right conservative
      let left-right-diagonal random-float 1.0
      ifelse( left-right-diagonal >= 0.5)[set left-right-diagonal 1][set left-right-diagonal -1]
      set left-right-diagonal left-right-diagonal * (random-exponential  40)
      let gaussian-x random-normal left-right-diagonal 50
      let gaussian-y random-normal (-1 * left-right-diagonal) 50
      if(gaussian-x > 220)[set gaussian-x 220]
      if(gaussian-x < -220)[set gaussian-x -220]
      if(gaussian-y > 220)[set gaussian-y 220]
      if(gaussian-y < -220)[set gaussian-y -220]
      setxy (gaussian-x) (gaussian-y)

      ;set education here according to distribution of educated voters
      ifelse ( random-float 1 < 0.629 )
      [
        set education 1
        ifelse( random-float 1 < possibility-populist-low-education )
        [
          set populist true
        ]
        [
          set populist false
        ]
      ]
      [
        set education 2
        ifelse( random-float 1 < possibility-populist-high-education )
          [
            set populist true
        ]
        [
          set populist false
        ]
      ]
      set age random 7
      create-preference-ballot
      set color grey
      set ballot (list 0 )
    ]
  ]
  ;;
  ask voters
  [
    set approval-cutoff random-normal approval-mean approval-SD
    set total-number-of-voters total-number-of-voters + 1

    if approval-cutoff < 0
    [
      set  approval-cutoff 0
    ]
    if approval-cutoff > 1
    [
      set  approval-cutoff 1
    ]
  ]
end 

to vote
  let totalballotcounter 0
  ask voters
  [
    ifelse(voting-method = "plurality")
    [

      ifelse(strategize = true)
      [
        plurality-strategize
      ]
      [
        plurality
      ]
      set progress  (progress + (1 / total-number-of-votes) * 100)
    ]
    [

      ifelse(strategize = true)
      [
        approval-strategize
      ]
      [

        approval
      ]
      ;set total-number-of-votes total-number-of-votes + ballotsize
      set  progress (progress + (1 /  total-number-of-voters) * 100)
      if item 0 ballot = 0
      [
        set ballot remove-item 0 ballot
      ]
      let size-counter length ballot

      set total-number-of-votes total-number-of-votes + length ballot
      ifelse (show-approval-ballots = true)
      [
        foreach ballot
        [
          current-party ->
          hatch 1
          [


            set approval-colorer true
            set size size-counter
            set color [secundary-party-color] of current-party
          ]
          set shape "circle"
        set size-counter size-counter - 1
        ]
      ]
      [

        set color item 0 [secundary-party-color] of parties with [name = [name] of item 0 [ballot] of myself]
        set size length ballot
      ]
    ]
  ]
    set average-utility approval-mean
end 

to plurality-strategize
  let i 0
  repeat total-number-of-parties [
    let current-prefered-array array:item preference-array i
    let current-party array:item current-prefered-array 0
    let current-weight array:item current-prefered-array 1
    if([frontrunner] of current-party = true)
    [
      set ballot lput current-party ballot
      ask current-party [ set votes votes + 1]
      set color [secundary-party-color] of current-party - 2.5
      set shape "square"
      stop
    ]
    set i i + 1
  ]
end 

to plurality
  let most-prefered-array array:item preference-array 0
  let most-prefered-party array:item most-prefered-array 0
  ask  most-prefered-party  [set votes votes + 1]
  set color lput 200 extract-rgb [secundary-party-color] of most-prefered-party
  set ballot lput most-prefered-party ballot
end 

to approval

  let i 0

  if(use-approval-mean = true)
  [
    get-approval-mean
  ]
  repeat total-number-of-parties [
    let current-pref array:item preference-array i
    let current-party array:item current-pref 0
    let current-weight array:item current-pref 1
    if(current-weight >= approval-cutoff)
    [
      ask current-party [ set votes votes + 1]
      set size size - 1
      ifelse ( item 0 ballot  = 0)
      [
        set shape "circle"
        set size 1
        set ballot (list current-party)
      ]
      [
        set ballot lput current-party ballot
      ]

    ]

    set i i + 1
  ]
end 

to approval-strategize
  let i 0
  let first-frontrunner true

  if(use-approval-mean = true)
  [
    get-approval-mean
  ]
  repeat total-number-of-parties [
    let current-pref array:item preference-array i
    let current-party array:item current-pref 0
    let current-weight array:item current-pref 1
    if(current-weight >= approval-cutoff)
    [
      ifelse([frontrunner] of current-party = true)
      [
        if(first-frontrunner = true )
        [
          ask current-party [ set votes votes + 1]
          set color [secundary-party-color] of current-party - 2.5
          set shape "circle"
          ifelse ( item 0 ballot  = 0)
          [
            set shape "circle"
            set size 1
            set ballot (list current-party)
          ]
          [
            set ballot lput current-party ballot
          ]
        ]
      ]
      [
        ask current-party [ set votes votes + 1]
        ifelse ( item 0 ballot  = 0)
        [
          set shape "circle"
          set size 1
          set ballot (list current-party)
        ]
        [
          set ballot lput current-party ballot
        ]
      ]
    ]
    set i i + 1
  ]
end 

to get-approval-mean
  set approval-cutoff 0
  let i 0
  repeat total-number-of-parties
  [
    let current-pref array:item preference-array i
    let current-weight array:item current-pref 1
    set approval-cutoff approval-cutoff + current-weight
    set i i + 1
  ]
  set approval-cutoff approval-cutoff / total-number-of-parties
end 


;alters preferences based on the current agents. this is somewhat based on assumptions and some truth. In reality, age, christianity and education are all correlated, so it is hard to draw conclusions.
;most of this was based on the kieskompas dataset and studies by Ipsos for NOS.
;some conclusions of factors are drawn by the accuracy they give, tested on 1000 elections each.

to apply-values
  ; this method finds parties given certain parameters of users, and adjusts those to new values
  let index 0
  foreach array:to-list preference-array
  [
    preference ->
    let current-weight array:item preference 1
    let current-party array:item preference 0
    if([name] of current-party = "50+")
    [
      if(age <= 5 or education = 2)
      [
        set current-weight current-weight / 5
        array:set preference-array index array:from-list (list current-party current-weight)
      ]
    ]
    ifelse(populist = true)
    [
      ifelse( member? [name] of current-party Populists)
      [
        set current-weight current-weight * 5 / 2
      ]
      [
        set current-weight current-weight / 3 * 2

      ]
      array:set preference-array index array:from-list (list current-party current-weight)
    ]
    [
      ifelse( member? [name] of current-party Populists)
      [
        set current-weight current-weight / 3 * 2
      ]
      [
        set current-weight current-weight * 3 / 2
      ]
      array:set preference-array index array:from-list (list current-party current-weight)
    ]
    ifelse(christian = true)
    [
      ;CDA has always been more of a mainline party, therefore it has a smaller christian following than other christian parties
      if([name] of current-party = "CDA")
      [
        set current-weight current-weight / christians-likelihood-to-CDA
        array:set preference-array index array:from-list (list current-party current-weight)
      ]
      if([name] of current-party = "CU")
      [
        set current-weight current-weight * ( 3 / 2 )
        array:set preference-array index array:from-list (list current-party current-weight)
      ]
      if([name] of current-party = "SGP")
      [
        set current-weight current-weight * (3 / 2)
        array:set preference-array index array:from-list (list current-party current-weight)
      ]
    ]
    [
      ;CDA has always been more of a mainline party, therefore it has a bigger non-christian following than other christian parties (ie. not that hard on abortion or same sex marriage)
      if([name] of current-party = "CDA")
      [
        set current-weight (current-weight * nonchristians-likelihood-to-CDA)
        array:set preference-array index array:from-list (list current-party current-weight)
      ]
      if([name] of current-party = "CU")
      [
        set current-weight (current-weight / 3)
        array:set preference-array index array:from-list (list current-party current-weight)
      ]
      if([name] of current-party = "SGP")
      [
        set current-weight (current-weight / 3)
        array:set preference-array index array:from-list (list current-party current-weight)
      ]
    ]
    set index index + 1
  ]
end 

to reorganize-array
  ; a bubblesort on all the parties and their weights after redistribution
  let i 0
  let j 0
  let array-as-list array:to-list preference-array
  repeat total-number-of-parties - 1
  [
    set array-as-list array:to-list preference-array

    set j 0
    let i-array array:to-list item i array-as-list
    let iw item 1 i-array
    let ip item 0 i-array
    repeat total-number-of-parties - 1 - i
    [
      let j-array array:to-list item j array-as-list
      let jw item 1 j-array
      let jp item 0 j-array
      let j+1-array array:to-list item (j + 1 ) array-as-list
      let jw+1 item 1 j+1-array
      let jp+1 item 0 j+1-array
      if(jw < jw+1)
      [
        set j-array array:from-list(list jp+1 jw+1)
        set j+1-array array:from-list(list jp jw)
        set array-as-list replace-item (j + 1 ) array-as-list j+1-array
        set array-as-list replace-item (j ) array-as-list j-array
        set preference-array array:from-list array-as-list
      ]
      set j j + 1
    ]
    set i i + 1
  ]
end 

to create-preference-ballot
  ;initializes (biblebelt) christians
  if(random-float 1 < christianity-percentage)[set christian true]

  ;randomly assigns strategizing voters
  ifelse( random-float 1 < percent-strategizing) [set strategize true][set strategize false]

  ;determine closest and furthest parties for distance estimations
  let closest-party min-one-of parties [distance myself]
  let furthest-party max-one-of parties [distance myself]

  ; makes a nested array in the form of a[1] is most preferred party and its array.
  ; a[1][0] is the party, and a[1][1] is the weight, ie the normalized distance to a party, in which 1 is closest and 0 is furthest.
  set preference-array array:from-list n-values total-number-of-parties [0]

  ;indexer
  let i 0

  ;go through each party on distance to myself and put them in a preference array
  foreach sort-on [distance myself] parties
  [
    current-party ->
    ;calculates the maximum spread between all parties
    let max-distance   [distance myself] of furthest-party  -  [distance myself] of closest-party
    ;initialize an array for the party, to be put in the larger array
    let preference array:from-list n-values 2 [0]

    ;set first index of array to the current party
    array:set preference 0 current-party

    ; makes random noise, this will give every party distance some randomness. this is true to real life as kieskompas is an approximation, and not everyone actually chooses the closest option
    let noise random-float maximum-noise
    ifelse( random-float 1 < 0.5 )[set noise 1 - noise][set noise 1 + noise]

    ;this way, all parties have a preference from 0 (least approved) to 1 ( most approved)
    let weight 1 - ( 1 / max-distance ) * ([distance myself] of current-party - [distance myself] of closest-party)
    set weight weight * noise

    ;store the weight in the preference
    array:set preference 1 weight
    ;add that preference to this voters preference array for all parties
    array:set preference-array i preference

    set i i + 1
  ]

  ;the following functions are needed to reorganize the arrays according to preferences,
  ;    and prepare those for the voting algorithms
  ;checks if (very) christian or the age is to young to vote for 50+ etc, and reshuffles the array
  apply-values

  set shape "circle"
  set size 7

  ; sorts the array to have highest scoring first and least last via bubble-sort
  reorganize-array

  ;renormalizes array
  let first-party true
  let index 0
  let highest-weight 0
  foreach array:to-list preference-array
  [
    preference ->
    let current-weight array:item preference 1
    let current-party array:item preference 0
    if first-party = true
    [
      set highest-weight current-weight
      set first-party false
    ]
    set current-weight current-weight / highest-weight
    array:set preference-array index array:from-list (list current-party current-weight)

    set index index + 1
  ]

  ; we need to count the votes correctly for the calculation of seats in government
  if(voting-method != "approval")
  [
    set total-number-of-votes total-number-of-votes + 1
  ]
end 

to form-cabinet

  let cabinet-seats 0
  set prime-minister ""
  set cabinet n-values 0 [0]
  foreach sort-by [[?1 ?2] -> [seats] of ?1 >[seats] of ?2] parties
  [
    current-party ->
    if(cabinet-seats < 75 )
    [

      if prime-minister = ""
      [
        set prime-minister [name] of current-party
      ]
      set cabinet-seats cabinet-seats + [seats] of current-party
      set cabinet lput [name] of current-party cabinet
    ]
  ]
  set cabinet-mean cabinet-seats / length cabinet
  initialize-satisfactions
end 

to update-election-results
  set-current-plot "Election results"
  clear-plot
  set-plot-x-range 0 count parties
  let kiesdeler total-number-of-votes / 150
  let highest-vote 0
  let i 0
  let seatcounter 0
  if(party-loyalty = true)
  [
    set kiesdeler total-number-of-votes / (150 - total-loyal-votes )
  ]
  let total-seats-wrong 0
  foreach sort-on[name] parties
  [
    current-party ->
    ask current-party
    [
      ifelse(party-loyalty = false)
      [
        set seats round(votes / kiesdeler)
        set seatcounter seatcounter + seats
      ]
      [
        set seats round(votes / kiesdeler + loyalty-seats)
        set seatcounter seatcounter + seats
      ]
      set total-seats-wrong total-seats-wrong + sqrt((seats  - [actual-seats] of current-party  ) ^ 2)

    ]
    if( [seats] of current-party > highest-vote)
    [
      set highest-vote [seats] of current-party
      set winner [name] of current-party
    ]
    ;output-type [name] of current-party output-type ": " output-type [seats] of current-party output-type " actual seats:" output-print[actual-seats] of current-party
    create-temporary-plot-pen [name] of current-party
    set-plot-pen-mode 1 ; bar mode
    set-plot-pen-color [secundary-party-color] of current-party
    foreach (range 0 [seats] of current-party 0.05) [ _y -> plotxy i _y ]
    set-plot-pen-color black
    plotxy i [seats] of current-party
    set-plot-pen-color [secundary-party-color] of current-party ; to get the right color in the legend
    set i i + 1


  ]

  set accuracy (150 - total-seats-wrong) / 150
  form-cabinet
end 

to actual-election-plot
  set-current-plot "Actual results"
  clear-plot
  set-plot-x-range 0 count parties
  let i 0


  foreach sort-on[name] parties
  [
    current-party ->
    ask current-party
    [

      set seats actual-seats


    ]
    create-temporary-plot-pen [name] of current-party
    set-plot-pen-mode 1 ; bar mode
    set-plot-pen-color [secundary-party-color] of current-party
    foreach (range 0 [seats] of current-party 0.05) [ _y -> plotxy i _y ]
    set-plot-pen-color black
    plotxy i [seats] of current-party
    set-plot-pen-color [secundary-party-color] of current-party ; to get the right color in the legend
    set i i + 1


  ]
end 

to plot-left-right
  let current-xcor -220
  set-current-plot "Voter population on Left Right axis"
  clear-plot
  set-plot-pen-mode 2

  if (voting-method = "approval")
  [
    auto-plot-on
  ]
  set-current-plot-pen "voters"
  let current-party-number 0
  let counter 0
  let highest-voter-slice 0
  let highest-xcor 0
  repeat 440
  [
    set current-party-number 0
    set counter 0
    let voters-in-slice count voters with [ xcor >= current-xcor - 5 and xcor < current-xcor + 5 and approval-colorer != true]
    if voters-in-slice > highest-voter-slice
    [
      set highest-voter-slice voters-in-slice
      set highest-xcor current-xcor
    ]
    repeat total-number-of-parties
    [
      ask voters with [ xcor >= current-xcor - 5 and xcor < current-xcor + 5 and member? party current-party-number ballot = true and approval-colorer != true]
      [
        ifelse strategize = true and display-strategy-in-graph = true
        [
          set-plot-pen-color [primary-party-color] of party current-party-number

        ]
        [

          set-plot-pen-color [secundary-party-color] of party current-party-number

        ]
        ifelse voting-method = "approval"
        [
          set counter (counter + (1 * (voters-in-slice / total-number-of-voters) ) )
        ]
        [
          set counter counter + 1
        ]

        plotxy current-xcor counter
      ]
      set current-party-number current-party-number + 1
    ]
    set current-xcor current-xcor + 1
  ]
  if(display-median = true)
  [
    ask patches with [pxcor = highest-xcor][set pcolor black]
  ]
end 

to plot-progressive-conservative
  let current-ycor -220
  set-current-plot "Voter population on Progressive Conservative axis"
  clear-plot
  set-plot-pen-mode 2
  if (voting-method = "approval")
  [
    auto-plot-on
  ]
  set-current-plot-pen "voters"
  let current-party-number 0
  let counter 0
  let highest-voter-slice 0
  let highest-ycor 0
  repeat 440
  [
    set current-party-number 0
    set counter 0
    let voters-in-slice count voters with [ ycor >= current-ycor - 5 and ycor < current-ycor + 5 and approval-colorer != true]
    if voters-in-slice > highest-voter-slice
    [
      set highest-voter-slice voters-in-slice
      set highest-ycor current-ycor
    ]
    repeat total-number-of-parties
    [
      ask voters with [ ycor >= current-ycor - 5 and ycor < current-ycor + 5 and  member? party current-party-number ballot = true and approval-colorer != true]
      [
        ifelse strategize = true and display-strategy-in-graph = true
        [
          set-plot-pen-color [primary-party-color] of party current-party-number

        ]
        [

          set-plot-pen-color [secundary-party-color] of party current-party-number

        ]
        ifelse voting-method = "approval"
        [
          set counter (counter + (1 * (voters-in-slice / total-number-of-voters) ) )
        ]
        [
          set counter counter + 1
        ]
        plotxy  counter current-ycor

      ]
      set current-party-number current-party-number + 1
    ]
    set current-ycor current-ycor + 1

  ]
  if (display-median = true)
  [
    ask patches with [pycor = highest-ycor][set pcolor black]
  ]
end 

; Please note utility and weights can be used interchangably

to initialize-satisfactions
  calculate-bayesian-regret
  calculate-proportionality
end 

; bayesian-regret measures the population satisfaction with the cabinet.
; bayesian regret does not measure from votes, only by the given weights/ utilities of the voter. it can be seen as the voters feeling of "being listened to" by the democratic system
; it is adjusted for proportionality by looking at party seats, as a voter might be unhappy that his preffered candidate only got 50% of the votes that the actual winner got.

to calculate-bayesian-regret
  let achieved-societal-utility 0
  let winner-seats item 0 [seats] of parties with [name = winner]
  ask voters
  [
    ;this is because of coloring with approval voting, which was kind of buggy due to Netlogo's insufficiencies
    if( approval-colorer != true)
    [

      let utility-winner 0
      foreach array:to-list preference-array
      [
        current-party-array ->
        let current-party array:item current-party-array 0
        ; we add 0.5 to the weight, because parties below 0.5 are disliked and above are liked, we can now measure that in [0.5 -> 1.5] which makes the weights more expressive when multiplied with seats.
        let current-weight (array:item current-party-array 1 + 0.5)  * ([seats] of current-party / winner-seats)
        if(member? [name] of current-party cabinet)
        [
          set utility utility + current-weight
        ]
      ]
      ;; utility is also a agent variable needed for 3D-view
      set utility utility / length cabinet
      set achieved-societal-utility achieved-societal-utility + utility
    ]
  ]
  set bayesian-regret (achieved-societal-utility / total-number-of-voters) - 0.5
end 

to calculate-proportionality
  ask voters
  [
    ;first, we calculate the total ammount of utility for each party
    if( approval-colorer != true)[
      foreach array:to-list preference-array
      [
        current-party-array ->
        let current-party array:item current-party-array 0
        let current-weight array:item current-party-array 1
        ask current-party
        [
          set  party-utility  party-utility + current-weight
        ]
      ]
    ]
  ]
  ;then we divide those, so we have a good measure of population broad utility per party
  ;also, we add all those party utilities up to get a total utility which we can use later
  let total-utility 0
  ask parties
  [
    set party-utility precision (party-utility / total-number-of-voters) 2
    set total-utility total-utility + party-utility
  ]
  ; as total utility will have to be divided among 150 seats, we can calculate how much seats a utility of 1 can buy
  let seats-per-utility 150 / total-utility


  let total-dif 0
  foreach sort-on[party-utility ] parties
  [
    current-party ->
    ask current-party
    [
      ;utility seats is the actual average voters desired amount of seats for that party
      set utility-seats precision (seats-per-utility * party-utility ) 2
      ;then we calculate how much distance the utility seats are from the actual seats given, and add those up.
      ;this gives us the disproportionality between utility and actual votes.
      set total-dif total-dif + (sqrt((seats - utility-seats) ^ 2) / (seats ^ 2 + utility-seats)^ 2)
    ]
  ]
  ;finally, we can set disproportionality, and output it to the model
  set disproportionality total-dif
end 

There is only one version of this model, created almost 2 years ago by Teun de Bilde.

Attached files

File Type Description Last updated
Plurality Versus Approval voting - An elaborate spatial model for voting systems - Online version.png preview Preview for 'Plurality Versus Approval voting - An elaborate spatial model for voting systems - Online version' almost 2 years ago, by Teun de Bilde Download

This model does not have any ancestors.

This model does not have any descendants.