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 ;;;