Netlogo: How to subset with row and column indexes - netlogo

Could someone help me out with the code on reading in data in Netlogo? I am trying to choose one element in multiple lists to assign it to the turtle as a variable (I have the data in a rectangular table read from a csv file).
In my current code, it reads as I want but the problem is it is reading only elements of one last row instead of iteratively reading elements (across columns) of all rows. What I need is to read one element of each row at a time.
here are some rows of my data
Here is what I have tried so far:
let residents-file "mock-data.csv"
let residents-list []
set residents-list csv:from-file residents-file
foreach residents-list [ ?1 ->
let hh-col ?1row
let residents-to-create 1
create-residents residents-to-create [ setxy random-xcor random-ycor ]
ask residents [
set shape "person"
set color 9
set ID item 0 hh-col
set occupancy item 1 hh-col]]

It looks like the issue is that you are using create-residents to create n residents, but then asking all residents to do something. In other words, no matter which row is currently being processed, all of the existing residents (whether created in this iteration or created in previous iterations) are being asked to pull the values from the row that is being processed on the current iteration.
The easiest way to fix this is probably just to have each resident pull the values as it's being created.
With this toy version of your dataset:
id occupancy
1 owner
2 renter
3 owner
4 renter
5 owner
Here is a simplified example:
breed [ residents resident ]
residents-own [ id occupancy ]
extensions [csv]
to setup
ca
let residents-file "mock-data.csv"
let residents-list but-first csv:from-file residents-file
foreach residents-list [ cur-row ->
create-residents 1 [
set id item 0 cur-row
set occupancy item 1 cur-row
]
]
ask residents [
print ( word "My who is " who ", my id is " id ", and my occupancy is " occupancy )
]
reset-ticks
end
Output should look something like:

Related

Netlogo, how to capture values of variables of turtles and add each turtles value, map them, and reduce them to a single #

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

Netlogo: values of same breed variables won't sum. The values are created and updated from models connected to the turtles via Levelspace

