This is relevant to the previous question just asked.
How can I convert list(which representing turtles) to a agentset?
For example, I want to make
agentset which contains 4 elements [turtle 0 turtle 3 turtle 4 turtle 7]
out of list ["turtle 0" "turtle 3" "turtle 4" "turtle 7"]
I've tried "foreach" before.
Thank you in advance~!!
I am not sure why you would need to work with a list like
["turtle 0" "turtle 3" "turtle 4" "turtle 7"]
in the first place. Storing references to agents as anything other than direct references to the agents is usually not a good idea.
That being said, you can convert such a string to an agentset with:
turtle-set map runresult ["turtle 0" "turtle 3" "turtle 4" "turtle 7"]
If any of those turtles don't exist, they will just be excluded from the resulting agentset.
Still, the whole thing strikes me as somewhat ill advised. If you tell us more about what you're trying to accomplish, maybe we could suggest a better approach altogether.
Are you constrained for some reason to working with a list of strings? If not, but you still want a list, I'd recommend just building your lists to contain agents in the first place. If you're writing this to a file later, it will be converted to string anyway. Internally it's much easier to work with the agents directly.
To make a list of agents based on a list of numbers:
globals [ turtle-list num-list]
to setup
ca
reset-ticks
crt 3
set num-list [ 0 1 2 ]
set turtle-list map [ i -> turtle i ] num-list
print turtle-list
end
Note that if the list contains a who number for a non-existent turtle, you will get a nobody in your list.
Nevermind all this, just do what #NicolasPayette says.
Then you *can* use `foreach` to easily build your agentset for your `turtle-list`:
foreach turtle-list [
t ->
set turtle-agentset (turtle-set turtle-agentset t )
]
However, if your end goal is an agentset and you don't need a list, you can skip a step and just build the agentset directly:
to setup
ca
reset-ticks
crt 3
set num-list [ 0 1 2 ]
set turtle-agentset nobody
foreach num-list [
n ->
set turtle-agentset (turtle-set turtle-agentset turtle n )
]
print turtle-agentset
end
Related
I'm creating clusters of agents using the nw extension weak-component-clusters.
It produces a list of agentsets.
My first goal is to calculate the average xcor and ycor of each of those agentsets in the list.
I can use map to count the number of agents in each agentset, but I can't map mean [xcor]
Example:
clear-all
create-turtles 5
ask turtle 0 [ create-link-with turtle 1 ]
ask turtle 0 [ create-link-with turtle 2 ]
ask turtle 3 [ create-link-with turtle 4 ]
let clusters nw:weak-component-clusters ; create list of agentsets
; output: [(agentset, 2 turtles) (agentset, 3 turtles)]
map count clusters ; Works
;output: [2 3]
map mean [xcor] clusters ; Does not work
;output: Expected a literal value
Secondary question: I will be calculating the distance between the clusters next and I was wondering if there was an extension or function that I could use instead of just using the distance between two points formula.
The problem is in the usage of your map function. As long as you are doing a very simple calculation (like for example your counting) map function list is sufficient. But when you want to calculate your mean xcor, you will need to add some anonymous procedure syntax.
map [ list-item -> function list-item ] list
In this case, you define a variable name that will be used for all the items of the list. This variable name is on the left of the ->. On the right side of the ->, you add a function utilising that variable. This function will then be applied to every item of the initial list, as you already know from map.
In your case, that gives us:
map [a-cluster -> mean [xcor] of a-cluster] clusters
Standard netlogo has a function for calculating the distance between agents (distance) and the distance between an agent and a point (distancexy) but no function for a distance between points. That said, the mathematical formula is simple so you could easily write your own function for that using to-report
How can I update the values in a list for the indices that are equal to everyone in the selected group agents?:
persons-own [
grouped
flockmates
]
to create-trustConnection
set nrPersons count persons
set vector []
repeat nrPersons [set vector 0.4 vector]
end
to updateVector
let alonePersons (count persons with [grouped = false])
set flockmates n-of (random alonePersons) persons
ask flockmates [
foreach vector [ i ->
set item i vector 0.6
]
]
end
You can use the replace-item reporter to update an item in a list.
Let this [ 1 2 3 4 ]
Let new-list replace-item 3 this “a”
Print new-list
Note that this does not affect the original list: it reports a new list with the specified item replaced with the given value.
Changing an item in a list of lists of similar.. but again, the entire list
Of lists is created anew.
But maybe use links?
In the case of using a list for a turtle to track its relationship with other turtles, or of groups, links are useful, and simplify managing those relationships, and enable things that are very difficult with lists.
LINKS are just another kind of agent, specifically for recording a relationship between two turtles. They have a pair of built-in variables, end1 and end2 that refer to those two turtles. The -own variables of the link can be used to record properties of the relationship. Like “anniversary” or “affinity” or whatever! Links can be directional, so the “intimacy” value can be different depending on the “direction” of the relationship.
Directed-link-breed [ relationships relationship]
Relationships-own [ intimacy ]
to setup-all-relationships
Ask protestors
[ setup-relationship ]
End
To setup-relationship
;; link with everyone else
Create-relationships-to other protestor
[ set intimacy .5 ]
End
The relationship between two turtles can be obtained in several ways.
(Link (this turtle) (that turtle))
Refers to the link from this turtle to that turtle.
Out-Link-neighbors is used to get the set of all turtles linked to from this turtle.
You can also use turtles to represent groups, and links to record membership in that group.
In that case, the members of the group are link-neighbors of the group.
While perhaps not a feature of your model, this opens up the possibility of multiple groups and of agents being members of more than one group, or of tracking things like former members.
Here is a complete, minimal reproducible example of what I think you are looking for. Note that one can just paste it into NetLogo and it compiles and runs. I've made some assumptions here - in particular that intimacy is a protesters-own variable, which it was not in the code you provided, but which your textual description seemed to indicate. Again, using who numbers is not a good idea, but that is a different question and answer. If I have time tomorrow, I might be able to provide you with an example of how one might use agentsets, but if intimacy values can vary from agent-pair to agent-pair, then links is really the way to go.
breed [protesters protester]
globals [numberOfProtesters intimacyVector]
protesters-own [
intimacy
partOfGroup ;initially set to false for all agents
myNRelatedProtesters
]
to setup
clear-all
create-protesters 10
create-intimacyRelationship
reset-ticks
end
to create-intimacyRelationship
ask protesters [
set numberOfProtesters count protesters
set intimacy []
repeat numberOfProtesters [set intimacy lput 0.2 intimacy]
set partOfGroup false
]
end
to updateIntimacy
let nrUngroupedProtesters (count protesters with [partOfGroup = false])
let NRelatedProtesters n-of (random nrUngroupedProtesters) protesters
ask NRelatedProtesters [
foreach ([who] of NRelatedProtesters) [ i -> set intimacy replace-item i intimacy 0.8 ]
set partOfGroup true
]
ask NRelatedProtesters [ show intimacy ]
end
to go
let ProportionProtestersInSubgroup (count protesters with [partOfGroup = true])/ numberOfProtesters
ifelse ((count protesters with [partOfGroup = false])/
numberOfProtesters) > ProportionProtestersInSubgroup
[
updateIntimacy
]
[
stop
]
tick
end
Hope this gets you started.
I want to store values from a variable in a list, adding new variable output for every tick. Lets say the variable outputs a different value every tick. For simplicity this is determined by the formula; 2 * ticks (var = 2 * ticks), thus the list should look something like this after five ticks [0 2 4 6 8]. I cannot get this to work however. Since NetLogo does not allow taking values from the past, how would I go about this?
I now have something like this:
ask turtles[
let var_list [ ]
foreach var_list [
set var_list lput var var_list
]
print var_list
]
This however only gives empty lists or lists only showing the most recent var value (when I change let var_list [] to let var_list [ 0 ]. How can I get it to correctly input the variable value in the table for every tick?
You are using let to create a temporary local variables. There's no problem in retaining values across ticks, but you do need to use global or turtle/patch/link variables.
Here's a complete model to demonstrate
turtles-own [my-list]
to setup
clear-all
create-turtles 1
[ set my-list []
]
reset-ticks
end
to go
ask turtles
[ set my-list fput random 10 my-list
print my-list
]
tick
end
Every time an agent gets a new value for some action they're performing, I want them to add it to the end of a list. If the list has ten or more items on it, I want them to remove the first item on the list, so that the list has the ten most recent values an agent has seen, in order. How might I do that? (Edit: forgot to ask an actual question.)
I want to be able to apply mathematical operations to each item on the list, so I don't want a list of cons cell-like lists, unless there's some easy way to apply mathematical operations to each item in such a list that I don't know about.
Let's build a simple example, where each turtle makes a slight right turn at a random angle at every tick, and stores the history of these angles in a list:
turtles-own [ history ]
to setup
clear-all
create-turtles 3 [
set history [] ; initialize history to an empty list
]
reset-ticks
end
to go
ask turtles [
let angle random 5
right angle
; add the angle of the most recent turn
; at the end of the list
set history lput angle history
if length history > 10 [
; remove the first item from the list
set history but-first history
]
forward 0.1
]
tick
end
I don't want a list of cons cell-like lists, unless there's some easy way to apply mathematical operations to each item in such a list that I don't know about.
I don't know what you mean by "a list of cons cell-like lists", but a simple list like the one we built here is by far the best thing you can use if you want to do math.
To apply an operation to each item, use map. And then you can use functions like sum or mean to operate on the whole list. For example:
to do-math
ask turtles [
let doubled-history map [ a -> a * 2 ] history
show history
show doubled-history
show mean doubled-history
]
end
(Note that this uses NetLogo 6.0.1 syntax.)
Let's see a demonstration:
observer> setup repeat 5 [ go ] do-math
(turtle 2): [4 3 2 1 2]
(turtle 2): [8 6 4 2 4]
(turtle 2): 4.8
(turtle 1): [4 0 1 1 4]
(turtle 1): [8 0 2 2 8]
(turtle 1): 4
(turtle 0): [2 0 4 1 0]
(turtle 0): [4 0 8 2 0]
(turtle 0): 2.8
I have to do some operations in netlogo using Lists. While i can do simple tasks with them i am not yet proficient enough to code my current requirements.
I have a scenario where turtles have variables called Current-Age and Previous-Age. And turtles can be born and die if they don't meet a certain threshold.
I want to implement the following formula for each patch.
Best-list = (-1/Previous-Age) * (Distance between Patch & Turtle) for all the turtles
Best = Min [ Best-list]
I know the steps involved but have been unsuccessful in coding them. Following are the steps:
Create a list with all the current turtles that are alive
Create a second list which contains the Previous-Age
Create a third list with the distance between an individual patch and each of the live turtles
Then create another list with the output from the the Best-List formula for all the turtles in the list
Finally find the Min value in the list and store the name/who# of turtle with the minimum value in a separate variable called Best-Turtle
This is the code that i tried but didn't work.
set turtle-list (list turtles)
set turtle-age-list n-values length(turtle-list) [0]
set turtle-patch-dist-list n-values length(turtle-list) [0]
set best-list n-values length(turtle-list) [0]
ask patches[
foreach turtle-list(
set turtle-age-list replace-item ?1 turtle-age-list Previous-Age of turtles with [turtle= ?1]
)
]
I couldn't proceed to the next steps since the above code itself was not correct.
Would appreciate help with the code, thanks in advance.
Regards
First, lists are probably not the simplest way to do this. However, if you must use lists for some reason, I think what you're asking for is possible. I'm not exactly sure what you mean with best- are you trying to have each patch assess which turtle is the best turtle for that patch, and store that variable in a global list? I'm going to assume that's what you mean, but if I'm misunderstanding I think you can adapt what I do here to what you need.
First, any list passed to foreach must be the same length. So, since you mean to do this per-patch, make sure that every patch calls the procedure of list creation, not just for checking the lists. Next, review the dictionary for n-values- the syntax for the reporter means you need to use the reporter you're trying to receive- using n-values length(turtle-list) [0] will just give you a list of zeroes that is the same length as the number of turtles.
So each patch needs to create these lists- make sure you either define the patches-own for the list variables, or just use let to define the lists inside the procedure. You would need a list of ordered turtles, their previous ages, and the distance from the patch calling the procedure to each turtle. Next, you can create a list that generates a value according to your formula. Then, you can use the position primitive to find the location of the minimum value in your formula-generated list and use that to index the turtle with that value.
It might look something like
to numerical
set best-turtle []
ask patches [
let turtle-list (sort turtles) ;;; list of sorted turtles
let turtle-prev-age-list n-values length(turtle-list) [ [i] -> [pre_age] of turtle i ] ;;; list of previous ages of turtles, in same order as above
let turtle-patch-dist n-values length(turtle-list) [ [i] -> distance turtle i ] ;;; list of distance from this patch to each turtle, in same order
set best-list n-values length(turtle-list) [ [i] -> ( ( -1 / ( item i turtle-prev-age-list ) ) * ( item i turtle-patch-dist ) ) ] ;;; list of calculated values for each turtle
let best-position position (min best-list) best-list ;;; gets the index of minimum value
set best-turtle lput item best-position turtle-list best-turtle ;;; adds the best turtle for this patch to the global list of best turtles
]
end
The above procedure assumes that your turtles have a pre_age variable, patches have a best-list variable, and the list of each patches 'best turtle' is held in the global variable best-turtle. From there, you can use foreach to ask turtles in the list to do something. Note that if a turtle's previous age is 0, you will get a divide by zero error.
turtles-own [age previous-age]
to-report evalfrom [_patch]
report (- distance _patch) / previous-age
end
to test
ca
crt 25 [
set age (10 + random 75)
set previous-age age - random 10
]
print min-one-of turtles [evalfrom (patch 0 0)]
end