simoncarrignon / mixed-transmission

GNU General Public License v3.0
1 stars 0 forks source link

Add in in-law transmission #14

Open ercrema opened 10 months ago

ercrema commented 10 months ago

https://github.com/simoncarrignon/mixed-transmission/blob/b0517951f5e6e6154d9c625f1d41ef75cc92cb20/R/modelVector.R#L43

Add 'in-law' transmission and remove it from social learning module

ercrema commented 10 months ago

@simoncarrignon I think it's a bit more complicated as the in-law transmission is a function of the post-marital residence. First it has no meaning in a neolocal context, and second it shouldn't happen for the individual who is staying the same community (e.g. in a matrilocal setting the male partner would never have chance to engage with the in-laws).

In practical terms it would be useful to define who is the individual relocating. I see the following line is the change in the residence:

https://github.com/simoncarrignon/mixed-transmission/blob/b0517951f5e6e6154d9c625f1d41ef75cc92cb20/R/modelVector.R#L72

where jc is determined by rho:

https://github.com/simoncarrignon/mixed-transmission/blob/b0517951f5e6e6154d9c625f1d41ef75cc92cb20/R/modelVector.R#L61-L68

So I assume we could:

remove: https://github.com/simoncarrignon/mixed-transmission/blob/b0517951f5e6e6154d9c625f1d41ef75cc92cb20/R/modelVector.R#L43

and then have between lines 71 and 72 something like:

