find lists intersection in NetLogo - netlogo

I have a list of n lists and want to find their intersection, like:
[[1 2 3 4][0 4][4 1]]
[4]
I have found a code here to find the intersection of two lists:
to-report intersect [a b]
report (filter [ member? ? b ] a)
end
but I cannot figure out how I can extend this concept to multiple lists.

Oh! This is a very nice use case for NetLogo's under-appreciated reduce function.
Given your intersect reporter above:
print reduce intersect [[1 2 3 4][0 4][4 1]]
Will give you:
[4]
reduce applies intersect to the first and second sub-lists, and then it applies intersect to the result of that and the third sub-list, and so on for as many sub-lists as you have in your master list...

Related

NetLogo: getting randomly chosen position of a repeated value in a list

If I have the following: set list [8 1 0 3 4 2 0 1 2 4 25 0 3 3]. I would like to find a way to get, for example, a random item position for zero (2, 6 or 11) or for three (3, 12 or 13).
I have tried with:
let i (position (one-of list = 0) list )
print i
However, that only returns a boolean i. I know I could use position 0 list, but that gives priority to the first position (2, in the case of zero) while I would like it to randomly chosen from all values equal to zero on the list. I thought of using a while[], but I was wondering if there is a faster and simpler way.
In general, when you are working with lists, it is a good idea to familiarise yourself with anonymous procedures and some related primitives like map and filter.
I wrote a quick procedure, called positions that should be able to take care of this. First I create a list containing all the possible indexes: index-list.
Next, I use map to simultaneously go through the input-list and the index-list. It uses ifelse-value to check for each item of the input-list whether or not it corresponds to the input-item that you wanted to check it against. If they correspond, it returns the position of that item in the input-list. Otherwise it returns FALSE.
The final step is to filter out all the FALSE responses so that you are left with a list containing only the positions of your input-item in the input-list.
to-report positions [ input-item input-list ]
let index-list range length input-list
let position-list (map [ [list-item index] -> ifelse-value input-item = list-item [index][FALSE] ] input-list index-list)
report filter [index -> index != FALSE] position-list
end
Testing this gives [2 6 11] as a result, which corresponds with what you would expect
to test
let my-list [8 1 0 3 4 2 0 1 2 4 25 0 3 3]
show positions 0 my-list ;[2 6 11]
end

Roulette Wheel Selection in Netlogo using Agent Variables, not Constants

I hope this is a simple solution, but I'm having a difficult time with it.
Problem:
I would like to weight the probability of something occurring by an variable not a constant
Setup
My agent is a farm.
Farms own four variables that represent the
number of cows, goats, pigs, and sheep on it.
When a farm wants to
remove an animal, I'd like the likelihood to remove a member of a
particular species to be directly proportional to quantity of each
species on the farm (i.e. if there are 7 goats, 2 cows, and 1 pig,
there is a 70% probability of taking a goat and a zero percent
probability of taking a sheep)
I have found formula like this for when you know the exact numerical weight that each value will have:
to-report random-weighted [values weights]
let selector (random-float sum weights)
let running-sum 0
(foreach values weights [
set running-sum (running-sum + ?2) ; Random-Weighted Created by NickBenn
if (running-sum > selector) [
report ?1
]
])
end
and the methods described in the rnd extension. But both of these throw the "expected a constant" error when i put "Cow" in instead of a constant.
Something like:
to example1
let values ["Cow" "Sheep" "Goat" "Pig"]
let probabilities [2 0 7 1]
let indices n-values length values [ ? ] ; Made by Nicolas Payette
let index rnd:weighted-one-of indices [ item ? probabilities ]
let loca item index values
end
works well, but if I were to replace it with:
to example1
let values ["Cow" "Sheep" "Goat" "Pig"]
let probabilities [Num-Cows Num-Sheep Num-Goats Num-Pigs]
let indices n-values length values [ ? ] ; Made by Nicolas Payette
let index rnd:weighted-one-of indices [ item ? probabilities ]
let loca item index values
end
it fails.
Alan is right: you need to use the list primitive (as opposed to just brackets) when you want to construct a list from anything else than constants.
I would add two things to that:
The latest version of the rnd extension has two sets of primitives: one for agentsets, and one for lists. So you should probably update and use the rnd:weighted-one-of-list primitive.
Your code is based around using indices to pick an item. That's fine, but that's not the only way to do it.
You could also have something like:
to example1
let values ["Cow" "Sheep" "Goat" "Pig"]
let probabilities (list Num-Cows Num-Sheep Num-Goats Num-Pigs)
let loca first rnd:weighted-one-of-list (map list values probabilities) last
end
This may be a bit trickier to understand, but here is the gist of it:
The (map list values probabilities) expression takes both your values list and your probabilities list and "zips" them together using the list primitive, resulting in a list of pairs: [["Cow" 2] ["Sheep" 0] ["Goat" 7] ["Pig" 1]].
We pass the last reporter to the rnd:weighted-one-of-list primitive to tell it that the last (i.e., second) item of each of these pairs should be used as the probability.
Since rnd:weighted-one-of-list operates on a list of pairs, the item it returns will be a pair (e.g., ["Goat" 7]). We are only interested in the first item of the pair, so we extract it with the first reporter.
Note that we use the NetLogo's concise syntax for tasks when passing list as an argument to map and last as an argument to rnd:weighted-n-of. You could replace list with [ (list ?1 ?2) ] and last with [ last ? ], but it would be uglier.

