Netlogo - find the closest agent based on Manhattan distance - algorithm

I am modelling a big warehouse operations (see below pic).
I have implemented a vertex on each patch (green dots) and link them so that I could compute the shortest path (using dijkstra algorithm) from each vertex to all other vertices, stored in a table (dictionary) of each vertex. This process is done during setup stage and is quite time-consuming. Then the yellow inventory cells (rectangle) will issue the demand request for task fulfillment.
The forklift truck (some in the path) is assuming to stay put on one of the vertex (node) when it's not busy. When get the demand request, it will ask its current standing vertex (node) to get the starting_node and the end_node of the inventory cell it is going to. Then the forklift ask the starting_node to get the shortest path from its table to get the shortest path (combination of nodes) and drive to the end_node (the yellow cell).
Currently, the yellow cells just randomly pick free forklift truck in the warehouse. As a further development, I want to add the function that allows the yellow cell to identify the free truck that is closest to it based on the actual distance (not the euclidean distance built in Netlogo). As there are many trucks so it's not good to use "foreach" to loop through all available trucks and compute the actual distance using above method. You could use primitive "distance myself" to locate the truck quickly but that's not accurate. Is there a good way to identify the closest truck with a faster computational method?

I don't know if this would work with your current setup, but you may also find the nw extension helpful. For example, try this setup (I apologize for the length, just approximating your world):
extensions [ nw ]
breed [ nodes node ]
breed [ trucks truck ]
breed [ cells cell ]
to setup
ca
resize-world -29 29 -14 14
ask patches with [ ( pxcor mod 5 = 0 or pycor = 0 ) ] [
set pcolor grey
sprout-nodes 1 [
set size 0.5
set shape "circle"
set color green
]
]
ask nodes [
create-links-with turtles-on neighbors4 [
set color green
]
]
ask n-of 5 nodes [
hatch 1 [
set size 1
set color red
set breed trucks
set shape "car"
]
]
ask n-of 2 trucks [
set color blue
]
ask one-of nodes [
ask one-of neighbors with [ pcolor = black ] [
sprout-cells 1 [
set size 1.5
set shape "box"
set color yellow
]
]
]
reset-ticks
end
Gives a simple world like this:
You can use the nw extension to calculate the distances on the fly, rather than storing them in a per-cell table, and have the forklifts (trucks, here) follow the shortest path. More details in comments:
to summon-nearest-truck
; Treat blue trucks as 'empty' and ready to go to a cell
let ready-trucks trucks with [ color = blue ]
; Get the nodes associated with those ready trucks
let truck-proxies turtle-set map [ i -> [nodes-on patch-here] of i ] sort ready-trucks
; Randomly ask one of the cells to
ask one-of cells [
; Choose one of the neighboring road nodes as a proxy for distance calculation
let node-proxy one-of nodes-on neighbors4
; Get the node proxy to:
ask node-proxy [
; Find the nearest (by network distance) trucks, and select the node
; located on the same patch as that truck
let my-truck-proxy min-one-of truck-proxies [length ( nw:turtles-on-path-to myself) ]
; Get that truck-proxy node to generate the path to the original asking node
; and have the appropriate truck follow that path
ask my-truck-proxy [
; Generate the path to follow
let path-to-follow nw:turtles-on-path-to myself
; Highlight that path for visualization
ask turtle-set path-to-follow [
set color orange
]
; Get the truck ready to move
let ready-truck one-of trucks-here with [ color = blue ]
ask ready-truck[
set color yellow
]
; Move that truck along the path-to-follow
ask ready-truck [
foreach path-to-follow [
n ->
face n
move-to n
; For visualization only
wait 0.1
]
]
]
]
]
end
This has the yellow box summon the nearest truck based on the length of nw:turtles-on-path-to that is returned. That truck follows the path to the summoning node:

Related

How to make turtles / agents go faster or slower when being on a certain patch?

I have to make turtles go faster when being on a green patch, and when they are on a blue patch the speed should go down. I added part of the code that I tried, but it doesn't work. Could someone please help me?
Thanks in advance!!
turtles-own [speed]
to go
ask turtles [
left 60
right random 60
forward 1
if any? neighbors with [pcolor = green]
[
set speed speed + 1
]
if any? neighbors with [pcolor = blue]
[
set speed speed + 0.1
]
]
reset-ticks
I think what user2901351 was getting at was that you are using neighbors in your example code. If you look at the dictionary entry for neighbors, you'll see that it references the 8 patches around the current patch. If you instead want the turtle to check the patch it's currently on, you can use the patch-here primitive or, as a shortcut, just ask the turtle to check a patch-owned variable directly. Below is a toy example that shows an example of this at work- more details in the comments.
turtles-own [speed]
to setup
ca
crt 5 [ set speed 1 ]
ask n-of 20 patches [
ifelse random-float 1 < 0.5
[ set pcolor green ]
[ set pcolor blue ]
]
reset-ticks
end
to go
ask turtles [
; Since 'pcolor' is a patch variable, if the turtle queries pcolor
; it will check the patch's variable directly.
if pcolor = green [ set speed speed + 0.5 ]
if pcolor = blue [ set speed speed - 0.5 ]
; Make sure that the turtles are moving forward by their speed value,
; rather than the hard-coded value of "1" in the example code. Also,
; I've included a check here so the turtles don't either stop moving
; or start moving backwards.
if speed < 1 [ set speed 1 ]
rt random-float 60 - 30
fd speed
show speed
]
tick
end