learner = c(c1,c2) [which(population[c(c1,c2),"community"]!=jc]
teacher.offspring = c(c1,c2) [which(population[c(c1,c2),"community"]==jc]
inlaw.father = which(population[,'fid']==teacher.offspring[,'fid'] & population[,'sex']==0)
inlaw.mother = which(population[,'fid']==teacher.offspring[,'fid'] & population[,'sex']==1)
for (i in 1:length(tp$s)) # for each trait
{
     if (tp$post[k,'i']==1)
        { 
            if (tp$s[i]==0) # learn from father in-law
               {
                  population[learner,paste0('t',i)] = population[inlaw.father,paste0('t',i)]
               }
            if (tp$s[i]==1) # lear from mother in-law
              {
                 population[learner,paste0('t',i)] = population[inlaw.mother,paste0('t',i)]
               }
            if (tp$s[i]==-1) # lear from one of the in-laws
               {
                  population[learner,paste0('t',i)] = population[sample(c(inlaw.mother,inlaw.father),size=1),paste0('t',i)]
               }
        }
}

And then add back population[c(c1,c2),"fid"]=maxcid #Family Id, to track kids afterwards?

simoncarrignon commented 10 months ago

A few things: 1.

inlaw.father = which(population[,'fid']==teacher.offspring[,'fid'] & population[,'sex']==0)
inlaw.mother = which(population[,'fid']==teacher.offspring[,'fid'] & population[,'sex']==1)

should be :

inlaw.father = which(population[,'cid']==teacher.offspring[,'fid'] & population[,'sex']==0)
inlaw.mother = which(population[,'cid']==teacher.offspring[,'fid'] & population[,'sex']==1)

right?

  1. I thought that tp$s was between 0 and 1 and was the probability to select trait from the mother ; thus 1-tp$s the probability to select traits from the father ; here you have -1 for random 0 father & 1 mother. advantage of have 0 and 1 is that you can use ifelse as I did here:

    https://github.com/simoncarrignon/mixed-transmission/blob/b0517951f5e6e6154d9c625f1d41ef75cc92cb20/R/socialLearning.R#L12C1-L18C2

but I realise while writing that that your method avoid useless use of random generation when bias is only mother in laws/father in laws ... which is way more efficient at the end. And if we don't plan to explore other bias (which I think we should not) then l think we should stick to your implement.

  1. In fact I am not sure we even need to change the 'fid' of the parents after the social learning. I think it could stay the same and can be use to track the great parents too. If inlaws social learning happens during marriage and we have previous situation simplified as :
teacher.offspring #the parents who stays
incomingpartner #the parents leaving the community  
inlaws= population[,population[,"cid"]==stayingparter[,"fid" ]]   
population[c(stayingpartner,incomingpartner),"cid"] = newcid #could be before or after doesn't mater

then it doesn't matter if the new couple get a new fid after that or not. When they get kids, the kids got the cid of the couple as fid and if one of the kid get married to someone moving in, we will use population[kids[,"fid"] == population[,"cid"],] to find back the parents so population[c(stayingpartner,incomingpartner),"fid"] don't really mater and can be still their original family id.

  1. Now I am a bit more worried about about the migration during marriage ; I never check that married people where from 2 different communities... But will discuss that in #8
ercrema commented 10 months ago

A few things: 1.

inlaw.father = which(population[,'fid']==teacher.offspring[,'fid'] & population[,'sex']==0) inlaw.mother = which(population[,'fid']==teacher.offspring[,'fid'] & population[,'sex']==1) should be :

inlaw.father = which(population[,'cid']==teacher.offspring[,'fid'] & population[,'sex']==0) inlaw.mother = which(population[,'cid']==teacher.offspring[,'fid'] & population[,'sex']==1) right?

Is it? My understanding is that nuclear family share the same fid, so you in order to get the parents of your partner you need to find individuals with the same fid, not cid?

I thought that tp$s was between 0 and 1 and was the probability to select trait from the mother ; thus 1-tp$s the probability to select traits from the father ; here you have -1 for random 0 father & 1 mother. advantage of have 0 and 1 is that you can use ifelse as I did here:

Ah yes my mistake, don't know why I changed it to some sort of character state. But this is a easy fix (I need to change this for the social learning module too)

In fact I am not sure we even need to change the 'fid' of the parents after the social learning. I think it could stay the same and can be use to track the great parents too. If inlaws social learning happens during marriage and we have previous situation simplified as : teacher.offspring #the parents who stays incomingpartner #the parents leaving the community
inlaws= population[,population[,"cid"]==stayingparter[,"fid" ]]
population[c(stayingpartner,incomingpartner),"cid"] = newcid #could be before or after doesn't mater then it doesn't matter if the new couple get a new fid after that or not. When they get kids, the kids got the cid of the couple as fid and if one of the kid get married to someone moving in, we will use population[kids[,"fid"] == population[,"cid"],] to find back the parents so population[c(stayingpartner,incomingpartner),"fid"] don't really mater and can be still their original family id.

Ok I am a bit confused now. Do you mean parents as in-laws or parents as the couple? teacher.offspring should be the partner that is not moving and the one from which the in-laws are identified. My understanding is that any new couple gets their own unique cid and their fid before reproduction refers to their parents (as part of the nuclear family) but after reproduction it becomes equal to their cid and their offspring inherits this value as fid. So before reproduction you can still track and identify someone's parent but after reproduction this connection is lost

simoncarrignon commented 10 months ago

Yeah so what I am saying is that cid should uniquely identify a couple ; then fid could/should identify only the children of this couple. We don't need the fid of the couple to match the fid of the childs.

Thus, at any given point in time, a nuclear family is given by all the individuals with the same fid --those are all the children, + the two individuals with the same cid, which match the fid of the childrens, those are the parents.

if we have:

p1 and p2 get married and got a new cid, 8 then:

Later on in time they have two kids

Later on k1 get married to a who move in k1,k2,p1,p2 communitys ; and a need to learn from one of k1's parents. we get those by doing:

k1.parents = population[population[,"cid"] == k1[,"fid"],]
a[,"traits"] = sociallearning(k1.parents)

in this case k1.parents should contain only p1 and p2 an noone else. What I say is that I think that we don't have to change p1 and p2 fid's. If don't change them we could even gets k1.greatparents doing:

k1.greatparents = population[ population[,"cid"] %in% k1.greatparents[,"fid"],]

Everything stays the same but we don't do:

population[c(c1,c2),"fid"]=maxcid
simoncarrignon commented 9 months ago

Looking a bit at the code for social learning and for in-law learning, I just wanted to draft what/how i had it in mind. I have the feeling that it may simplify your socialLearning function and avoid the cases where there is no traits to learn ; but this imply coming back to the bias being $s\in[0,1]$. This:

learner = c(c1,c2)[which(population[c(c1,c2),"community"]!=jc)]
teacher.offspring = c(c1,c2)[which(population[c(c1,c2),"community"]==jc)]
inlaw.father = which(population[,'cid']==population[teacher.offspring,'fid'] & population[,'sex']==0)
inlaw.mother = which(population[,'cid']==population[teacher.offspring,'fid'] & population[,'sex']==1)
for (i in 1:length(tp$s)) # for each trait
{
    if (tp$post[i,'i']==1)
    { 
        if (tp$s[i]==0) # learn from father in-law
        {
            population[learner,paste0('t',i)] = population[inlaw.father,paste0('t',i)]
        }
        if (tp$s[i]==1) # lear from mother in-law
        {
            population[learner,paste0('t',i)] = population[inlaw.mother,paste0('t',i)]
        }
        if (tp$s[i]==-1) # lear from one of the in-laws
        {
            population[learner,paste0('t',i)] = population[sample(c(inlaw.mother,inlaw.father),size=1),paste0('t',i)]
        }
    }
}

Would then be:

learner = c(c1,c2)[which(population[c(c1,c2),"community"]!=jc)]
teacher.offspring = c(c1,c2)[which(population[c(c1,c2),"community"]==jc)]
inlaw.father = which(population[,'cid']==population[teacher.offspring,'fid'] & population[,'sex']==0)
inlaw.mother = which(population[,'cid']==population[teacher.offspring,'fid'] & population[,'sex']==1)
inlawtraits=traitsid[tp$post[,"i"]==1]
if(length(inlawtraits)>0){
    fathertraits=population[inlaw.father,inlawtraits]
    mothertraits=population[inlaw.mother,inlawtraits]
    population[learner,inlawtraits]=sexbiascopy(fathertraits,mothertraits,tp$s[tp$post[,"i"]==1])
}

I put it here also as a not for myself if at some point I want to compare and try different approaches.

simoncarrignon commented 9 months ago

new code for inlaw transmission using drawFromPool here :https://github.com/simoncarrignon/mixed-transmission/blob/fc836d2e616624e386dc489a430df76121eaa585/R/modelVector.R#L88-L100

need to put in in socialLearning.R maybe directly in social.learning?

Also still problem when one or zero parents ; cf issue #26 and discussion #25.