;Nodes represent the retailers, distributers, and factory. breed [nodes node] ;breed [links link] ;nodes have color of either: green, red, blue ;distances: [ [agent distance][...]] used to calculate min distance to every other agent nodes-own [distances cluster-coefficient] ;components is a list of agents, each a member of a different component globals [changed-distances? characteristic-path-length clustering-coefficient components max-distance size-max-component] to ultralog while [count nodes < num-nodes] [ layout-spring nodes links 0.2 2 1 let partner find-preferential-partner ;apply Pi function: choose stochastically based on degree let new-node-who 0 create-nodes 1 [ set new-node-who who set shape "circle" set color generate-node-color setup-distances if (color = blue) [ ;battalion create-link-with partner [ ;first edge attaches with set color gray ] if (random-float 1.0 < p) [ ;create second link let nodes-at-distance-two nodes with [get-distance-to myself = 2] if (any? nodes-at-distance-two) [ create-link-with (one-of nodes-at-distance-two) [ set color gray ] ] ] ] if (color = red) [; FSB- Forward Support Battalion create-link-with partner [ ;first edge attaches with set color gray ] let nodes-at-distance-lte-3 nodes with [self != myself and get-distance-to myself <= 3 and (not link-neighbor? myself)] ifelse (count nodes-at-distance-lte-3 >= 2) [ create-links-with (n-of 2 nodes-at-distance-lte-3) [ set color gray ] ][ if (any? nodes-at-distance-lte-3) [ ;there is only 1 create-links-with nodes-at-distance-lte-3 [ set color gray ] ] ] ] if (color = green)[ let list-of-neighbors fput self [] repeat 5 [ let n find-preferential-partner-not-in list-of-neighbors if (n != nobody) [ create-link-with n [ set color gray ] ] set list-of-neighbors fput n list-of-neighbors ] ] ] ;update distances. update-distances-new-node (turtle new-node-who) calculate-distances ] end to setup-attachment [find-fun] while [count nodes < num-nodes] [ layout-spring nodes links 0.2 2 1 create-nodes 1 [ set shape "circle" set color generate-node-color let num-attachments 1 setup-distances if (color = blue) [ set num-attachments num-attachments + ifelse-value (random-float 1.0 < p) [1][0] ] if (color = red) [ set num-attachments 3 ] if (color = green) [ set num-attachments 5 ] let list-of-neighbors fput self [] repeat num-attachments [ let n run-result (word find-fun " list-of-neighbors") if (n != nobody) [ create-link-with n [ set color gray ] ] set list-of-neighbors fput n list-of-neighbors ] ] ] end to-report find-preferential-partner let total random-float sum [count my-links] of nodes let partner nobody ;; reporter procedures always run without interruption, ;; so we don't need "without-interruption" in order to ;; make the turtles go one at a time ask nodes [ let nc (count my-links) if partner = nobody [ ifelse nc > total [ set partner self ] [ set total total - nc ] ] ] if (partner = nobody) [ ;this only happens if there are no edges in the graph (initial condition) so just pick one at random report one-of nodes ] report partner end to-report find-preferential-partner-not-in [list-of-agents] let candidates nodes with [not member? self list-of-agents] let total random-float sum [count my-links] of candidates let partner nobody ;; reporter procedures always run without interruption, ;; so we don't need "without-interruption" in order to ;; make the turtles go one at a time ask candidates [ let nc (count my-links) if partner = nobody [ ifelse nc > total [ set partner self ] [ set total total - nc ] ] ] report partner end to-report find-random-partner-not-in [list-of-agents] let candidates nodes with [not member? self list-of-agents] report one-of candidates end to setup-initial-nodes let who-of-first 0 create-nodes 1 [ set who-of-first who set color generate-node-color setup-distances set shape "circle" ] create-nodes 1 [ set color generate-node-color setup-distances set shape "circle" create-link-with (turtle who-of-first) [ set color gray ] ] end ;Reports node color based on ratios specified by user to-report generate-node-color let s ratio-of-red + ratio-of-blue + ratio-of-green let r random s if (r < ratio-of-red) [ report red ] if (r < ratio-of-red + ratio-of-blue) [ report blue ] report green end to preferential-attachment setup-attachment "find-preferential-partner-not-in" end to random-attachment setup-attachment "find-random-partner-not-in" end to setup ca ask patches [set pcolor white] set components [] setup-initial-nodes run model layout-spring nodes links 0.2 5 1 set-current-plot "Edge Distribution" ; histogram-from nodes [count my-links] calculate-distances set-components let max-component get-largest-component set characteristic-path-length get-characteristic-path-length max-component set clustering-coefficient get-clustering-coefficient max-component set max-distance get-max-distance max-component set size-max-component get-size-of-largest-component end to run-test [choose] setup repeat (.8 * num-nodes) [ set-current-plot "Characteristic Path Length" plot characteristic-path-length set-current-plot "Largest Component" plot size-max-component set-current-plot "Max Distance" plot max-distance if (choose = "random") [ ask one-of nodes [die] ] if (choose = "targeted") [ ask (max-one-of nodes [count my-links]) [die] ] ask nodes [ setup-distances ] set num-nodes num-nodes - 1 calculate-distances set-components let max-component get-largest-component set characteristic-path-length get-characteristic-path-length max-component set clustering-coefficient get-clustering-coefficient max-component set max-distance get-max-distance max-component set size-max-component get-size-of-largest-component repeat 5 [layout-spring nodes links 0.2 5 1] ] end to layout layout-spring nodes links 0.2 2 1 end ;---------- ;global utility/graph functions ;get all nodes to calculate their distances matrix ;implement dijikstra's algorithm to calculate-distances set changed-distances? true; ; ask nodes [setup-distances] ;probably don't need to do this as we are only adding nodes.... while [changed-distances?] [ set changed-distances? false ask nodes [update-distances] ] end ;Updates everyone's distances by adding a distance to new-node which is 1 + their distance to ; a randomly chosen neighbor of new-node. This might be too big so we still need to calculate-distances after this. ;This function speeds up the later call to calculate-distances (a bit). ;Assumes connected graph. to update-distances-new-node [new-node] let new-node-neighbor [one-of link-neighbors] of new-node ask nodes with [self != new-node][ set-distance-to new-node (get-distance-to new-node-neighbor + 1) ] end ;Report a list of all pairs (n choose 2) from the-list. Does not contain duplicates (permutations) to-report get-all-pairs [the-list] let result [] foreach the-list [ let a ? foreach the-list [ if (? != a) [ set result fput list a ? result ] ] ] report result end to-report get-all-pairs-agents [agent-set] report get-all-pairs [self] of agent-set end ;Calculates the characteristic path length, which is the smallest number of links it takes to connect one node to another, averaged ;over all pairs of nodes in the network. ;Do this by first having each node calculate its minimun distance to every other node and then we average over all pairs to-report get-characteristic-path-length [component] let pairs get-all-pairs-agents (nodes with [get-component = component]) if (length pairs = 0) [report 0] let sum-distances 0 foreach pairs [ ask (first ?) [ ;since Im assuming bidirections it does not matter which one I ask. ; show get-distance-to (item 1 ?) set sum-distances sum-distances + get-distance-to (item 1 ?) ] ] report sum-distances / length pairs end to-report get-max-distance [component] report max [max map [item 1 ?] distances] of (nodes with [get-component = component]) end to-report get-clustering-coefficient [component] ask nodes with [get-component = component] [ set cluster-coefficient get-node-clustering-coefficient ] report mean [cluster-coefficient] of (nodes with [get-component = component]) end to-report closest-xy [x y agent-set] ; Return closest agent to x, y report min-one-of agent-set [distancexy-nowrap x y] end to set-components ask nodes [ without-interruption [ if (get-component = nobody) [ set components fput self components ] ] ] end ;reports the agent that is the representative for the largest component to-report get-largest-component let whole-component reduce [ifelse-value (count ?1 > count ?2)[?1][?2]] (map [nodes with [get-component = ?]] components) report [get-component] of (one-of whole-component) end to-report get-size-of-largest-component report max map [count ?] (map [nodes with [get-component = ?]] components) end ;------------------------------------------------------------- ;node functions ;------------- ;graph calculations ; ; The second measure is the clustering coefficient. This measures the amount of cliquishness ; of the network, that is, the fraction of neighbouring nodes that are also connected to one another. For example, in an all-to-all ; connected network, the clustering coefficient is one. ; ;Calculate distances to every other node using Dijistra's max-flow algorithm ; ;set distance to myself to be 0 to setup-distances set distances fput (list self 0) [] end to-report assoc [element lst] foreach lst [ if (first ? = element) [ report ?] ] report [] end to-report get-component foreach (components) [ if (get-distance-to ? > -1) [ report ? ] ] report nobody end to-report get-distance-to [the-other] foreach distances [ if (first ? = the-other) [ report (item 1 ?) ] ] report -1 end to set-distance-to [the-other num] let already-there false set changed-distances? true foreach distances [ if (first ? = the-other) [ without-interruption [ ;don't want someone else reading after delete but before addition set distances remove ? distances set distances fput (list the-other num) distances set already-there true ] ] ] if (not already-there) [ set distances fput (list the-other num) distances ] end ;node updates its "distances" variable by adding 1 to neighbors' distances, if that is smaller. to update-distances let n-distances [distances] of link-neighbors set n-distances ifelse-value (empty? n-distances) [ [] ] [reduce [sentence ?1 ?2] n-distances] ; show n-distances foreach n-distances [ let mine get-distance-to (first ?) if (mine = -1 or item 1 ? + 1 < mine) [ set-distance-to (first ?) (item 1 ? + 1) ] ] end ;report my clustering coefficient: the fraction of my neighbors who are also connected to each other ;requires: 'distances' matrix must already be calculated ;assume bidirection, but this should probably change to-report get-node-clustering-coefficient let neighbors-list remove-duplicates [self] of link-neighbors let pairs get-all-pairs neighbors-list let num-pairs-connected 0 foreach pairs [ ask (first ?) [ if (get-distance-to (item 1 ?) = 1) [ set num-pairs-connected num-pairs-connected + 1 ] ] ] if (length pairs = 0) [report 1.0] report num-pairs-connected / length pairs end @#$#@#$#@ GRAPHICS-WINDOW 243 10 673 461 17 17 12.0 1 10 1 1 1 0 1 1 1 -17 17 -17 17 0 0 1 ticks CC-WINDOW 5 646 890 741 Command Center 0 BUTTON 7 16 79 49 NIL setup NIL 1 T OBSERVER NIL NIL NIL NIL CHOOSER 7 53 230 98 model model "ultralog" "preferential-attachment" "random-attachment" 0 SLIDER 10 153 182 186 ratio-of-blue ratio-of-blue 1 50 25 1 1 NIL HORIZONTAL SLIDER 10 188 182 221 ratio-of-red ratio-of-red 1 50 4 1 1 NIL HORIZONTAL SLIDER 10 224 182 257 ratio-of-green ratio-of-green 1 50 1 1 1 NIL HORIZONTAL SLIDER 11 110 183 143 num-nodes num-nodes 10 100 2 1 1 NIL HORIZONTAL SLIDER 10 269 182 302 p p 0 1 0.5 0.01 1 NIL HORIZONTAL MONITOR 186 99 243 152 nodes count nodes 0 1 13 BUTTON 82 16 159 49 NIL layout T 1 T OBSERVER NIL NIL NIL NIL PLOT 11 308 211 458 Edge Distribution # edges NIL 1.0 10.0 0.0 10.0 true false PENS "default" 1.0 1 -16777216 true MONITOR 678 116 881 169 Characteristic Path Length characteristic-path-length 2 1 13 MONITOR 676 176 848 229 Clustering Coefficient clustering-coefficient 2 1 13 MONITOR 679 239 834 292 Largest Component get-size-of-largest-component 0 1 13 PLOT 289 462 576 632 Characteristic Path Length Nodes Removed CPL 0.0 10.0 0.0 1.0 true false PENS "default" 1.0 0 -16777216 true BUTTON 677 25 827 58 Random Attacks run-test \"random\" NIL 1 T OBSERVER NIL NIL NIL NIL PLOT 8 462 280 632 Largest Component Nodes Removed Size 0.0 10.0 0.0 10.0 true false PENS "default" 1.0 0 -16777216 true PLOT 582 462 838 632 Max Distance Nodes Removed Distance 0.0 10.0 0.0 10.0 true false PENS "default" 1.0 0 -16777216 true MONITOR 681 300 825 353 Max Distance in LC max-distance 0 1 13 BUTTON 677 74 832 107 Targeted Attacks run-test \"targeted\" NIL 1 T OBSERVER NIL NIL NIL NIL @#$#@#$#@ Title: Supply Network Survivability Author: Jose M Vidal Description: This model shows how various supply-chain network topologies fare under attack. The original model was developed to study the military's supply chain vulnerability to terrorist or military attacks, part of the Ultralog project.