I am currently creating a Multi-level ABM using Levelspace. In the parent model I'm trying to sum the values of one variable of multiple turtles of the same breed (the number of turtles are determined by a different breeds-own variable). The variable for each turtle receives it's value from their respective child models connected via Levelspace.
Currently the parent model can receive the values from the child models. I have written a code that has a parent model turtle select particular turtles representing child models, have those selected turtles constantly update their variables totals (received from their respective child models) and display each updated total at each tick.
My problem is summing each updated child model totals into one total in the parent model that updates after each tick. Here's the code that so far:
ask turtle 0 [
if breed = Epics
[
let closteams Teams with [AsgnEpic = "Epic 1"]
foreach sort-on [who] closteams
[
the-closeteams -> ask the-closeteams [show reduce + [Value] of the-closeteams]
]
]
]
I've added a variable in the foreach block and tried to sum the totals but only received 0 as an output (see code below):
foreach sort-on [who] closteams
[
the-closeteams -> ask the-closeteams [show reduce + [Value] of the-closeteams]
let vartot sum [value] of closteams
]
Can anyone guide me on how to solve this problem?
Thanks
Rudy
----------------------------------UPDATED INFO-----------------------------------
The model has three levels consisting of several models connected by the Levelspace extension.
The top level is the parent model. The parent model is a Graphical User Interface model created with the extrawidget extension. Users enter information in this parent model to customize the model. This Graphical User Interface model sends all entered information to a second model (the first level child model) via Levelspace. The second model is where the user runs the model.
Here is the part of the setup procedure from the second model (the first child model). It creates Epics and teams (teams call their own child models (the second level child models) via Levelspace):
to setup
ls:reset
let n length TotEpics
let horizontal-interval (world-width / n)
foreach n-values n [ [i] -> i ] [ [i] ->
create-Epics 1 [
set label item i TotEpics
set color item i ColorEpics
set shape "box"
setxy (min-pxcor - 0.5 + horizontal-interval * (0.5 + who)) 15
set size 8
]
]
let o length TN1
foreach n-values o [ [i] -> i ] [ [i] ->
create-Teams 1 [
set label item i TN1
set color color
set Members item i TM1
set AsgnEpic item i Epic1
set Value []
set xcor -16
set ycor 12 + i * -7
set size 4.5
ls:create-interactive-models 1 "Problem_Solving.nlogo"
set model-id last ls:models
ls:hide model-id
]
ask Teams [
if AsgnEpic = "Epic 1" [
create-link-with epic 0
set xcor [xcor] of epic 0
set ycor [ycor - 8] of epic 0
set color blue ]
while [any? other turtles-here] [if can-move? 2 [set heading 180 fd 5 set
color blue + 2]]
if model-id = 0
[
ls:let name label
ls:let mem Members
ls:let AE AsgnEpic
ls:ask 0 [
set Number-of-Agents mem
set Epic AE
setup ]
]
if model-id = 1
[
ls:let name label
ls:let mem Members
ls:let AE AsgnEpic
ls:ask 1 [
set Number-of-Agents mem
set Epic AE
setup ]
]
;this is repeated several times with the model-id number and ask number
;increasing incrementally to accommodate multiple teams
]
reset-ticks
end
The setup procedure does not have a "clear-all" in it because "clear-all" wipes out all the information received from the Graphical User Interface parent model.
Below is the portion of the go procedure that runs the model and collects the input for the Teams "Value" variable from their respective child models:
to go
ask Teams
[
if model-id = 0 [ls:ask 0 [go] set Value lput [average-score] ls:of 0 Value
]
if model-id = 1 [ls:ask 1 [go] set Value lput [average-score] ls:of 1 Value
]
;this is repeated several times with the model-id number increasing
;incrementally to accommodate multiple teams
]
Value-of-Stories1
tick
end
So the "Value" variable of each team receives it's value from a separate Levelspace connected child models "average-score" global variable. I then sum the totals of each teams Value input every tick with the code below.
to Value-of-Stories1
ask turtle 0 [
if breed = Epics
[
let closteams Teams with [AsgnEpic = "Epic 1"]
foreach sort-on [who] closteams
[
the-closeteams -> ask the-closeteams [show reduce + [Value] of the-
closeteams]
]
]
]
end
Totaling the separate Teams "Value" totals into one number is the challenge.
There's more code then this but I believe this is the code relevant to what I'm trying to resolve.
Thanks
Rudy

Netlogo - Sum of lists of turtles

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

Read a file one line per tick

I model archaeological settlement distributions and dynamics.
I want to annually update the number of houses at the settlement sites using a .csv file similar to this one:
Settlement 1
0
1
5
...
I have two questions on that:
1) I do not succeed with the procedure as proposed in the Netlogo manual. There it reads
"to go
if file-at-end? [ stop ]
set data csv:from-row file-read-line
tick
end"
BUT csv:from-row results in an error message ("nothing named... is defined"). How do I do this?
2)
I have more than just one site. Is there a way to use only one .csv - file such as
Settlement 1,Settlement 2,Settlement 3
0,0,0
1,0,0
5,0,1
...
and make sure that Settlement 1 updates houses according to column 1, Settlement 2 according to column 2 etc?
Thank you for your help!
Til
extensions [csv]
globals [settlements-list] ;;to keep them in order
breed [settlements settlement]
settlements-own [n-houses]
to setup
file-close-all
ca
create-settlements 3 ;;3 settlements, to match your example
set settlements-list [self] of settlements ;;or sort if you wish
file-open "c:/temp/temp.csv"
let _trash file-read-line ;;discard headers
end
to go
file-open "c:/temp/temp.csv"
if file-at-end? [ stop ] ;;or at least, stop reading data!
let _data csv:from-row file-read-line ;;get data as list
foreach n-values length settlements-list [?] [
ask (item ? settlements-list) [set n-houses item ? _data]
]
ask settlements [
show n-houses
]
end

NetLogo : what is a good way for Storing link values and deducting the dead link values without calling links more than 1 time?

