Divide regions accordingly to physical features - netlogo

I'm working on a smaller project and got stuck on an issue, I'm not really sure if it's possible to solve it in NetLogo but I want to give StackOverflow a go!
I got a model that divides the world into different parts and randomly add physical features (such as rivers). If a feature goes through the whole region, I want it to separate the region and make into two regions. As an example, in the picture below, I want to separate the purple region into two unique regions accordingly to the physical feature (black).
The code I used to generate the picture above, can be found below.
to setup
ca
;Setting world.
resize-world 0 19 0 19
;Creating regions.
let x 5
let y 5
let col 45
while [y <= max-pycor + 1][
while [x <= max-pxcor + 1 ][
ask patches with [pxcor < x and pxcor >= x - 5 and pycor < y and pycor >= y - 5][
set pcolor col
]
set x x + 5
set col col + 10
]
set x 5
set y y + 5
]
;Generating physical features.
ask n-of 5 patches[ sprout 1[
set pcolor black]
]
let i 0
while [ i < (max-pycor * 2 )][
ask turtles [
fd 1
set pcolor black
ifelse (random 20 <= 1)
[
rt one-of [-90 0 90]
forward 1
]
[
fd 1
set pcolor black
fd 1
set pcolor black
]
set pcolor black
set i i + 1]
]
ask turtles [die]
end

My strategy for handling this is to realize that all we really need to do is "flood" a patch out by color and tag all the found adjacent patches, then repeat for any un-tagged, non-black patches until they are all done.
NetLogo does not have a "flood" command to get all patches adjacent to a patch meeting a criteria, so we make a special reporter of our own to handle it, patches-adjacent. Then it's just easy to ask those patches-adjacent to set their region to the currently chosen region.
I don't love this code, it's a little finicky and would be prone to infinite loops if tweaked incorrectly, but it should work. I bet there is a cleaner way to do this that I'm not thinking of at the moment.
; add a variable to track the different regions
; the default value will be `0` for each patch when `clear-all` is called
patches-own [ region ]
to set-regions
let current-region 1
; only act on non-black patches that haven't yet been assigned a region
let untagged patches with [ region = 0 and pcolor != black ]
while [any? untagged] [
ask one-of untagged [
ask patches-adjacent [
set region current-region
]
]
; update the region and the untagged patches we have left to process
set current-region current-region + 1
set untagged patches with [ region = 0 and pcolor != black ]
]
; this is just to get a view of the regions to quickly see if our code worked, it can be removed
ask patches [ set plabel region ]
end
to-report patches-adjacent
report patches-adjacent-ex (patch-set self) pcolor
end
to-report patches-adjacent-ex [found pc]
let newly-found neighbors4 with [ (not member? self found) and pcolor = pc and region = 0 and pcolor != black ]
set found (patch-set found newly-found)
ask newly-found [
; use recursion to find the patches adjacent to each newly-found one
; relying on updating the `found` agentset as we go to avoid duplicates
; or looping forwarder
set found (patches-adjacent-ex found pc)
]
report found
end

I solved this by using the Patch Clusters model that can be found in the NetLogo model library.

Related

How to extract a highly linked node from a network

I want to extract a node with highest degree centrality from the network. I don't want to extract a node with max links only. I want to extract the node along with the nodes adjacent to it.
Below is the code. In this code, I have loaded a network using nw extensions.
extensions [nw]
turtles-own [ explored? ]
to setup
ca
crt 25
ask turtles [fd random 15]
load-graph
extract_deg
end
to load-graph
let filename user-file
if (filename != false) [
nw:load-graphml filename [
set shape "circle"
set size 1
]
nw:set-context turtles links
]
end
to extract_deg
let n turtles with [my-links = max [count link-neighbors] of turtles]
ask n [show other turtles network:in-link-radius 1 turtles]
end
to layout
ask turtles [ set size sqrt count my-links ]
layout-spring turtles links 0.5 2 1
ask turtles [
facexy 0 0
fd (distancexy 0 0) / 100 ]
end
The code below will choose one of the nodes with largest degree (just remove one-of if you want all of them), turn it red and make its network neighbours green.
You don't need the expression [my-links = max [count link-neighbors] of turtles], standard NetLogo includes the very useful with-max primitive. However, I think your construction would have worked if you had counted my-links (like let n turtles with [count my-links = max [count link-neighbors] of turtles]). Then you have some syntax errors in the next line (the extension is nw and you don't need the turtles.
to extract_deg
let maxk-set one-of turtles with-max [count my-links]
ask maxk-set
[ set color red
ask other nw:turtles-in-radius 1 [set color green]
]
end

