NetLogo: link an agent to another, ask things to the agent and other things to the linked agent - netlogo

I'm working on extending NetLogo Robotic Factory with a mechanism where there can be only one robot per machine and where the machine takes several ticks to perform the task.
To model this, I'm creating a link between the robot and the machine. And there can only be one link per machine.
It is the first time I'm using NetLogo. So I'm not used to switching contexts. I'm trying to find out how I can give orders to both the robot and the machine when they are linked.
to move
ask robots [
if waiting = 0 [
if can-move? 1 [forward 1 face destination]
set energy energy - 1
]
if waiting > 0 [
set waiting waiting - 1
]
]
end
to set-robots-destination
ask robots [
(ifelse
; ---------------
; Step1: forges
; ---------------
[ breed ] of destination = forges [
ifelse any? forges-here [
if [count links] of one-of forges-here = 0 [
create-link-with one-of forges-here
set color of one-of forges-here red
set waiting 5
if waiting = 0 [
set costs costs + 1
set destination one-of forges
set [color] of one-of materials-here blue
ask my-links [ die ]
]
]
]
[ move ]
]
...
As you can see, repeating one-of forge there create several issues. First of all the syntax to change its color is incorrect. Then, it is unclear if the color will actually turn blue by the end or if the robot will already have left.
I would prefer to find a way to switch context with the linked forge and give it orders directly. Is this possible?

Related

Stopping turtles from having negative resources

My model creates a relationship between employees and citizens. Whereby the employees obtain office and then distribute to the employees:
globals [
office-space
]
breed [ offices office ]
breed [ service-desks service-desk ]
breed [ employees employee ]
breed [ citizens citizen ]
offices-own [ money ]
employees-own [ money ]
citizens-own [ money ]
to setup
clear-all
create-offices 1 [
set shape "building institution"
set size 4
set color yellow
set money num-of-money
]
create-employees num-of-employees [
set shape "person"
set size 1.5
set color blue
setxy random-xcor random-ycor
]
create-citizens num-of-citizens [
set shape "person"
set size 1.5
set color white
setxy random-xcor random-ycor
]
;; create 4 service desks
let service-desk-patches (patch-set patch 0 8 patch 8 0 patch 0 -8 patch -8 0)
ask service-desk-patches [
sprout-service-desks 1 [
set shape "building institution"
set color pink
set size 3
]
]
;; create office space
set office-space patches with [pxcor <= 8 and pxcor >= -8 and pycor <= 8 and pycor >= -8 ]
ask office-space [set pcolor grey]
;; set all employees randomly within the grey box
place-on-color-employees
;; set all citizens randomly outside of the grey box
place-on-color-citizens
reset-ticks
end
to place-on-color-employees
let _patches (patches with [pcolor = grey])
ask employees [
move-to one-of (_patches with [not any? turtles-here])
]
end
to place-on-color-citizens
let _patches (patches with [pcolor = black])
ask citizens [
move-to one-of (_patches with [not any? turtles-here])
]
end
to go
ask employees [
set label money
]
ask citizens [
set label money
]
employee-movement-without-money
employee-take-money
employee-movement-with-money
citizens-movement
citizen-take-money
tick
end
to employee-movement-with-money
ask employees [
ifelse [ pcolor ] of patch-ahead 1 = black
[ rt random-float 360 ]
[ forward 1 ]
let target min-one-of citizens [ distance myself ]
if money > 0 [
face target
fd 1
]
]
end
to employee-movement-without-money
ask employees [
let target patch 0 0
if ( money = 0 ) or ( money < 0 ) [
face target
fd 1
]
]
end
to citizens-movement
ask citizens [
ifelse [pcolor] of patch-ahead 1 = grey
[ rt random-float 360 ]
[ forward 1 ]
let target min-one-of service-desks [ distance myself ]
if money = 0 [
set heading (towards target )
]
]
end
to employee-take-money
ask employees [
if any? offices-here [
set money money + 1
set color green
;set label money
]
]
end
to citizen-take-money
ask citizens [
if any? employees in-radius 0.5 [
ask employees [
set money money - 1
]
]
set money money + 1
set color orange
]
end
When this model is run, the employees collect money and go to meet citizens, however, in the citizen-take-money procedure, I have not found a way to prevent the citizens from taking money from the employees so they don't have negative values. I tried adding the employee-movement-without-money to force the employees to turn move away from the citizens, but they just congregate on patch 0 0.
I also tried adjusting the citizens-take-money procedures by creating an if and arugment:
to citizen-take-money
ask citizens [
if (any? employees in-radius 0.5) and (employees money > 0) [
ask employees [
set money money - 1
]
]
set money money + 1
set color orange
]
end
But that didn't work either.
First piece of advice, build NetLogo models gradually. You need to make sure each piece works before adding the slightly more complicated behaviour. You should never have more than one thing wrong in a NetLogo model at the same time, very hard to debug.
Here, the basic problem appears to be that you are acting on all turtles instead of just the relevant turtle. Here is your supplementary code that tries to introduce a check:
to citizen-take-money
ask citizens [
if (any? employees in-radius 0.5) and (employees money > 0) [
ask employees [
set money money - 1
]
]
set money money + 1
set color orange
]
end
First, have a look at your check - conceptually, what are you testing with the second part employees money > 0. That doesn't actually look like valid NetLogo code to me, are you trying to ask if there are any employees with with money > 0?
Regardless, let's say it gets past that check, the next line is ask employees - at this point you are telling EVERY employee in the model to reduce their money.
What you need to do is just find the right employees and have those ones reduce their money. Something more like:
to citizen-take-money
ask citizens
[ let nearby employees in-radius 0.5 with [money > 0]
if any? nearby
[ ask nearby [ set money money - 1 ]
set money money + 1
set color orange
]
]
end
Also, this procedure is asking every citizen to do this and you have named it as if only one citizen is doing it. So think about which way you actually want the process to work.
Finally, what happens if you have several citizens close to several employees. Say 3 citizens reduce their money because they are close to the same employee - at the moment, the employee only increases their money by 1 and the remaining 2 disappears. This is an example of what I mean by build gradually and check it works before adding in the next thing. Perhaps you could have them just change colours if the condition is met before trying to add in the money transfers. That would help you spot that you had lots of people triggered at once.

To do a netlogo model with several patch layers (think floors of a building) do I need to go to Netlogo 3D?

I have a netlogo application in mind which involves multiple non interacting layers. Think floors of a building. Would I need to go to netlogo 3D or is there a suggested way to handle in regular netlogo?
This was an interesting enough question that I decided to make a simple sample.
The method I use is to have a global variable to track the number-of-floors we'll have in our building, as well as the active-floor that we are currently working with. Then all our agents, walls and workers, have a floor-num that tracks which they are on. We have a set-active-floor procedure that handles switching our currently active floor that we want to see and work with, making the patches a certain color (active-color) if they have a wall agent present and swapping which workers are hidden?. In this way, most of the magic happens in the setup-floor and set-active-floor procedures, and the real work of our model in go can be pretty typical NetLogo code asking the active-workers to do whatever we want.
While the model is running you can call set-active-floor n to any value 0 to 4 to change the current workers and walls. I also included a show-all procedure that'll un-hide all the walls and workers and let you see where they are at; you'll need to run that with the model stopped.
globals [colors active-color number-of-floors active-floor]
turtles-own [floor-num]
breed [walls wall]
breed [workers worker]
to setup
clear-all
set colors (list red blue green orange violet)
set number-of-floors 5
foreach (range 0 number-of-floors) setup-floor
reset-ticks
set-active-floor 0
end
to setup-floor [num]
set active-floor num
set active-color (item num colors)
ask patches [ set pcolor black ]
; make some random walls
create-walls (count patches * 0.2) [
set floor-num num
set hidden? true
set size 0.5
setxy random-pxcor random-pycor
set pcolor active-color
]
; only one wall per patch
ask patches [
let patch-walls floor-walls-here
let wall-count count patch-walls
if (wall-count > 1) [
ask n-of (wall-count - 1) patch-walls [ die ]
]
]
; make some workes
create-workers 10 [
set floor-num num
set hidden? true
set shape "person"
set color active-color - 2
move-to one-of patches with [pcolor != active-color]
]
end
to go
; this only "runs" the active floor, but you could run all of them
; using the same `foreach (range 0 number-of-floors) ...` code as
; in the `setup` procedure.
set-active-floor active-floor
ask active-workers [
; this code can be about the same as you'd write in a normal model...
move-to one-of patches with [pcolor != active-color]
]
tick
end
to set-active-floor [num]
set active-floor num
set active-color (item num colors)
; after the `pcolor` is set, we can use that to determine if a wall
; exists or not for an `active-worker`, we don't have to check the
; floor number at all while we do our work.
ask walls [ set hidden? true ]
ask patches [
set pcolor ifelse-value no-walls-here [ black ] [ active-color ]
]
ask workers [
set hidden? floor-num != active-floor
]
end
to-report active-workers
report workers with [floor-num = active-floor]
end
to-report floor-walls-here
report walls-here with [floor-num = active-floor]
end
to-report no-walls-here
report (count floor-walls-here = 0)
end
to show-all
foreach (range 0 number-of-floors) [ num ->
ask patches [
set pcolor ifelse-value any? walls-here [ red - 3 ] [ black ]
]
ask turtles with [floor-num = num] [
set color item num colors
set hidden? false
]
]
end
Finally, if things got much more complicated than this, I would probably choose to move to NetLogo 3D instead.

Netlogo: How to make a turtle move towards an unique patch target?

I have turtles (patients), and they can only use only one bed each (white patch). Since patients are randomly generated in a waiting room (green patches), sometimes two or more of them get at the same distance and therefore they find the same patch as its target. I tried to add an attribute to the patch with the purpose of assigning that particular bed to a specific patient. The idea is something like this (please indulge on the ugly code, I'm learning :P):
globals [
waitxmax
waitxmin
waitymax
waitymin
box
]
breed [ patients patient ]
patients-own [ target ]
patches-own [ assigned ]
to setup-wait-room
set waitxmax -15
set waitxmin 15
set waitymax 11
set waitymin 15
ask patches with [
pxcor >= waitxmax and
pxcor <= waitxmin and
pycor >= waitymax and
pycor <= waitymin
] [ set pcolor green ]
end
to setup-beds
let cmy 7
let cmx 15
let dst 3
let nbox 7
ask patch cmx cmy [ set pcolor white ]
let i 1
while [ i < nbox ] [
ask patch (cmx - dst) cmy [ set pcolor white ]
set i i + 1
set cmx cmx - dst
]
ask patches with [ pcolor = white ] [ set assigned false ]
set box patches with [ pcolor = white ]
end
to setup-patients
create-patients start-patients [
set shape "person"
set target nobody
move-to one-of patches with [ pcolor = green ] ]
end
to setup [
clear-all
setup-wait-room
setup-beds
reset-ticks
]
to go
ask patients [ go-to-bed ]
tick
end
to go-to-bed
let _p box with [ self != [ patch-here ] of myself ]
if target = nobody [
set target min-one-of _p [ distance myself ]
ask target [ set assigned myself ]
]
;;; FIXME
if ([ assigned ] of target) != self [ show "not true" ]
if target != nobody [
face target
fd 1
]
end
When I print the two sides of the comparison below FIXME, from the command center I actually get the expected result. For example: both patient 0 and patient 1 have the same target (patch -3 7), but that patch is assigned to (patient 0). I would have expected that comparison to force patient 1 to get a new target since the bed doesn't have his name (I haven't written that code yet), but it always evaluates to true. This is more notorious as more patients I add over available beds (if no beds available, they should wait as soon as one gets free).
When inspecting trough the interface I also see that the patch -3 7 says (patient 0), so I don't know what's happening. Command center example:
observer> show [ assigned ] of patch -3 7
observer: (patient 0)
observer> if ([ assigned ] of patch -3 7) = [self] of patient 0 [ show "true" ]
observer: "true"
observer> if ([ assigned ] of patch -3 7) = [self] of patient 1 [ show "true" ]
;;;; SETUP AND GO
(patient 0): (patch -3 7)
(patient 0): (patient 0)
(patient 0): "true"
(patient 2): (patch 12 7)
(patient 2): (patient 2)
(patient 2): "true"
(patient 1): (patch -3 7)
(patient 1): (patient 1)
(patient 1): "true"
Maybe I'm just overthinking this and there are is a simpler way to assign a bed to a patient and vice versa?
There seems to be a chunk or two missing from your code above (I can't copy-paste and run it), so please have a look at the option below.
This version works by having a single place to store the 'claimed' beds- in the turtle variable. Since the turtle variables can be queried as a list using of, a bed-less turtle can check if there are any beds that are not already present in that list and, if so, claim one.
turtles-own [ owned-bed ]
to setup
ca
ask n-of 5 patches [
set pcolor green
]
crt 10 [
set owned-bed nobody
claim-unclaimed-bed
if owned-bed != nobody [
print word "I own the bed " owned-bed
]
]
reset-ticks
end
to claim-unclaimed-bed
; If I have no bed
if owned-bed = nobody [
; Pull the current owned beds for comparison
let all-owned-beds [owned-bed] of turtles
; Pull those beds that are green AND are not found in 'all-owned-beds'
let available-beds patches with [
pcolor = green and not member? self all-owned-beds
]
; If there are any beds available, claim one
ifelse any? available-beds [
set owned-bed one-of available-beds
] [
; If there are none available, print so
print "There are no available beds."
]
]
end
Edit: Forgot the actual question title- to actually move to their owned-bed (if they have one) in the example above, they simply face it and move how you like- for example:
to go
ask turtles with [ owned-bed != nobody ] [
ifelse distance owned-bed > 1 [
face owned-bed
fd 1
] [
move-to owned-bed
]
]
tick
end
Edit: added complexity
Ok, for an added element of severity, you will likely want to avoid using multiple with [ ... = x statements, and instead to use a primitive called min-one-of which returns the agent with the minimum value of some reporter. Then, you want to tell NetLogo to keep asking the next most severe and the next most severe, etc. One way to do this is with a while loop, which basically says "While this condition is met, continue evaluating the following code." Be careful with while loops- if you forget to write your code such that eventually the condition is no longer true, the while loop will just continue running until you will eventually Tools > Halt your model (or, as has happened to me with a large model, NetLogo crashes).
I've reworked the code (much of what was above is unchanged) to include such a while loop. Note as well that, since the model needs to check which beds are available multiple times, I've made that code into a to-report chunk to condense / simplify.
turtles-own [ owned-bed severity ]
to setup
ca
ask n-of 5 patches [
set pcolor green
]
crt 10 [
set owned-bed nobody
set severity random-float 10
]
let current-available-beds report-available-beds
while [any? current-available-beds] [
; From the turtles with no bed, ask the one with the lowest severity number to
; claim an unclaimed bed. Then, reset the current-available-beds
ask min-one-of ( turtles with [owned-bed = nobody] ) [ severity ] [
claim-unclaimed-bed
if owned-bed != nobody [
show ( word "I have a severity of " severity " so I am claiming the bed " owned-bed )
]
]
set current-available-beds report-available-beds
]
reset-ticks
end
to-report report-available-beds
let all-owned-beds [owned-bed] of turtles
report patches with [
pcolor = green and not member? self all-owned-beds
]
end
to claim-unclaimed-bed
; If I have no bed
if owned-bed = nobody [
let available-beds report-available-beds
; If there are any beds available, claim one
ifelse any? available-beds [
set owned-bed one-of available-beds
] [
; If there are none available, print so
print "There are no available beds."
]
]
end

Simulating the spread of a virus from an infected individual to a susceptible individual in a small world network using netlogo?

I am simulating the spread of a virus across a small world network in netlogo. Using the existing model netlogo offers of a small world network where nodes can connect with other nodes using the 'Rewire One' button on the interface I am trying to get it so that if an initially infected individual gets rewired with a susceptible individual the virus will then transfer to that individual and the turtles color will update to red.
Here is the code im using to rewire one turtle with another:
to rewire-one
if count turtles != num-nodes [
setup
]
set rewire-one? true
set rewire-all? false
let potential-edges links with [ not rewired? ]
ifelse any? potential-edges [
ask one-of potential-edges [
let node1 end1
;; if "a" is not connected to everybody
if [ count link-neighbors ] of end1 < (count turtles - 1)
[
;; find a node distinct from node1 and not already a neighbor of node1
let node2 one-of turtles with [ (self != node1) and (not link-neighbor? node1) ]
;; wire the new edge
ask node1 [ create-link-with node2 [ set color cyan set rewired? true ] ]
ask links
[ reed-frost-children]
ask links
[ increment-children ]
set number-rewired number-rewired + 1 ;; counter for number of rewirings
;; remove the old edge
die
]
]
;;I am then using the reed-frost function as the force of infection which can be seen below
to reed-frost-children
ask children with [ child-sus = 1]
[
set num-infected-neighbours length filter [[ child-infected = 1] of ?]
[other-end] of my-links with [not rewired?] ;; i.e not closed? i.e open
set force-of-infection 1 - (1 - prob-infection-child) ^ num-infected- neighbours
if(random-float 1 <= force-of-infection)
[
set child-sus 0
set child-inncubated 1
set child-infected 0
set child-almost-infected 0
set child-recovered 0
set inncubation-period 100
show-turtle
set color orange
set size 1
ask link-neighbors with [ child-infected = 1]
[
ask my-links
[
set color orange show-link
ask other-end
[
set color orange
]
]
]
ask my-links [set closed? false] ;; closed i.e. not open
]
]
However the virus is not transmitting when an infected rewires with a susceptible. Any ideas?

Preferential attachment: Selecting a node to attach

I've been struggling with this one for the last 24 hours or so I feel like I'm missing something relatively simple here.
to setup-scale-free-network
clear-all
;; Make a circle of turtles
set num-nodes (num-children + num-adults + num-toddlers)
create-children num-children
create-adults num-adults
create-toddlers num-toddlers
layout-circle turtles (max-pxcor - 8)
ask turtles[
create-links-with turtles with [self > myself and random-float 5 < probability]
]
setup
end
to-report find-partner
report [one-of both-ends] of one-of links
end
The above code creates a set number of turtles of various breeds and creates a number of links between these breeds.
to go
reset-ticks
make-link find-partner
tick
end
The two procedures would be called until the needed level of degree distribution as been met.
What I want to do is use the find-partner procedure to move towards preferential attachment to do this I need to modify this code to create a link from the node find partner has selected to one of each of the other three types of breeds in my network.
to make-node [old-node]
crt 1
[
set color red
if old-node != nobody
[ create-link-with old-node [ set color green ]
;; position the new node near its partner
move-to old-node
fd 8
]
]
end
My own attempts have lead no where to be honest. I know I'm asking for a lot of help but I'm at my wits end here, thank you for your help and patience.
I was unable to completely understand your question. I am guessing that you wish to create another type of link which you call preferential attachment (with green color) between turtles who are already a part of the network.
One thing you might want in this situation is that you do not pick turtles which are already in a preferential attachment network. [this is just my assumption]
I have modified your code (as follows) to get the desired network with preferential attachment shown with green colored links, have added a turtle-variable already-attached which is used to exclude turtles which are already preferentially attached to others.
Hope this helps!
breed [ children child ]
breed [ adults adult ]
breed [ toddlers toddler ]
children-own [ already-attached ]
adults-own [ already-attached ]
toddlers-own [ already-attached ]
to setup-scale-free-network
clear-all
let num-children 5
let num-adults 5
let num-toddlers 5
let probability 1
;; Make a circle of turtles
create-children num-children [ set color orange ]
create-adults num-adults [ set color green ]
create-toddlers num-toddlers [ set color blue ]
layout-circle turtles (max-pxcor - 8)
ask turtles
[
create-links-with turtles with [self > myself and random-float 5 < probability]
]
end
to go
setup-scale-free-network
ask turtles with [already-attached = 0]
[
attach-to-one-of-each-breed self
]
end
to attach-to-one-of-each-breed [ source-node ]
ask source-node
[
if any? other children with [ already-attached = 0 ]
[
ask one-of other children
[
set already-attached 1
create-link-with source-node [ set color green ]
]
]
if any? other adults with [ already-attached = 0 ]
[
ask one-of other adults
[
set already-attached 1
create-link-with source-node [ set color green ]
]
]
if any? other toddlers with [ already-attached = 0 ]
[
ask one-of other toddlers
[
set already-attached 1
create-link-with source-node [ set color green ]
]
]
]
end