-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgentaxelling-0.2.17.nlogo
2525 lines (2270 loc) · 74.7 KB
/
gentaxelling-0.2.17.nlogo
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
extensions [table]
globals [immigration districts file-name-pop file-name-entropy file-name-prices file-name-income file-name-world file-name-allured version save-directory
allured-districts firstallure declining neighbourhoods-table ;; compiles a list of neighbouhoods at start for quick lookup when running
disp-freq ;; how many ticks between updates of entropy graph
disp? ;; whether entropy graph should be displayed this tick
city-allure profit-n profit-s profit-ne profit-nw profit-c profit-sw profit-se profit-e profit-w
av-income sd-income sd-income+ sd-income- occupation-rate gentrified-districts downfiltered-districts
recolonisation degentrification recreation regentrification
housing-waiting-list file-name-donut totalcondition file-name-repair medianprices median-income
]
breed [citizens citizen]
breed [people person]
links-own [time]
turtles-own [mobility-propensity months-here birthday culture income dissonance place-changes time-in-a-slum]
patches-own [ref condition price centre? dist local-dist premium price-gap months-empty neighbourhood allure social? last-renovated]
to setup
clear-all
set version "0.2.17"
set save-directory "../results/"
set disp-freq 5
set disp? false
set firstallure 0
set allured-districts table:make
set gentrified-districts table:make
set downfiltered-districts table:make
set housing-waiting-list table:make
set declining []
set recolonisation []
set degentrification []
set regentrification []
set recreation []
set totalcondition []
set medianprices []
set median-income []
set city-allure n-values traits ["x"]
ifelse enable-culture [
set Mixing? true
set PULL? true
set PUSH? true
set strong-neighbourhood? true
]
[
set Mixing? false
set PULL? false
set PUSH? False
set strong-neighbourhood? false
]
if Record? [movie-cancel]
;set allured-districts []
ask patches
[ set pcolor white
set social? false
set condition random-float 1
create-price
set months-empty 0
set allure []
set-neighbourhood
;set centreness 0.00001
; if areamax? [set premium 1]
]
set districts remove-duplicates [neighbourhood] of patches
set neighbourhoods-table table:from-list map [list ? (patches with [neighbourhood = ?])] districts
set-centres-and-distances
ask patches [
color-patches
;set-last-renovated
]
create-people N-Agents * 10 [
;set size 0.01
set size 0.5
set birthday 0
create-culture
reset-mobility-propensity
set hidden? true
]
set-default-shape turtles "circle"
create-economic-status
allocate-agents
reset-ticks
if Record? [movie-start "/home/stefano/gentaxelling.mov"]
if write-csv? or paperstuff? [prepare-data-save]
end
to create-price ;; Price dependant on condition + location. We need to look into this.
set price condition + 0.1
if neighbourhood = "cbd" [set price price * 1.60]
if price > 1 [set price 1]
end
to set-centres-and-distances
foreach districts [
let x (([pxcor] of max-one-of patches with [neighbourhood = ?] [pxcor] - [pxcor] of min-one-of patches with [neighbourhood = ?] [pxcor]) / 2) + [pxcor] of min-one-of patches with [neighbourhood = ?] [pxcor]
let y (([pycor] of max-one-of patches with [neighbourhood = ?] [pycor] - [pycor] of min-one-of patches with [neighbourhood = ?] [pycor]) / 2) + [pycor] of min-one-of patches with [neighbourhood = ?] [pycor]
ask patch x y [
if neighbourhood = ? [
set centre? true
set pcolor blue
]
]
]
ask patches [
let centre min-one-of patches with [centre? = true] [distance myself] ;; policentric city
set local-dist distance centre
set dist distancexy 0 0
if kind = "policentric" [set dist local-dist]
if kind = "no centres" [set dist 1]
]
end
to set-neighbourhood
if pxcor >= -10 and pxcor < -2 and pycor > 2 and pycor <= 10 [set neighbourhood "nw"]
if pxcor <= 10 and pxcor > 2 and pycor > 2 and pycor <= 10 [set neighbourhood "ne"]
if pxcor >= -2 and pxcor <= 2 and pycor >= -2 and pycor <= 2 [
set neighbourhood "c"
;set plabel "CBD"
]
if pxcor >= -10 and pxcor < -2 and pycor < -2 and pycor >= -10 [set neighbourhood "sw"]
if pxcor >= -10 and pxcor <= -3 and pycor > -4 and pycor < 4 [set neighbourhood "w"]
if pxcor <= 10 and pxcor > 2 and pycor < -2 and pycor >= -10 [set neighbourhood "se"]
if pxcor <= 10 and pxcor >= 3 and pycor > -4 and pycor < 4 [set neighbourhood "e"]
if pxcor >= -3 and pxcor <= 3 and pycor < -2 and pycor >= -10 [set neighbourhood "s"]
if pxcor >= -3 and pxcor <= 3 and pycor > 2 and pycor <= 10 [set neighbourhood "n"]
end
to create-culture
set culture n-values traits [random values]
end
to create-economic-status
ask people [set income random-float 0.90]
if random-income? = false [create-skewed-economic-status]
end
to allocate-agents
while [count citizens < N-Agents] [
ask one-of people [
if any? patches with [count citizens-here = 0 and price <= [income] of myself]
[
move-to one-of patches with [count citizens-here = 0 and price <= [income] of myself ]
set breed citizens
set hidden? false
color-agent
]
set months-here 0
]
]
end
to reset-mobility-propensity
set mobility-propensity (random-float prob-move) + 0.01
end
to create-skewed-economic-status
;; adjust one up and one down each time since this method changes the mean - Not SURE this is an improvement!
let thresh 0.05
let chng 0.8
let chng-abs 0
let med 0
if init-gini - gini people > thresh [
while [init-gini - gini people > thresh] [
set med mean ([income] of people)
ask one-of people with [income > med] [
set chng-abs chng * (income - med)
set income income + chng-abs
]
ask one-of people with [income < med] [
set income max list 0 income - chng-abs
]
; show (word med " " gini people)
]
]
if gini people - init-gini > thresh
[ while [gini people - init-gini > thresh] [
set med mean ([income] of people)
ask one-of people with [income < med] [
set chng-abs chng * (med - income)
set income income + chng-abs
]
ask one-of people with [income > med] [set income max list 0 income - chng-abs]
; show (word med " " gini people)
]
]
ask turtles with [income > 1][set income 1]
end
to-report gini [group]
let sorted-wealths sort [income] of group
let total-wealth sum sorted-wealths
let wealth-sum-so-far 0
let index 0
let gini-index-reserve 0
let lorenz-points []
repeat count group [
set wealth-sum-so-far (wealth-sum-so-far + item index sorted-wealths)
set lorenz-points lput ((wealth-sum-so-far / total-wealth) * 100) lorenz-points
set index (index + 1)
set gini-index-reserve gini-index-reserve + (index / count group) - (wealth-sum-so-far / total-wealth)
]
report (gini-index-reserve / count group) / 0.5
end
to-report occupancy [place]
let total place
if not is-patch-set? place [set total patches with [neighbourhood = place]]
let occupied count total with [count citizens-here > 0]
report occupied / count total
end
to color-patches
if condition >= 0.75 [set pcolor white]
if condition < 0.75 and condition > 0.50 [set pcolor grey + 2]
if condition <= 0.50 and condition > 0.25 [set pcolor grey - 2]
if condition <= 0.25 [set pcolor black]
if social? [set pcolor red]
end
to set-last-renovated
if condition <= 0.15 [set last-renovated 120 + random 120]
if condition > 0.15 and condition <= 0.25 [set last-renovated 60 + random 120]
if condition > 0.25 and condition <= 0.5 [set last-renovated 60 + random 60]
if condition > 0.5 and condition <= 0.75 [set last-renovated 24 + random 60]
if condition > 0.75 [set last-renovated random 48]
end
to determine-phenomenon [place]
ifelse median [income] of citizens-on patches with [neighbourhood = place] > item 0 table:get allured-districts place
[
table:put gentrified-districts place (list median [income] of citizens-on patches with [neighbourhood = place] median [price] of patches with [neighbourhood = place] occupancy place)
show word "Here is a gentrified neighbourhood: " place
if write-csv? [export-view (word save-directory "/pics/" "GENTRIFIED_DISTRICT -" "K" Kapital "-t" ticks "-" place ".png")]
]
[
table:put downfiltered-districts place (list median [income] of citizens-on patches with [neighbourhood = place] median [price] of patches with [neighbourhood = place] occupancy place)
show word "Here is a downfiltered neighbourhood: " place
if write-csv? [export-view (word save-directory "/pics/" "DOWNFILTERED_DISTRICT -" "K" Kapital "-t" ticks "-" place ".png")]
]
end
to determine-super-phenomenon [district case] ;; when a place lost than regained uniformity. What's happening???
ifelse case = 0 [ ;; in this case originally gentrification dissolved uniformity
ifelse median [income] of citizens-on patches with [neighbourhood = district] >= (item 0 table:get gentrified-districts district - 0.1) and median [price] of patches with [neighbourhood = district] >= (item 1 table:get gentrified-districts district - 0.1)
[
show word "Here is a recolonised neighbourhood: " district
if not member? district recolonisation [set recolonisation fput district recolonisation]
;set recolonisation recolonisation + 1
if write-csv? [export-view (word save-directory "/pics/" "RECOLONISED_DISTRICT -" "K" Kapital "-t" ticks "-" district ".png")]
]
[
if not member? district degentrification [set degentrification fput district degentrification]
show word "Here is a DEGENTRIFIED neighbourhood: " district
;set degentrification degentrification + 1
]
] [ ; here originally downfiltering dissolved uniformity
ifelse mean [income] of citizens-on patches with [neighbourhood = district] <= (item 0 table:get downfiltered-districts district + 0.1)
[set recreation fput district recreation]
[set regentrification fput district regentrification]
]
end
to go
;if fixed-premium? = false [set-premia]
ifelse ticks mod disp-freq = 0 [set disp? true] [set disp? false]
ask patches [
ifelse have-demand-premium [
ifelse occupancy neighbourhood >= 0.8 ;; NON DEVE ESSERE SOLO NEIGHBOURHOOD !!!
[set premium 1 + renovation-premium]
[ifelse occupancy neighbourhood >= 0.5
[set premium 1 + random-float renovation-premium]
[set premium 1 + random-float (renovation-premium * 0.8)]
]
] [set premium 1 + renovation-premium]
if enable-economy? [
if gaps = "mean" [set-gaps-mean]
if gaps = "max" [set-gaps-max]
if gaps = "unified" [set-gaps-unified]
if gaps = "new" [set-gaps-new]
if gaps = "lnd" [set-gaps-lnd]
decay
reconsider-price
]
update-emptiness
;update-centreness
]
if ticks > 0 and (ticks = 24 or ticks mod 60 = 0) [
set-city-allure
foreach districts [
if occupancy ? > 0.3 [set-allure ?]]
]
;if ticks < 1000 and any? patches with [allure = 0] [check-new-allure]
;if ticks mod 24 = 0 and table:length allured-districts > 0 [check-existing-allure]
;; +++++++ ADD SOMETHING HERE TO MONITOR GENTRIFICATION / SEGREGATION (not related to culture) +++++++++++++++
update-links
update-dissonance
update-propensity
if Mixing? [interact]
ask citizens [
set months-here months-here + 1
if decide-moving [seek-place]
; set size 0.01 * months-here
; if size >= 1.4 [set size 1.4]
]
if ticks > 0 and ticks mod 6 = 0 [
if enable-economy? [do-business]
if inmigration [inmigrate]
if (any? patches with [social? and not any? citizens-here]) and (table:length housing-waiting-list > 0) [assign-social-housing]
if any? patches with [social?][check-social-residents]
]
ask patches [color-patches]
;cluster-cultures
;update-vacancy-rates
set av-income mean [income] of citizens
set sd-income standard-deviation [income] of citizens
set sd-income+ standard-deviation [income] of citizens with [income >= av-income]
set sd-income- standard-deviation [income] of citizens with [income <= av-income]
set occupation-rate count patches with [any? citizens-here] / count patches
check-prices
if Record? [movie-grab-view]
tick
if ticks = end-tick and (write-csv? or paperstuff?) [save-data]
if paperstuff? and (ticks = 2 or ticks = 300 or ticks = 600 or ticks = 900 or ticks = (end-tick - 1))
[
set totalcondition lput wellmaintained totalcondition
set medianprices lput median [price] of patches with [condition >= 0.15] medianprices
set median-income lput median [income] of citizens median-income
;export-view (word save-directory Kapital "-t" ticks ".png")
]
if ticks = end-tick [
; if paperstuff? [export-plot "Mean prices by neighbourhood" (word save-directory kapital)]
if Record? [movie-close]
stop
]
end
to check-social-residents
ask citizens-on patches with [social?][
if months-here >= max-time-in-social-housing * 12 [seek-place]
]
end
to-report wellmaintained ;; With this and the function below we check how many districts in the city achieve 75% or more locations with mainiteniance >= 0.50.
let well 0
foreach districts [set well well + well-maintained? ?]
report well
end
to-report well-maintained? [zone]
let total patches with [neighbourhood = zone]
if count total with [condition >= 0.49] / count total >= 0.75 [report 1]
report 0
end
to assign-social-housing
repeat count patches with [social? and not any? citizens-here] [
let everybody []
foreach table:keys housing-waiting-list [set everybody lput turtle ? everybody]
let candidates sublist everybody 0 4
let housedperson min-one-of turtle-set candidates [income]
let locality table:get housing-waiting-list [who] of housedperson
table:remove housing-waiting-list [who] of housedperson
ifelse locality != "" and any? patches with [social? and not any? citizens-here and neighbourhood = locality]
[move-to-social-housing housedperson locality]
[move-to-social-housing housedperson ""]
]
end
to move-to-social-housing [agent area]
ask agent [
set breed citizens
set months-here 0
set hidden? false
ifelse area = ""
[move-to one-of patches with [social? and not any? citizens-here]]
[move-to one-of patches with [social? and not any? citizens-here and neighbourhood = area]]
]
end
to check-prices
foreach districts [
ifelse member? ? declining
[if median [price] of patches with [neighbourhood = ?] >= 0.25 [set declining remove ? declining] ]
[if median [price] of patches with [neighbourhood = ?] < 0.25 [set declining fput ? declining] ]
]
end
to mutate-off
ask one-of citizens [
set culture replace-item (random traits) culture (random values)
]
end
to mutate
let where [neighbourhood] of patch-here
let trait (random traits)
let most one-of modes [item trait culture] of citizens-on patches with [neighbourhood = where]
set culture replace-item trait culture most
end
to do-business
let howmany (Kapital * count patches) / 2
let goodgap patches with [price-gap >= (price * profit-threshold) and not social? and condition <= 0.8];
; let goodgap patches with [price-gap >= profit-threshold]; and condition <= 0.75];
if count goodgap < howmany [set howmany count goodgap]
let torenovate max-n-of howmany goodgap [price-gap]
if any? torenovate with [neighbourhood = "c"][set profit-c sum [price-gap] of torenovate with [neighbourhood = "c"] / sum [price] of torenovate with [neighbourhood = "c"]]
if any? torenovate with [neighbourhood = "nw"][set profit-nw sum [price-gap] of torenovate with [neighbourhood = "nw"] / sum [price] of torenovate with [neighbourhood = "nw"]]
if any? torenovate with [neighbourhood = "ne"][set profit-ne sum [price-gap] of torenovate with [neighbourhood = "ne"] / sum [price] of torenovate with [neighbourhood = "ne"]]
if any? torenovate with [neighbourhood = "sw"][set profit-sw sum [price-gap] of torenovate with [neighbourhood = "sw"] / sum [price] of torenovate with [neighbourhood = "sw"]]
if any? torenovate with [neighbourhood = "se"][set profit-se sum [price-gap] of torenovate with [neighbourhood = "se"] / sum [price] of torenovate with [neighbourhood = "se"]]
if any? torenovate with [neighbourhood = "n"][set profit-n sum [price-gap] of torenovate with [neighbourhood = "n"] / sum [price] of torenovate with [neighbourhood = "n"]]
if any? torenovate with [neighbourhood = "s"][set profit-s sum [price-gap] of torenovate with [neighbourhood = "s"] / sum [price] of torenovate with [neighbourhood = "s"]]
if any? torenovate with [neighbourhood = "e"][set profit-e sum [price-gap] of torenovate with [neighbourhood = "e"] / sum [price] of torenovate with [neighbourhood = "e"]]
if any? torenovate with [neighbourhood = "w"][set profit-w sum [price-gap] of torenovate with [neighbourhood = "w"] / sum [price] of torenovate with [neighbourhood = "w"]]
ask torenovate [renovate]
end
to inmigrate
let howmany 1 + ((count citizens * immigration-rate) / 2)
ask n-of howmany people [
let myprice income
if any? patches with [price <= myprice and not any? citizens-here and not social?]
[
let whoami who
; set income random-float 1
set breed citizens
set hidden? false
seek-place
ifelse table:has-key? housing-waiting-list whoami ;; if the person is from the housing list we take him away
[table:remove housing-waiting-list whoami]
[ ;; if not he becomes a citizen ;-)
set birthday ticks
create-culture
color-agent
reset-mobility-propensity
]
]
]
end
to color-agent
if income >= 0.80 [set color green]
if income < 0.80 and income > 0.5 [set color green + 4]
if income <= 0.5 and income >= 0.25 [set color violet + 2]
if income < 0.25 [set color violet - 1]
end
to-report decide-moving
if ([price] of patch-here > income and not [social?] of patch-here) or (random-float 1 < mobility-propensity) [
set place-changes place-changes + 1
report true
]
report false
end
to enter-housing-list [agent place]
;; set housing-waiting-list lput (list(agent)(place)) housing-waiting-list
table:put housing-waiting-list [who] of agent place
ask agent [
set breed people
set hidden? true
]
end
to leave-city
ask my-links [die]
set breed people
set hidden? true
end
to renovate
set price price + price-gap
if price >= 1 [set price 0.98]
set condition 0.95
set last-renovated ticks
end
to decay
; if state = "RENTED" [set decay-factor depreciation * 2] ;; We don't have this yet
let depr monthly-decay
let time ticks - last-renovated
if time < 48 [set depr 0]
if time >= 48 and time <= 60 [set depr depr / 2]
if time >= 120 and time <= 240 [set depr depr * 2]
if not any? citizens-here [set depr depr * 1.20]
ifelse condition - depr <= 0
[set condition 0]
[set condition condition - depr]
if condition <= 0.2 and social? [set condition 0.55]
end
to reconsider-price
ifelse social?
[set price (mean [price] of patches) / 2]
[
let depr yearly-depreciation / 12
let time ticks - last-renovated
if time <= 48 [set depr 0]
if time > 48 and time <= 60 [set depr depr / 2]
if time >= 120 and time <= 240 [set depr depr * 2]
if months-empty > tolerable-vacancy [set depr depr * 2]
ifelse price - (price * depr) <= 0
[set price 0.01]
[set price price - (price * depr)]
]
end
to update-emptiness
ifelse count citizens-here = 0
[set months-empty months-empty + 1]
[set months-empty 0]
end
to update-links
ask links [ ;; First we check existing links. If the agents are still neighbours we reinforce the relationship, if not we weaken it.
let stillclose false
ask one-of both-ends [if neighbourhood = [neighbourhood] of other-end or distance other-end <= 2 [
set stillclose true] ]
ifelse stillclose
[if time < 12 [set time time + 1]]
[
set time time - 1
if time <= 0 [die]
]
]
ask citizens [ ;; Then we create new links for neighbours that still don't have one (i.e. new neighbours)
let myneighbours other citizens with [distance myself <= 2 and link-neighbor? myself = false]
let goodneighbours myneighbours with [(similarity self myself / traits) >= similarity-for-friendship]
ask goodneighbours [
create-link-with myself [
set time 1
set hidden? true
]
]
]
end
to build-social-housing [howmany]
let sofar 0
let zerop min [price] of patches
let zeroc min [condition] of patches
let avg mean [price] of patches with [count citizens-here > 0]
let firstsocial nobody
let worst patches with [not any? citizens-here and price <= zerop and condition <= zeroc]
ifelse any? worst
[set firstsocial min-one-of worst [price-gap]]
[set firstsocial max-one-of patches [months-empty]]
ask firstsocial [
set social? true
set price avg / 2
set condition 0.95
set sofar sofar + 1
while [sofar < howmany] [
ask one-of patches in-radius 4 with [not social?] [
if not any? citizens-here [
set social? true
set price avg / 2
set condition 0.95
set sofar sofar + 1
]
]
]
]
end
to regenerate
;; Regeneration is intended in the anglo-saxon, "small state but lets-be-compassionate-shall-we" way.
;; Money is put in the areas least desirable to investors (= those with the most narrow price-gap)
;; that are also empty and in run-down condition. These areas are brought to the maximum condition
;; and to the mean price of the city. The idea is to check whether this practice can trigger further private investment.
let zerop min [price] of patches
let zeroc min [condition] of patches
let avg mean [price] of patches with [count citizens-here > 0]
let worst patches with [not any? citizens-here and price = zerop and condition = zeroc]
ask min-one-of worst [price-gap] [
set price avg
set condition 0.95
ask neighbors with [not social?] [
set price avg
set condition 0.95
]
]
end
to update-dissonance
ask citizens [
ifelse [condition] of patch-here < 0.15 or mean [condition] of other patches in-radius 2 < 0.15
[set time-in-a-slum time-in-a-slum + 1]
[set time-in-a-slum 0]
if PUSH? [
if count citizens-on neighbors > 0 [
let alltraits count citizens-on neighbors * traits
let simil 0
ask citizens-on neighbors [set simil simil + similarity self myself]
ifelse (simil / alltraits) <= similarity-for-dissonance
[set dissonance dissonance + 1]
[set dissonance 0]
]
]
]
end
to update-propensity
ask citizens [
if time-in-a-slum = 0 and dissonance <= tolerable-dissonance [reset-mobility-propensity]
if ((time-in-a-slum >= 12) and (income > ([price] of patch-here * 1.20))) ;; If I can afford to, I leave the ghetto
or (income >= ((median [condition] of neighbors) * 1.50)) ;; This reflects the preference of middle class people towards status over convenience.
[set mobility-propensity mobility-propensity * 1.50]
if (dissonance > tolerable-dissonance) [
set mobility-propensity mobility-propensity * 1.50
if random-float 1 < 0.05 [mutate]
]
if mobility-propensity > 1 [set mobility-propensity 1]
]
end
;; The idea here is that prolonged co-location leads to cultural mixing.
;; We need each household to keep track of how long they have been neighbours with each other
to interact
ask links with [time >= 12] [
let a end1
let c-a [culture] of a
let b end2
let c-b [culture] of b
if c-a != c-b [
;; if similarity a b < traits [
let whichone random traits
let i-a item whichone c-a
let i-b item whichone c-b
if i-a != i-b [
ifelse random 1 = 0
[ask b [set culture replace-item whichone culture i-a]]
[ask a [set culture replace-item whichone culture i-b]]
]
]
]
end
to-report entropy [district]
let common 0
let thispeople citizens-on patches with [neighbourhood = district]
let pairs (count thispeople * (count thispeople - 1)) / 2
ask n-of (count thispeople / 2) thispeople [
ask other thispeople [
set common common + (similarity self myself / traits)
]
]
report safe-division common pairs
end
to-report entropy-old [district]
let common 0
let thispeople citizens-on patches with [neighbourhood = district]
let pairs (count thispeople * (count thispeople - 1)) / 2
ask thispeople [
ask other thispeople [
set common common + (similarity self myself / traits)
]
]
report safe-division (common / 2) pairs
end
; =============================== RESIDENTIAL LOCATION PROCESS =========================================================
;; When seeking a spot we consider vacant affordable places close to the origin (cbd) and with a pleasant cultural mix.
;; This is in line with Jackson et al. 2008, although they have a Schelling-like ethnic (not cultural) mix.
;; In this version agents only evaluate the CULTURAL ALLURE of a district, not the STATUS.
;; If we are to finegrain the model we could also include status in the decision process.
to seek-place
ifelse PULL? and table:length allured-districts > 0
[
let where set-place
ifelse where != "" [
ifelse strong-neighbourhood?
[relocate-to where]
[weak-relocate-to where]
][relocate]
]
[relocate]
end
to-report set-place ;; ========= nononon questo si deve cambiare per rflettera la nuova composiziopne della allure che abbiamo appena fatto...
let best_ftr 1
let bestdistrict ""
foreach table:keys allured-districts [
let this_similarity similarity self one-of patches with [neighbourhood = ?]
if this_similarity >= best_ftr [
set best_ftr this_similarity
set bestdistrict ?
]
]
report bestdistrict
end
to relocate
set months-here 0
let baseline patches with [(count citizens-here = 0) and (condition > 0) and (social? = false)]
if enable-economy? [set baseline baseline with [(price <= [income] of myself)]]
ifelse any? baseline [
let testbed n-of 5 patches
; let secondbest baseline with [(price <= [income] of myself) and (count citizens-here = 0) and (condition >= (mean [condition] of testbed - (mean [condition] of testbed * 0.15 )))] ;; if we can't find a place we like then we move to one we can afford
let secondbest baseline with [(price <= [income] of myself) and (count citizens-here = 0) and (condition >= 0.25)] ;; if we can't find a place we like then we move to one we can afford
ifelse any? secondbest
[move-to min-one-of secondbest [dist]]
[move-to min-one-of baseline [dist]]
]
[enter-housing-list self ""]
end
to relocate-to [place]
set months-here 0
let baseline patches with [(price <= [income] of myself) and (count citizens-here = 0) and (condition > 0) and (social? = false)] ;Add to prevent people from moving to decrepit loc:; and (condition > 0)
ifelse any? baseline [
;let testbed n-of 5 patches
;let condi mean [condition] of testbed
;let ideal baseline with [(neighbourhood = place) and (condition >= (condi - (condi * 0.15 )))]
let ideal baseline with [(neighbourhood = place) and (condition > 0.25)]
ifelse any? ideal
[move-to min-one-of ideal [local-dist]]
[
let apex patches with [centre? = true and neighbourhood = place]
let acceptable baseline with [condition >= 0.10] ;;; change this: acceptable condition should vary across agents
let secondbest acceptable with [neighbourhood = place] ;; change this: if nothing is available in place look at the edges
ifelse any? secondbest
[move-to min-one-of secondbest [local-dist]]
[ifelse any? acceptable
[move-to min-one-of acceptable [distance one-of apex]] ;; If we can't find anything in the desired area we try somewhere close
[move-to min-one-of baseline [dist]]
]
]
]
[enter-housing-list self place]
end
to weak-relocate-to [place]
let ideal patches with [(price <= [income] of myself) and (count citizens-here = 0) and (neighbourhood = place) and (condition >= (mean [condition] of patches - (mean [condition] of patches * 0.15 )))]
ifelse any? ideal
[move-to min-one-of ideal [dist]]
[ let testbed n-of 5 patches
let secondbest patches with [(price <= [income] of myself) and (count citizens-here = 0) and (condition >= (mean [condition] of testbed - (mean [condition] of testbed * 0.15 )))] ;; if we can't find a place we like then we move to one we can afford
ifelse any? secondbest
[move-to min-one-of secondbest [dist]]
[let thirdbest patches with [(price <= [income] of myself) and (count citizens-here = 0) ] ;; Uncomment the following to prevent people from moving in decrepit locations ;and (condition > 0)
ifelse any? thirdbest [move-to min-one-of thirdbest [dist]] [enter-housing-list self place] ;; if no place exists we leave the city.
]
]
end
; =============================== PRICE GAPS ====================================
to set-gaps-lnd-off
let sample max [price] of patches in-radius 3
let areaprice median [price] of patches with [neighbourhood = [neighbourhood] of myself] * (1 + renovation-premium)
let whichprice sample
if areaprice > sample [set whichprice areaprice]
ifelse whichprice > price
[set price-gap (sample - price)]
[set price-gap 0]
end
to set-gaps-lnd
let whichprice 0
let neigh-price 0
let areaprice 0
let sample patches in-radius 2 with [count citizens-here > 0]
ifelse any? sample
[set areaprice mean [price] of sample]
[set areaprice (mean [price] of patches in-radius 2) * 0.65]
set whichprice areaprice * (1 + renovation-premium)
ifelse whichprice > price
[
ifelse any? citizens-here with [income < whichprice / 2]
[set price-gap (whichprice - (price + (resident-removal-cost * price)))] ;; we anticipate whether we will have to kick someone out
[set price-gap (whichprice - price)]
]
[set price-gap 0]
end
to set-gaps-new ;; Maximum of moore neighbourhood or district median
let whichprice 0
let neigh-price 0
let area-price 0
set neigh-price max [price] of neighbors
set area-price median [price] of patches with [neighbourhood = [neighbourhood] of myself] * premium
ifelse neigh-price > area-price
[set whichprice neigh-price]
[set whichprice area-price]
ifelse whichprice > price
[ifelse any? citizens-here with [income < whichprice] ; We anticipate whether we will have to kick someone out...
[set price-gap (whichprice - (price + resident-removal-cost))] ; The removal cost affects the profit prospect...
[set price-gap (whichprice - price)]
]
[set price-gap 0]
end
to set-gaps-unified ;;
let whichprice 0
let localprice mean [price] of neighbors * (1 + renovation-premium)
if occupancy neighbors >= 0.85 [set localprice max [price] of neighbors * (1 + renovation-premium) ]
ifelse occupancy neighbourhood >= 0.85
[set whichprice max [price] of patches with [neighbourhood = [neighbourhood] of myself] * (1 + renovation-premium)]
[set whichprice mean [price] of patches with [neighbourhood = [neighbourhood] of myself] * (1 + renovation-premium)]
if localprice > whichprice [set whichprice localprice]
ifelse whichprice > price
[ifelse any? citizens-here with [income < whichprice] ; We anticipate whether we will have to kick someone out...
[set price-gap (whichprice - (price + resident-removal-cost))] ; The removal cost affects the profit prospect...
[set price-gap (whichprice - price)]
]
[set price-gap 0]
end
to set-gaps-mean
let whichprice 0
let localprice mean [price] of neighbors * premium
;if count citizens-on neighbors / count neighbors >= 0.85 [set localprice max [price] of neighbors * premium ]
;ifelse occupancy neighbourhood >= 0.85
;[set whichprice max [price] of patches with [neighbourhood = [neighbourhood] of myself] * premium]
set whichprice mean [price] of patches with [neighbourhood = [neighbourhood] of myself] * premium
if localprice > whichprice [set whichprice localprice]
ifelse whichprice > price
[ifelse any? citizens-here with [income < whichprice] ; We anticipate whether we will have to kick someone out...
[set price-gap (whichprice - (price + resident-removal-cost))] ; The removal cost affects the profit prospect...
[set price-gap (whichprice - price)]
]
[set price-gap 0]
end
to set-gaps-max
set premium 1.001
let whichprice 0
let localprice max [price] of neighbors * premium
;if count citizens-on neighbors / count neighbors >= 0.85 [set localprice max [price] of neighbors * premium ]
;ifelse occupancy neighbourhood >= 0.85
;[set whichprice max [price] of patches with [neighbourhood = [neighbourhood] of myself] * premium]
set whichprice max [price] of patches with [neighbourhood = [neighbourhood] of myself] * premium
if localprice > whichprice [set whichprice localprice]
ifelse whichprice > price
[ifelse any? citizens-here with [income < whichprice] ; We anticipate whether we will have to kick someone out...
[set price-gap (whichprice - (price + resident-removal-cost))] ; The removal cost affects the profit prospect...
[set price-gap (whichprice - price)]
]
[set price-gap 0]
end
; =================== ALLURE ====================================================
to-report update-city-culture
let newallure n-values traits [0]
let trt 0
while [trt < traits] [
let thistrait one-of modes [item trt culture] of citizens
set newallure replace-item trt newallure thistrait
set trt trt + 1
]
report newallure
end
to set-city-allure
let city-culture update-city-culture
let pallure []
let trait 0
while [trait < traits] [
set pallure lput ifelse-value (count citizens with
[(item trait culture = item trait city-culture)] >= (count citizens * 0.3))
[item trait city-culture] ["x"] pallure
set trait trait + 1
]
set city-allure pallure
end
to-report localculture [district]
if any? citizens-on patches with [neighbourhood = district] [
let people-here citizens-on patches with [neighbourhood = district]
let newallure n-values traits [0]
let trt 0
while [trt < traits] [
let thistrait one-of modes [item trt culture] of people-here
set newallure replace-item trt newallure thistrait
set trt trt + 1
]
report newallure
; ask patches with [neighbourhood = district] [set pculture newallure]
]
end
to set-allure [place]
let ppl citizens-on patches with [neighbourhood = place]
let areaculture localculture place
let pallure []
let trait 0
while [trait < traits] [
set pallure lput ifelse-value
(count ppl with [item trait culture = item trait areaculture] > count ppl * 0.3 and
item trait areaculture != item trait city-allure and
item trait city-allure != "x"
)
[item trait areaculture] ["x"] pallure
set trait trait + 1
]
let peculiar length filter [? != "x"] pallure
set-current-plot "peculiarity"
set-current-plot-pen place
plotxy ticks peculiar
ifelse peculiar > peculiarity-for-allure [
ask patches with [neighbourhood = place] [set allure pallure]
if not table:has-key? allured-districts place
[table:put allured-districts place (list (median [income] of citizens-on patches with [neighbourhood = place]) (median [price] of patches with [neighbourhood = place]) (occupancy place) (ticks))]
]
[if table:has-key? allured-districts place [
let longevity ticks - item 3 table:get allured-districts place
if longevity > 60 [table:remove allured-districts place]]
]
end
; =================== SUPPORTING ====================
to-report safe-division [a b]
if a = 0 or b = 0 [report 0]
report a / b
end
to-report similarity [a b]
report similarity-of ([culture] of a) (ifelse-value is-turtle? b [[culture] of b] [[allure] of b])
end
to-report similarity-of [ls1 ls2] ;;;;;; DA QUA DOBBIAMO PRENDERE IL CODICE PER FARE IL NUOVO ENTROPY
report length filter [?] (map [?1 = ?2] ls1 ls2)
end
; =================== PLOTTING ====================================================
to plot-ent [dis]
if disp? [repeat disp-freq [plot entropy dis]]
end
to-report medianincome [area]
ifelse any? citizens-on patches with [neighbourhood = area] [
report median [income] of citizens-on patches with [neighbourhood = area]
][report 0]
end
; =========================== DATA OUTPUT ==========================================
to prepare-data-save
let run-number 0
;let maxmean "MEAN"
let pull ""
let mix ""
;if areamax? [set maxmean "MAX"]
if PULL? [set pull "PULL"]
if behaviorspace-run-number != 0 [set run-number behaviorspace-run-number]
;set file-name-entropy (word save-directory "gentax-" version "-ENTROPY-" pull "-K" Kapital "-#" run-number ".csv")
;set file-name-pop (word save-directory "gentax-" version "-POPULATION-" pull "-K" Kapital "-#" run-number ".csv")
;set file-name-prices (word save-directory "gentax-" version "-PRICES-" pull "-K" Kapital "-#" run-number ".csv")
;set file-name-donut (word save-directory "gentax-" version "-DONUT-" pull "-K" Kapital "-#" run-number ".csv")
;set file-name-income (word save-directory "gentax-" version "-INCOME-" pull "-K" Kapital "-#" run-number ".csv")
set file-name-repair (word save-directory "gentax-" version "-ALL.csv")
;set file-name-allured (word save-directory "gentax-" version "-ALLURE.csv")
;file-delete file-name-entropy
;file-delete file-name-pop
;file-delete file-name-prices
;file-delete file-name-income
;file-open file-name-entropy
;file-write "ticks;"
;foreach districts [file-write (word ? ";")]
;file-print ""
;file-open file-name-pop
;file-write "ticks;"
;foreach districts [file-write (word ? ";")]
;file-print ""
;file-open file-name-prices
;file-write "ticks;"
;foreach districts [file-write (word ? ";")]
;file-print ""
;file-open file-name-income
;file-write "ticks;"
;foreach districts [file-write (word ? ";")]
;file-print ""
;file-open file-name-donut
;file-print "ticks;centre;semicentre;periphery"
;file-open file-name-repair
; file-print "K;300;600;900;end-tick"
; file-close-all
end