Finding blocks in Netlogo

I have a question about Netlogo.
Is there any smart way how to find block of patches (in my case, I need to find block of three patches with yellow color => more precisely, I need to find row or column with three yellow patches next to each other).
Is there any Netlogo function I could use or is it neccessary to use loops and work as I would with two-dimensional array?n
blckbird is correct, if you want you can extract all coordinates of yellow patches and process those coordinates to figure out which patches are adjacent.
If all you need is to know where your rows or columns of threes are, however, you could also get all the yellow patches to check the color of neighboring patches and tell you if a row or column is formed. For an example, see the code below.
to setup
ca
reset-ticks
ask n-of 150 patches [
set pcolor yellow
]
end
to find-threes
;; for rows
ask patches with [ pcolor = yellow ] [
if ( [pcolor] of patch-at 1 0 = yellow ) and ( [pcolor] of patch-at -1 0 = yellow ) [
;; do whatever you need
set pcolor pcolor - 3
show ("I am the center of a row of three")
]
]
;; for columns
ask patches with [ pcolor = yellow ] [
if ( [pcolor] of patch-at 0 1 = yellow ) and ( [pcolor] of patch-at 0 -1 = yellow ) [
;; do whatever you need
set pcolor pcolor - 3
show ("I am the center of a column of three")
]
]
end
With ask patches you can loop over all patches. Further a condition can be applied to the ask statement by using with. So you are looping over all the patches meeting that condition. Here I just put the x and y coordinates of the patches in a list which you can then further process.
let yellow_patches []
ask patches with [pcolor = yellow] [
set yellow_patches lput [pxcor pycor] yellow_patches
]

Create clusters of patches without changing occurrence

I am writing a Netlogo model which only involves patches. I have managed to create a landscape consisting of patches of 6 different colours (each representing a different vegetation in my project) according to probability. So red patches have a probability of 10% to occur on each patch, yellow 5%, brown 20% and so on.
An example of my code where this probability is set up:
let i random-float 1
ifelse i + random-float 0.1 <= 0.8 ;random 0.1 threshold for environmental noise
[ set pcolor green ]
[ ifelse i + random-float 0.1 <= 0.9
[ set pcolor yellow ]
[ set pcolor blue ] ]
However, this creates a random pattern for each colour. But I would like to create a clustered spatial pattern for one of them.Specifically, in my landscape, I want the proportion of brown patches to be 50%. But if I were to set this 50% probability for every patch, the brown patches will be randomly distributed. How do I get it to occupy 50% of my landscape, but appear in a clustered pattern?
I tried creating the clustered pattern using the Moore neighbourhood, but that obviously changes the proportion of brown patches.
I hope this is somewhat clear. Thanks for any help in advance.
You could seed based on your weights and then grow around the seeds. Here is a different approach: color all patches based on your weights, and then cluster the colors.
extensions [rnd] ;use the rnd extension
globals [threshold]
to setup
ca
set threshold 2
let _cw [[red 10] [yellow 20] [blue 70]] ;colors with weights
ask patches [set pcolor first rnd:weighted-one-of-list _cw [last ?]]
repeat 20 [cluster] ;adjust to taste
end
to cluster
ask patches [
if unhappy? [
swap-pcolor
]
]
end
to swap-pcolor
let _c pcolor
let _p one-of neighbors with [pcolor != [pcolor] of myself]
set pcolor [pcolor] of _p
ask _p [set pcolor _c]
end
to-report unhappy?
let _ct count neighbors with [pcolor = [pcolor] of myself]
report (_ct < threshold)
end

