I would like to sum several lists of turtles. Lets call each variable turtle-list. There is only one list per variable, each list has the same number of items. If I have n turtles, I know that I can write
show (map + [turtle-list] of turtle 0 [turtle-list] of turtle 1 ... [turtle-
list] of turtle n)
Nevertheless, it may be very long and does not work if the number of turtles changes.
Is it possible to do it without writing the variable of each turtle ? Thank you for your help
I think you want to use reduce and sentence to convert a list of lists (from [turtle-list] of turtles) to a single list of values, then just sum that list:
turtles-own [ turtle-list ]
to setup
ca
crt 5 [
set turtle-list map [ i -> ( who + 1 ) * i ] [ 1 2 3 ]
]
reset-ticks
end
to sum-turtle-lists
show sum reduce sentence [turtle-list] of turtles
end
Let me know if that's not quite what you're after.
Edit:
Based on your comment, try this version:
to sum-turtle-lists
show reduce [ [ i a ] -> ( map + i a ) ] [turtle-list] of turtles
end
Related
I have created an opinion dynamics model, that works just fine. But now I wanted to see, how the opinion of all of my turtles changes. So I created the reporter "report [opinion] of turtles". When I put this in behaviorspace I get wildly jumping results that do not correspond with what I observe. If I test this with individual turtles like "report [opinion] of turtle 0", I get the smooth curve progression that I expected to see.
Does anyone know why this is happening? I would find it rather unwieldy, if I had to put every turtle individually in my behaviorspace, because I have sliding Agentsnumbers.
You can let each turtle have a list variable, at the beginning of which each turtle will record its ID. At every step, each turtle will append its opinion value.
Then you can have a global variable, which you will use as a list of lists, to which at the end of the simulation each turtle will append its own list.
In BheaviorSpace, you will only need to use one reporter (the list of lists) at the end of each experiment's run.
See below for a working example:
globals [
results
]
turtles-own [
opinion
my-list
]
to setup
clear-all
reset-ticks
set results (list)
create-turtles 3 [
set opinion random 10
set my-list list self opinion
]
end
to go
if (ticks = 5) [
ask turtles [
set results lput my-list results
]
stop
]
ask turtles [
set opinion opinion + 1
set my-list lput opinion my-list
]
tick
end
At the end of each run, the results reporter will look like:
[[(turtle 2) 3 4 5 6 7 8] [(turtle 0) 0 1 2 3 4 5] [(turtle 1) 5 6 7 8 9 10]]
Note that, this way, the lists in results will always be in random order.
If you're interested in having them ordered according to some criterion, you can do it.
The example below changes the if (ticks = 5) statement to order results according to turtles' ID, but you can just use sort on whatever characteristic you're interested in.
if (ticks = 5) [
let sorted-turtles sort turtles
foreach sorted-turtles [this-turtle -> ask this-turtle [set results lput my-list results]]
stop
]
I am trying to write a procedure where a turtle of a certain breed asks turtles of the same breed, within a certain distance, the value of a certain variable. The asking turtle will then capture the values add them to it's own, map + them and then reduce + to a single number. Here's the code
ask Teams
[ if AsgnE = "E 1"
[
ask Teams with [ distance myself < 25]
[
; assuming that there are no more then 2 teams within distance
let Val1 []
let Val2 []
let Val3 []
set Val1 Value
set Val2 Value
set Val3 [Value] of self
let Val4 (map + Val1 Val2 Val3)
set Val4 (reduce + Val4)
set Storys1 [Stories] of Epic 0
if Storys1 > 0 [ set TotValue1 Val4 ]
]
]
]
The values of each Team continuously update as long as the go button is pressed. The issue is that the resulting number never matches the aggregate of all the values. As the number updates they never match the totals of the separate Teams. Sometimes the number drops to a lower number (I'm assuming it's representing a single teams value) before jumping back to a higher number.
Any idea on how to fix this?
Thanks
Rudy
My guess is that it's a synchronicity problem. The ask will iterate (in random order) through all the turtles. Let's say it starts with turtle 1 - so turtle 1 updates its value to be the sum of its old value and all the values of the nearby turtles. Then the ask moves on to turtle 2, and turtle 2 happens to be nearby to turtle 1. That means turtle 2 adds all the numbers again, with turtle 1 having its adjusted value. With just these two turtles, the value for turtle 2 gets added in twice because turtle 1 also has it hidden in its new value.
If this is not the behaviour you want, the easiest thing to do is to have an extra variable called something like next-value. Calculate next-value for each turtle as the appropriate sum. Then, in a new ask, get each turtle to set value next-value to update them all at the same time.
Also, your map and reduce seems unnecessarily complicated. If what you are trying to achieve is to add the value of a variable over a bunch of turtles, then you can simply do a sum of the variable after constructing the relevant turtle agentset. But it may be that you simplified for the purposes of the question, in which case just ignore this!
UPDATE ---- added complete model example
turtles-own
[ team
myval
nextval
]
to setup
clear-all
create-turtles 20
[ setxy random-xcor random-ycor
set team one-of ["A" "B"]
set myval 1
]
reset-ticks
end
to go
ask turtles
[ let myteam turtles with [team = [team] of myself]
set nextval sum [myval] of myteam
]
type "total before: " print sum [myval] of turtles
ask turtles
[ set myval nextval
]
type "total after: " print sum [myval] of turtles
end
I have several turtles each with three variables opinion1, opinion2 and opinion3. I need them to:
identify which of these three variables has the highest value
find another turtle in their network with a value at least as high
as the one found in 1.
update its own value found in 1. with
respect to that of the turtle found in 2.
What I have done doesn't really work because it only updates looking at o1 without really having a look at which of the tree (opinion1, opinion2 or opinion3) is the highest and THEN looking for a neighbour.
to update-opinion
ask turtles [
let my-nearby-turtles nw:turtles-in-radius 1
let my-opinion1 opinion1
set neighbour one-of my-nearby-turtles with [ opinion1 > my-opinion1 ]
if neighbour != nobody [
let opinion_n [opinion1] of neighbour
set opinion1 ((opinion1 + opinion_n) / (2))
]
]
end
I don't know a simple way to do this with unique variables like opinion1 etc, but maybe having a list of opinions instead of individual variables for each opinion will work. For example, with this setup:
extensions [ nw ]
turtles-own [
opinions
]
to setup
ca
resize-world -5 5 -5 5
set-patch-size 30
crt 30 [
set shape "dot"
set opinions n-values 3 [ precision random-float 10 2]
set color scale-color blue sum opinions -5 35
while [ any? other turtles-here ] [
move-to one-of neighbors4
]
]
ask turtles [
create-links-with turtles-on neighbors4
]
reset-ticks
end
You get something like this:
Where each turtle has an opinions list variable that is three items long. Now, you can have each turtle determine its highest opinion value using max, get that maximum values index position in the list using position, and then query that turtle's neighbors to see if any of them have a higher value in the same index position. If they do, modify your asking turtles opinions list using replace-item to be the average of the two values:
to go
ask turtles [
; Get adjacent turtles
let my-nearby-turtles nw:turtles-in-radius 1
; Identify the highest highest value variable of
; the current turtle, and get its list position
let my-opinion max opinions
let my-op-ind position my-opinion opinions
; Pick one of the turtles whose value in the same indexed
; position is higher than my-opinion
let influence one-of my-nearby-turtles with [
item my-op-ind opinions > my-opinion
]
; If that turtle exists, update my own opinions list as appropriate
if influence != nobody [
let new-opinion precision (
( [ item my-op-ind opinions ] of influence + my-opinion ) / 2
) 2
set opinions replace-item my-op-ind opinions new-opinion
]
set color scale-color blue sum opinions -5 35
]
tick
end
Hopefully that is sort of on the right track, not sure if a list will work for what you need. If you must have the variables as standalone values at each tick, I suppose you could convert them to a list then follow the procedure above. If you only need them for output, you could just update your unique variables as needed based on the values in the list (as long as you are consistent with the order).
In my code all turtles own n-features represented by a n-tuple (a1,a2,...,an). where each ai can take values 0 or 1.
I have created some links between turtles. If two turtles share k-features (coordinate-wise matching) and there is a link between them then we call the link as k-link.
How can I find for each k (between 0 to n) how many k-links are there in total?
You don't tell us much about how you have structured your code, so I'm going to assume that your n-tuples are implemented as lists (which would make the most sense in NetLogo).
Here is a full example:
turtles-own [ a ]
links-own [ k ]
globals [ n ]
to setup
ca
set n 5
crt 10 [ ; create turtles with random feature lists
set a n-values n [ random 2 ]
]
ask turtles [ ; make a full network
create-links-with other turtles
]
ask links [ ; calculate k for all links
set k k-of-feature-lists ([a] of end1) ([a] of end2)
]
foreach n-values (n + 1) [ ? ] [ ; display number of k-links
show (word ? "-links: " count links with [ k = ? ])
]
end
to-report k-of-feature-lists [ a1 a2 ]
report length filter [?] (map = a1 a2)
end
Apart from k-of-feature-lists, this is fairly trivial code. What k-of-feature-lists does is to:
transform two lists of features into a single list of booleans containing a true value if the corresponding element is equal in both feature lists and false if it is not. This is accomplished using map and the concise task syntax for =;
filter the list of booleans to keep only the true values;
report the length of that filtered list, which is equal to the number of features that where the same in a1 and a2;
There are plenty of other ways to do that (some more efficient) but this one is nice and concise.
how can i create a dynamic number of breeds at runtime?
I want my user to be able to choose the amount of breeds.
I thought about something like
to setup_breeds
let j 1
while[j <= n_groups][
breed[j]
]
end
where n_groups is the number of breeds whick is taken from a slider.
But unfortunatly i cannot use breed inside a method...
Any ideas?
Thanks!
You need to explicitly declare each breed with the breed keyword, so the short answer is: no, you can't have a dynamic number of breeds.
But do you really need actual NetLogo breeds? The main purpose of having different breeds is to have different variables for each breed. If that is not case, perhaps you can get away with having a group-id turtle variable. To create a certain number of turtles for each of n_groups, you could just do something like:
turtles-own [ group-id ]
to setup
clear-all
let n_groups 10
let n-turtles-per-group 5
foreach n-values n_groups [ ? ] [
create-turtles 10 [ set group-id ? ]
]
ask turtles [ set label group-id ]
; do something with only turtles of, e.g., group 2:
ask turtles with [ group-id = 2 ] [
fd 5
]
end
If you think you really need breeds, edit your question to tell us why, and we'll see if we can find a solution for you.
Side note:
I used foreach n-values n_groups [ ? ] to loop through your n groups. That's the equivalent of:
let i 0
while [ i < n_groups ] [
set i i + 1
]
...but arguably more "NetLogo-ish".