问题
In my model the turtles have two sexes where the males have two potential tactics. The females count the number of males in a set radius.
I want the females to weight their probability of selecting from the group of males (without replacement) depending on the relative frequency of the two male tactics.
I already have the code for the probability of selecting from the males (matingPoolProbAnad
and matingPoolProbRes
) but I don't know how to implement it, though the rnd
extension seems the way to go, specifically rnd:weighted-n-of size agentset [ reporter ]
.
It's complicated by three things (1) the males can mate with more than one female but (2) only once with a given female and (3) females can only mate with a maximum of five males.
to count-mates ; ask the females to count the number of males in a 10 patch radius & then
; determine the frequency of the resident males in their patch
ask turtles with [sex = "female"]
[
if any? turtles with [sex = "male"] in-radius 10
[ set potentialMates turtles with [sex = "male"] in-radius 10
ifelse any? potentialMates with [anadromousM = 1]
[ set FA count potentialMates with [anadromousM = 1] / count potentialMates ]
[ set FA 0]
ifelse any? potentialMates with [anadromousM = 0]
[ set FR count potentialMates with [anadromousM = 0] / count potentialMates ]
[ set FR 0]
]
]
end
to mating-pool-prob ; negative frequency dependency which is based on the number of male
; resident turtles
ask turtles with [sex = "female"]
[
ifelse (FA = 1) and (FR = 0)[
set matingPoolProbAnad 1
set matingPoolProbRes 0
]
[ifelse (FA > 0) and (FR < 1)
[
set matingPoolProbRes exp(a - b * (FR - c ))/(1 + exp(a - b * (FR - c)))
set matingPoolProbAnad 1 - matingPoolProbRes
]
[
set matingPoolProbAnad 0
set matingPoolProbRes 1
]
]
]
end
回答1:
This example may approach what you're getting at, but obviously would need to be adapted from this toy version. This setup sprouts 75% of males with strategy A and the rest with strategy B, and gives all turtles an empty agentset of mates to start off:
breed [ males male ]
breed [ females female ]
turtles-own [ mates ]
males-own [ strategy ]
females-own [ max-mate-count mate-count ]
to setup
ca
ask n-of 200 patches [
sprout-males 1 [
ifelse random-float 1 < 0.75 [
set strategy "A"
set color orange
] [
set strategy "B"
set color violet
]
]
]
ask n-of 50 patches with [ not any? turtles-here ] [
sprout-females 1 [
set color green
]
]
ask turtles [
set mates ( turtle-set )
]
reset-ticks
end
Use a while loop to have each female iteratively assess the strategy proportions of the males available to her, then add them to her 'mates' list. More detail in comments:
to choose-mates
ask females [
; set a cap on possible mates for females; 5, or the number
; available within the radius if less than 5
let availa-males males in-radius 10
let n-max count availa-males
set max-mate-count ifelse-value ( n-max < 5 ) [ n-max ] [ 5 ]
; Until a female has chosen up to her maximum number of mates:
while [ mate-count < max-mate-count ] [
; determine which available males are not already in her 'mates' agentset
set availa-males availa-males with [ not member? self [mates] of myself ]
; assess the proportion of B strategy in remaining available males
let prop_B ( count availa-males with [ strategy = "B" ] ) / n-max
; example probability choice, just meant to choose B males
; with a frequency disproportionate to availability
let proba_B ifelse-value ( prop_b * 2 < 0.6 ) [ prop_b * 2 ] [ 0.6 ]
; use a random float to determine which strategy type is chosen
set mates ( turtle-set mates ifelse-value ( random-float 1 < proba_B )
[ one-of availa-males with [ strategy = "B" ] ]
[ one-of availa-males with [ strategy = "A" ] ] )
; count the current mates to break the while loop once
; the maximum number of mates is reached
set mate-count count mates
]
; have the female's males add her to their own mates agentset
ask mates [
set mates ( turtle-set mates myself )
]
]
end
To check that 'B' males are being chosen disproportionately to their availability:
to check-values
let all-mates map [ i -> [strategy] of i ] [mates] of females
print word "Average proportion of 'B' mates chosen: " mean map b-proportion all-mates
print word "Actual proportion of 'B' males: " ( ( count males with [ strategy = "B" ] ) / count males )
end
to-report b-proportion [ input_list ]
let tot length input_list
let nb length filter [ i -> i = "B" ] input_list
report nb / tot
end
I'm not 100% sure that that's what you're after- maybe you can use the rnd
package to clean up the loop.
Edit in response to comment
If you modify the end of the `choose-mates like so:
...
...
; have the female's males add her to their own mates agentset
ask mates [
set mates ( turtle-set mates myself )
]
if n-max < count mates [
print "Fewer available males than mates"
]
]
end
And your go
looks like:
to go
choose-mates
end
You can run setup
and go
as many times as you like and you should never see the printout "Fewer available males than mates":
to repeat-1000
repeat 1000 [
setup
go
]
end
I ran that a few times and never had count availa-males
be less than the count of mates
. However, if you add in movement without allowing the females
to reset their mates
agentset, you do start to see it- for example, try running this a few times:
to go
choose-mates
ask turtles [ fd 1 ]
end
Now, because the turtles are moving around, you have some cases where females
held on to their mates from the previous function call and then moved into a space where there were fewer availa-males
. The quick and easy fix is to have females clear their mates each time. Where you do that depends on your model goals (how often do females choose mates? Do they only forget some of their previous ones? etc), but here's a very simple way:
to go
ask turtles [ set mates ( turtle-set ) ]
choose-mates
ask turtles [ fd 1 ]
end
Now you can run that as many times as you like and shouldn't see the "Fewer available males than mates" printout.
来源:https://stackoverflow.com/questions/50699599/how-to-select-up-to-a-maximum-number-of-turtles-using-roulette-wheel-selection