I am sorry to keep asking about links, but one of the features that I am going to add to my model is considering collective mutual relationship of people of different villages in village's future relationships,
I have a few thousand links and it's not efficient to call links and get their value whenever the village wants to make a decision (the decision is made every 48 ticks at clock 0)
Agents own belongs_to which is one one "Village1" Village2" Village3" or "Village4"
Links have a Value of Relationship.
This is the function I used to update links value:
to Update_link_Values [Other_Agent Value]
if self != Other_Agent
[
ifelse out-link-neighbor? Other_Agent
[
ask out-link-to Other_Agent
[
set Value-Of-The-Relationship Value-Of-The-Relationship + Value
set-List-of-Mutual-Obligations
]
]
[
create-link-to Other_Agent
[
set Value-Of-The-Relationship Value-Of-The-Relationship + Value
set-List-of-Mutual-Obligations
]
]
]
end
if I use following formula to store sum of relationship values for different villages it takes 0.003 MS to calculate all mutual relationship values
if [belongs_to] of end1 = "Village1" and [belongs_to] of end2 = "Village2"
[
set List-of-Mutual-Obligations replace-item 0 List-of-Mutual-Obligations (item 0 List-of-Mutual-Obligations + Value-Of-The-Relationship)
]
While this one takes 1.002 MS to execute,
if [belongs_to] of end1 = "Village1" and [belongs_to] of end2 = "Village2"
[
set List-of-Mutual-Obligations replace-item 0 List-of-Mutual-Obligations sum [Value-Of-The-Relationship] of links with [[Belongs_to] of end1 = "Village1" and [Belongs_to] of end2 = "Village2"]
]
my problem with first version is that it adds the value of each link to sum of all values of previous links in that group and does not consider if a link is dead or not, but second one is more accurate.
Since Value of relationship is link property I don't want to ask links more than once in the code and I update the sum values whenever a link is being changed or created.
I thought it might be better to update the values every 48 ticks , since many agents might call this function every tick, but for doing that I have to call links and I am not sure which way is better?
Update:
I have changed my code so I will calculate the links I need whenever a decision is made:
to-report Value-of-Mutual-Obligations [Village1 Village2]
report sum [Value-Of-The-Relationship] of links with [[Belongs_to] of end1 = Village1 and [Belongs_to] of end2 = Village2]
end
Another way of thinking of it.
Create a breed for the Villages.
breed [ villages village ]
Create new link breeds, one for the villages, and one for people. (you can't use the built-in links breed when you have any custom links breed):
directed-link-breed [ village-links village-link ]
directed-link-breed [ person-links person-link ]
give village-links a variable VALUE-OF-MUTUAL-OBLIGATIONS
give the villages a variable VALUE-OF-SELF-OBLIGATIONS -- this is to handle cases where both persons are from the same village -- sadly, netlogo does not allow self-links.
Create a village turtle for each village. They can be hidden. You can apply the name of the village ("Village 1") to the label of the village.
Link all the villages to each other, in both directions.
A person's belongs-to contains a village turtle.
e.g. to randomly assign a village:
set belongs-to one-of villages
So, now, rather than having to calculate the value of mutual obligations wholesale, you can alter it directly, as it changes.
Whenever you change the value of a link, you can also change the VOMO variable for the village link. You use the who numbers of the villages to figure out the link ID, or to use the SELF-OBLIGATIONS version in that special case.
to update-relationship-value [ #value ] ;; run by the person's LINK
set value-of-the-relationship value-of-the-relationship + #value
let from-village [ belongs-to ] of end1
let to-village [ belongs-to ] of end2
ifelse from-village != to-village
[ ask village-link ([who] of from-village ) ([who] of to-village)
[ set value-of-mutual-obligations value-of-mutual-obligations + #value
]
]
[ ask from-village ;; update self-obligation value
[ set value-of-self-obligations value-of-self-obligations + #value
]
]
end
So, you only touch the value of mutual obligations once, when you update the relationship value.
You could probably make this slightly more efficient by extracting the village link update code so that it's run by the turtle, not by the link, so that you don't have the extra "[stuff] of end1" stuff.