How to create two different random color groups in NetLogo 6.1.1?

How to create two different random color groups in NetLogo 6.1.1?
I am trying to create two different groups from the group of 250 turtles. The starting situation is that all 250 turtles are gray and then they will turn to yellow and pink groups one by one.
This code of mine makes all turtles in the beginning to be gray and then they will all turn to pink. I do not want this but I want two randomly made groups where pink turtles is typically either larger or smaller group of turtles than the yellow group of turtles in the end of the code run.
I just started to code with NetLogo 6.1.1. Thank you for understanding and all help and have a nice day.
[
time
person
]
turtles-own [ x ]
to setup
clear-all
reset-ticks
set time 0
create-turtles 250
[
setxy random-xcor random-ycor
]
ask turtles
[
set shape "person"
set size 1
set color gray
]
end
to go
ask turtles
[
show random 2 = x
if x = 1 [set color yellow]
if x = 0 [set color pink]
]
end ```
I don't see any place where the values for the turtle variable x are set, so they will always have the default value of 0. In NetLogo = is used to check equality, not for assignment, so show random 2 = x is just going to print true or false depending on if random 2 is 0 or not (in case you thought that was assignment). You'd want something like this:
to go
ask turtles
[
set x random 2
if x = 1 [set color yellow]
if x = 0 [set color pink]
]
end
Or you could move the set x random 2 to the setup procedure if you just want to set the value once to use later in go.

NetLogo: patchy forest - keep total area and blob size stable and not overlap

I realize that my question is just slight modification of questions:
Adding patch clusters in a landscape
How to create cluster patches that do not overlap between them
and
To build patch clusters at large spatial scales
but I can't modify them to satisfied my needs.
I need to produce a patchy forest landscape. Each setup, the total area of "green" patches has to be same (20%, 10%... of total count patches) and the size of one blob should be same. Thus: blob_size = area / number_blobs
I suggest that
to create-forests
clear-all
ask n-of 1 patches [ set pcolor green ]
repeat 6 [
ask one-of patches with [pcolor = green ] [
ask one-of neighbors4 with [pcolor = black] [
set pcolor green ]
]
]
end
should be the answer, as by n-of 1 (number_blobs) patches I create number of blobs needed, and blob_size is constrained by repeat 6 (blob_size). However, in my simple example I have an error ASK expected input to be an agent or agentset but got NOBODY instead. apparently because one-of patches with [pcolor = green] has not black neighbors.
Please, how can I include the condition ask one-of patches with [pcolor = green ] and with min-one of neighbors4 with [pcolor = black] in my code?
Or what is the different way to do this? I need to keep my total area of green patches same, and patches size +- same too, the best would be if they will not overlap. Thank you a lot!
to create-forests
clear-all
ask n-of 1 patches [ set pcolor green ]
repeat 6 [
ask one-of patches with [pcolor = green and any? neighbors4 with [ pcolor = black ] ] [
ask one-of neighbors4 with [pcolor = black] [
set pcolor green ]
]
]
end
Modified to make-blob from: Creating a random shape (blob) of a given area in NetLogo
my blobs still can overlap but at least total "area" is the same for every run
to make-blob
let total_area 500 ; how patches I want to turn green
repeat 5 [ ; number of blobs I want to have
let blob-maker nobody
crt 1 [ set blob-maker self
setxy random-xcor random-ycor] ; set random position of "blob-makers"
repeat 10 [ ; size of one blob (number of patches of the same color close one to another)
ask blob-maker [
ask min-one-of patches with [ pcolor = black ] [ distance myself ] [ set pcolor green ]
rt random 360
fd 1
]
]
ask blob-maker [ die ]
]
end
resulting in

Export part of the view in NetLogo

I want to, given a list of turtles, export the part of the view that contains those turtles as an image. Being able to export part of the view specified by a set of boundaries would solve this problem. That is, a function like export-view-of-turtles list-of-turtles or export-view-rectangle min-xcor max-xcor min-ycor max-ycor would be ideal.
Obviously, a solution that works entirely in NetLogo would be best, but I find that unlikely: export-view is the only function I know of that exports an image of the view at all, and that only does the whole view. However, if there's a plugin for this, that would be awesome.
My last resort is to just export the view and then run a script that clips it accordingly. If there isn't a better solution, I'll do this, and post the script.
Alright, this is kind of dirty, but it seems to work. Basically, the below exports the world state in a temp file, records the data about the turtles in question, resizes the view based on the distance of those turtles from the center, recreates just those turtles from the recorded data, exports the view, then restores the original world state. Here's the code:
to export-view-of-turtles [ filename the-turtles ]
let center-patch min-one-of patches [ sum [ (distance myself ^ 2) ] of the-turtles ]
let turtle-props [ (list
(- distance center-patch * sin towards center-patch) ; xcor relative to center patch
(- distance center-patch * cos towards center-patch) ; ycor relative to center patch
heading size shape label color
) ] of the-turtles
let max-x max map [ first ? + item 3 ? ] turtle-props
let min-x min map [ first ? - item 3 ? ] turtle-props
let max-y max map [ item 1 ? + item 3 ? ] turtle-props
let min-y min map [ item 1 ? - item 3 ? ] turtle-props
let world-state-backup (word "temp-world-" date-and-time ".csv")
export-world world-state-backup
resize-world min-x max-x min-y max-y
foreach turtle-props [
crt 1 [
setxy first ? (item 1 ?)
set heading (item 2 ?)
set size (item 3 ?)
set shape (item 4 ?)
set label (item 5 ?)
set color (item 6 ?)
]
]
export-view filename
import-world world-state-backup
file-delete world-state-backup
end
Example of use. Given:
Calling export-view-of-turtles "test.png" [ turtles in-radius 5 ] of turtle 85 gives:
Notes:
This perfectly supports world wrapping.
It will ONLY show the given turtles. Patches, drawing layer, and other turtles will not be shown. That said, it could easily be modified so that they patches and other turtles are shown.
As with any code that uses import and export world (not recommended for this kind of thing), this will likely break in many corner cases.

How to speed up least-cost path model at large spatial extents

Following on from How can I increase speed up simulation of my least-cost path model, I try to find a way to speed up my least-cost path model that runs at a large spatial scale. My landscape has an extent of 100kmĀ² (1000 patches x 1000 patches with 1 patch = 1 pixel).
For the moment, my code seems to work but it runs very slow: my code takes several hours to draw one least-cost path. The problem is that my model evolves according to discrete time steps of two minutes during 100 days and I have 1000 wolves in my landscape. For each wolf and at each time step, my model has to build the least-cost path between a polygon (composed of several patches) where there is a wolf and all polygons that are situated in a radius of 3km around the wolf.
I used the new version of NW-extension and I tried to optimize my model by saving all costs that have already been calculated to avoid to re-draw the least-cost paths. Unfortunately, my code is yet too slow and I don't know how to speed up it. Here is my code to calculate the cost of one least-cost path (If need be, I can provide more code to someone)
to-report path-cost-between-polygons [ID-polygon-1 ID-polygon-2]
let path-cost -1
;; Define polygon edges
ask patches with [ID-polygon != ID-polygon-1] [
ask neighbors with [ID-polygon = ID-polygon-1] [
ask nodes-here [
set color red ] ] ]
ask patches with [ID-polygon != ID-polygon-2] [
ask neighbors with [ID-polygon = ID-polygon-2] [
ask nodes-here [
set color red ] ] ]
;; Calculate path cost
foreach sort ( (nodes-on patches with [ID-polygon = ID-polygon-1]) with [color = red] ) [
let node-on-polygon-1 ?
foreach sort ( (nodes-on patches with [ID-polygon = ID-polygon-2]) with [color = red] ) [
let node-on-polygon-2 ?
ask node-on-polygon-1 [
let cost nw:weighted-distance-to node-on-polygon-2 "link-cost"
if path-cost = -1 or cost < path-cost [
set path-cost cost ] ] ] ]
;; Save path cost between polygons
set list-ID-polygons lput (list ID-polygon-1 ID-polygon-2) list-ID-polygons
set list-path-costs-between-polygons lput path-cost list-path-costs-between-polygons
ask nodes with [color = red] [ set color white]
report path-cost
end
Thanks very much for your help.
I'm currently working on a new version of the NW-extension that will be much faster. Unfortunately, for weighted paths, it won't be available till NetLogo 5.0.6 comes out.
Until then, you could code your own least-cost path code. A* would be perfect for your situation. Implementing would definitely be somewhat tricky, but doable. If I have the time, I'll give it shot and post it here.

Resources