rnd:weighted-one-of-list work doesn't return the distribution I think it should - netlogo

I trying to use the rnd extension's function weighted-one-of-list.
My list looks like
observer>show female-yr-run-stats
observer: [[117 0.001169] [118 0.002684] [119 0.004697] [120 0.003368] [121 0.004871] [122 0.018738] [123 0.034986] [124 0.070616] [125 0.035608] [126 0.012939] [127 0.011883] [128 0.016594] [129 0.068837] [130 0.044391] [131 0.028422] [132 0.053251] [133 0.023741] [134 0.042111] [135 0.035811] [136 0.022447] [137 0.031563] [138 0.024253] [139 0.030213] [140 0.024372] [141 0.033266] [142 0.059869] [143 0.028711] [144 0.030863] [145 0.04043] [146 0.008819] [147 0.012308] [148 0.008638] [149 0.021345] [150 0.016176] [151 0.009815] [152 0.017242] [153 0.014362] [154 0.010717] [155 0.015868] [156 0.003865] [157 0.008441] [158 0.004358] [159 0.003113] [160 0.002464] [161 0.001768]]
The first item is day-of-the-year and the second is the probability (all sum to one).
I am using the code
repeat 50000[
let tempo first rnd:weighted-one-of-list female-yr-run-stats [ [p] -> last p ]
file-open "C://temp//check_wgt_random.csv"
file-print (word tempo)
file-close
]
to randomly select a day-of-the-year 50000 times to check that the rnd:weighted-one-of-list function is doing what I want it to do. From the results, I get a distribution of day-of-the-year. But when I compare the resulting distribution to the original probability distribution, they are quite different.
I am thinking that the rnd:weighted-one-of-list with my list would be equivalent to randomly drawing from a multinomial distribution like R's rmultinom function. Am I correct? Am I doing something wrong?
Any help would be appreciated.
The graph below shows the comparisons

The rnd:weighted-one-of-list primitive works the way (I think) you think it works. From your data, it draws the value 112 with probability 3.04E-4, value 113 with probability 0.001236 etc. The probabilities don't have to add to 1 (I have assumed that you are correct that yours do). I can't see anything wrong with your use of this primitive for your draws.
But I am not sure about the file construction. You have the file-open and file-close inside the repeat so the file is opened, the new data is appended, the file is closed. It is not clear whether you ever clear the dataset. So perhaps the problem is that you have some data left over from when you were building your code. Do you get the same problem if you clear out all the old data and start again?

Sorry to waste your time. I discovered what happened. I had two probabilities stream mixed up.

Related

Get a count of turtles with a combination of values

I am trying to count the number of "buyer" type turtles, which have a certain surplus (turtle variable) greater than or equal to zero, and price (another turtle variable) greater than the current turtle's price (already grabbed in local variable myprice...although there may be a more direct way to put it in)
let countup count buyers with ([surplus >= 0] and [price > myprice])
NetLogo returns
Expected a TRUE/FALSE here, rather than a list or block.
let countup count buyers with (surplus >= 0 and price > myprice) returns
WITH expected this input to be a TRUE/FALSE block, but got a TRUE/FALSE instead
Close! You're looking for:
let countput count buyers with [ surplus >= 0 and price > myprice ]
with is a report that takes two arguments, like so
<turtleset> with <report block>
where the reporter block is a clump of code surrounded by [ ] that will result in either true or false. In general [ ] is netlogo's way of grouping together code so you can doing something special with it, such as having each agent in an agentset run it. Hope that helps!
Also, I assume you've got something like let myprice price on, say, the line above this one. You can combine those lines like so (not saying this code is the right way to do it, just wanted to show another option):
let countput count buyers with [ surplus >= 0 and price > [ price ] of myself ]
Checkout the docs for (the very poorly named) myself.

Netlogo: How to compute sum of items of lists within a list?

