globals [ ;; population dimensions max-dist ;; the maximum distance a borrower is away from every one else min-dist ;; the minimum distance a borrower is away from every one else mean-dist ;; the average of the maximum and minimum distance stdv-dist ;; the standard deviation of the distances mean-cult ;; the average of the randomly assigned cultural scores of borrowers stdv-cult ;; the standard deviation of the culture scores group-size ;; the size of borrowing groups tier1 tier2 tier3 ;; list containing members of the 3 tiers ;; financial parameters ideal-payment ;; how much a borrower should be paying each week ideal-savings ;; how much a borrower should be saving each week contributions ;; total contributions (an outcome of total savings minus total debt) assumed-debt ;; debt bank writes off final-defaulters ;; percentage of defaulters at the end of the loan cycle final-contrib ;; final amount in community pot at end of loan cycle clustering-coefficient ;; network clustering coefficient avg-cc ;; average network clustering coefficient avg-dc ;; average network degree centrality rc ] breed [borrowers borrower] breed [spinners spinner] borrowers-own [ dummy ;; a dummy average that factors in the effects of other unconsidered variables in the model principal ;; amount owed at any given time (including interest) payment ;; total amount paid over loan cycle my-trib ;; contribution to the community pot my-debt ;; money borrowed from community pot my-savings ;; how much money I save init-savings ;; how much savings you start with minimum-contribution ;; minimum each person has to contribute at the end of a loan cylce internal-default ;; true or false - whether the borrower defaults in a loan cycle external-default ;; true or false - whether the borrower needs to be kicked out time-alive ;; how many months the borrower has been in the group cult_prox ;; type of culture (0-8) 0 = grad student; 8 = lumber jack culture-z-score ;; standard deviation from mean dist_prox ;; average walking distance (in time) from other nodes in the group ;; percentage of people within 10 mins of a node tier ;; which level the borrower is on enemies ;; list of people you break up with init-influence ;; initial probability for influence to pay node-clustering-coefficient ;; the clustering coefficient of the node node-avg-dc ;; the average degree of the node node-avg-cc ;; the average clustering coefficient ] links-own [ influence ;; probablity of influence the connected nodes have on each toerh ] ;; --- Simulation -- ;; Runs the model x times -- x is defined by the interface slider -- and prints out csv file with ;; degree centrality and clustering coefficient numbers for further analysis to run-x-times set rc 0 let net_output (word "Average Degree Centrality,Average Clustering Coefficient, Percentage defaulters (" num-borrowers "), Total Contributions\n") let node_output (word "Average Degree,Average Clustering Coefficient, Defaulter, Total Contributions\n") setup while [rc < run-time] [ if (rc > 0) [ setup-again ] while [ not cycle-end ] [ (simulate true) set avg-dc avg-dc + degree-centrality set avg-cc avg-cc + clustering-coefficient ask borrowers [ let d (count link-neighbors) - (length enemies) set node-avg-dc ifelse-value (d <= 0) [ node-avg-dc + 0 ] [ node-avg-dc + d] set node-avg-cc node-avg-cc + node-clustering-coefficient ] ] ask borrowers [ let d (count link-neighbors) - (length enemies) set node-avg-dc ifelse-value (d <= 0) [ node-avg-dc + 0 ] [ node-avg-dc + d ] set node-avg-cc node-avg-cc + node-clustering-coefficient ] set net_output (word net_output (avg-dc / ticks) "," (avg-cc / ticks) "," final-defaulters "," final-contrib "\n") ask borrowers [ let d ifelse-value (dummy < dummy-var or external-default = true) [ 1 ] [ 0 ] set node_output (word node_output (node-avg-dc / ticks) "," (node-avg-cc / ticks) "," d "," my-trib "\n") ] set rc rc + 1 ] ;;(print-csv-file net_output) ;;(print-csv-file node_output) end ;; makes a movie of the model and exports movie to a file to make-movie ;; prompt user for movie location user-message "First, save your new movie file (choose a name ending with .mov)" let path user-new-file if not is-string? path [ stop ] ;; stop if user canceled ;; run the model setup movie-start path movie-set-frame-rate 3 movie-grab-interface while [ not cycle-end ] [ simulate true movie-grab-interface ] ;; export the movie movie-close user-message (word "Exported movie to " path) end ;; main simulation loop ;; @param once if true stops simulation after each week to simulate [once] tick update-spinner ;; make payments ask borrowers [ set time-alive time-alive + 1 ;; increase time in group ;; make payment calculations only if borrower has not defaulted if external-default = false [ (process_payment ticks) let my-size size ifelse (my-debt > 0) [ set my-size ifelse-value (my-size > 2) [ my-size - 2][ 2 ] ][ set my-size ifelse-value (my-size < 24) [ my-size + 1][ 24 ] ] set size my-size ] if internal-default = true [ mad_friends ] ] set contributions (sum [my-trib] of borrowers) - (sum [my-debt] of borrowers) do-plots ; end of loan cycle if cycle-end [ ; deal with defaulters handle-defaulters ask borrowers [ if internal-default = true [ mad_friends ] ] set final-defaulters ((count borrowers with [dummy < dummy-var]) / num-borrowers) report-savings print-output-files do-plots ; end when lending period is over if ((ticks + 1) > (loan-cycle * 4)) [ stop ] ; stop if we are going one week at a time if once = true [ stop ] ] ; print new weekly graph print-output-files end ;; -------- Financial calculations --------------------- to process_payment [ week ] ;; charge interest every month if ((week mod 4) = 0) [ if (principal > 0) [ set principal principal * interest-rate ]] ;; figure out how much to pay back this week let payprob (calc_payment_prob culture-z-score dist_prox) ;; payment based on culture/distance/others let pay-amount 2 * ideal-payment * payprob let trib-amount 2 * ideal-savings * payprob ;; put all your money towards the principal if savings is adequate if ((my-trib + my-savings) >= minimum-contribution) [ set pay-amount trib-amount + pay-amount set trib-amount 0 ] ;; handle debts if (my-debt > 0 and trib-amount > 0) [ ifelse (trib-amount > my-debt) [ set trib-amount trib-amount - my-debt set my-debt 0 ][ set my-debt my-debt - trib-amount set trib-amount 0 ] ] if (my-debt > 0 and pay-amount > 0) [ ifelse (pay-amount > my-debt) [ set pay-amount pay-amount - my-debt set my-debt 0 ][ set my-debt my-debt - pay-amount set pay-amount 0 ] ] ;; handle savings let paid-savings false if (my-savings < init-savings) [ set paid-savings true ifelse ((pay-amount + my-savings) > init-savings) [ set pay-amount pay-amount - (init-savings - my-savings) set my-savings init-savings ][ set my-savings my-savings + pay-amount set pay-amount 0 ] ] ;; borrow from savings if (principal > 0 and paid-savings = false) [ if (pay-amount < 2) [ ifelse (my-savings > (ideal-payment - pay-amount)) [ set my-savings my-savings - (ideal-payment - pay-amount) set pay-amount ideal-payment ][ let debt ideal-payment - pay-amount - my-savings ifelse ((contributions - debt) > 0) [ set my-debt my-debt + debt set my-savings 0 set pay-amount ideal-payment ][ set assumed-debt debt - (pay-amount + my-savings) set pay-amount pay-amount + my-savings (handle_external_defaulters who) ] ] ] ] ifelse (principal > 0) [ ifelse (pay-amount > principal) [ set trib-amount trib-amount + (pay-amount - principal) set pay-amount principal set principal 0 ][ set payment payment + pay-amount set principal principal - pay-amount ] if (principal < 0) [ set principal 0 ] ][ set principal 0 set trib-amount trib-amount + pay-amount set pay-amount 0 ] set my-trib my-trib + trib-amount ifelse (my-debt > 0) [ set internal-default true ] [ set internal-default false ] end ;; calculate probability of how much to repay to-report calc_payment_prob [cult dist] let score 0 let cult-score 0 let dist-score 0 ;; calculate distance score let d abs (dist - max-dist) ifelse dist > 5 [ set dist-score (d / max-dist) ][ set dist-score 1 ] ;; figure out culture score let max-stvd-cult max [culture-z-score] of borrowers ifelse (cult = max-stvd-cult and max-stvd-cult >= 2) [ set cult-score 0.05 ][ ifelse (cult = max-stvd-cult) [ set cult-score 1 ][ set cult-score (max-stvd-cult - cult) / max-stvd-cult ] ] ;; take average of scores set score (cult-score + dist-score) / 2 let mr (random 160) / 100 report score * dummy * mr end to handle-defaulters let defaulters [] ;; list of defaulters let defaulters-count 0 ;; number of people who have defaulted let profit contributions set final-contrib contributions set contributions 0 foreach sort-by [[principal] of ?1 < [principal] of ?2] borrowers [ ask ? [ ifelse external-default = true [ set defaulters lput who defaulters set defaulters-count defaulters-count + 1 ][ if principal > 0 [ set internal-default true set color black let new-trib profit - principal ifelse (new-trib >= 0) [ ifelse (principal <= my-trib) [ set my-trib my-trib - principal ][ set my-trib 0 ] set profit profit - principal set my-debt my-debt + principal set internal-default false ][ (handle_external_defaulters who) set defaulters lput who defaulters set defaulters-count defaulters-count + 1 ] ] if (my-savings + my-trib) < minimum-contribution [ set internal-default true set color black ] ] ] ] ;; get what's left of seed money set profit profit - 50 ;; split the rest of the contributions equally among the non-defaulters if ( (num-borrowers - defaulters-count) > 0 and (profit > 0)) [ ask borrowers [ set my-savings my-savings + (profit / (num-borrowers - defaulters-count)) ] ] end to handle_external_defaulters [ me ] ask borrower me [ set shape "face sad" set my-savings 0 set external-default true ask link-neighbors [ ask link-with myself [ hide-link set influence 0 ] if (not member? [who] of myself [enemies] of self) [ set enemies lput [who] of myself enemies set [enemies] of myself lput who [enemies] of myself ] ] ] end ;; make your friends mad at you for defaulting to mad_friends set internal-default false set color black ;; lose some prestige with friends, but let what's left of your friendship influence your paying probability ifelse (count link-neighbors > 0 and (count link-neighbors > length enemies)) [ ask one-of link-neighbors with [not member? [who] of myself [enemies] of self][ set enemies lput [who] of myself enemies set [enemies] of myself lput who [enemies] of myself ask link-with myself [ hide-link ] (mad_friends_of_friends [who] of myself [who] of self [enemies] of myself) ] let frebate ((inf-level who) / (init-influence)) set dummy (dummy - frebate) * 0.5 ][ set dummy dummy - 0.5 ] if (dummy <= 0) [ set dummy 0.1 ] end to mad_friends_of_friends [defaulter pissedoff myenemies] ;; get friends of pissed off friend that are your friends to be mad at you too ask borrower pissedoff [ ask link-neighbors [ if (link-neighbor? borrower defaulter and (not member? defaulter [enemies] of self)) [ let inf 1 ask link [who] of self defaulter [ set influence influence - 0.25 if (influence <= 0) [ set influence 0 hide-link ] set inf influence ] if (inf = 0) [ set [enemies] of self lput defaulter [enemies] of self let s [who] of self ask borrower defaulter [ set enemies lput s enemies] ] ] ] ] end ;; ========== NETWORK METRICS ============== ;; Freeman to-report degree-centrality let degrees [] let sumdiff 0 let norm (num-borrowers - 1) * (num-borrowers - 2) ask borrowers [ set degrees lput ((count my-links) - (length enemies)) degrees ] let max-degree max degrees foreach degrees [ set sumdiff sumdiff + (max-degree - ?) ] report (sumdiff / norm) end to-report in-neighborhood? [ hood ] report ( member? end1 hood and member? end2 hood ) end to find-clustering-coefficient ifelse all? borrowers [(count link-neighbors) - (length enemies) <= 1 ] [ ;; it is undefined ;; what should this be? set clustering-coefficient 0 ] [ let total 0 ask borrowers with [ (count link-neighbors) - (length enemies) <= 1] [ set node-clustering-coefficient 0 ] ask borrowers with [ (count link-neighbors) - (length enemies) > 1] [ let hood link-neighbors with [not member? [who] of myself [enemies] of self] set node-clustering-coefficient (2 * count links with [ in-neighborhood? hood ] / ((count hood) * (count hood - 1)) ) ;; find the sum for the value at turtles set total total + node-clustering-coefficient ] ;; take the average set clustering-coefficient total / count borrowers with [count link-neighbors > 1] ] end ;; --- Initialization ------- to setup clear-all set max-dist 0 set mean-dist 0 set min-dist 0 set mean-cult 0 set stdv-cult 0 set group-size 30 set assumed-debt 0 set contributions 50 set ideal-payment round ((initial-amount * interest-rate) / (loan-cycle * 4)) set ideal-savings round ((0.2 * initial-amount * interest-rate) / (loan-cycle * 4)) set avg-cc 0 set avg-dc 0 set final-defaulters 0 set final-contrib 0 setup-borrowers (num-borrowers) create-spinner end to setup-again set max-dist 0 set mean-dist 0 set min-dist 0 set mean-cult 0 set stdv-cult 0 set group-size 30 set assumed-debt 0 set contributions 50 set ideal-payment round ((initial-amount * interest-rate) / (loan-cycle * 4)) set ideal-savings round ((0.2 * initial-amount * interest-rate) / (loan-cycle * 4)) set final-defaulters 0 set final-contrib 0 ct setup-borrowers (num-borrowers) ;create-spinner end to setup-borrowers [ num-of-borrowers ] create-borrowers num-of-borrowers [ ;; mfi attributes set payment 0 set my-trib 0 set my-debt 0 set my-savings random-normal 8 2.6 set init-savings my-savings set internal-default false set external-default false set time-alive 0 set dummy dummy-var let adj_div ifelse-value (diversity = 0) [ .000001 ][ ((5 * diversity) / 50) + .0001 ] set cult_prox round (random-normal 2.5 adj_div) let adj_dev ifelse-value (proximity = 0) [ 3 ][ 9.928 ] set dist_prox round (abs (random-normal proximity adj_dev)) set principal initial-amount * interest-rate set minimum-contribution my-savings + (initial-amount * 0.2) set enemies [] set node-avg-dc 0 set node-avg-cc 0 ;; node attributes set size 12 set shape ifelse-value (cult_prox >= 0 and cult_prox <= 5) [ "person graduate"] [ "person lumberjack" ] ] ;; figure out mean and standard deviation of culture set mean-cult mean [cult_prox] of borrowers set stdv-cult standard-deviation [cult_prox] of borrowers set max-dist max [dist_prox] of borrowers set min-dist min [dist_prox] of borrowers set mean-dist mean [dist_prox] of borrowers set stdv-dist standard-deviation [dist_prox] of borrowers ask borrowers [ set culture-z-score (abs ((cult_prox - mean-cult) / stdv-cult)) ifelse show-labels? [ set label (word "who_ " who) ] [ set label "" ] ] render-borrowers link-borrowers find-clustering-coefficient set avg-dc degree-centrality set avg-cc clustering-coefficient ask borrowers [ set node-avg-dc count link-neighbors set node-avg-cc node-clustering-coefficient ] end ;; ---------- The following set ups the world and positions the borrowers ------------------ ;; make the spinner for the upper right hand corner to create-spinner create-spinners 1 [ set shape "default" setxy (max-pxcor - 10) (max-pycor - 10) set color gray - 1.5 set size 16 set heading 0 set label 0 ] end to link-borrowers let done [] ;; keep track of edges to avoid double edges set tier1 [] set tier2 [] set tier3 [] let edge1 "" let edge2 "" let idx 0 ;; borrowers in 3 tiers according to their distances from an imaginary bank ask borrowers [ if (dist_prox < (max-dist / 3)) [ set tier1 lput who tier1 set tier 1 ] if (dist_prox <= ((2 * max-dist) / 3) and dist_prox > (max-dist / 3)) [ set tier2 lput who tier2 set tier 2 ] if (dist_prox <= max-dist and dist_prox > ((2 * max-dist) / 3)) [ set tier3 lput who tier3 set tier 3 ] ] ;; set up probabilities of linking let t1_t1_rep n-values (length tier1) [ 0 ] repeat round (0.60 * (length tier1)) [ set idx random (length tier1) while [(is-one idx t1_t1_rep)][ set idx random (length tier1) ] set t1_t1_rep replace-item idx t1_t1_rep 1 ] let t2_t2_rep n-values (length tier2) [ 0 ] repeat round (0.30 * (length tier2)) [ set idx random (length tier2) while [(is-one idx t2_t2_rep)][ set idx random (length tier2) ] set t2_t2_rep replace-item idx t2_t2_rep 1 ] let t2_t1_rep n-values (length tier1) [ 0 ] repeat round (0.30 * (length tier1)) [ set idx random (length tier1) while [(is-one idx t2_t1_rep)][ set idx random (length tier1) ] set t2_t1_rep replace-item idx t2_t1_rep 1 ] let t3_t3_rep n-values (length tier3) [ 0 ] repeat round (0.05 * (length tier3)) [ set idx random (length tier3) while [(is-one idx t3_t3_rep)][ set idx random (length tier3) ] set t3_t3_rep replace-item idx t3_t3_rep 1 ] let t3_t2_rep n-values (length tier2) [ 0 ] repeat round (0.20 * (length tier2)) [ set idx random (length tier2) while [(is-one idx t3_t2_rep)][ set idx random (length tier2) ] set t3_t2_rep replace-item idx t3_t2_rep 1 ] let t3_t1_rep n-values (length tier1) [ 0 ] repeat round (0.10 * (length tier1)) [ set idx random (length tier1) while [(is-one idx t3_t1_rep)][ set idx random (length tier1) ] set t3_t1_rep replace-item idx t3_t1_rep 1 ] ;; connect people in tier 1 ask borrowers with [ tier = 1 ][ ask other borrowers with [ [tier] of self = 1][ let know-each-other item random (length t1_t1_rep) t1_t1_rep if (know-each-other = 1) [ set edge1 (word [who] of myself "-" [who] of self) set edge2 (word [who] of self "-" [who] of myself) ifelse ((member? edge1 done) or (member? edge2 done)) [ ][ create-link-with myself [ set thickness 0.75 set color (62 + abs([cult_prox] of myself - [cult_prox] of end1)) set influence ifelse-value (color - 62 < .25) [ 1 ][ 0.75 ] ] set done lput edge1 done set done lput edge2 done ] ] ] ] ;; connect people in tier 2 to each other and people in tier 1 ask borrowers with [ tier = 2 ][ ask other borrowers with [ [tier] of self = 2][ let know-each-other item random (length t2_t2_rep) t2_t2_rep if (know-each-other = 1) [ set edge1 (word [who] of myself "-" [who] of self) set edge2 (word [who] of self "-" [who] of myself) ifelse ((member? edge1 done) or (member? edge2 done)) [ ][ create-link-with myself [ set thickness 0.75 set color (62 + abs([cult_prox] of myself - [cult_prox] of end1)) set influence ifelse-value (color - 62 < .25) [ 0.75 ][ 0.5 ] ] set done lput edge1 done set done lput edge2 done ] ] ] ask other borrowers with [ [tier] of self = 1][ let know-each-other item random (length t2_t1_rep) t2_t1_rep if (know-each-other = 1) [ if ( [shape] of myself = [shape] of self ) [ set edge1 (word [who] of myself "-" [who] of self) set edge2 (word [who] of self "-" [who] of myself) ifelse ((member? edge1 done) or (member? edge2 done)) [ ][ create-link-with myself [ set thickness 0.75 set color (62 + abs([cult_prox] of myself - [cult_prox] of end1)) set influence ifelse-value (color - 62 < .25) [ 0.75 ][ 0.5 ] ] set done lput edge1 done set done lput edge2 done ] ] ] ] ] ;; connect people in tier 3 to each other and people in tiers 2 and 1 ask borrowers with [ tier = 3 ][ ask other borrowers with [ [tier] of self = 3][ let know-each-other item random (length t3_t3_rep) t3_t3_rep if (know-each-other = 1) [ set edge1 (word [who] of myself "-" [who] of self) set edge2 (word [who] of self "-" [who] of myself) ifelse ((member? edge1 done) or (member? edge2 done)) [ ][ create-link-with myself [ set thickness 0.75 set color (62 + abs([cult_prox] of myself - [cult_prox] of end1)) set influence ifelse-value (color - 62 < .25) [ 0.5 ][ 0.25 ] ] set done lput edge1 done set done lput edge2 done ] ] ] ask other borrowers with [ [tier] of self = 2 ][ let know-each-other item random (length t3_t2_rep) t3_t2_rep if (know-each-other = 1) [ if ( [shape] of myself = [shape] of self ) [ set edge1 (word [who] of myself "-" [who] of self) set edge2 (word [who] of self "-" [who] of myself) ifelse ((member? edge1 done) or (member? edge2 done)) [ ][ create-link-with myself [ set thickness 0.75 set color (62 + abs([cult_prox] of myself - [cult_prox] of end1)) set influence ifelse-value (color - 62 < .25) [ 0.5 ][ 0.25 ] ] set done lput edge1 done set done lput edge2 done ] ] ] ] ask other borrowers with [ [tier] of self = 1 ][ let know-each-other item random (length t3_t1_rep) t3_t1_rep if (know-each-other = 1) [ if ( [shape] of myself = [shape] of self ) [ set edge1 (word [who] of myself "-" [who] of self) set edge2 (word [who] of self "-" [who] of myself) ifelse ((member? edge1 done) or (member? edge2 done)) [ ][ create-link-with myself [ set thickness 0.75 set color (62 + abs([cult_prox] of myself - [cult_prox] of end1)) set influence ifelse-value (color - 62 < .25) [ 0.75 ][ 0.5 ] ] set done lput edge1 done set done lput edge2 done ] ] ] ] ] ;; set initial influence scores ask borrowers [ set init-influence (inf-level who) ] end to do-plots find-clustering-coefficient set-current-plot "Network Metrics" set-current-plot-pen "degree-pen" plot degree-centrality set-current-plot-pen "clust-pen" plot clustering-coefficient end to update-spinner ask spinners [ set heading ticks * 22.5 set label ticks ] end to render-borrowers layout-circle borrowers with [ dist_prox <= (max-dist / 3)] ((world-width - 2) / 5 - 1) layout-circle borrowers with [ dist_prox <= ((2 * max-dist) / 3) and dist_prox > (max-dist / 3)] ((world-width - 5) / 3 - 1) layout-circle borrowers with [ dist_prox <= max-dist and dist_prox > ((2 * max-dist) / 3)] ((world-width - 15) / 2 - 1) end ;;;; ------------ FILE REPORTING --------------- to print-output-files print-pajek-file print-guess-file end to print-csv-file [ csv ] ;; prompt user for file location user-message "Name of new CSV file (choose a name ending with .csv)" let path user-new-file if not is-string? path [ stop ] ;; stop if user canceled file-open path file-print csv file-close end to print-pajek-file let fname "dontusethis" ;;comment out this line and fill in the one below ;;let fname (word "yourfilelocation/yourfilename" ticks ".gdf") let done [] ;; keep track of edges to avoid double edges let edge1 "" let edge2 "" ;; Print nodes if (file-exists? fname) [ file-delete fname ] file-open fname file-print (word "*Vertices " num-borrowers) let style 2 let co "Blue" let sc "Blue" foreach sort-by [[who] of ?1 < [who] of ?2] borrowers [ ask ? [ ifelse (external-default = true) [ set sc "Black" set co "Red" ][ set co ifelse-value (shape = "person graduate") [ "Salmon" ][ "Blue" ] set sc ifelse-value (dummy < dummy-var) [ "Red" ][ co ] ] file-print (word (who + 1) " \"who_" who "\" 0.0 0.0 0.0 ic " co " bc " sc) ] ] ;; print edges file-print (word "*Edges") ask borrowers [ ask link-neighbors with [not member? [who] of myself [enemies] of self][ set edge1 (word [who] of myself "-" [who] of self) set edge2 (word [who] of self "-" [who] of myself) let c "LightCyan" if (([tier] of myself = [tier] of self) and tier = 1) [ set c "Orange" ] if (([tier] of myself = [tier] of self) and tier = 2) [ set c "Green" ] if (([tier] of myself = [tier] of self) and tier = 3) [ set c "Periwinkle" ] ifelse ((member? edge1 done) or (member? edge2 done)) [ ][ let wme ([who] of self) + 1 let wthem ([who] of myself) + 1 file-print (word wthem " " wme " 4 c " c) set done lput edge1 done set done lput edge2 done ] ] ] file-close ;;print (word "Saved " fname) end to print-guess-file let fname "dontusethis" ;;comment out this line and fill in the one below ;;let fname (word "yourfilelocation/yourfilename" ticks ".gdf") let done [] ;; keep track of edges to avoid double edges let edge1 "" let edge2 "" ;; Print nodes if (file-exists? fname) [ file-delete fname ] file-open fname file-print (word "nodedef>name VARCHAR(8),savings INT,style,color,strokecolor") let style 2 let co "blue" let sc "blue" foreach sort-by [[who] of ?1 < [who] of ?2] borrowers [ ask ? [ ifelse (external-default = true) [ set sc "black" set co "red" ][ set co ifelse-value (shape = "person graduate") [ "salmon" ][ "blue" ] set sc ifelse-value (dummy < dummy-var) [ "red" ][ co ] ] let sv (my-trib - my-debt) file-print (word "\"who_" who "\"," sv ","2","co","sc) ] ] ;; print edges file-print (word "edgedef>node1 VARCHAR(8),node2 VARCHAR(8),color") ask borrowers [ let me who ask link-neighbors with [not member? [who] of myself [enemies] of self][ set edge1 (word [who] of myself "-" [who] of self) set edge2 (word [who] of self "-" [who] of myself) let c "lightcyan" if (([tier] of myself = [tier] of self) and tier = 1) [ set c "orange" ] if (([tier] of myself = [tier] of self) and tier = 2) [ set c "green" ] if (([tier] of myself = [tier] of self) and tier = 3) [ set c "periwinkle" ] ifelse ((member? edge1 done) or (member? edge2 done)) [ ][ file-print (word "\"who_"[who] of myself "\",\"who_"[who] of self "\","c) set done lput edge1 done set done lput edge2 done ] ] ] file-close end ;; ---------- Utility functions ---------- to report-savings ;;print (word "\nFor loan cycle " (ticks / (loan-cycle * 4)) " (" (ticks / 4) " months elapsed):\n") ;foreach sort-by [[principal] of ?1 < [principal] of ?2] borrowers [ ; ask ? [ ;print (word "B" who "=> Pr:" principal "\tPay: " payment "\tTribs: " my-trib "\tDebt: " my-debt "\tIDef: " internal-default "\tEDef: " external-default "\tSvgs: " (my-savings - init-savings) "\tDummy: " dummy);;"\tCult: " culture-z-score "\tDist: " dist_prox) ;] ;] end to-report cycle-end if (ticks = 0) [ report false ] report ifelse-value ((ticks mod (loan-cycle * 4)) = 0 or ((ticks + 1) > 48)) [ true ][ false ] end to-report is-one [ idx lst ] report ifelse-value ((item idx lst) = 1) [ true ] [ false ] end to-report inf-level [ me ] let sc 0 ask borrower me [ ask my-links [ set sc sc + influence ] ] report sc end @#$#@#$#@ GRAPHICS-WINDOW 498 10 1095 628 120 120 2.436 1 10 1 1 1 0 0 0 1 -120 120 -120 120 1 1 1 Weeks CC-WINDOW 5 642 1104 737 Command Center 0 SLIDER 8 303 180 336 diversity diversity 0 50 20 10 1 NIL HORIZONTAL SLIDER 8 254 180 287 proximity proximity 0 60 13 1 1 min HORIZONTAL BUTTON 213 58 279 91 Setup setup NIL 1 T OBSERVER NIL NIL NIL NIL SWITCH 6 10 144 43 show-labels? show-labels? 0 1 -1000 BUTTON 370 60 452 93 Go simulate(false) T 1 T OBSERVER NIL NIL NIL NIL MONITOR 6 344 58 389 Grad S count borrowers with [ shape = \"person graduate\" ] 1 1 11 MONITOR 62 343 145 388 Lumberjacks count borrowers with [shape = \"person lumberjack\"]\n\n\n 1 1 11 SLIDER 9 213 206 246 num-borrowers num-borrowers 3 100 30 1 1 people HORIZONTAL SLIDER 7 93 179 126 initial-amount initial-amount 0 500 150 50 1 $ HORIZONTAL SLIDER 7 173 193 206 loan-cycle loan-cycle 1 12 4 1 1 months HORIZONTAL BUTTON 285 59 366 92 go once simulate (true) NIL 1 T OBSERVER NIL NIL NIL NIL BUTTON 321 13 429 46 NIL make-movie NIL 1 T OBSERVER NIL NIL NIL NIL PLOT 213 154 491 388 Network Metrics Week vals 0.0 16.0 0.2 0.3 true true PENS "degree-pen" 1.0 0 -2674135 true "clust-pen" 1.0 0 -13345367 true MONITOR 342 106 488 151 Clustering coefficient clustering-coefficient 2 1 11 MONITOR 214 104 334 149 Degree Centrality degree-centrality 3 1 11 SLIDER 6 51 178 84 run-time run-time 1 1000 1 1 1 times HORIZONTAL BUTTON 211 13 315 46 Run X times run-x-times NIL 1 T OBSERVER NIL NIL NIL NIL SLIDER 7 136 179 169 interest-rate interest-rate 0 1.5 1.03 .01 1 NIL HORIZONTAL MONITOR 17 401 81 446 Counter rc 17 1 11 SLIDER 10 466 182 499 dummy-var dummy-var 0 10 1 0.5 1 NIL HORIZONTAL @#$#@#$#@ WHAT IS IT? ----------- This section could give a general understanding of what the model is trying to show or explain. HOW IT WORKS ------------ The model runs a simulation over a period of the loan cycle (specified in months) -- each tick represents a week. During the initialization of the model, the following happens: - The community pot is set to $50 to prevent people from defaulting in the first round - The ideal payment is set to the average payment a borrower will have to make to repay the borrowed amount, including interest, at the end of the loan cycle. - The ideal savings is 20% of the average payment a borrower will have to make to repay the borrowed amount, including interest, at the end of the loan cycle - The specified number of borrowers are created, each having the following attributes: - - TERMINOLOGY ----------- Assumed debt: On the occassion that a borrower externally defaults, any of the left over debt that is not covered by the contributions is assumed by the lending institution. Borrowers: The models agent - they are part of a group and receive an initial loan amount which they need to pay back at the end of the loan cycle Community Pot: Each week, every borrower contributes a portion of their income to a community pot that all can borrow from. At the end of the loan cycle, any money left over in the community pot is shared equally among borrowers who did not default in the loan cycle. External Default: A borrower defaults externally when they cannot pay off a debt using funds from either their savings or the community pot. When a borrower externally defaults, they lose their links and are not considered in subsequent runs until the end of the loan cycle. Ideal Payment: how much a borrower should be paying each week to pay off the borrowed amount at the end of the loan cycle Ideal Savings: how much a borrower should be saving each week to meet their minimum contribution requirement Internal Default: A borrower defaults internally if they cannot make a payment during the week and end up borrowing from the community pot. Internally defaulting results in a randomly chosen friend of the borrower and any of their mutual friends getting "pissed off." In some cases links with these friends will be broken when a certain threshold is exceeded Loan cycle: This defines the time the borrowers have to pay back the money borrowed. The borrowers are expected to pay back a portion of their loan each week during the loan cycle. HOW TO USE IT ------------- This section could explain how to use the model, including a description of each of the items in the interface tab. THINGS TO NOTICE ---------------- This section could give some ideas of things for the user to notice while running the model. THINGS TO TRY ------------- This section could give some ideas of things for the user to try to do (move sliders, switches, etc.) with the model. EXTENDING THE MODEL ------------------- This section could give some ideas of things to add or change in the procedures tab to make the model more complicated, detailed, accurate, etc. NETLOGO FEATURES ---------------- This section could point out any especially interesting or unusual features of NetLogo that the model makes use of, particularly in the Procedures tab. It might also point out places where workarounds were needed because of missing features. RELATED MODELS -------------- This section could give the names of models in the NetLogo Models Library or elsewhere which are of related interest. CREDITS AND REFERENCES ---------------------- This section could contain a reference to the model's URL on the web if it has one, as well as any other necessary credits or references. @#$#@#$#@ default true 0 Polygon -7500403 true true 150 5 40 250 150 205 260 250 airplane true 0 Polygon -7500403 true true 150 0 135 15 120 60 120 105 15 165 15 195 120 180 135 240 105 270 120 285 150 270 180 285 210 270 165 240 180 180 285 195 285 165 180 105 180 60 165 15 arrow true 0 Polygon -7500403 true true 150 0 0 150 105 150 105 293 195 293 195 150 300 150 box false 0 Polygon -7500403 true true 150 285 285 225 285 75 150 135 Polygon -7500403 true true 150 135 15 75 150 15 285 75 Polygon -7500403 true true 15 75 15 225 150 285 150 135 Line -16777216 false 150 285 150 135 Line -16777216 false 150 135 15 75 Line -16777216 false 150 135 285 75 bug true 0 Circle -7500403 true true 96 182 108 Circle -7500403 true true 110 127 80 Circle -7500403 true true 110 75 80 Line -7500403 true 150 100 80 30 Line -7500403 true 150 100 220 30 butterfly true 0 Polygon -7500403 true true 150 165 209 199 225 225 225 255 195 270 165 255 150 240 Polygon -7500403 true true 150 165 89 198 75 225 75 255 105 270 135 255 150 240 Polygon -7500403 true true 139 148 100 105 55 90 25 90 10 105 10 135 25 180 40 195 85 194 139 163 Polygon -7500403 true true 162 150 200 105 245 90 275 90 290 105 290 135 275 180 260 195 215 195 162 165 Polygon -16777216 true false 150 255 135 225 120 150 135 120 150 105 165 120 180 150 165 225 Circle -16777216 true false 135 90 30 Line -16777216 false 150 105 195 60 Line -16777216 false 150 105 105 60 car false 0 Polygon -7500403 true true 300 180 279 164 261 144 240 135 226 132 213 106 203 84 185 63 159 50 135 50 75 60 0 150 0 165 0 225 300 225 300 180 Circle -16777216 true false 180 180 90 Circle -16777216 true false 30 180 90 Polygon -16777216 true false 162 80 132 78 134 135 209 135 194 105 189 96 180 89 Circle -7500403 true true 47 195 58 Circle -7500403 true true 195 195 58 circle false 0 Circle -7500403 true true 0 0 300 circle 2 false 0 Circle -7500403 true true 0 0 300 Circle -16777216 true false 30 30 240 cow false 0 Polygon -7500403 true true 200 193 197 249 179 249 177 196 166 187 140 189 93 191 78 179 72 211 49 209 48 181 37 149 25 120 25 89 45 72 103 84 179 75 198 76 252 64 272 81 293 103 285 121 255 121 242 118 224 167 Polygon -7500403 true true 73 210 86 251 62 249 48 208 Polygon -7500403 true true 25 114 16 195 9 204 23 213 25 200 39 123 cylinder false 0 Circle -7500403 true true 0 0 300 dot false 0 Circle -7500403 true true 90 90 120 face happy false 0 Circle -7500403 true true 8 8 285 Circle -16777216 true false 60 75 60 Circle -16777216 true false 180 75 60 Polygon -16777216 true false 150 255 90 239 62 213 47 191 67 179 90 203 109 218 150 225 192 218 210 203 227 181 251 194 236 217 212 240 face neutral false 0 Circle -7500403 true true 8 7 285 Circle -16777216 true false 60 75 60 Circle -16777216 true false 180 75 60 Rectangle -16777216 true false 60 195 240 225 face sad false 0 Circle -7500403 true true 8 8 285 Circle -16777216 true false 60 75 60 Circle -16777216 true false 180 75 60 Polygon -16777216 true false 150 168 90 184 62 210 47 232 67 244 90 220 109 205 150 198 192 205 210 220 227 242 251 229 236 206 212 183 fish false 0 Polygon -1 true false 44 131 21 87 15 86 0 120 15 150 0 180 13 214 20 212 45 166 Polygon -1 true false 135 195 119 235 95 218 76 210 46 204 60 165 Polygon -1 true false 75 45 83 77 71 103 86 114 166 78 135 60 Polygon -7500403 true true 30 136 151 77 226 81 280 119 292 146 292 160 287 170 270 195 195 210 151 212 30 166 Circle -16777216 true false 215 106 30 flag false 0 Rectangle -7500403 true true 60 15 75 300 Polygon -7500403 true true 90 150 270 90 90 30 Line -7500403 true 75 135 90 135 Line -7500403 true 75 45 90 45 flower false 0 Polygon -10899396 true false 135 120 165 165 180 210 180 240 150 300 165 300 195 240 195 195 165 135 Circle -7500403 true true 85 132 38 Circle -7500403 true true 130 147 38 Circle -7500403 true true 192 85 38 Circle -7500403 true true 85 40 38 Circle -7500403 true true 177 40 38 Circle -7500403 true true 177 132 38 Circle -7500403 true true 70 85 38 Circle -7500403 true true 130 25 38 Circle -7500403 true true 96 51 108 Circle -16777216 true false 113 68 74 Polygon -10899396 true false 189 233 219 188 249 173 279 188 234 218 Polygon -10899396 true false 180 255 150 210 105 210 75 240 135 240 house false 0 Rectangle -7500403 true true 45 120 255 285 Rectangle -16777216 true false 120 210 180 285 Polygon -7500403 true true 15 120 150 15 285 120 Line -16777216 false 30 120 270 120 leaf false 0 Polygon -7500403 true true 150 210 135 195 120 210 60 210 30 195 60 180 60 165 15 135 30 120 15 105 40 104 45 90 60 90 90 105 105 120 120 120 105 60 120 60 135 30 150 15 165 30 180 60 195 60 180 120 195 120 210 105 240 90 255 90 263 104 285 105 270 120 285 135 240 165 240 180 270 195 240 210 180 210 165 195 Polygon -7500403 true true 135 195 135 240 120 255 105 255 105 285 135 285 165 240 165 195 line true 0 Line -7500403 true 150 0 150 300 line half true 0 Line -7500403 true 150 0 150 150 pentagon false 0 Polygon -7500403 true true 150 15 15 120 60 285 240 285 285 120 person false 0 Circle -7500403 true true 110 5 80 Polygon -7500403 true true 105 90 120 195 90 285 105 300 135 300 150 225 165 300 195 300 210 285 180 195 195 90 Rectangle -7500403 true true 127 79 172 94 Polygon -7500403 true true 195 90 240 150 225 180 165 105 Polygon -7500403 true true 105 90 60 150 75 180 135 105 person graduate false 0 Circle -16777216 false false 39 183 20 Polygon -1 true false 50 203 85 213 118 227 119 207 89 204 52 185 Circle -7500403 true true 110 5 80 Rectangle -7500403 true true 127 79 172 94 Polygon -8630108 true false 90 19 150 37 210 19 195 4 105 4 Polygon -8630108 true false 120 90 105 90 60 195 90 210 120 165 90 285 105 300 195 300 210 285 180 165 210 210 240 195 195 90 Polygon -1184463 true false 135 90 120 90 150 135 180 90 165 90 150 105 Line -2674135 false 195 90 150 135 Line -2674135 false 105 90 150 135 Polygon -1 true false 135 90 150 105 165 90 Circle -1 true false 104 205 20 Circle -1 true false 41 184 20 Circle -16777216 false false 106 206 18 Line -2674135 false 208 22 208 57 person lumberjack false 0 Polygon -7500403 true true 105 90 120 195 90 285 105 300 135 300 150 225 165 300 195 300 210 285 180 195 195 90 Polygon -2674135 true false 60 196 90 211 114 155 120 196 180 196 187 158 210 211 240 196 195 91 165 91 150 106 150 135 135 91 105 91 Circle -7500403 true true 110 5 80 Rectangle -7500403 true true 127 79 172 94 Polygon -6459832 true false 174 90 181 90 180 195 165 195 Polygon -13345367 true false 180 195 120 195 90 285 105 300 135 300 150 225 165 300 195 300 210 285 Polygon -6459832 true false 126 90 119 90 120 195 135 195 Rectangle -6459832 true false 45 180 255 195 Polygon -16777216 true false 255 165 255 195 240 225 255 240 285 240 300 225 285 195 285 165 Line -16777216 false 135 165 165 165 Line -16777216 false 135 135 165 135 Line -16777216 false 90 135 120 135 Line -16777216 false 105 120 120 120 Line -16777216 false 180 120 195 120 Line -16777216 false 180 135 210 135 Line -16777216 false 90 150 105 165 Line -16777216 false 225 165 210 180 Line -16777216 false 75 165 90 180 Line -16777216 false 210 150 195 165 Line -16777216 false 180 105 210 180 Line -16777216 false 120 105 90 180 Line -16777216 false 150 135 150 165 Polygon -2674135 true false 100 30 104 44 189 24 185 10 173 10 166 1 138 -1 111 3 109 28 plant false 0 Rectangle -7500403 true true 135 90 165 300 Polygon -7500403 true true 135 255 90 210 45 195 75 255 135 285 Polygon -7500403 true true 165 255 210 210 255 195 225 255 165 285 Polygon -7500403 true true 135 180 90 135 45 120 75 180 135 210 Polygon -7500403 true true 165 180 165 210 225 180 255 120 210 135 Polygon -7500403 true true 135 105 90 60 45 45 75 105 135 135 Polygon -7500403 true true 165 105 165 135 225 105 255 45 210 60 Polygon -7500403 true true 135 90 120 45 150 15 180 45 165 90 square false 0 Rectangle -7500403 true true 30 30 270 270 square 2 false 0 Rectangle -7500403 true true 30 30 270 270 Rectangle -16777216 true false 60 60 240 240 star false 0 Polygon -7500403 true true 151 1 185 108 298 108 207 175 242 282 151 216 59 282 94 175 3 108 116 108 target false 0 Circle -7500403 true true 0 0 300 Circle -16777216 true false 30 30 240 Circle -7500403 true true 60 60 180 Circle -16777216 true false 90 90 120 Circle -7500403 true true 120 120 60 tree false 0 Circle -7500403 true true 118 3 94 Rectangle -6459832 true false 120 195 180 300 Circle -7500403 true true 65 21 108 Circle -7500403 true true 116 41 127 Circle -7500403 true true 45 90 120 Circle -7500403 true true 104 74 152 triangle false 0 Polygon -7500403 true true 150 30 15 255 285 255 triangle 2 false 0 Polygon -7500403 true true 150 30 15 255 285 255 Polygon -16777216 true false 151 99 225 223 75 224 truck false 0 Rectangle -7500403 true true 4 45 195 187 Polygon -7500403 true true 296 193 296 150 259 134 244 104 208 104 207 194 Rectangle -1 true false 195 60 195 105 Polygon -16777216 true false 238 112 252 141 219 141 218 112 Circle -16777216 true false 234 174 42 Rectangle -7500403 true true 181 185 214 194 Circle -16777216 true false 144 174 42 Circle -16777216 true false 24 174 42 Circle -7500403 false true 24 174 42 Circle -7500403 false true 144 174 42 Circle -7500403 false true 234 174 42 turtle true 0 Polygon -10899396 true false 215 204 240 233 246 254 228 266 215 252 193 210 Polygon -10899396 true false 195 90 225 75 245 75 260 89 269 108 261 124 240 105 225 105 210 105 Polygon -10899396 true false 105 90 75 75 55 75 40 89 31 108 39 124 60 105 75 105 90 105 Polygon -10899396 true false 132 85 134 64 107 51 108 17 150 2 192 18 192 52 169 65 172 87 Polygon -10899396 true false 85 204 60 233 54 254 72 266 85 252 107 210 Polygon -7500403 true true 119 75 179 75 209 101 224 135 220 225 175 261 128 261 81 224 74 135 88 99 wheel false 0 Circle -7500403 true true 3 3 294 Circle -16777216 true false 30 30 240 Line -7500403 true 150 285 150 15 Line -7500403 true 15 150 285 150 Circle -7500403 true true 120 120 60 Line -7500403 true 216 40 79 269 Line -7500403 true 40 84 269 221 Line -7500403 true 40 216 269 79 Line -7500403 true 84 40 221 269 x false 0 Polygon -7500403 true true 270 75 225 30 30 225 75 270 Polygon -7500403 true true 30 75 75 30 270 225 225 270 @#$#@#$#@ NetLogo 4.0 @#$#@#$#@ @#$#@#$#@ @#$#@#$#@ @#$#@#$#@ @#$#@#$#@ default 0.0 -0.2 0 0.0 1.0 0.0 1 1.0 0.0 0.2 0 0.0 1.0 link direction true 0 Line -7500403 true 150 150 90 180 Line -7500403 true 150 150 210 180 @#$#@#$#@