Netlogo: Can a turtle include another turtle? - windows

Netlogo: Can a turtle include another turtle?
Pseudocode:
If turtle1 < 5 radius from turtle2
include turtle1 in turtle2;
turtle1 die

Maybe not exactly include, but turtles may collect a list of other unlucky agents in their own variable. Look at agentsets in the manual.
Example:
Declare turtle variable
turtles-own [
swallowed; agentset of the turtles I've eaten
]
Set this agentset to empty when creating agents
to setup
create-turtles 1 [
set swallowed no-turtles
]
end
Enable turtles to eat each other
to swallow
if any? other turtles-here [
set swallowed (turtle-set swallowed other turtles-here)
]
end
Ask turtles to do so:
to go
; ...
ask turtles[ swallow ]
; ...
end
But - don't ask the swallowed turtles to die (as proposed in your pseudocode), because they will disappear from the agentsets too. Define another agent variable (for example is-alive?) and set it to false in the swallow procedure. You can then hide all eaten agents.

Thank you again for your answer.
Pseudocode:
Ifelse Turtle1 dies ;; Turtle1 and Turtle2 are from different breeds
;; It is not a case of canibalism

Related

How to distribute agents' attributes randomly according to specific probabilities in Netlogo?

I am relatively new to Netlogo, having completed only a handful of models. Currently working on one for my dissertation where I need to distribute agents' attributes randomly according to specific probabilities, some at the onset of the simulation, other attributes to be distributed throughout. This is connected with an extension of the trust game, for those familiar with it. I completed the conceptual model with a colleague who doesn't use Netlogo, so I am a bit stuck at the moment.
I think the rnd extension might be useful, but I can't quite figure out how to use it. My apologies if this seems redundant to any of you, but I really hope to get some help here.
extensions [ rnd]
;; divides agents into two types
breed [ sexworkers sexworker ]
breed [ officers officer ]
;; determines attributes of agents
sexworkers-own
[ assault? ;; is assaulted
trust? ;; probability to trust police to report assault
protection? ;; probability of good experience with police during report
prob-trust ] ;; probability to trust overall
officers-own
[ behavior ] ;; probability of treating sex workers well/badly during report
This is the start of the model, and then I want to distribute the attributes according to specific probabilities. I honestly haven't found a way to do this that works as I intend it to.
What I want is to start off, for every sex worker alike, a probability of 0.01 to be assaulted (prob-assault; assault?=true). Afterwards, with each tick, there is again the chance of 0.01 for sex workers to be assaulted.
Afterwards, in the subset of assault?=true, there is then a probability to report the assault (prob-report, 0.5. This is expressed by trust?=true/false. Within the subset of those who report, there is then a final probability of having a good/bad experience with police (prob-protection), here protection?=true/false.
These three attributes should be randomly distributed according to the probabilities, and also then result in a combined probability to trust police in the future, prob-trust. (prob-trust = prob-assault + prob-report + prob-protection).
What I have done (without rnd extension so far is this:
;; determines sex workers' behavior
ask sexworkers [ move ]
ask sexworkers [ victimize ]
ask sexworkers [ file ]
to victimize
ask sexworkers [
ifelse random-float 1 <= 0.0001
[ set assault? 1 ]
[ set assault? 0 ]
]
end
to file
ask sexworkers with [ assault? = 1 ] [
ifelse random-float 1 <= 0.5
[ cooperate ]
[ avoid ]
]
end
to cooperate
ask sexworkers [ set trust? 1 ]
end
to avoid
ask sexworkers [ set trust? 0 ]
end
What happens at the moment though is that there is no variation in attributes, all sex workers seem to have no assault and trust/not trust varying all simultaneously. I am not sure what is going on.
(1) You don't need the rnd extension for anything you are trying to do here. If you just want to take some action with some probability then your approach of if random-float 1 < <probablility value> is the correct approach. The rnd extension is when you want to get into weighted probability, for example choosing agents based on their income.
(2) NetLogo recognises true and false (capitalisation does not matter) as specific truth values. You should not use 1 and 0 as proxies for true and false. There are several advantages to using the truth values directly. The most obvious is readability, you can have statements like set trust? true and if trust? = true [do something]. More compactly, you can simply say if trust? [do something]. Other advantages include access to logical operators such as not and and for your conditions.
With regard to your actual problem of every agent having the same behaviour, you have nested your ask turtles type statements. For example, you have:
to file
ask sexworkers with [ assault? = 1 ] [
ifelse random-float 1 <= 0.5
[ cooperate ]
[ avoid ]
]
end
If you substitute the cooperate and avoid procedures into this code, you would get:
to file
ask sexworkers with [ assault? = 1 ] [
ifelse random-float 1 <= 0.5
[ ask sexworkers [ set trust? 1 ] ]
[ ask sexworkers [ set trust? 0 ] ]
]
end
So, if your random number is, say, 0.4 then ALL your sexworkers will have trust set to 1, not just the particular sexworker who 'rolled the die'.
You either need:
to file
ask sexworkers with [ assault? = 1 ] [
ifelse random-float 1 <= 0.5
[ set trust? true ]
[ set trust? false ]
]
end
Or you need:
to cooperate
set trust? true
end
to avoid
set trust? false
end
Use the first option if there's not really anything else that is being done. Use the second option if setting the trust? value is just one of many actions that the turtle should take when it is cooperating or avoiding.

Get all pixels location

I using PixelSearch function, I know how to find 1 pixel that match to my criteria, but the problem is that I would like to find all pixels of specific color and add this to array, so after I can use it to rand one and click on it.
Source code:
Local $aCoord = PixelSearch(0, 0, $clientSize[0], $clientSize[1], 0x09126C, 10, 1, $hWnd)
If Not #error Then
; add to array and search next
Else
GUICtrlSetData($someLabel, "Not Found")
EndIf
I want to find ALL PIXELS, not one "the first". How can I do this? Am I missing something?
This can't be done using PixelSearch because it stops executing when a matching pixel is found.
It can be done by looping PixelGetColor over your area. Something like:
For $x = 0 To $clientSize[0] Step 1
For $y = 0 To $clientSize[1] Step 1
If PixelGetColor($x,$y,$hWnd) = 0x09126C Then
;Add $x and $y to Array using _ArrayAdd() (or whatever you prefer)
EndIf
Next
Next
This might feel slower than PixelSearch because it now has to scan the entire area, instead of stopping at the first match, but it shouldn't be, since PixelSearch is based on the same principle.

Seeking alternative strategy for forming assortative network in netlogo

In my netlogo simulation, I have a population of turtles that have several sociologically-relevant attributes (e.g., gender, race, age, etc.). I want them to form a network that is assortative on multiple of these attributes. The strategy that I’ve been trying to use to accomplish this is to: (i) form all possible links among the turtles, (ii) calculate a propensity to pair index for each of these “potential” links which is a weighted linear combination of how similar two turtles on the relevant attributes, and (iii) then run a modified version the “lottery” code from the models library so that links with higher propensities to pair are more likely to be selected, the selected links are then set to be “real” and all the potential links that didn’t win the lottery (i.e., are not set to real) are deleted. The problem that I’m running into is that forming all possible links in the first steps is causing me to run out of memory. I’ve done everything I can to maximize the memory that netlogo can use on my system, so this question isn’t about memory size. Rather, it’s about modeling strategy. I was wondering whether anyone might have a different strategy for forming a network that is assortative on multiple turtle attributes without having to form all potential links. The reason I was forming all potential links was because it seemed necessary to do so in order to calculate a propensity to pair index to use in the lottery code, but I’m open to any other ideas and any suggestions would be greatly appreciated.
I’m including a draft of the modified version of the lottery code I’ve been working, just in case it’s helpful to anyone, but it may be a little tangential since my question is more about strategy than particular coding issues. Thank you!
to initial-pair-up
ask winning-link [set real? true]
end
to-report winning-link
let pick random-float sum [propensitypair] of links
let winner nobody
ask not real? links
[if winner=nobody
[ifelse similarity > pick
[set winner self] [set pick pick-similarity] ] ]
report winner
end
For a "lottery" problem, I would normally suggest using the Rnd extension, but I suspect it would not help you here, because you would still need to create a list of all propensity pairs which would still be too big.
So, assuming that you have a propensity reporter (for which I've put a dummy reporter below) here is one way that you could avoid blowing up the memory:
to create-network [ nb-links ]
; get our total without creating links:
let total 0
ask turtles [
ask turtles with [ who > [ who ] of myself ] [
set total total + propensity self myself
]
]
; pre-pick all winning numbers of the lottery:
let picks sort n-values nb-links [ random-float total ]
let running-sum 0
; loop through all possible pairs...
ask turtles [
if empty? picks [ stop ]
ask turtles with [ who > [ who ] of myself ] [
if empty? picks [ stop ]
set running-sum running-sum + propensity self myself
if first picks < running-sum [
; ...and create a link if we have a winning pair
create-link-with myself
set picks but-first picks
]
]
]
end
to-report propensity [ t1 t2 ]
; this is just an example, your own function is probably very different
report
(1 / (1 + abs ([xcor] of t1 - [xcor] of t2))) +
(1 / (1 + abs ([ycor] of t1 - [ycor] of t2)))
end
I have tried it with 10000 turtles:
to setup
clear-all
create-turtles 10000 [
set xcor random-xcor
set ycor random-ycor
]
create-network 1000
end
It takes a while to run, but it doesn't take take much memory.
Maybe I have misunderstood, but I am unclear why you need to have the (potential) link established to run your lottery code. Instead, you could calculate the propensity for a pair of nodes (nodeA and nodeB) and create a link between them if the random-float is lower than the propensity. If you want it proportional to the 'share' of the propensity, calculate the total propensity over all pairs first and then the probability of creating the link is this-pair-propensity / total-propensity.
Then the only issue is running through each pair exactly once. The easiest way is probably an outer loop (nodeA) of all agents and an inner loop of agents (nodeB) with a who number that is greater than the outer loop asker (myself). Something like:
to setup
clear-all
create-turtles 30
[ set xcor random-xcor
set ycor random-ycor
]
ask turtles
[ ask turtles with [ who > [who] of myself ]
[ if random-float 1 < 0.4 [create-link-with myself]
]
]
end

Effectively deactivating specific links between specific agents and breeds in a social network

A social network of agents of different ages is set up in NetLogo similarly to the following, which results in a circle of agents connected by links. The overall purpose of these links is to represent contact between those links. The model simulates the spread of infection through the network. Agents begin as susceptible, with the possibility of becoming infected if they come into contact with an infectious link neighbour. I want to model for example the isolation or quarantine of an infected individual. i.e. their links to others would be deactivated completely or at least the majority of their links would be deactivated. Ideally I'd press a button on the observer interface to deactivate the links of infected agents. I'd also like to be able to model the closure of a school for instance whereby the majority of toddlers and children and their connections between each other would be deactivated, stopping the ability of infection between children. Their links to adults should probably remain open if fewer of them, though it may be better to just focus on links between one breed at a time for now.
breed [ toddlers toddler ]
breed [ children child ]
breed [ adults adult ]
breed [ over45s over45 ]
globals
[
num-nodes
num-infected
num-susceptible
prob-infection-toddler
prob-infection-child
prob-infection-adult
prob-infection-over45
force-of-infection
]
turtles-own
[
temp-infected? ;; temporary infected state
infected? ;; true if agent has been infected
susceptible?
num-infected-neighbors
]
links-own
[
closed?
]
to setup
clear-all
create-toddlers 20
create-children 20
create-adults 20
create-over45s 20
create-network
reset-ticks
layout-circle (sort turtles) max-pxcor - 8
ask turtles
[
facexy 0 0
if who mod 2 = 0 [fd 4]
]
ask turtles
[set susceptible? true]
ask one-of turtles
[
set infected? true
set susceptible? false
set color red
]
display
end
to create-network
let connexions (list
(list toddlers toddlers 5)
(list toddlers children 2)
(list toddlers adults 2)
(list toddlers over45s 1)
(list children toddlers 3)
(list children children 8)
(list children adults 5)
(list children over45s 1)
(list adults toddlers 1)
(list adults children 3)
(list adults adults 6)
(list adults over45s 3)
(list over45s toddlers 1)
(list over45s children 1)
(list over45s adults 5)
(list over45s over45s 5)
)
foreach connexions [
let source-breed item 0 ?
let target-breed item 1 ?
let num-connexions item 2 ?
let reverse-num-connexions item 2 first filter [
item 0 ? = target-breed and item 1 ? = source-breed
] connexions
ask source-breed [
repeat num-connexions [
let possible-targets other target-breed with [
(not member? myself link-neighbors) and
(count link-neighbors with [ breed = source-breed ] < reverse-num-connexions)
]
let target one-of possible-targets
if target != nobody [ create-link-with target ]
]
]
]
ask links [set closed? false]
end
to spread
;;; there is one of these for each age group as they have different probabilities for infection
ask toddlers with [ susceptible? = true ]
[
;;tried changing to something like this but this is the line that throws up an error
ask my-links with [closed? = false][
set num-infected-neighbors count (link-neighbors with [infected? = true])
]
;;should only include active links
set force-of-infection (prob-infection-toddler) ^ num-infected-neighbors ;;paraphrased equation but num-infected-neigbours is important
if ( random-float 1 <= force-of-infection) ;; infect with probability p
[
set temp-infected? true
set susceptible? false
]
]
ask turtles with [temp-infected? = true]
[
set infected? true
set temp-infected? false
]
end
to isolate-infected
;;for all infected individuals deactivate their links
end
to close-schools
ask toddlers
[
ask my-links [set closed? true]
]
end
to close-offices
;; e.g cut the number of links between adults and so on
end
As you can see there are two problems here, one being the deactivation (ideally they could be turned on again once school closures are over or once an infected individual recovers for example) of links based on what state the end nodes are in or the breed that they are.
And the second problem of counting the number of infected link-neighbours without including the links which are deactivated. Hiding a link does not stop it from existing it just becomes invisible and thus doesn't stop the contact. I've also considered simply changing the color of the deactivated links to for example black. Is there a way in which I can rewrite the counting of infected neighbors to count only links that aren't black or hidden for example set num-infected-neighbors count (link-neighbors with [infected? = true]...and link hidden? = false.... or link-color "!=" black? )
I feel the second problem is probably the easier of the two but I may be mistaken. I've hit too many brick walls at this stage and my head is fried on the matter. Any help would really be greatly appreciated. Thanks for your time reading this already, I realise it was a bit of a rant :) Thanks again to Nicolas Payette for his help previously
EDIT: Added links-own boolean for closed?
Tried to alter the section which counts the number of infected neighbours on open links but I get the error
this code can't be run by a link
error while link 14 15 running SET
called by procedure SPREAD
called by Button 'Spread'
Also added in a function in "to close-schools" which gives a very basic closure of all toddlers links by setting closed? to true
Edit: Would this be a possible solution here
set num-infected-neighbors 0
ask my-links with [closed? = false][
ask other-end [if (infected?) [set num-infected-neighbors num-infected-neighbors + 1 ]]
]
set force-of-infection 1 - (1 - prob-infection-adult) ^ num-infected-neighbors
Edit: num-infected-neighbors should be a turtles-own variable as far as I can tell, but when I put a watch on a turtle and run the simulation, the num-infected-neighbors that a turtle has seems to consistently surpass the actual number of link-neighbors that the turtle has. It is also just wrong. I can't see why though....
Edit:
let infectnum 0
set num-infected-neighbors 0
ask my-links with [closed? = false][
ask other-end [if (infected?) [set infectnum infectnum + 1 ]]
;;set num-infected-neighbors count (link-neighbors with [infected? = true])
]
set num-infected-neighbors infectnum
doesn't seem to be working properly either...
Edit: For future reference problem was solved by -
set num-infected-neighbors length filter [[infected?] of ?]
[other-end] of my-links with [not closed?]
First a list is formed of the link-neighbors on not-closed links, then that is filtered to give just the infected ones. num-infected-neighbors is the length of that list
First some general advice: It would be better to give a minimum working example (MWE), i.e. one that's stripped down to the bare minimum to show the problem. This code has too much detail, so people are less likely to answer. Also, sometimes once you strip it down, you'll figure out the answer. This code doesn't work, either: The definitions for the global variables are missing.
You might want to take a look at "Virus on a Network" in the Models Library that comes with NetLogo. It does similar things, but using a more "NetLogoey" coding style.
You can test links for their color. i.e. you could use the fact that a link is the "deactivated" color to test whether it should be counted, or followed. A better idea would be to give the links a variable using links-own, and test that. But here is some example code (modified from a procedure in "Virus on a Network") that uses color for this purpose:
to spread-virus
ask turtles with [infected?]
[ ask my-links with [color != red]
[ask other-end
[ if (not resistant?) and (random-float 100 < virus-spread-chance)
[ become-infected ] ] ] ]
end
The trick is that rather than looking directly at link-neighbors, I ask each turtle for its my-links, then test their colors. Then for each link that passes the test, I ask it for its other-end, i.e. the turtle that is not the turtle that found the link via my-links. Then the virus is transmitted to that turtle--but only if the link had not been disabled. (I think this code works right--seems to. But you should test it thoroughly if you do something like this.) Counting disabled or non-disabled links using my-links should be even easier. For isolate-infected you can do something like ask turtles with [infected?] [ask my-links [set color/deactivated/etc. ]]. Haven't tested that.
For the new error in the edited version in response to my answer, I think the problem might be this code:
ask my-links with [closed? = false][
set num-infected-neighbors count (link-neighbors with [infected? = true])
]
This asks some links to run the procedure link-neighbors, but that procedure is only designed to be run by turtles. (In NetLogo, certain procedures are only to be designed to be run "by an agent", e.g. within braces after ask .... However, some of these procedures only work in turtle agents, and others only work in link agents.) You probably should use other-end, which is a procedure designed to be run by a link. (It's kind of a funny procedure, though, because it's only designed to be run by a link when the ask command that's asking the link to run other-end, was an ask invoked by a turtle. So other-end only works if you've got something like ask turtle 1 [ask mylinks [ ... other-end ...]].)
(It is possible to reference an agent inside another agent that the first agent asked. For one level of this, you can use myself. For additional levels of asks, you can define variables at the outer levels and then reference them in the inner levels.)

How can I generate random integers in a range in Smalltalk?

A class I am taking currently requires us to do all of our coding in smalltalk (it's a Design class). On one of our projects, I am looking to do some things, and am having a tough time finding how to do them. It seems that what most people do is modify their own version of smalltalk to do what they need it to do. I am not at liberty to do this, as this would cause an error on my prof's computer when he doesn't have the same built-in methods I do.
Here's what I'm looking to do:
Random Numbers. I need to create a random number between 1 and 1000. Right now I'm faking it by doing
rand := Random new.
rand := (rand nextValue) * 1000.
rand := rand asInteger.
This gives me a number between 0 and 1000. Is there a way to do this in one command? similar to
Random between: 0 and: 1000
And/Or statements. This one bugs the living daylights out of me. I have tried several different configurations of
(statement) and: (statement) ifTrue...
(statement) and (statement) ifTrue...
So I'm faking it with nested ifTrue statements:
(statement) ifTrue:[
(statement) ifTrue:[...
What is the correct way to do and/or and Random in smalltalk?
The problem is that
(expr) and: (expr) ifTrue: aBlock
is parsed as the method and:ifTrue: If you look at the Boolean class (and either True or False in particular), you notice that ifTrue: is just a regular method, and that no method and:ifTrue: exists - however, plain and: does. So to make it clear that these are two messages, write
((expr) and: (expr)) ifTrue: aBlock
For longer boolean combinations, notice that there are also methods and:and: and and:and:and: implemented.
(1 to: 1000) atRandom
If you're using VisualWorks, and: takes a block as an argument, so you'd write:
(aBoolean and: [anotherBoolean]) ifTrue: [doSomething].
There's also &, which does not take a block as argument,
aBoolean & anotherBoolean ifTrue:[doSomething].
The difference is and: only evaluates what's in the block if the first bool is true (similar to java), while & always evaluates both.
Thus and: comes in handy if the second condition is computationally expensive, or if it includes state alterations which should only happen when the first condition is true. (that's usually a bad design though).
As for the Random, as long as you deliver your custom method, Random >> between: and: as well as the rest of your code, it runs fine on your professors computer. How to do that specifically, depends on the format in which you are supposed to deliver the assignment.
As for the Random issue: it depends on what ST version you use. In Squeak 3.9, there is Random>>#nextInt:, which is documented as "Answer a random integer in the interval [1, anInteger].". Its implementation reads
(self next * anInteger) truncated + 1
So I have two comments here:
You should really learn to use the class browser. This can answer the (frequent) questions "what messages can I send to objects of class X"
It is common, in ST, to add new methods to existing classes. So if you want Random to have between:and:, just add it, e.g. as
between: low and: high
^(self next * (high-low+1)) truncated + low
To put it simply, without knowing the Smalltalk dialect, I can only give a general answer. The way you stated the random question, yes that's the only way to do it if your professor needs a generic answer.
As for the and/or statements question,
And/Or statements. This one bugs the living daylights out of me. I have tried several different configurations of
(statement) and: (statement) ifTrue...
(statement) and (statement) ifTrue...
What you want to try is:
(statement) and: [statement] ifTrue: [ ... ]
note the brackets, the and: method takes a block as an argument.
To create several random integers between 1 and 1000
First create a random number series. Do this just once.
Then create a new random number by taking the next number from the series. Repeat as necessary.
aRandomSeries := Random new .
"Seed a new series of random numbers"
aRandomInt := aRandomSeries newInt: 1000 .
"generate a random integer between 0 and 1000"
anotherRandomInt := aRandomSeries newInt: 1000 .
"generate another random integer between 0 and 1000"
Logical operations
aBoolean will respond to and: and or:. They both take block arguments.
Here is how they work.
and: alternativeBlock
If the receiver is true, answer the value of alternativeBlock; otherwise answer false without evaluating alternativeBlock.
or: alternativeBlock
If the receiver is false, answer the value of alternativeBlock; otherwise answer true without evaluating alternativeBlock.
e.g.
( 3 > 2 ) or: [ 3 < 4 ] ifTrue: [ ]
aBoolean and: [ anotherBoolean ] ifFalse: [ ]
However, Squeak and Pharo Smalltalks will both accept an argument in parentheses ( )
Dolphin Smalltalk will not, and strictly requires the standard Smalltalk syntax of a block argument.
Other related methods:
& an AND that does not require a square bracketted (i.e. block) argument
| an OR that does not require a square bracketted (i.e. block) argument
& and | work in Amber, Cuis, Gnu, Pharo, Squeak, VisualAge and VisualWorks Smalltalks.
Squeak Smalltalk also provides:
and:and: }
and:and:and: } These take multiple block arguments
and:and:and:and }
or:or: }
or:or:or: } These take multiple block arguments
or:or:or:or: }

Resources