limitation of forming subset in netlogo

Dear Netlogo community,
Last week I posted the question on the same forum about forming subset from a set in netlogo. Here is the link.
How to form subset form a set of numbers in Netlogo
The problem with the above thread is that it wont give the subsets if the set contains more than 21 elements. It throws java heap space out of memory exception. I believe this is because the above thread stored all subsets in one list and eventually list of list reached to its maximum range and throws java heap space out of memory exception. Any help in this regard will be valuable.
A set with N elements has 2^N subsets. Computationally, you cannot do anything with all of them once N is big, but you can still pick from them randomly. Let's assume your N elements are in a list. Then you can pick a random subset:
to-report random-subset [#lst]
let _result []
foreach #lst [
if (one-of [true false]) [
set _result lput ? _result
]
]
report _result
end
Note that this is equivalent to picking a random number in [0..(2^N-1)] and then selection the subset "corresponding" to that number.
If you prefer a more functional approach, you can use
to-report random-subset02 [#lst]
report filter (task [one-of [true false]]) #lst
end
Here is code that runs a task on every subset as soon as that subset is generated, without accumulating all of the subsets in memory:
to foreach-subset [xs fn]
foreach-subset-helper [] xs fn
end
to foreach-subset-helper [prefix xs fn]
ifelse empty? xs
[ (run fn prefix) ]
[ foreach-subset-helper prefix butfirst xs fn
foreach-subset-helper lput (first xs) prefix butfirst xs fn ]
end
Sample run:
observer> foreach-subset [1 2 3] task print
[]
[3]
[2]
[2 3]
[1]
[1 3]
[1 2]
[1 2 3]
Tasks in NetLogo are documented at http://ccl.northwestern.edu/netlogo/docs/programming.html#tasks.

NetLogo: procedure for performing an operation on one item in a list in a compact way?

New to NetLogo... wondering if there's a procedure that performs an operation on one item in a list in a compact way (like map but for one item).
For example, say I wanted to add 3 to the item at index i in list blah.
Right now I'm doing this like:
set blah replace-item i blah (item i blah + 3)
It seems a little clunky, and like there would be a procedure that does that, but I haven't been able to find one. Just wanted to make sure I wasn't missing something.
Thank you!
Taylor
There isn't something built in that does this. But you could define it yourself as a procedure that takes a task as input:
;; replace item i of xs with the result of applying fn to that item
to-report mapping-replace-item [i xs fn]
report replace-item i xs (runresult fn item i xs)
end
Sample usage:
observer> show mapping-replace-item 2 [10 20 30 40] task [? * ?]
observer: [10 20 900 40]

NetLogo : How to do multiple operations on lists (find, get , replace, remove , search elements within lists , ....)

I am new to NetLogo and I was wondering if there is a complete reference to do operations on lists, I have read most of the posts here in addition to Netlogo dictionary but for example if I need a list of pairs of numbers like
[[1 2] [2 2] [2 3] ,,, ]
when I search
member? 3 thislist
Will I have the option to say which element of inner list I am considering for the search ? for instance I will get false if it search first element and true if I search second element.
Can anybody please clarify the use of lists in Netlogo?
map, filter, reduce, foreach, n-values, and sort-by provide customizable operations on lists, using tasks. See http://ccl.northwestern.edu/netlogo/docs/programming.html#tasks.
Here's your example using map:
observer> show member? 3 map first [[1 2] [2 2] [2 3]]
observer: false
observer> show member? 3 map last [[1 2] [2 2] [2 3]]
observer: true
It appears Seth answered your initial question. To answer your follow up question on changing an item, you can use replace-item See: http://ccl.northwestern.edu/netlogo/docs/dictionary.html#listsgroup
or use map. Below is an example replacing the first item with a -99 if the second item is 3:
let aList [[1 2] [2 2] [2 3] [4 4] [5 3]]
set aList map [(list ifelse-value (item 1 ? = 3) [-99][item 0 ?] item 1 ?)] aList