Public Choice Tiebout Sorting
Do you have questions or comments about this model? Ask them here! (You'll first need to log in.)
WHAT IS IT?
The Tiebout hypothesis states that people who are unsatisfied with the policies currently implemented in their community can vote with their feet. This means nothing else that they are allowed to move elsewhere, where they expect to be more satisfied.
HOW IT WORKS
There are three types of agents, citizens, parties and communities. Citizens vote for parties and parties try to achieve a high share of votes and make their program the one that is implemented in the party's community. Citizens also try to maximize their utility by always moving to the community that offers the best policy platform for them.
HOW TO USE IT
The NUM-JURISTDICIONS slider controls how many communities there are in total. Every patch is one community. The NUM-AGENTS slider controls how many citizens there are in the world. The NUM-ISSUES slider controls how many issues are being discussed in every community. The NUM-PARTIES slider controls how many parties there are in every community. This does have no effect if the VOTING-SYSTEM chooser is set to "direct-democracy". The VOTING-SYSTEM chooser lets you choose how citizens preferences are being aggregated. The PROBABILITY-OF-CHANGE-MIND slider controls how volatile citizens preferences are. The AFFLUENCE-NEEDED-TO-MOVE slider controls how wealthy a citizen needs to be to actually move when desired. The WEALTH-DIST chooser lets you choose how the wealth distribution in the society should be initialized. "Normal" is more equal than "beta". The three plots show WELATH ON PATCHES, the numbers of RELOCATIONS having happened so far and the DISTANCE BETWEEN THE REGION PLATFORMS. The latter tells how different the policies are that are currently implemented in the regions.
THINGS TO NOTICE
Every differently shaded patch represents one community. Every yellow figure is a party and every green dot is a citizen. For reasons of space, there are monitors for up to six patches so far. If there are more than six communities, more monitors would have to be added.
THINGS TO TRY
Run the model with different numbers of jurisdictions and see how the average utility on the patches changes.
EXTENDING THE MODEL
Currently issues are binary. This means agents can either be pro (1) or against (0) an issue. Here a more nuanced preference structure would be a very interesting this to study. Currently a maximum of ten percent of citizen change their mind. A even more volatile electorate might have even more disturbing effects across all voting systems.
NETLOGO FEATURES
There is no implemented beta distribution implemented as a NetLogo primitive so far. The workaround was fairly simple tough, as the beta distribution can be derived from a gamma distribution. There were also a few runtime issues, since the Behavior Space experiments grew quite large. This is the reason for the use of the many while-loops because they were found to be the fastest performing loops in most cases. If I am wrong about that, would be grateful for any hints and tips in that direction. Also, the party algorithms take the most runtime in the simulation, comments on improving speed here are also very welcome.
RELATED MODELS
This Model extends and builds upond the three models quoted in the next section.
CREDITS AND REFERENCES
Kollman, Ken, John Miller und Scott Page. 1997. Political Institutions and Sorting in a Tiebout Model. The American Economic Review 87 (5), 977–992. http://www.jstor.org/stable/2951336.
Seagren, Chad W. 2015. A Replication and Analysis of Tiebout Competition Using an Agent-Based Computational Model. Social Science Computer Review 33 (2), 198–216. https://doi.org/10.1177/0894439314534810.
Janssen, Marco. 2019. Tiebout sorting: ComSES. https://www.comses.net/codebases/ab497c2b-0d2d-468a-81ed-3ebedba84f59/releases/1.0.0.
Comments and Questions
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;; BREEDS AND GLOBAL VARIABLES ;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; globals [ relocations interjuris] ; global variable to count relocations and interjuris-distance breed [ parties party ] breed [ citizens citizen ] patches-own [ current-platform ; a list positions (0 = no; 1 = yes) on every issue currently in force in every jusristicion majorparty ; the current biggest party in this community sharevotes; the share of votes every party in the juristicion currently holds mean-wealth ; mean wealth (money) of citizens on this patch max-wealth ; wealth of richest agent on patch ] parties-own [ platform ; a list of positions on every issue the party currently propagates prop-platform ; a helper list to store a hypothetical platform a party could progapagate, to see how well it would do in elections newsharevotes ; a helper variable to store the votes a party would get with prop-platform lastexpsharevotes ; a helper variable to store the parties votes with their last proposed platform party-id ; a id that numerates all parties within their community ] citizens-own [ preferences ; a list of utility gained, if a issue were implemented utility ; the actual utility gained in the community the agent is currently living in exp-utility ; utility the agent would expect to recieve in another community party-distance ; a list to calculate the distance from the agents positions to every parties position on every issue in the community destination ; the x-coordinate of the patch where an agent can expect higher utility money ; money to move rank-list ; ranking of parties for borda count ] ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;; SETUP PROCEDURES ;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; to setup clear-all reset-ticks setup-patches ; sets up all patches, also sets up the party-agents within all the patches setup-citizens ; creates all citizens with their initial variables calculate-utility end to setup-citizens create-citizens num-agents ask citizens [ set shape "circle" set size 0.04 set color green if wealth-dist = "beta" [set money (random-beta 2 5) * 1000] ; a society with a skewed distribution of wealth if wealth-dist = "normal" [set money random-normal 500 125] ; a society with a quite egalitarian distribution of wealth set utility 0 ; initialize utility for every agent at -10 set preferences [] ; empty list for storing preferences let i 0 while [i < num-issues] ; loop over all issues; [ let pref random-float ( 800 / num-issues) - (400 / num-issues) ; use condition applied by Kollman et al. (1997) set preferences lput pref preferences ; append preference on issue i to preference lists of agents set i i + 1 ; preferences are drawn from a random distribution, the more issues there are the more split ] ; up the preferance space gets (e.g. with 2 issues the maximum value of utility of each ; issue is 200; with 10 issues this value shrinks to 40 go-to patch-at random-pxcor random-pycor ; moves agents around inside their patch, so they dont stack on one another in the middle ] end to-report random-beta [ p q ] let gamma1 random-gamma p 1 let gamma2 random-gamma q 1 let result gamma1 / ( gamma1 + gamma2 ) report result end to setup-patches resize-world 0 (num-jurisdictions - 1) 0 0 ; create patches given by the slider, all alonge the x-axis ask patches [ if any? citizens-here[ set mean-wealth mean [money] of citizens-here set max-wealth max [money] of citizens-here] set pcolor random 10 set current-platform [] ; empty list for platform on num-issues let i 0 while [ i < num-issues ] [ set current-platform lput random 2 current-platform ; let the patches platforms be randomly chosen form 0 (con) and 1 (pro) set i i + 1 ] ; create parties in each justisticion if voting-system = "two-party-majority" [ set num-parties 2 sprout-parties num-parties set sharevotes n-values num-parties [0]] ; two parties on every patch with initial sharevotes 0 if voting-system = "multi-party-proporional" [ sprout-parties num-parties set sharevotes n-values num-parties [0]] ; num-parties parties on every patch with initial sharevotes 0 if voting-system = "multi-party-relative-majority" [ sprout-parties num-parties set sharevotes n-values num-parties [0]] ; num-parties parties on every patch with initial sharevotes 0 if voting-system = "borda-count" [ sprout-parties num-parties set sharevotes n-values num-parties [0]] ] ; num-parties parties on every patch with initial sharevotes 0 ask parties[ set size 0.1 set shape "person" set color yellow set party-id who mod num-parties ; enumerates all parties from 0 to num-parties within every community go-to patch-here set platform [] let i 0 while [i < num-issues] [ set platform lput random 2 platform ; let the parties platforms be randomly chosen form 0 (con) and 1 (pro) set i i + 1 ] ] end ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;; GO PROCEDURES ;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; to go calculate-utility ; calculates the utility agents get in their current community move-citizens ; exit, citizens move to another community, where they expect the recieve more utility let r 0 while [r < 5] [ parties-change ; gives the parties a chance to adapt their platforms, according to voters tastes set r r + 1 ] alter-platform calculate-interjuris-distance change-preferences tick end to go-to [ some-patch ] setxy ([ pxcor ] of some-patch + (random-float 0.9) - 0.45) ([ pycor ] of some-patch + (random-float 0.9) - 0.45) end to calculate-utility ask patches[ ask citizens-here[ set utility 0 let i 0 while [ i < num-issues ] [ set utility utility + item i preferences * item i current-platform set i i + 1 ] ] ] end to move-citizens ; citizens may move to other jurisdictions if they expect a higher utility ask citizens[ ; asks all citizens to do something let agent self ; sets the current citizen doing something let j 0 while [ j < num-jurisdictions ] ; loop over all jurisdictions [ let exp-utility_help [utility] of agent ; a helper variable to store the citizens utility for patch j-1 set exp-utility 0 ; set the expected utility of the agent (self) 0 ask patch j 0 [ ; ask patch j to do something let i 0 while [ i < num-issues ] ; loop over all issues [ ask agent [ set exp-utility exp-utility + item i preferences * item i [current-platform] of patch j 0 ] ; calculate the expected utility set i i + 1 ] ] ask agent [ if exp-utility > exp-utility_help [ set destination j ; set the x-coordinate of the patch the agent will move to set utility exp-utility ; set the new utility ] ] set j j + 1 ] ] ask citizens [ if [pxcor] of patch-here != destination and ( money > ( affluence-needed-to-move * [mean-wealth] of patch destination 0 ) ) ; or random 101 < 10 ) ; affluence-needed-to-move is the percentage of wealth (his money) an agent needs to have in relation to his destination patch ; if this condition is fulfilled, the agent wants to move. if he has to money to do so, he will do it, otherwise its a game of chance [move-to patch destination 0 go-to patch-at random-pxcor random-pycor set relocations relocations + 1 ]] ; whenever an agent finds a patch with higher utility, the relocation counter ; is increased, agents reloate all at once ask patches [ if any? citizens-here [set mean-wealth mean [money] of citizens-here]] end to change-preferences if random 101 < probability-of-change-mind [ ; chance thank an "event" takes place in whichs consequence some citizens change their mind ;ask n-of (int (0.10 * count citizens)) citizens [ ; only every 10th citizen is influenced ask citizens [ ;ask citizens with [who mod 10 = 0][ ; only every 10th citizens is influenced let i 0 while [i < num-issues] [ if random 101 < probability-of-change-mind ; in addition to an event taking place, that event has to actually ; influence the opinion of an agent [ let pref random-float ( 800 / num-issues ) - ( 400 / num-issues ) set preferences replace-item i preferences pref ] set i i + 1 ] ] ] end to alter-platform if voting-system = "direct-democracy"[ ask patches [ ; in direct democracy the median vote is the platform that wins let i 0 if count citizens-here > 0[ while [ i < num-issues ] [ let medianvote median [item i preferences] of citizens-here;loop over issues and calculate median of citizens ifelse medianvote < 0 ;if preferences of citizens are negative towards issue i... [set current-platform replace-item i current-platform 0];...the platform of the patch is 0 (agianst issue) [set current-platform replace-item i current-platform 1];...else...the platform of the patch is 1 (pro issue) ;print medianvote set i i + 1 ] ] ] ] if voting-system = "two-party-majority" [ vote ask patches [ let maxsharevotes max sharevotes let j 0 while [j < num-parties] [ if maxsharevotes = item j sharevotes [set majorparty j] set j j + 1 ] set current-platform [platform] of one-of parties-here with [party-id = majorparty] ; KANN DAS NICHT VERKÜRZT WERDEN??? ] ] if voting-system = "multi-party-proporional" [ vote ask patches [ let i 0 while [ i < num-issues ] [ let j 0 let voteissue 0 ; local variable to store proporional representation for each issue, considering all party proporional to their voteshare while [ j < num-parties ] [ set voteissue voteissue + item j sharevotes * [item i platform] of one-of parties-here with [party-id = j] ; if for example a party has 0.3 of the votes and is in favour of an issue the result for this party is the following: ; 0.3*1, so the pro vote of that party on the issue is taken into account proporional to its electoral success ; if it is against an issue: 0.3*0, therefore the whole vote is weight down in direction of 0, which makes it harder ; for other parties that are in favour of that issue to still reach the threshold of 0.5 to pass a 'yes' vote on the issue set j j + 1 ] ifelse voteissue = 0.5 [][ ; in case of an exact parity of votes, nothing happens, otherwise... ifelse voteissue < 0.5 ;...if the the proportional votes are below 0.5... [set current-platform replace-item i current-platform 0];...the patches platform is set to zero [set current-platform replace-item i current-platform 1]];...otherwise the patches platform is set to one set i i + 1 ] ] ] if voting-system = "multi-party-relative-majority" [ ; in a system with many parties and relative majority ... vote ; ... again, people vote ask patches [ let maxsharevotes max sharevotes let j 0 while [j < num-parties] [ if maxsharevotes = item j sharevotes [set majorparty j] ; just as with absolute majority, the party that has the most votes ... set j j + 1 ; ... will win. The only difference is, that now a party can win with e.g. 30% of the votes, if no other as more ] set current-platform [platform] of one-of parties-here with [party-id = majorparty] ; patches platform is set to winning parties platform ] ] if voting-system = "borda-count"[ ; in a borda count system with many parties vote ask patches [ let maxsharevotes max sharevotes let j 0 while [j < num-parties] [ if maxsharevotes = item j sharevotes [set majorparty j] ; just as with absolute majority, the party that has the most votes ... set j j + 1 ; ... will win. The only difference is, that now a party can win with e.g. 30% of the votes, if no other as more ] set current-platform [platform] of one-of parties-here with [party-id = majorparty] ; patches platform is set to winning parties platform ] ] end to vote ask patches [ let cumvotes n-values num-parties [0] ; list with zeros to store cumulated votes of all parties ask citizens-here [ set party-distance n-values num-parties [0] ; fill list of citizens to measure distance to parties with zeros let j 0 while [j < num-parties] ; loop over parties... [ let i 0 while [ i < num-issues]; ... and over issues [ ;if one-of parties-here with party-id = j set party-distance replace-item j party-distance (item j party-distance + (item i preferences) * ([item i platform] of one-of parties-here with [party-id = j])) ; the line above gives every citizen a utility according to a parties platform (wether the party ; show party-distance set i i + 1 ] set j j + 1 ] ifelse voting-system = "borda-count" [ ;;;;;;;;;;;;;;;;;;;;;;;;;; voting for borda ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; let party-dist-sorted sort-by < party-distance ; sort parties in increasing order set rank-list [] foreach party-distance [ x -> set rank-list lput ( position x party-dist-sorted ) rank-list ; show party-distance ; show rank-list ] let kk 0 while [kk < num-parties] [ set cumvotes replace-item kk cumvotes (item kk cumvotes + item kk rank-list) set kk kk + 1 ]] [ ;;;;;;;;;;;;;;;;;;;;;;;;;; voting in all other systems with parties ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; let kk 0 while [kk < num-parties] [ if max party-distance = item kk party-distance [set cumvotes replace-item kk cumvotes (item kk cumvotes + 1)] set kk kk + 1 ] ] ;;;;;;;;;;;;;;;;;;;;;;;;;;; calculating vote share, same for borda and others ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; let k 0 while [k < num-parties] [ set sharevotes replace-item k sharevotes ( item k cumvotes / ( sum cumvotes + 0.0000000000000000000000001 ) ) set k k + 1 ] ] ] end to poll-voters set newsharevotes n-values num-parties [0] ; list of zeros to store every parties new voteshare let cumvotes n-values num-parties [0] ; list of zeros to store every parties new cumulated votes ask n-of (int (0.10 * count citizens-here)) citizens-here [ ; poll only 10 percent of citizens let exputility-party n-values num-parties [0] ; list of zeros to store citizens expected utility from parties let j 0 while [j < num-parties] [ let exputil_help 0 let party_j one-of parties-here with [party-id = j] let i 0 while [ i < num-issues] [ set exputil_help exputil_help + (item i preferences) * ([item i prop-platform] of party_j) set i i + 1 ] set exputility-party replace-item j exputility-party exputil_help set j j + 1 ] let kk 0 while [kk < num-parties] [ if max exputility-party = item kk exputility-party [set cumvotes replace-item kk cumvotes (item kk cumvotes + 1)] set kk kk + 1 ] ] let i 0 while [i < num-parties] [ set newsharevotes replace-item i newsharevotes (item i cumvotes / (sum cumvotes + 0.0000000000000000000000001)) set i i + 1 ] end to parties-change ask parties [set prop-platform platform] ask parties [ poll-voters set lastexpsharevotes item party-id newsharevotes let k 0 while [k < 8] [ set prop-platform platform let i 0 while [i < 3] ; every party has 3 chances to change its platform to get a higher voter turnout [ set prop-platform replace-item ( random num-issues ) prop-platform ( random 2 ) set i i + 1 ] poll-voters if item party-id newsharevotes > lastexpsharevotes [set platform prop-platform set lastexpsharevotes item party-id newsharevotes] set k k + 1 ] ] end to calculate-interjuris-distance let j 0 let k 1 ; start k one ahead of j let cumsum 0 while [j < num-jurisdictions] ; to achieve all possible pairwise comparisons we have to go over all patches ... [ while [k < num-jurisdictions] ; ... and every patch that is one index higher [ let list1 [current-platform] of patch j 0 ; get platform of patch j let list2 [current-platform] of patch k 0 ; get platform of patch k let diff (map - list1 list2) ; calculate the difference of every item in the plaforms let diff2 (map * diff diff) ; square it, so that there are no negative values (its all zeros and ones anyway, so nothing bad will happen) let sumdiff sum diff2 ; get the sum of that list set cumsum cumsum + sumdiff ; cumulate that sum set k k + 1 ] set j j + 1 ; set j to the next patch ... set k j + 1 ; ... and set k to one index higher then j ] set interjuris cumsum set interjuris ( cumsum / num-issues) ; interjuris distance is calculated by dividing the cumulated error sum by the number of issues ... set interjuris ( interjuris / ( ( num-jurisdictions * ( num-jurisdictions - 1 ) ) / 2 ) ) ; ... and also take the mean of all possible pairwise comparisons end
There is only one version of this model, created over 6 years ago by Patrick Schwabl.
Attached files
File | Type | Description | Last updated | |
---|---|---|---|---|
Public Choice Tiebout Sorting.png | preview | Preview for 'Public Choice Tiebout Sorting' | over 6 years ago, by Patrick Schwabl | Download |
This model does not have any ancestors.
This model does not have any descendants.