The applet requires Java 5 or higher. Java must be enabled in your browser settings. Mac users must have Mac OS X 10.4 or higher. Windows and Linux users may obtain the latest Java from Oracle's Java site.
powered by NetLogo
view/download model file: wealth_taxation_elections.nlogo
The simulation of a simplified society includes agents able to find, consume and store resources (grain) coming from the environment. It shows how wealth distribution and resource availability are related and how they evolve.
In addition, an elementary democratic system has been included. Representatives can change three different taxation levels. Taxation income is transferred to the poorest creating a primitive redistribution system.
The goal is to study how redistribution, taxation and elections affect the economy of such agents.
Two sliders allow the observer to choose a rectangle of space in which resources will be present. There is only one resource, called "grain", and its amount varies in spece.
Turtles collect grain, store it, and consume a certain part of their resources in each time unit. They have a limited "vision", in fact they notice the presence of grain only if it is not too far, furthermore they are able to move towards the patch with the highest grain quantity they can see.
Grin income, storage and consumption are liable for taxation.
Besides such basic skills, all turtles are required to choose a number of representatives proportional to their number.
Voting for a particular candidate id determined by the difference between agent's and candidate's preferences about taxation levels.
Elections consist of two steps: the creation of candidates and the choice of representatives; a switch allows to decide whether reelection is possible or not.
Representatives can form alliances, represented by links, on the basis of their preferences in the field of taxation. The largest alliance becomes the majority and it will be able to vary taxation levels.
The observer can channel taxation income into grain redistribution for the poorest agents' benefit.
It is possible to choose if agents are subject to death caused by absence of grain or by old age; if so, and if the agents' wealth crosses a certain threshold, they can reproduce and they have share their current grain amount with the new agent.
The "go" procedure is the core of the model. First of all it makes turtles move towards the best source of grain. When different turtles reach the same patch, they divide up the grain available. The procedure "go-towards-grain" is very similar to the one used in the NetLogo Library model "Wealth Distribution".
The procedure "update-economy" updates incomes and wealths, implements taxation and redistribution, while "simulate-gov" allows majority to modify taxation levels and updates redistribution levels ("wealth0" ,...).
"recolor-turtles" enables the observer to recognize turtles of different classes at a glance, since they are colored according to their wealth class.
The democratic system is regulated by "simulate-elections": candidates are chosen randomly, reelection can be forbidden by the observer as well as government duration. The number of representatives is proportional to the population number by means of a constant fixed by the observer.
Globals and interface
Taxation variables and election-related agentsets are represented by global variables and are updated regularly; "wealth0", etc. can be interpreted as artificial poverty levels: if a turtle's values get under them, the turtle is suitable for redistribution. In our case such levels are fractions of the respective mean value.
The interface is divided into three groups of operating controls, which govern, respectively, turtles, patches and social behavior.
Two important regulations concern the already mentioned death switch and the "check" switch: the first one strongly influences the evolution of the model and the second one ensures that taxation levels make sense (between 1 and 99 per cent).
Patches
There are two variables related to patches, grain-here reports the current amount of grain present on each patch, while max-grain here is the maximum amount of grain that a patch can contain. The first variable changes in each time unit, while the second one is determined (up to a random variable) only at the beginning of every simulation.
Patches whose coordinates are smaller (in absolute value) of X and Y will contain grain, the other won't. Grain is not uniformly distributed: it is abundant in the upper right corner of the world and it is lacking in the opposite corner.
In order to have a gradual variation of grain quantity, patches are asked to diffuse their grain; the process is repeated five times so that the result is (aesthetically) better. The intensity of patches color is proportional to their grain abundance.
Turtles
If the death switch is on, turtles grow in age, consume grain and con reproduce (with a sort of mitosis), age, predetermined life expectancy, grain consumption (metabolism) and number of children is saved in two corresponding variables.
Every turtle has a non-negative grain income and consumption (for the sake of simplicity, the last one is equal to metabolism). Obviously, Income is added to wealth while consumption is subtracted, which means wealth might be negative (if turtles can't die).
"Candidate" and "representative" are true if the considered turtle belongs to the corresponding agentset. Turtles identify a set of candidates whose three taxation preferences differ less than "tolerance" from their own. If such set is empty, "abstention" becomes true, otherwise they chose randomly one of their candidates and make his number of votes increase.
Links
Links represent alliances between representatives. First representatives with similar preferences create a link, then all turtles connected in some way create new links with each other (complete graph). This last operation is repeated by the largest alliance in order to form the majority.
Several experiments can be conducted from the interface using Rserve extension: after creating a connection between NetLogo and R ("init"), the observer should write in two input boxes the name of the desired switch and turtle variable.
Pressing "experiment" button we get a table consisting of four plot: the first column is referred to the "off" state of the switch, the second one to the "on" state. The upper plots contain time on the horizontal axis and the evolution of the mean of our variable on the vertical one; also the regression line of these data is drawn. The underlying plots are "boxplot" of the previous sequences.
I used commands "run" and "runresult" in order to make Netlog transform input strings into variables, then I sent data to R and put them in the form of "data frames", finally I used "lm" (linear model) to perform linear regression.
I suggest trying different combinations of patch parameters and different dimension of the "fertile rectangle". Furthermore the observer can choose to activate only a part of the many switches present in the model.
It could be interesting to change maximum grain available on patches, creating artificial economic crisis or expansion, or to simulate a catastrophe with button "black death".
This model could be improved in a huge number of ways: public services and public costs might be included, different electoral rules could be implemented.
It would be challenging to introduce competition or cooperation between turtles, as well making them change preferences according to a suitable happiness indicator.
Wilensky, U. (1998). NetLogo Wealth Distribution model. Center for Connected Learning and Computer-Based Modeling, Northwestern Institute on Complex Systems, Northwestern University, Evanston, IL.
Jan C. Thiele, Boxplot example of Rserve-extension, University of Goettingen.
;;; Luca Alasio - Wealth Distribution and Elections - 08/2013 ;;; globals [ tax-income candidates representatives majority wealth-tax income-tax consumption-tax wealth0 income0 consumption0 ] patches-own [ grain-here max-grain-here ] turtles-own [ age life-expectancy metabolism vision children wealth-tax-pref income-tax-pref consumption-tax-pref candidate representative num-votes income wealth consumption abstention tolerance ] extensions [rserve] ;;; SETUP to setup ca if myseed != 0 [random-seed myseed] ;print myseed set tax-income 0 setup-patches setup-turtles setup-voting-system reset-ticks setup-my-plots update-my-plots end to setup-patches ;; give some patches the highest amount of grain possible -- ;; these patches are the "best land" ask patches [ set max-grain-here 0 if (abs(pxcor) < X and abs(pycor) < Y) [ if (random-float 100.0) <= percent-best-land [ set max-grain-here max-grain set grain-here max-grain-here if (pxcor > X / 2 and pycor > Y / 2) [ set max-grain-here max-grain * 3 set grain-here max-grain-here ] if (pxcor < (-1 * X / 2) and pycor < (-1 * Y / 2)) [ set max-grain-here max-grain / 3 set grain-here max-grain-here ] ] ]] ;; spread that grain around the window a little and put a little back ;; into the patches that are the "best land" found above repeat 5 [ ask patches with [max-grain-here != 0] [ set grain-here max-grain-here ] diffuse grain-here 0.25 ] repeat diffusion [ diffuse grain-here 0.25 ] ;; spread the grain around some more ask patches [ set grain-here floor grain-here ;; round grain levels to whole numbers set max-grain-here grain-here ;; initial grain level is also maximum recolor-patch ] end to recolor-patch ;; patch procedure -- use color to indicate grain level set pcolor scale-color yellow grain-here 0 max-grain end ;; set up the initial values for the turtle variables to setup-turtles set-default-shape turtles "person" crt num-people [ move-to one-of patches set size 1.5 set-initial-turtle-vars set age random life-expectancy ] recolor-turtles end to set-initial-turtle-vars set age 0 face one-of neighbors4 set life-expectancy life-expectancy-min + random (life-expectancy-max - life-expectancy-min + 1) set metabolism metabolism-min + random metabolism-max set wealth metabolism + random 50 set vision 1 + random max-vision set children 0 end ;; Set the class of the turtles -- if a turtle has less than a third ;; the wealth of the richest turtle, color it red. If between one ;; and two thirds, color it green. If over two thirds, color it blue. to recolor-turtles let max-wealth 0 if (count turtles > 0) [ set max-wealth max [wealth] of turtles ] ask turtles [ ifelse (wealth <= max-wealth / 5) [ set color red ] [ ifelse (wealth <= (max-wealth * 2 / 5)) [ set color orange ] [ ifelse (wealth <= max-wealth * 3 / 5) [ set color yellow ] [ ifelse (wealth <= (max-wealth * 4 / 5)) [ set color green ] [ set color blue ] ] ] ] ] end to setup-voting-system set candidates no-turtles set representatives no-turtles ask turtles [ set wealth-tax-pref abs random-normal 0 0.01 set income-tax-pref abs random-normal 0.3 0.1 set consumption-tax-pref abs random-normal 0.2 0.1 set candidate false set representative false set num-votes 0 set abstention 0 set tolerance random-float init-tolerance ] set income-tax random-float 0.4 set wealth-tax random-float 0.005 set consumption-tax random-float 0.2 set majority no-turtles end ;;; GO to go ask turtles [ turn-towards-grain ] ;; choose direction holding most grain within the turtle's vision simulate-economy simulate-gov ask turtles [ move-eat-age-die ] recolor-turtles if update-pref? = true [update-preferences turtles with [representative = false]] if ticks mod grain-growth-interval + floor ( abs( random-normal 0 2 ) ) = 0 [ ask patches [ grow-grain ] ] simulate-elections ifelse show-links = false [ask links [ set hidden? true ]] [ask links [ set hidden? false ]] check-values tick update-my-plots end ;; determine the direction which is most profitable for each turtle in ;; the surrounding patches within the turtles' vision to turn-towards-grain ;; turtle procedure set heading 0 let best-direction 0 let best-amount grain-ahead set heading 90 if (grain-ahead > best-amount) [ set best-direction 90 set best-amount grain-ahead ] set heading 180 if (grain-ahead > best-amount) [ set best-direction 180 set best-amount grain-ahead ] set heading 270 if (grain-ahead > best-amount) [ set best-direction 270 set best-amount grain-ahead ] set heading best-direction end to-report grain-ahead ;; turtle procedure let total 0 let how-far 1 repeat vision [ set total total + [grain-here] of patch-ahead how-far set how-far how-far + 1 ] report total end to grow-grain ;; patch procedure ;; if a patch does not have it's maximum amount of grain, add ;; num-grain-grown to its grain amount if (grain-here < max-grain-here) [ set grain-here grain-here + num-grain-grown + random-normal 0 5 ;; if the new amount of grain on a patch is over its maximum ;; capacity, set it to its maximum if (grain-here < 0 ) [ set grain-here 0 ] if (grain-here > max-grain-here) [ set grain-here max-grain-here ] recolor-patch ] end ;; each turtle harvests the grain on its patch. if there are multiple ;; turtles on a patch, divide the grain evenly among the turtles to simulate-economy ask turtles [ set income grain-here / (count turtles-here) set wealth (wealth + income) ] calc-taxes ask turtles [ set grain-here 0 recolor-patch ] if redistribution? = true [redistribute] end to redistribute ask turtles [ if (color = red) [ set wealth wealth + 0.6 * tax-income / (1 + count turtles with [color = red] ) ] if (color = orange) [ set wealth wealth + 0.3 * tax-income / (1 + count turtles with [color = orange] ) ] ] set tax-income tax-income / 10 end to move-eat-age-die fd 1 ;; consume some grain according to metabolism set wealth (wealth - metabolism) ;; grow older set age (age + 1) if (death = True) [ if (wealth < 0) [ die ] if (age >= life-expectancy + random-normal 0 3) [;set grain-here grain-here + wealth ;set pcolor green die] if (wealth > cost-of-children) and (age <= random-normal 0 5 + life-expectancy / 2) and (age >= random-normal 0 5 + life-expectancy / 5 and count turtles < count patches) [ set wealth ( wealth / 2) hatch 1 [ lt 45 fd 1 set age 0 set children 0 set metabolism floor ( 1 + abs ( metabolism + random-normal 0 2 ) ) set life-expectancy life-expectancy + random-normal 0 5 set income-tax-pref income-tax-pref + random-normal 0 0.1 set wealth-tax-pref income-tax-pref + random-normal 0 0.01 set consumption-tax-pref income-tax-pref + random-normal 0 0.1 ] set children children + 1 ] ] end to simulate-elections ifelse ticks mod gov-duration = 0 [ ask turtles [set num-votes 0] ask links [die] ask turtles [forward random 10 set size 1] choose-candidates vote ] [ ifelse ticks mod gov-duration = 1 [ choose-representatives make-alliances form-majority ] [if rep-retribution? = true [pay-representatives]] ] end to choose-candidates ifelse re-election = true [ cancel-representatives create-candidates ] [ create-candidates cancel-representatives ] end to cancel-representatives ask representatives [set representative false set label ""] set representatives no-turtles end to create-candidates repeat ceiling count turtles / prop-candidates [ ifelse death = true [ let poss-cand turtles with [candidate = false and representative = false and age >= 18 and age <= 90 ] if any? poss-cand [ ask one-of poss-cand [set candidate true] ] ] [ ask one-of turtles with [candidate = false and representative = false ] [set candidate true] ] ] set candidates turtles with [candidate = true] ask candidates [set label "C"] end to vote ask turtles [ let my-wealth-tax-pref [wealth-tax-pref] of self let my-income-tax-pref [income-tax-pref] of self let my-consumption-tax-pref [consumption-tax-pref] of self let my-candidates candidates with [ abs ( income-tax-pref - my-income-tax-pref) < tolerance and abs ( wealth-tax-pref - my-wealth-tax-pref) < tolerance and abs ( consumption-tax-pref - my-consumption-tax-pref) < tolerance ] ifelse any? my-candidates [ ask one-of my-candidates [set num-votes num-votes + 1] set abstention 0 ] [set abstention 1] ] end to choose-representatives repeat ceiling count turtles / prop-representatives [ ask one-of candidates with [num-votes = max [num-votes] of candidates] [ set candidate false set representative true set candidates turtles with [candidate = true] ] ] cancel-candidates set representatives turtles with [representative = true] ask representatives [set label "R"] end to pay-representatives ask representatives [set income income + tax-income / (10 * count representatives)] end to cancel-candidates ask candidates [set candidate false set label ""] set candidates no-turtles end to make-alliances ask representatives [ let my-wealth-tax-pref [wealth-tax-pref] of self let my-income-tax-pref [income-tax-pref] of self let my-consumption-tax-pref [consumption-tax-pref] of self ;let my-gov-spending-pref [gov-spending-pref] of self ;let my-synthesis my-wealth-tax-pref + my-income-tax-pref + my-consumption-tax-pref let my-allies other representatives with [ abs ( income-tax-pref - my-income-tax-pref) < tolerance and abs ( wealth-tax-pref - my-wealth-tax-pref) < tolerance and abs ( consumption-tax-pref - my-consumption-tax-pref) < tolerance ] create-links-with my-allies ;ask my-allies [ create-links-with other my-allies ] ] ask representatives [ let my-allies representatives with [link-neighbor? myself = true] ask my-allies [ create-links-with other my-allies setxy [xcor] of myself [ycor] of myself ] ] end to form-majority set majority representatives with [count my-links = max [count my-links] of turtles] ask majority [set size 2.5] if majority != no-turtles [ let maj-income-tax-pref mean [income-tax-pref] of majority let maj-wealth-tax-pref mean [income-tax-pref] of majority let maj-consumption-tax-pref mean [income-tax-pref] of majority ask representatives [ if size < 2.5 and abs ( income-tax-pref - maj-income-tax-pref) < tolerance and abs ( wealth-tax-pref - maj-wealth-tax-pref) < tolerance and abs ( consumption-tax-pref - maj-consumption-tax-pref) < tolerance [set size 2.5] ] ] set majority turtles with [size = 2.5] ask majority [ create-links-with other majority ] end to simulate-gov if majority != no-turtles [ ifelse income-tax > mean [income-tax-pref] of majority [set income-tax income-tax - 0.01] [set income-tax income-tax + 0.01] ifelse wealth-tax > mean [wealth-tax-pref] of majority [set wealth-tax wealth-tax - 0.001] [set wealth-tax wealth-tax + 0.001] ifelse consumption-tax > mean [consumption-tax-pref] of majority [set consumption-tax consumption-tax - 0.01] [set consumption-tax consumption-tax + 0.01] ] set tax-income (sum [income] of turtles with [income > 0]) * income-tax + (sum [wealth] of turtles with [wealth > 0]) * wealth-tax + (sum [consumption] of turtles with [consumption > 0]) * consumption-tax set income0 0.5 * mean [income] of turtles set wealth0 0.1 * mean [income] of turtles set consumption0 0.5 * mean [income] of turtles end to calc-taxes ask turtles with [income > income0] [ set income income * (1 - income-tax) set consumption metabolism set wealth (wealth + income - consumption) * (1 - wealth-tax) ] end to update-preferences [agentset] ask agentset with [representative = false ] [ ifelse income > income0 [set income-tax-pref income-tax-pref - 0.01] [set income-tax-pref income-tax-pref + 0.01] ifelse wealth > wealth0 [set wealth-tax-pref wealth-tax-pref - 0.001] [set wealth-tax-pref wealth-tax-pref + 0.001] ifelse consumption > consumption0 [set consumption-tax-pref consumption-tax-pref - 0.01] [set consumption-tax-pref consumption-tax-pref + 0.01] ] end to check-values if check = true [ ask turtles [ if income-tax-pref <= 0 [set income-tax-pref 0.01] if income-tax-pref >= 1 [set income-tax-pref 0.99] if wealth-tax-pref <= 0 [set wealth-tax-pref 0.001] if wealth-tax-pref >= 0.1 [set wealth-tax-pref 0.09] if consumption-tax-pref <= 0 [set consumption-tax-pref 0.01] if consumption-tax-pref >= 1 [set consumption-tax-pref 0.99] ] if income-tax <= 0 [set income-tax 0.01] if income-tax >= 1 [set income-tax 0.99] if wealth-tax <= 0 [set wealth-tax 0.001] if wealth-tax >= 0.1 [set wealth-tax 0.09] if consumption-tax <= 0 [set consumption-tax 0.01] if consumption-tax >= 1 [set consumption-tax 0.99] ] end to black-death ask turtles [ if ( xcor > 0 ) [ die ] ] end to crisis ask patches [ set max-grain-here max-grain-here - 1 recolor-patch ] end to boom ask patches [ set max-grain-here max-grain-here + 1 recolor-patch ] end ;;; PLOTTING to setup-my-plots set-current-plot "Class Plot" set-plot-y-range 0 num-people set-current-plot "Class Histogram" set-plot-y-range 0 num-people set-current-plot "people" set-current-plot "children" set-current-plot "metabolism" set-current-plot "wealth" set-current-plot "age" end to update-people-plot set-current-plot "people" plot count turtles end to update-meta-plot set-current-plot "metabolism" plot mean [metabolism] of turtles end to update-wealth-plot set-current-plot "wealth" set-current-plot-pen "wealth" plot mean [wealth] of turtles set-current-plot-pen "max-wealth" plot max [wealth] of turtles end to update-age-plot set-current-plot "age" set-current-plot-pen "age" plot mean [age] of turtles set-current-plot-pen "max-age" plot max [age] of turtles end to update-children-plot set-current-plot "children" set-current-plot-pen "n-children" plot mean [children] of turtles set-current-plot-pen "max" plot max [children] of turtles end to update-tax-plot set-current-plot "tax-income" set-current-plot-pen "tax-income" plot tax-income end to update-my-plots if (count turtles > 0) [ update-class-plot update-class-histogram update-people-plot update-children-plot update-meta-plot update-wealth-plot update-age-plot update-tax-plot ] end ;; this does a line plot of the number of people of each class to update-class-plot set-current-plot "Class Plot" set-current-plot-pen "low" plot count turtles with [color = red] set-current-plot-pen "mid-low" plot count turtles with [color = orange] set-current-plot-pen "mid" plot count turtles with [color = yellow] set-current-plot-pen "mid-up" plot count turtles with [color = green] set-current-plot-pen "up" plot count turtles with [color = blue] end ;; this does a histogram of the number of people of each class to update-class-histogram set-current-plot "Class Histogram" plot-pen-reset set-plot-pen-color red plot count turtles with [color = red] set-plot-pen-color orange plot count turtles with [color = orange] set-plot-pen-color yellow plot count turtles with [color = yellow] set-plot-pen-color green plot count turtles with [color = green] set-plot-pen-color blue plot count turtles with [color = blue] end ;;; Rserve to init carefully [rserve:init 6311 "localhost"] [user-message "Warning, Rserve connection needed"] end to close carefully [rserve:close] [user-message "Warning, Rserve connection needed"] end to experiment carefully [ if myseed = 0 [set myseed new-seed] let temp (word "set " switch-name " false") run temp run-exp num-ticks 1 let temp1 (word "set " switch-name " true") run temp1 run-exp num-ticks 2 ] [user-message "Warning, Rserve connection needed"] end to run-exp [numrep n] setup let var [] set var [runresult(var-name)] of turtles rserve:put "x" mean var rserve:put "t" ticks rserve:eval "df1 <- data.frame(variable = x)" rserve:eval "df2 <- data.frame(time = t)" repeat numrep [ go set var [runresult(var-name)] of turtles rserve:put "x" mean var rserve:put "t" ticks rserve:eval "df1 <- rbind(df1, x)" rserve:eval "df2 <- rbind(df2, t)" ] rserve:eval "df <- cbind(df1, df2)" rserve:eval "attach(df)" rserve:eval "regr <- lm(variable~time)" if n = 1 [rserve:eval "par(mfcol=c(2,2))"] rserve:eval "plot(time, variable)" rserve:eval "abline(regr)" rserve:eval "boxplot(variable)" end ;;; Luca Alasio - Wealth Distribution and Elections - 08/2013 ;;;