-
Notifications
You must be signed in to change notification settings - Fork 10
/
Copy pathDC_Gentrification.nlogo
1648 lines (1465 loc) · 49.9 KB
/
DC_Gentrification.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
; Load NetLogo extension to handle GIS functionality
extensions [gis]
; Set global variables for shapefiles, school graduation rates and agent lists
globals [
DCblockdemo
DCblockdemo07
;; the following are graduation rates for 5 public schools in the area.
Anacostiagrad
Easterngrad
Dunbargrad
Spingarngrad
Wilsongrad
maxHUperpatch
metropatches ; agent set of patches which are the locations of metro rail stations
publicpatches ; agent set of patches which are the locations of public housing properties
myblocks
DCmeanincome
housingcostsincrease
demandinflation
incomeincrease
newrents
metropref
nummoveout
maxHUpersqmi
yearlyhouseholdincrease
percenthouseholdsmove
q
;; the following are needed for the file input routines
mypath
myfolder
myfile
csvheaders
csvdata
]
breed [hs-labels hs-label] ; breed used to dispaly labels for GIS
breed [blocks block] ; dummy agent used to hold initiation data for each block group
breed [households household] ; turtle breed representing households
; patch (housing unit) variables
patches-own [ HS pPOP2000 pPOP2010 POPchange ptract pBLKGRP phouseholds10 pMetro pPublic
pdistancetometro pdistancetopublic pdistancetoCBD ptractblockgrp pnumHU pnum_occ pnum_vac pnum_pub prent developed? pactual_incomeincr rank
ppropcrime psimulation_incomeincr psimulation_meanincomeincr
]
; block (aggregate variables)
blocks-own [tractblkgrp tract block_Group num_HU currentnum_HU new_HU %incr_per_yr_HU %incr_HU num_occ num_vac calc_vac_rate
num_historic calc_historic_rate %moves median_monthly_costs median_monthly_budget median_income %incr_median_income median_to_mean
median_home_value num_public_housing %public_housing violentcrime_rate propertycrime_rate crimelist startmedianincome endmedianincome
startmeanincome endmeanincome simulated%increasemeanincome simulated%increasemedianincome rentinflation]
; Household variables
households-own [income householdblock budget happy? looking?]
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; setup routine ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
to setup
;ca
clear-all
reset-ticks
; Load the projection system for the shapefiles
gis:load-coordinate-system "data/tractdata/WGS_84_Geographic.prj"
set DCblockdemo gis:load-dataset "data/tractdata/blkgrp_DConly_Concentrated/blkgrp_DConly_Concentrated.shp"
set DCblockdemo07 gis:load-dataset "data/tractdata/blkgrp07_DConly_Concentrated/blkgrp07_DConly_Concentrated.shp"
gis:set-world-envelope gis:envelope-of DCblockdemo
; set global economic and spatial variables
set maxHUpersqmi 17000
set DCmeanincome 70401
set incomeincrease 5 ; 5% based on 3% average for US (US labor dept) and 2% more for DC than US average
set housingcostsincrease 6.26 ; average annualized home cost increases for neighborhoods in question from zillow.com
set maxHUperpatch int (maxHUpersqmi / 5000) + 1
; type "maxHUperpatch " print maxHUperpatch
set newrents 2000 ; based on average housing costs of $4000 in 2013 for recent construction and assuming 6% increase per year.
set metropref (1 - lowcrimepref - publichousingpref)
type "metropref " print metropref
set nummoveout 0
set q 0
set yearlyhouseholdincrease 0.015 ; based on census data
set percenthouseholdsmove 15 ; based on census data
; initialize the model with census data and metro and public housing locations
input2000data
setupblockprofiles
setHSgradrates
loadDCblockgroupdemographics
loadDCSchools
viewDCmetrostations
viewpublichousing
ask patch -120 53 ;; set the location of the central business district
[ set pcolor red set plabel "CBD"]
ask patch -100 53
[set plabel "CBD"]
ask blocks
[
set %incr_HU (read-from-string %incr_per_yr_HU) ; convert string to numeric
if %incr_HU < 0 [ set %incr_HU 0]
set currentnum_HU (read-from-string num_HU)
]
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;set crime rates exogenously for ten years and then stay the same
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
ask blocks with [tract = "6400"] [set crimelist [ 57 52 57 42 39 47 47 53 40 21 40 36] ]
ask blocks with [tract = "6700"] [set crimelist [ 50 70 52 48 37 45 29 36 51 61 38 41] ]
ask blocks with [tract = "6801"] [set crimelist [ 21 39 36 39 41 36 35 44 43 44 33 33] ]
ask blocks with [tract = "6802"] [set crimelist [ 32 61 36 44 33 32 31 27 44 27 24 31] ]
ask blocks with [tract = "6900"] [set crimelist [ 93 150 94 69 80 76 60 81 96 81 73 57] ]
ask blocks with [tract = "7000"] [set crimelist [ 90 105 97 69 78 52 47 63 57 70 59 50] ]
ask blocks with [tract = "7100"] [set crimelist [ 47 47 51 41 44 33 23 42 50 66 57 60] ]
ask blocks with [tract = "7200"] [set crimelist [ 267 295 207 137 109 92 116 76 53 44 44 47]]
ask blocks with [tract = "7901"] [set crimelist [ 28 41 35 45 43 34 34 21 31 30 26 27] ]
ask blocks with [tract = "7903"] [set crimelist [ 29 35 48 61 57 43 48 45 36 42 34 36] ]
ask blocks with [tract = "8001"] [set crimelist [ 30 56 51 54 51 66 52 45 50 51 52 56] ]
ask blocks with [tract = "8002"] [set crimelist [ 59 67 63 82 61 77 52 41 46 41 48 40] ]
ask blocks with [tract = "8100"] [set crimelist [ 46 104 80 80 84 95 42 40 42 35 30 39] ]
setuphousing ;; call subroutine to initialize housing and households based on census data
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; go routine ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
to go
if q > 100 [
print "not enough affordable vacancies "
let temp count patches with [developed? = true and pnum_vac > 0]
type "vacant patches " print temp
if temp > 0 [ print median [prent] of patches with [developed? = true and pnum_vac > 0]]
stop]
; type "households " print count households
; type "developed patches " print count patches with [developed? = true]
; type "housing units " print sum [pnumHU] of patches with [developed? = true]
; type "public housing " print sum [pnum_pub] of patches with [developed? = true]
; type "vacant " print sum [pnum_vac] of patches with [developed? = true]
; type "average income " type mean [income] of households type "median income " print median [income] of households
; type "average rent " type mean [prent] of patches with [developed? = true] type "median rent " print median [prent] of patches with [developed? = true]
; type "rent<0 " print count patches with [developed? = true and prent < 0]
; type "unhappy? " print count households with [happy? = false]
; type "aver rent pubHU " type mean [prent] of patches with [developed? = true and pnum_pub > 0]
createincominghousingunits ; add new construction
identifyunhappyhouseholds ; identify households who want to move
movehouseholds ; move households
calculateglobalincreases ; calculate global increases
createincominghouseholds ; create newcomers to DC
calculateincomeincrease ; calcualte aggregate increases in income for each block group
tick ; increase time step
if ticks = (Years_Simulated + 1) [stop]
end
to setHSgradrates ;; set HS Graduation Rates
set Easterngrad 0.70
set Dunbargrad 0.60
set Spingarngrad 0.48
set Wilsongrad 0.74
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; globalincreases ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
to calculateglobalincreases
set DCmeanincome (1 + ((1 + incomeincrease) / 100)) * DCmeanincome ; increase the average income of newcomers
type "dcmeanincome " print DCmeanincome
set newrents (1 + (housingcostsincrease / 100)) * newrents ; increase the average housing costs of new construction
ask households
[
set income (1 + (incomeincrease / 100)) * income ; increase income and monthly budget of household agents
set budget (1 + (incomeincrease / 100)) * income
]
foreach myblocks [
x -> ask x
[
let blockID [tractblkgrp] of x
let blockcrimerate item 10 [crimelist] of x
; type "block " type blockID type " " type "% incr " print [%incr_HU] of ?
if ticks < 11
[
set blockcrimerate item ticks [crimelist] of x ; update the property crime per 1000 to the next item in the list
;type blockID type " block crimerate " print blockcrimerate
]
ask patches with [developed? = true and ptractblockgrp = blockID]
[
set ppropcrime blockcrimerate ; update each patch (housing unit) with the crime rate
ifelse pnum_pub > 0
[
set prent (1 + (housingcostsincrease / 100)) * prent ; update housing costs (rents)
;set prent (1 + ((housingcostsincrease / 2) / 100)) * prent
]
[set prent (1 + (housingcostsincrease / 100) ) * prent]
; [set prent (1 + (housingcostsincrease / 100) + [rentinflation] of ?) * prent]
; [
; set prent ((1 + (housingcostsincrease / 100) + (10 * [%incr_HU] of ?)) * prent)
;]
]]
]
ask blocks ; calculate number of new housing units coming in next year.
[
let blockID tractblkgrp
set new_HU (%incr_HU * currentnum_HU) ; new_HU increases each year based upon exogenous percentages for a 10 yr period evenly distributed per year.
set currentnum_HU (currentnum_HU + new_HU)
]
rankpatches ; re-rank the patches based up updated crime information
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; hold block group data ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
to setupblockprofiles ;; set up dummy agents to store the Census block group data read in from the file
create-blocks 29
[
hide-turtle]
set myblocks sort blocks
let j 0
foreach myblocks [
x ->
ask x
[
set tractblkgrp (word "00" item j (item 0 csvdata))
set tract item j (item 1 csvdata)
set num_HU item j (item 3 csvdata)
set %incr_per_yr_HU item j (item 4 csvdata)
set num_occ item j (item 5 csvdata)
set num_vac item j (item 6 csvdata)
set calc_vac_rate item j (item 7 csvdata)
set num_historic item j (item 8 csvdata)
set calc_historic_rate item j (item 9 csvdata)
set %moves item j (item 10 csvdata)
set median_monthly_costs item j (item 11 csvdata)
set median_monthly_budget item j (item 12 csvdata)
set median_income item j (item 13 csvdata)
set median_to_mean item j (item 14 csvdata)
set median_home_value item j (item 15 csvdata)
set num_public_housing item j (item 16 csvdata)
set %public_housing item j (item 17 csvdata)
set violentcrime_rate item j (item 18 csvdata)
set propertycrime_rate item j (item 19 csvdata)
set %incr_median_income (read-from-string item j (item 20 csvdata))
;show %incr_median_income
]
set j (j + 1)
]
; ask blocks [ ;; verify block group agents are intialized correctly
; ;type who type " " type tractblkgrp type " " print propertycrime_rate
; ]
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Set-up Housing ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
to setuphousing ;; set up the patches to hold housing data and household agents
set myblocks sort blocks
;;;;;;
;the next few lines makes some corrections to the shapefiles to match with census or metro maps
;;;;;;
; rename tract 7000 block groups 1 and 2 to be 2 and 3 to match Census
ask patches with [ptractblockgrp = "0070002"]
[ set ptractblockgrp "0070003"]
ask patches with [ptractblockgrp = "0070001"]
[ set ptractblockgrp "0070002"]
; rename tract 8002 block group 2 to be 3 to match Census
ask patches with [ptractblockgrp = "0080022"]
[ set ptractblockgrp "0080023"]
; rename tract 7200 block groups 1 and 2 to be all block group 1 to match Census
ask patches with [ptractblockgrp = "0072002"]
[ set ptractblockgrp "0072001"]
foreach myblocks [
x ->
;; For each of the 29 Census tract-blockgroups
let blockID [tractblkgrp] of x
let blockIDpatches patches with [ptractblockgrp = blockID]
let blockincrease [%incr_median_income] of x
;type blockID type "count patches " print count blockIDpatches
let number_HU (read-from-string [num_HU] of x) ;; keep this as a permanent value since it gets incremented each year.
let num_pub (read-from-string [num_public_housing] of x ) ;; use read-from-string to convert string to numeric
;show num_pub
let medianrent (read-from-string [median_monthly_costs] of x )
let medianmean (read-from-string [median_to_mean] of x )
;show medianmean
let vacancyrate (read-from-string [calc_vac_rate] of x )
let num_patches count patches with [ptractblockgrp = blockID ]
let developedrate (number_HU / (maxHUperpatch * num_patches))
let patchesdeveloped (number_HU / maxHUperpatch) ;number of patches with housing units
let blockcrimerate item 10 [crimelist] of x
if ticks < 11 ; after 10 years, keep the last crime rate
[set blockcrimerate item ticks [crimelist] of x
]
;type blockID type "year " type ticks type "crime " print blockcrimerate
;type "patchesdevelope " print patchesdeveloped
ask blockIDpatches
[
set developed? false
set pactual_incomeincr blockincrease ; record the actual increase in income to campare with simulation
]
let averageHU number_HU / patchesdeveloped
;type blockID type " " type "numpatches " print num_patches
ask n-of patchesdeveloped patches with [ptractblockgrp = blockID] ;; first, evenly distribute housing among the patches in that block-group
[
set developed? true
; NUMBER OF HOUSING UNITS ALGORITHM - USE INTEGER PART TO ASSIGN NUMBER TO EACH PATCH, THEN USE FRACTION
;; e.g. if average number of HU per patch is 2.33, then set all patches = 2, and for
;; 33% of patches, set num_HU = 3
set pnumHU int averageHU
if random-float 1 < (averageHU - pnumHU)
[set pnumHU pnumHU + 1] ;; for a fraction of patches, set increment numHU in order fulfill total number of housing units
if random-float 1 < vacancyrate
[set pnum_vac pnumHU] ;; for a fraction of patches set all housing units in patch as vacant
;; second, calculate distances to metro and CBD
set ppropcrime blockcrimerate
set pdistancetometro distance (min-one-of metropatches [distance myself])
set pdistancetopublic distance (min-one-of publicpatches [distance myself])
set pdistancetoCBD distancexy -120 53 ;; patch -120, 53 is chosen as CBD for this map)
;; if there are housing units on this patch
; if random-float 1 < (read-from-string [calc_vac_rate] of ? )
; [ set
set prent random-normal medianrent medianrent ;; third, rent based on random normal distribution
while [prent < 0] [set prent random-normal medianrent medianrent]
sprout-households (pnumHU - pnum_vac) ;; fourth, set up households
[
;hide-turtle
set budget (medianmean * random-poisson prent)
set income 3 * budget * 12
set happy? true
set looking? false
;type income type " "
set householdblock blockID ;of patch-here
]
]
;; fifth, set up public housing units
;; the following code sets all the units in the lowest rent patches to be public housing
;; up to number of public housing units in the block
let n 0
let incpubHU 0
foreach sort-on [prent] patches with [ptractblockgrp = blockID]
[
y ->
if n < num_pub [
ask y [set pnum_pub pnumHU
set incpubHU pnumHU
]
set n (n + incpubHU)
]]
; verify initialization is correct
; type blockID type " " type "sum of HU" print sum [pnumHU] of patches with [ptractblockgrp = blockID]
; type blockID type " " type "sum of pubHU" print sum [pnum_pub] of patches with [ptractblockgrp = blockID]
;type blockID type " " type "sum of vacant" print sum [pnum_vac] of patches with [ptractblockgrp = blockID]
; type blockID type " " type "median rent" type median [prent] of patches with [ptractblockgrp = blockID]
;type blockID type " " type "num households" print (sum [pnumHU] of patches with [ptractblockgrp = blockID] - sum [pnum_vac] of patches with [ptractblockgrp = blockID] )
;type blockID type " " type "median income" print median [income] of households with [householdblock = blockID]
ask x ; in loop foreach myblocks)
[
set startmeanincome mean [income] of households with [ householdblock = blockID] ; record the starting mean and median income for change comparisons
set startmedianincome median [income] of households with [ householdblock = blockID]
]
]
rankpatches ; rank patches based on preferences
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Identify Movers
;; set up household data for those moving in. identify unhappy households, mark those locations as vacant -
;; add unhappy to those moving in - Move to vacant spots. if don't find a suitable house - leave area
;; add additional agents to fill spots for those who left area
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
to identifyunhappyhouseholds ; identify the households that will move this year
; show count households
;type "movers " print ((percenthouseholdsmove / 100 ) * count households)
ask n-of ((percenthouseholdsmove / 100 ) * count households) households
[set happy? false
set pnum_vac pnum_vac + 1
]
ask households
[
if (prent > budget and happy? = true ) ; those whose rent is greater than their budget with also move
[
set happy? false
set pnum_vac pnum_vac + 1
if random 2 = 0 [die]
]]
;type "movers " print count households with [happy? = false] ; verify starting number of households who want to move.
;type "close to metro " print count households with [happy? = false and pdistancetometro < 20]
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Create New Construction ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
to createincominghousingunits
foreach myblocks [ ;; For each of the 29 Census tract-blockgroups
x -> ask x
[
let blockID [tractblkgrp] of x
let newunits [new_HU] of x
let blockcrimerate item 10 [crimelist] of x
if ticks < 11
[set blockcrimerate item ticks [crimelist] of x
]
let k count patches with [ptractblockgrp = blockID and developed? = false]
ifelse k < (newunits / maxHUperpatch)
[ask x [set %incr_HU 0]]
[
ask n-of (newunits / maxHUperpatch) patches with [ptractblockgrp = blockID and developed? = false] ;; randomly select available patches for new units
[
set pnumHU maxHUperpatch
set pnum_vac maxHUperpatch
set pnum_pub 0 ; existing public housing units maintained but no new units added.
set developed? true
set prent random-normal newrents newrents
while [prent < 0] [set prent random-normal newrents newrents]
set ppropcrime blockcrimerate
set pdistancetometro distance (min-one-of metropatches [distance myself])
set pdistancetopublic distance (min-one-of publicpatches [distance myself])
set pdistancetoCBD distancexy -120 53 ;; patch -120, 53 is chosen as CBD for this map)
]
]
]
]
rankpatches ; rank the new contruction units
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; create new residents ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
to createincominghouseholds
let incomingHU (yearlyhouseholdincrease * count households) + nummoveout ;; how many incoming residents
;type "nummoveout " type nummoveout type " " print yearlyhouseholdincrease
;print incomingHU
let p 0
set q 0
while [p < incomingHU and q <= 100] [ ; keep creating agents until total new households for the year have been created
create-households 1
[
;hide-turtle
set income random-normal DCmeanincome DCmeanincome ; set income
while [income < 0] [set income random-normal DCmeanincome DCmeanincome]
set budget (income / 12 ) / 3 ; set budget
set happy? false
set looking? true
;set householdblock blockID
; type "original " type xcor type " " print ycor type " " type "num vac " print pnum_vac
let tempbudget budget
let affordablevacancies patches with [pnum_vac > 0 and prent <= tempbudget ] ; identify affordable vacancies
let k count affordablevacancies
;if affordablevacancies < ( incomingHU - p + 1) [stop]
;type "vacancies " print count affordablevacancies
;ifelse any? affordablevacancies
let target 0
ifelse any? affordablevacancies
[
;let target one-of affordablevacancies
; let target min-one-of affordablevacancies [rank]
; let target 0
ifelse High_Value_Preference?
[
ifelse k >= 3 [set target max-one-of (min-n-of (k / 3) affordablevacancies [rank]) [prent]] ; satisficing finds top third of ranked patches - choose best (highest value) of these
[set target min-one-of affordablevacancies [rank]]
]
[set target min-one-of affordablevacancies [rank]
;print target
]
move-to target ; move to new home and set patch variables to know that you are here
set pnum_vac pnum_vac - 1
set happy? true
set householdblock ptractblockgrp
show-turtle
set p (p + 1)
]
[; print "no affordable vacancies"
set q (q + 1)
if q > 100 [
; print "sampled 100 incoming "
; type "total added " print p
stop
]]
]
] ; end while
ask households with [happy? = false] [die] ; if you don't find affordable housing then leave area
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ranking routine ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
to rankpatches ; rank patches according to crime and distance preferences
let maxdistancetometro (max [pdistancetometro] of patches with [developed? = true] + 1) ; add 1 so you don't have any distances of 0 which would make the rank 0
let maxdistancetopublic (max [pdistancetopublic] of patches with [developed? = true] + 1)
let maxproprate max [ppropcrime] of patches with [developed? = true]
ask patches
; set rank according to crime and distance to metro and public housing
[
ifelse Public_Housing = "Proximity_to"
[
set rank ((ppropcrime / maxproprate) ^ lowcrimepref) * ((pdistancetometro / maxdistancetometro) ^ metropref ) * ((pdistancetopublic / maxdistancetopublic) ^ publichousingpref )]
; else public housing preference is "Distance_from"
[set rank ((ppropcrime / maxproprate) ^ lowcrimepref) * ((pdistancetometro / maxdistancetometro) ^ metropref ) * ((1 - (pdistancetopublic / maxdistancetopublic)) ^ publichousingpref )]
]
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; move routine ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
to movehouseholds ; move existing households
ask households with [happy? = false] [
let tempbudget budget
let affordablevacancies patches with [pnum_vac > 0 and prent <= tempbudget ]
let k count affordablevacancies
let target 0
if any? affordablevacancies
[
ifelse High_Value_Preference? ; choose best (highest value) among set of properties that satisfy budget and preference needs
[
ifelse k >= 3 [set target max-one-of (min-n-of (k / 3) affordablevacancies [rank]) [prent]]
[set target min-one-of affordablevacancies [rank]]
]
[set target min-one-of affordablevacancies [rank] ]
move-to target
set pnum_vac pnum_vac - 1
set happy? true
show-turtle
]
]
set nummoveout count households with [happy? = false] ; the rest move out
ask households with [happy? = false] [die]
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; calculate income increase routine ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
to calculateincomeincrease
ask blocks
[
let temptrak tractblkgrp
let currentmeanincome mean [income] of households with [ householdblock = temptrak]
let currentmedianincome median [income] of households with [ householdblock = temptrak]
set simulated%increasemeanincome (currentmeanincome - startmeanincome) / startmeanincome
set simulated%increasemedianincome (currentmedianincome - startmedianincome) / startmedianincome
; type temptrak type " sum vacancies " print sum [pnum_vac] of patches with [ptractblockgrp = temptrak]
]
foreach myblocks
[
x ->
if ticks = 10 [ print [simulated%increasemeanincome] of x] ; collect output data for run validation
let blockID [tractblkgrp] of x
ask patches with [ptractblockgrp = blockID]
[
set psimulation_incomeincr [simulated%increasemeanincome] of x ; update patches with income increase to display
set psimulation_meanincomeincr [simulated%increasemedianincome] of x
]
]
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; display actual income increase ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
to showactualincomeincrease ; called from user interface button
ask patches with [pactual_incomeincr > 0]
[
;set pcolor scale-color pink (.25 + ln pactual_incomeincr) 0 1.5
ifelse pactual_incomeincr < 0.5 [set pcolor pink - 5]
[ifelse pactual_incomeincr < 1.0 [set pcolor pink - 3.5]
[ifelse pactual_incomeincr < 1.5 [set pcolor pink - .5]
[ifelse pactual_incomeincr < 2.0 [set pcolor pink + 2 ]
[set pcolor pink + 4.5 ]]]]
]
; pink and cyan are good choices
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; display simulation income increase ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
to showsimulationincomeincrease ; called from user interface button
ask patches with [psimulation_incomeincr > 0]
[
;set pcolor scale-color pink (.25 + ln psimulation_incomeincr) 0 1.5
ifelse psimulation_incomeincr < 0.5 [set pcolor pink - 5]
[ifelse psimulation_incomeincr < 1.0 [set pcolor pink - 3.5]
[ifelse psimulation_incomeincr < 1.5 [set pcolor pink - .5]
[ifelse psimulation_incomeincr < 2.0 [set pcolor pink + 2 ]
[set pcolor pink + 4.5 ]]]]
]
; pink and cyan are good choices
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Load GIS Shapefiles ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
to viewDCmetrostations
let DCmetro gis:load-dataset "data/MetroStn_Concentrated/MetroStn_Concentrated.shp"
;gis:set-drawing-color white
;gis:draw DCmetro 0.5
foreach gis:feature-list-of DCmetro[
feature ->
gis:set-drawing-color blue
gis:draw feature 5.0
]
ask patches gis:intersecting DCmetro ; identify the patches with metro station
[ set pMetro true ]
; ask patch -120 -28 ;; add a waterfront metro rail station so that coordinates show up on map.
; [ set pMetro true
; set pcolor blue ]
set metropatches patches with [pMetro = true]
end
to viewDCSchools
let DC gis:load-dataset "data/DCschools/SHSBNDYPLY_WGS84.shp"
foreach gis:feature-list-of DC
[
feature ->
gis:set-drawing-color white
gis:draw feature 2.0
]
; gis:apply-coverage DC "SCHOOLNAME" HS ; color map according to school district
;ask patches
; [if (HS = "Anacostia") [set pcolor blue + 3]
; if (HS = "Coolidge") [set pcolor green + 3]
; if (HS = "Eastern") [set pcolor yellow + 3]
; if (HS = "Roosevelt") [set pcolor grey + 3]
; if (HS = "Spingarn") [set pcolor orange + 3]
; if (HS = "Woodson, H.D.") [set pcolor violet + 3]
; if (HS = "Wilson, W.") [set pcolor red + 3]
; if (HS = "Ballou") [set pcolor brown + 3]
; if (HS = "Cardozo") [set pcolor pink + 3]
; if (HS = "Dunbar") [set pcolor cyan + 3]]
; gis:set-drawing-color blue
foreach gis:feature-list-of DC ; label the school district
[
feature ->
let centroid gis:location-of gis:centroid-of feature
if not empty? centroid
[ create-hs-labels 1
[ set xcor item 0 centroid + 2
set ycor item 1 centroid
set size 0
set label-color Cyan
set label gis:property-value feature "SCHOOLNAME" ]]
]
end
to loadDCSchools
let DC gis:load-dataset "data/DCschools/SHSBNDYPLY_WGS84.shp"
gis:apply-coverage DC "SCHOOLNAME" HS
end
to loadDCblockgroupshapefile
gis:load-coordinate-system "data/tractdata/WGS_84_Geographic.prj"
set DCblockdemo gis:load-dataset "data/tractdata/blkgrp_DConly_Concentrated/blkgrp_DConly_Concentrated.shp"
gis:set-world-envelope gis:envelope-of DCblockdemo
foreach gis:feature-list-of DCblockdemo
[
feature ->
gis:set-drawing-color violet
gis:draw feature 1.5
]
gis:apply-coverage DCblockdemo "TRACT" ptract
gis:apply-coverage DCblockdemo "BLKGRP" pBLKGRP
ask patches with [ptract > 0]
[
set ptractblockgrp word ptract pBLKGRP
]
end
to loadDCblockgroupdemographics
foreach gis:feature-list-of DCblockdemo
[
feature ->
gis:set-drawing-color violet + 3
gis:draw feature 2
]
; Using gis:apply-coverage to copy values from a polygon dataset
; to a patch variable
gis:apply-coverage DCblockdemo "POP2000" pPOP2000
gis:apply-coverage DCblockdemo "POP2010" pPOP2010
gis:apply-coverage DCblockdemo "TRACT" ptract
gis:apply-coverage DCblockdemo "HOUSEHOLDS" phouseholds10
gis:apply-coverage DCblockdemo "BLKGRP" pBLKGRP
ask patches with [pPOP2000 > 0]
[
set ptractblockgrp word ptract pBLKGRP
]
end
to viewpublichousing
let DCpublichouse gis:load-dataset "data/tractdata/Public_Housing_Pointfinala/Public_Housing_Pointfinala.shp"
foreach gis:feature-list-of DCpublichouse
[
feature ->
gis:set-drawing-color lime + 1
gis:draw feature 5.0
]
ask patches gis:intersecting DCpublichouse ; identify the patches with metro station
[ set pPUblic true ]
set publicpatches patches with [pPublic = true]
end
to clearCanvas
ca
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; File Input Routines adapted from ;;
;; suggestions of Steve Scott, CSS PhD ;;
;; candidate ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
to input2000data
setup-globals
read-csv
;print-results
end
; setup globals
to setup-globals
set myfile "data/inputdata/DC Data 2000.csv"
set csvheaders []
set csvdata []
end
;
; helper function to parse a comma-separated line
;
to-report parse-line [ aline ]
let parsed-list []
let separator ","
let i 0
let ch ""
let token ""
while [ i < length aline ] [
set ch item i aline
ifelse (ch = separator) [
set parsed-list (lput token parsed-list)
set token ""
]
[
set token (word token ch)
]
set i (i + 1)
]
set parsed-list (lput token parsed-list)
report parsed-list
end
;
; read the CSV
; first line is comma-separated headers
; 2nd thru Nth lines are comma-separated values
;
; does not strip out blank spaces, so ", foo" gets parsed as " foo".
;
to read-csv
;let csvfile myfile
print (word "DEBUG: processing file " myfile)
; open the file
ifelse file-exists? myfile [
file-open myfile
; read first line with headers
let headers file-read-line
let tokens parse-line headers
; for each column, put column header in csvheaders, put empty list in csvdata.
foreach tokens [
x ->
set csvheaders (lput x csvheaders)
set csvdata (lput [] csvdata)
]
; read rest of file
let i 0
while [ not file-at-end? ] [
let line file-read-line
;;print (word "DEBUG: just read line # " i ", = " line)
set tokens parse-line line ; list containing items in line
let k 0
; for each item in the line, place in next column list
foreach tokens [
x ->
let datalist item k csvdata
set datalist (lput x datalist)
set csvdata replace-item k csvdata datalist
set k (k + 1)
]
set i (i + 1)
]
file-close-all
]
[
print (word "error: unable to open file " myfile)
]
end
to print-results
; print out the list of CSV headers
foreach csvheaders [
x ->
type x type " "
]
print " "
; loop thru and print out each row of data
let numcols length csvheaders
let numitems length item 0 csvdata
type "numitems" print numitems
let i 0
while [ i < numitems ] [
let j 0
while [ j < numcols ] [
let value item i (item j csvdata)
type value type ", "
set j (j + 1)
]
set i (i + 1)
print ""
]
; print out each tract
set i 0
while [ i < numitems ] [
let j 0
let value item i (item j csvdata)
type value type ", "
set i (i + 1)
]
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@#$#@#$#@
GRAPHICS-WINDOW
209
13
785
496
-1
-1
2.36
1
10
1
1
1
0
0
0
1
-120
120
-100
100
1
1
1
ticks
30.0
BUTTON
8
13
103
71
Setup
setup
NIL
1
T
OBSERVER
NIL
NIL
NIL
NIL
1
BUTTON
903
484
1001
517
View Metro
viewDCmetrostations
NIL
1
T
OBSERVER
NIL
NIL
NIL
NIL
1
BUTTON
787
484
903
517
View Public Housing
viewpublichousing
NIL
1
T
OBSERVER
NIL
NIL
NIL
NIL
1
CHOOSER
800
555
1028
600
DC_Map
DC_Map
"data/Ward6.png" "data/Ward6-transparent.png"
0
BUTTON
8
135
198
168
NIL
import-drawing DC_Map
NIL
1
T
OBSERVER
NIL
NIL
NIL
NIL
1
BUTTON
669
528
786
561
NIL
clear-all
NIL
1
T
OBSERVER
NIL
NIL
NIL