I would like to make the sum = the total of pollen recieved by a plant from other plants (Donnors) which is stored in a list of a list (own by each turtle = plant).
The following code make an error (when computing the sum):
OF expected input to be an agent or agentset but got the list
[[119.05593 50 50] [301.25853 50 50] [30.23906 50 50] [460.525845 50
50] [55.16717 50 50] [301.25853 50 50]] instead.
Does any one could help me about the mistake in the line "set Tot_pol sum ..." ?
Many thanks for your help.
to check-pol [m] ;; we check the pollen recieved by the two morphs
set Donnors [] ;; empty list of pollen donnors
ask zsps with [morph = m] ;; morph of the pollen reciever
[
set totpol 0
;; check for pollen donnors and morph for compatiblity within a radius :
ask zsps with[distance myself <= 20 and morph != m]
[
set totpol (NMaleFlowers * 100 * item round (distance myself) pollination-list) ;; the farther the less pollen
set Donnors lput [ (list totpol NMaleFlowers NFemFlowers)] of myself Donnors
]
set Tot_pol sum [ item (position 0 Donnors) Donnors ] of Donnors ;; total of pollen recieved
]
end
Luke's answer is good and should fix your problem. I suspect, however, that you are going to be doing lots of these types of sums. You may wish to set up a to-report that you can use for whichever item you want to sum over, just by passing the item number and the name of the list of lists. It would look like this:
to-report sum-item [#pos #listoflists ]
let items map [ x -> item #pos x ] #listoflists
report reduce [ [a b] -> a + b] items
end
The first line extracts the relevant item (remember index from 0) into a new list which the second line sums.
You would then use it with set Tot_pol sum-item 0 Donnors
Here's an answer that is not actually responding to your question. Instead, it is a more NetLogo-ish way of doing what I think you are trying to do with your code.
to check-pol [m]
ask zsps with [morph = m]
[ let senders zsps with [distance myself <= 20 and morph != m]
set totpol sum [NMaleFlowers * 100 * round (distance myself)] of senders
]
end
Your code gets into levels of ask that I think are unnecessary. What I think you are doing with your list is keeping track of the pollen donors. But an agentset is a cleaner approach and then you can simply pull out the information you want from the agentset using of.
Further, when you ask zsps with[distance myself <= 20 and morph != m] to set variable values in your code, then THOSE agents (not the receiving agent) are the ones having their variables changed. I think you are trying to take the perspective of the receiver of pollen, who looks around and received pollen from the other agents that are close enough. So the receiving agent should have the value changed.
This is not tested.
I'm not 100% sure what you're after here (you may want to look at the Minimum, Complete, and Verifiable Example guidelines), but if I'm reading you right you want the sum of the first item for each entry in the Donners list.
As to why your approach didn't work- NetLogo is telling you with that error that you've used of with a list, but of only works with agents or agentsets. Instead, you have to use a list processing approach. The simplest way might be to use sum in conjunction with map first in order to get what you need:
to sum-first-item
let example-list [ [ 1 2 3 ] [ 4 5 6 ] [ 7 8 9 ] ]
let sum-of-firsts sum map first example-list
print sum-of-firsts
end
To translate to Donnors, try:
set Tot_pol sum map first Donnors
That should work, but without reproducible a code example I can't check.

How to compare two turtles in Netlogo by going through a list of their attributes?

My turtles have more than 30 attributes of boolean values and I would like to use a foreach loop to compare turtles and rank them based on their similarity without the need to compare each attribute individually. I might be missing an obvious point here, I have tried having a list of attributes, but it didn't work and all turtles got the maximum similarity score.
Here's some code that calculates the Hamming distance between two lists. Note that the very clever reduce code is taken directly from the NetLogo dictionary.
to testme
let ll1 (list TRUE TRUE FALSE FALSE)
let ll2 (list TRUE FALSE TRUE FALSE)
let ll3 ( map = ll2 ll1 )
show ll3
show reduce [ [occurrence-count next-item] ->
ifelse-value (next-item) [occurrence-count + 1] [occurrence-count] ] (fput 0 ll3)
end
If you were wanting to calculate the similarity score of a pair of turtles, you could turn this into a reporter that takes the two turtles as arguments. But it's not clear that comparing two turtles is what you want to do, so I haven't written code for that.

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.

netlogo: send message to all but one agent

I'm new at NetLogo. I'm not new at agent-based modeling. Now and then I see people saying NetLogo is so fun and easy that I'm giving it a try.
I'm stuck at square 1, can't figure out code for messaging between agents, scheduling actions for subsets of agents, other basic ABM things.
I'm working on a majority rule election model in which the turtles are voters with randomly placed x,y coordinates. Candidates (a new breed) make promises in x,y plane, the winning candidate is the one preferred by (closer to) more agents.
The patches play no role at all, except the spatial graph seems to require use of a grid
I'm having trouble in the updating of candidate positions. I conceived this as follows: Remove a 'winner' agent from the candidate agentset, tell the other candidates to adjust, then put the winner back in the agent list and see who wins in the next time.
I believe the following is close to minimum reproducible example. Please look at adjustOfferings. (Sorry, I left in a lot of show statements, otherwise can't tell what's going on.)
; Paul Johnson
; 20160801
breed [candidates candidate]
globals[
N
D
]
; turtles are voters, Euclidean-based preferences. Use
; built-in 2d coordinates for ideal points for now,
; need to learn how to create weighted multi-dimensional
; preferences later
turtles-own
[
name
]
to setup
ca ; clear all
reset-ticks ; time start 0
set N 100
; N voters with random x,y ideal points
create-turtles N
[
setxy random-xcor random-ycor
]
set D 2
create-candidates D
[
setxy random-xcor random-ycor
set shape "square"
set size 2
]
end
; collect up the votes. Don't worry about invading agent
; privacy, just measure for them
to-report election2 [choices]
let fave [min-one-of choices [distance myself]] of turtles
report fave
end
; Ask all non winners to adjust their offering
to adjustOfferings [winner]
show (word "in adjustOfferings, winner was: " winner)
let losers candidates with [self != winner]
show (word "adjustOfferings losers are: " losers)
ask losers
[
setxy random-xcor random-ycor
]
end
; ask each voter for its favorite,
; use modes to calculate the winner
to electionCycle
let theVotes election2 candidates
show (word "electionCycle: " theVotes)
let winner modes theVotes
show (word "electionCycle Winner: " winner)
adjustOfferings winner
end
to go
tick
if ticks > 1000
[
stop
]
electionCycle
end
The setup works fine, I see agents and candidates. When I hit the "Step button", I can see the election works, a winner is selected, but all candidates adjust (not just losers). Here's the console:
observer: "electionCycle: [(candidate 100) (candidate 101)
(candidate 101) (candidate 101) (candidate 100) (candidate 101)
[snip]
(candidate 100) (candidate 101)]"
observer: "electionCycle Winner: [(candidate 100)]"
observer: "in adjustOfferings, winner was: [(candidate 100)]"
observer: "adjustOfferings losers are: (agentset, 2 turtles)"
Appears to me this is the source of error:
let losers candidates with [self != winner]
The winner is still in losers after that.
I realize now you can't actually run this without the rest of the NetLogo file. What is your custom here for providing the fully runable example? Can I point you at a file on a website? http://pj.freefaculty.org/scraps/majority.nlogo. I could put this in GitHub or someplace else if you prefer.
I appreciate your advice.
The problem is indeed with the line you suggested. Both agents report true for the condition [self != winner], but why is it the case. Look at how you create and pass the winner variable to the function. You create it by using the modes primitive, which is a good idea. But modes will report you a list with one element. The problem is that you pass this list directly to your adjustofferings function. This means, the agents than compare [self != [(candidatexy)]]instead of [self != (candidatexy)] (mind the additional brackets in the first example, indicating the list).
To solve the problem, you have to extract the winner agent from the list by using the first primitive, which reports you the first item of a list. You only have to add this to the line, where you define the winnervariable: let winner first modes theVotes