NetLogo: identification of valleys = rivers location in artificial landscape

I want to produce the artificial landscape, containing hills, slopes and valleys. So far, so good. Now, I want to place a rivers in the bottom of the valley. I thought that the easiest way will be ask turtle to move uphill/downhill by elevation as drops here: http://modelingcommons.org/browse/one_model/2352#model_tabs_browse_info
However, as my landscape is not real, my valleys are also not linears, but just the "depressions" in the terrain, and thus my river localisation is really weird looking?
Please, is there a way to create hills and valleys reflecting the real terrain in netlogo without using GIS extension? I've found great models of Erosion, Watershed and GIS gradient example, but how can I initially place my turtles to stay only in valleys?
EDIT
the GIS gradient example provide excellent problem solving of movement of all the cells over the space, and they aggregate in valleys. However, as I want to by movement of my turtle "create" the river bed on the bottom of the valley, how can I place it? maybe start at the lowest point and stop after several ticks to not to allow to get on the top of the hill? thank you !
globals [
low
high
range ]
patches-own [
altitude ]
to setup
clear-all
setup-hills
scale-patches
color-patches
end
to setup-hills
ask n-of 2 patches [
set pcolor magenta ]
ask patches [
let max_dist sqrt (world-width ^ world-width + world-height ^ world-height)
set altitude world-width - distance patch 10 10
set altitude world-width - distance min-one-of patches with [pcolor = magenta][distance myself]
]
crt 1 [ ; create a turtle, needed to identify the lowest slope
set color red
let bottom_valley min-one-of patches [altitude]
move-to bottom_valley
]
end
to scale-patches
set low [altitude] of min-one-of patches [altitude]
set high [altitude] of max-one-of patches [altitude]
set range high - low
ask patches [
set altitude altitude - low ; shift every patch down so lowest altitude is 0
set altitude altitude * 99.0 / range ; scale every patch so that the lowest is 0 and highest is 999
]
repeat 5 [
diffuse altitude 0.5 ]
end
to color-patches
ask patches [
set pcolor scale-color green altitude 0 100]
end
to create-river
ask turtles [
let p max-one-of neighbors in-radius 1 [altitude]
if [altitude] of p >= altitude [
face p
move-to p
set pcolor blue
]
]
end
You have the right general idea. I recommend checking out the "GIS Gradient" model on your landscape. You can find it in the Models Library under Code Examples/GIS. Then think how to filter patches that have a minimum number of water particles passing through it over time.
Identification of system of rivers on the landscape using GIS Gradient Example:
http://modelingcommons.org/browse/one_model/2352#model_tabs_browse_info
The whole process of identification of the river system on the complex landscape is composed by 3 subprocesses:
identify the highest points of the landscape
place here the river source (create-source)
identify patches for a downhill stream
from the highest river source, by decreasing elevetion of neighboring cells to the lowest elevation of the river valley
when turtle reaches the edge of the world, turtle dies (go-downhill)
remove top hill points (as the river does not read the summit of the hill)
the river does not start at the top of the hill, but at the highest point of the valley
the highest "river" patches from the river beds system are removed (remove-river-from-top-hill)
The number of sources depends of type of GIS data you have available. The same for the number of patches you wish to remove from the top of the hill.
;; ----------------------------------------------
;; create river
;; ----------------------------------------------
to create-source
; identify the 5 highest points of the landscape
repeat 5 [
; avoid the highest points to be close to each other
ask max-one-of patches with [ not any? turtles-here and not any? turtles in-radius 20 ] [p_elev] [
;ask patches to sporout turtles
sprout 1 [
set size 1
set color orange
]
]
]
end
to go-downhill
; stop if there is no more turtles
if not any? turtles with [color = orange]
[ stop ]
; ask turtles located on top of thehills to move downhill
ask turtles with [color = orange] [
; die when you reach the edge of the world
if ([pxcor] of patch-here = max-pxcor) or ([pycor] of patch-here = max-pycor)
or ([pxcor] of patch-here = min-pxcor) or ([pycor] of patch-here = min-pycor) [
die ]
move-to patch-here ; go to patch center
set pcolor blue ; identify the use of patch
set p min-one-of neighbors with [pcolor != blue ] [p_elev] ;; or neighbors4 with [pcolor != blue]patches in-radius 3
if p != nobody [
; move downhill if elevation of patch you are standing on is higher then one of the neighboring patches
ifelse [p_elev] of p <= p_elev
[
face p
move-to p
set pcolor blue ; identify the use of patch
]
[
;move-to min-one-of patches with [pcolor != blue] [distance myself]
move-to min-one-of patches in-radius 2 with [pcolor != blue] [p_elev]
set pcolor blue ; identify the use of patch
]
]
]
end
to remove-river-from-top-hill
; remove 5% of the blue (river) patches placed on the top of the hill
let total_blue count patches with [pcolor = blue]
repeat total_blue * 0.05 [
ask max-one-of patches with [pcolor = blue] [p_elev] [
set pcolor yellow ]
]
end
Complex river system identified:
(river bed = BLUE, removed top of the hill = YELLOW):

