NetLogo: pair lists containing similar elements - netlogo

I wonder if anyone can help with this question for which I am a bit lost. I have turtles with three-dimensional boolean lists [a b c] where a, b, c in {0, 1}. I would like each turtle to create a link with another one who has 1 on all the same positions of the list. A turtle should thus identify where in its list it has 1 and look for another turtle that has 1 in the every same position. Where the original turtle has 0, the second one can have either 1or 0.
That is:
Turtle 1 [0 1 0]
Turtle 2 [1 1 1]
Turtle 3 [1 0 1]
Turtle 4 [0 1 1]
Turtle 1 should create links with Turtle 2 or Turtle 4 (because both have 1 on item 1, the second position) but not with Turtle 3 since it has a 0in that position. Turtle 4 should create a link with Turtle 2 only (1 in the second and third positions), as should Turtle 3 (1in the first and third position), and Turtle 2 should be unable to create links (no turtles with 1 in all three positions).
What I have is
let candidate one-of turtles with [list1 = [list1] of myself]
create-link-with candidate
Which of course doesn't work since the turtle will look for another one that has exactly the same list (including zeros) and not one that has the same positions for 1 only. I know this should be related to foreach, map, reduceand filterbut I can't quite get the syntax right...
Happy end of year to everyone

I'm sure someone who is better at lists will be able to do this with reduce or other clever tools. However, since position only gives the first position, I can't see any vectorised way to do this. So I have iterated with foreach instead.
to testme
let list1 [0 1 0]
let list2 [1 1 1]
let list3 [1 0 1]
let list4 [0 1 1]
type "check 1, 2: " print match-ones list1 list2
type "check 1, 3: " print match-ones list1 list3
type "check 1, 4: " print match-ones list1 list4
type "check 2, 1: " print match-ones list2 list1
type "check 2, 3: " print match-ones list2 list3
type "check 2, 4: " print match-ones list2 list4
type "check 3, 1: " print match-ones list3 list1
type "check 3, 2: " print match-ones list3 list2
type "check 3, 4: " print match-ones list3 list4
type "check 4, 1: " print match-ones list4 list1
type "check 4, 2: " print match-ones list4 list2
type "check 4, 3: " print match-ones list4 list3
end
to-report match-ones [#source #target]
foreach range length #source
[ x -> if item x #source = 1 and item x #target != 1
[ report false
]
]
report true
end
The reporting procedure takes the first list and simply runs through checking each item. If it's a 1 and the other list doesn't have a 1 then the procedure reports false (and ends without testing the others). If that never happens, the the procedure reports true.
The testme procedure is simply there to call the procedure and check your test data. The code is a complete model.

Here's a recursive solution:
to-report match-ones [source target]
if empty? source [ report true ]
if first source = 1 and first target != 1 [ report false]
report match-ones butfirst source butfirst target
end
and a version that uses foreach without using indexing:
to-report match-ones [source target]
(foreach source target [[?s ?t] ->
if ?s = 1 and ?t != 1 [ report false ]
])
report true
end
I think this last version is probably clearest, but it's a matter of personal preference.

Related

Cannot find item in list based on index in NetLogo

im using a sorted list in netlogos but when i run my code i get an error message that it can't find element 3 because the lenght of the list is 3, that sounds really strange and counter intuative to me. what goes wrong
globals [
allehøjder
min_højde
nedre_højde
median_højde
øvre_højde
max_højde
]
breed [personer en_person]
personer-own [højde skostørrelse]
to setup ; runs when the button "setup" is pressed
clear-all
;kom alle højder ind i højde
;sorter højde listen
;find 5 kvartil værdien ud fra højder[]
create-personer 3
[
set color white
set højde (150 + ( random ( 190 - 150 )))
set skostørrelse (38 + (random ( 47 - 38 )) )
setxy random-xcor random-ycor
set size 10
]
set allehøjder [højde] of personer
set alleskostørrelser [skostørrelse] of personer
show sort allehøjder
show sort alleskostørrelser
;sætter de 5 kvartilværdier for højde
; sætter min
set min_højde item 1 (sort allehøjder)
;sætter max
**bold** set max_højde item 3 (sort allehøjder)
; sætter median
ifelse 3 mod 2 = 0
;lige antal
[
set median_højde item ((3 + 1 / 2) ) (sort allehøjder)
]
;ulige antal
[
set median_højde ((item ((3 + 1) / 2) (sort allehøjder) + item (((3 + 1) / 2) + 1) (sort allehøjder)) / 2)
]
reset-ticks
end
regards morten
The indexing of lists' items starts from 0, hence the third element will have index 2.
The NetLogo Programming Guide and the NetLogo Dictionary linked above should have you covered with this type of problems.

NetLogo database resultlist loading problem

I am trying to get some integer values from database (almost 30.000 rows) and it gives error "error while observer running READ-FROM-STRING in procedure GET-IMAGEDB Expected a constant." I considered it may happen because of requiring waiting time to not set a null value to variable of NetLogo and added "print" lines to delay the process. It worked for small sized datasets for instance 30.000 rows. However, when the dataset size increased to 250.000 rows, now I am getting same error again. I am not sure about reason of the error. I have also tried to get all rows from the dataset with single query and set it to NetLogo list, but still gives same error and extremely slow. I have attached the code. Thank you for any help.
let total ( (width + 1) * (height + 1) )
let counter 0
while [ counter < total ]
[ set query "select x, y, r, g, b, background from colorinfo where pixelId = \""
set query (word query counter "\"" )
let resultList (mysql:executeQuery db query)
let stringList item 0 resultList
print (word "wait 1")
let x read-from-string item 0 stringList
print (word "wait 2")
let y read-from-string item 1 stringList
let r read-from-string item 2 stringList
let g read-from-string item 3 stringList
let b read-from-string item 4 stringList
let background read-from-string item 5 stringList
ask patch (x + width + 2) ( y) [ set pcolor (list r g b) ]
print counter
set counter (counter + 1)
set stringList [ ]
set resultList [ ]
]

How to replace all items meeting a given criteria in a list

I've been using this post (how to do replacing-item in use nested list) as a guide to work out how to replace items in a list, that meet a given criteria.
Specifically, I want to replace all zeros in a list with the value = 0.5. However, the code I've come up with only seems to replace the first zero in the list and I can't seem to work out why.
This is my code:
to-report A-new-list-without-zeros [old new the-list]
let A-index-list n-values length the-list [?]
( foreach A-index-list the-list
[ if ?2 = old
[ report replace-item ?1 the-list new ]
])
report the-list
end
And this is what happens:
observer> show A-new-list-without-zeros 0 0.5 [0 1 0 5 5 0]
observer: [0.5 1 0 5 5 0]
Any help would be much appreciated! Thanks
This task is more easily accomplished with map than foreach.
NetLogo 6 syntax:
to-report A-new-list-without-zeros [old new the-list]
report map [[x] -> ifelse-value (x = old) [new] [x]] the-list
end
NetLogo 5 syntax:
to-report A-new-list-without-zeros [old new the-list]
report map [ifelse-value (? = old) [new] [?]] the-list
end
Anytime you use report, it exits the procedure and reports the output at that point. The quick fix using your code is to change the report line in your if statement so that it replaces the item at the current index:
to-report A-new-list-without-zeros [old new the-list]
let A-index-list n-values length the-list [?]
( foreach A-index-list the-list
[ if ?2 = old
[ set the-list replace-item ? the-list new ]
])
report the-list
end
observer> print A-new-list-without-zeros 0 0.5 [ 0 1 0 5 5 0 ]
[0.5 1 0.5 5 5 0.5]

How make a list of cumulative sum in netlogo

How can i make a list of cumulative sum of a other list?
i tried it that way:
;;all temperatrue-values around the turtle saved in list
set temperature_values (list [(output-heat + 1)^ Freedom] of neighbors)
;;build cumulative value of temperatures and put each value in list
let tempsum 0
set tempsum_list []
foreach temperature_values
[set tempsum (tempsum + ? )
set tempsum_list fput tempsum tempsum_list
]
but it doesn't work. can anyone fix this problem? it says that "+ excepted a input but gets a list instead".
your code for a cumulative sum works (except that I think you need lput rather than fput. You can see it with this:
to test
let ll [1 2 3 4]
let tempsum 0
let tempsum_list []
foreach ll
[ set tempsum (tempsum + ? )
set tempsum_list lput tempsum tempsum_list
]
print tempsum_list
end
Did the error highlight the line set temperature_values (list [(output-heat + 1)^ Freedom] of neighbors)? Try putting a space after between ) and ^. NetLogo is picky about space around mathematical operators.
As Jen suggested, you can use foreach. Another nice approach is reduce:
to-report partial-sums [#lst]
set #lst (fput [0] #lst) ;;prepare for reduce
report butfirst reduce [lput (?2 + last ?1) ?1] #lst
end
Similar to Alan's solution (Just an update for the recent version of NetLogo that replaces ? with -> for anonymous procedures.)
to-report partial-sums [lst]
report butfirst reduce [[result-so-far next-item] -> lput (next-item + last
result-so-far) result-so-far] fput [0] lst
end
This is like Alan's solution, just abstracted a bit further. (Perhaps too far, depending on your taste! I like JenB's solution as well.)
Let's first define a thing like reduce, but that keeps all the intermediate results:
to-report scan [fn xs]
report reduce [lput (runresult fn ?2 last ?1) ?1]
(fput (list first xs) butfirst xs)
end
Now we can use it to compute partial sums:
observer> show scan task + [1 2 3 4 5]
observer: [1 3 6 10 15]
but we are also free to swap in a different operation:
observer> show scan task * [1 2 3 4 5]
observer: [1 2 6 24 120]

Nested foreach in NetLogo

I am trying to calculate the Gini coefficient of a set of numbers. The Gini coefficient is half the mean absolute difference. That is, for every possible pair of numbers in the list, I need to take their absolute difference and add these differences together (and some other stuff). This is my code
to-report calc-Gini [list-Values]
let sumdiff 0
foreach list-Values
[ foreach list-Values
[ set sumdiff sumdiff + abs ( ?1 - ?2 )
]
]
report 0.5 * sumdiff / (mean list-Values * (length list-Values) ^ 2)
end
When I test it (eg show calc-Gini (list 1 2 3)) I get an error "task expected 2 inputs, but only got 1" on the second foreach.
I think the problem is that NetLogo wants to run through the foreach loops simultaneously. So if the list length is N, then it creates only N pairs (that is, first item in list1 and first item in list2, then the second item in each list etc) which is where the requirement for equal length lists comes from. But I need it to work with the N^2 pairs obtained by crossing the lists.
How can I make the nested foreach do what I want and/or is some other primitive more appropriate?
NetLogo doesn't have a mechanism for binding ?1 and ?2 to an outer and an inner task. When it sees ?1 and ?2 in your code, it expects that both inputs will come from the inner task. And since the inner foreach only provides one input, NetLogo complains.
You can get around that problem by simply assigning the input of the outer foreach to a local variable:
to-report calc-Gini [list-Values]
let sumdiff 0
foreach list-Values
[ let v ?
foreach list-Values
[ set sumdiff sumdiff + abs ( v - ? )
]
]
report 0.5 * sumdiff / (mean list-Values * (length list-Values) ^ 2)
end
That being said, here is an alternative implementation:
to-report calc-gini [ xs ]
report 0.5 * sum map [ sum-diff ? xs ] xs / (mean xs * (length xs) ^ 2)
end
to-report sum-diff [ x xs ]
report sum map [ abs (x - ?) ] xs
end
I can't solve your nested foreach approach, but this might be an alternative way to do your calculation:
If you use ordered data, you can use this equation for the Gini coefficient (given a vector $y$ with $y_i$, $i=1,...,n$)
$$ G(y) = \frac{1}{n} (n + 1 - 2 * \frac{ \sum_{i=1}^{n} (n + 1 - i) y_{i} }{ \sum_{i=1}^{n} y_i} $$
and the following reporter should deliver the result in NetLogo:
to-report calc-Gini [list-Values]
let values sort list-Values ; making sure values are in a non-decreasing order
let n length values
let i 1
let numerator []
foreach values
[ set numerator lput ( (n + 1 - i) * ? ) numerator
set i i + 1
]
report 1 / n * ( n + 1 - 2 * (sum(numerator) / sum(values)) )
end