unable to make non-stationary turtles change their direction if an obstacle a patch ahead

If any one please give some time.
I have an area(say a colony) with boundary wall as black patches and at some point within the boundary there is one building with building wall as blue patches. People(breed) are normally moving inside boundary and the building as well. Also they are entering and going out of the boundary. Due to some reason (suppose rumor) and after certain condition (if more than 15 person hears the rumor) they starts moving randomly with any of the headings 0, 90, 180 and 270. So, the problem I am unable is, to apply check on the turtles(people) randomly moving to change their heading or turn back if they sense the boundary or wall a patch ahead.
I tried following ways but not working, they simple passes form these patches
1) Asked the turtles if heard-rumor? and times-heard > 1 [
if [pcolor] of patch-ahead 1 = blue [set heading [heading] of self - 180]
if [pcolor] of patch-ahead 1 = black [set heading [heading] of self - 180] ]
2) set patches with boundary-wall [set pcolor black] and building-wall [set pcolor blue] and then set patch variables boundary-wall? And building-wall? true on these patches. Further asked the turtles
if heard-rumor? and times-heard > 1 [
if boundary-wall? or building-wall? [ set heading [heading] of self - 180 ] ]
The procedure sequence is
to go
ask people [ ;breed
fd speed
spread-rumor
people-wander ]
end
So after spread-rumor function,
to people-wander
if heard-rumor? and times-heard > 1 and inside-boundary?
[
if people-heard-rumor > 10 [ set heading one-of (list 0 90 180 270) ] ];random 360
;people-heard-rumor is a count how many have received rumor
if heard-rumor? or fear-worst? [
; if [pcolor] of patch-ahead 1 = blue [set heading [heading] of self - 180]]
; if [pcolor] of patch-ahead 1 = black [set heading [heading] of self - 180]]
boundary-wall? or temple-wall? [set i? true set heading [heading] of self - 180 show 5] ]
end
I don’t know what wrong I am doing. But surely I am not using proper way. Any help is deeply thankful.
You start out with fd speed so your people will go right through the barriers on that command without ever testing for a barrier. Note that even if you were to test 1 patch ahead before doing that, if speed can be greater than 1, you could still go right through the barriers. Furthermore, in a corner a person might have a barrier both in front of it and behind it, so reversing course can also be a problem.
Btw, [heading] of self is the same as heading, and to turn around it is more natural to say rt 180.
EDIT (in response to comment):
Here is a simple example of moving step by step, checking along the way:
to fd-with-checks [#speed]
repeat #speed [
ifelse (isbarrier? patch-ahead 1) [
stop
] [
fd 1
]
]
end
to-report isbarrier? [#patch]
report pcolor = blue or pcolor = black
end