Offspring Number Capping

44 views
Skip to first unread message

Olivia Johnson

unread,
Oct 26, 2021, 8:10:29 AM10/26/21
to slim-discuss
Hi everyone,

I am looking to cap offspring number. I have been utilising a fitness function from Wittmann et al (2017; https://www.pnas.org/content/114/46/E9932)  to simulate polygenic selection; however, I have been finding that this skews the distribution of relative fitness such that a small number of highly fit individuals produce most of the offspring, see minimal example below. 
I want to somehow modify how parents are sampled such that should a parent have already contributed to X number of offspring (X>=2 to fill the population), it can no longer be selected as a parent for further offspring. As the fitness of individuals is never 0, Wittmann et al do this in their simulations by changing the individual's fitness to 0 after it contributes to its Xth offspring, thereby giving individuals with smaller relative fitness a chance to contribute to the next generation. I am happy to use this method, or any other that you can suggest.

I currently simulate a WF model but can change to non-WF should that be the best way to achieve offspring number capping.

Any assistance would be greatly appreciated.

Thanks
Olivia

// Minimal example: strong polygenic selection leading to extreme per-individual offspring numbers


initialize() {

initializeSLiMOptions(keepPedigrees=T);

initializeMutationRate(0);

initializeMutationType("m1", 0.5, "f", 0.0);  // QTLs

m1.convertToSubstitution = F;

initializeGenomicElementType("g1", m1, 1);

initializeGenomicElement(g1, 0, 9);

initializeRecombinationRate(0.5);

}


1 late() {

sim.addSubpop("p0", 1000);

for (pos in 0:9){

target = sample(p0.genomes, asInteger(100));   // Add mutations at 5% frequency

target.addNewDrawnMutation(m1, asInteger(pos));

}

cat("Largest per-individual offspring count:");

}


fitness(NULL) {

phenotype = sum(c(genome1,genome2).countOfMutationsOfType(m1));

return (1+phenotype)^8;

}


1:50 late() {

catn(max(p0.lifetimeReproductiveOutput));

}



Ben Haller

unread,
Oct 26, 2021, 6:35:10 PM10/26/21
to Olivia Johnson, slim-discuss
Hi Olivia!

Well, this turned out to be much more complicated than expected!  The change needed to your model is simple; just drop this modifyChild() callback into your script:

modifyChild()

{

// disallow too many offspring from one parent

// note reproductiveOutput has already been incremented when this is called!

// so to get a maximum of 10, return F when it is already greater than 10!

if ((parent1.reproductiveOutput > 10) | (parent2.reproductiveOutput > 10))

return F;

return T;

}


The reason it was complicated is that this work exposed a bug in SLiM that I needed to fix: when a modifyChild() callback rejected a proposed child, the reproductiveOutput counters for the parents nevertheless got incremented.  That bug prevented the code above from working at all; since individuals were so often rejected as parents, their reproductiveOutput counters would spin upward like crazy – even if the offspring had been rejected because the *other* parent's reproductiveOutput value was too high.  So everybody soon got disqualified as a parent, and SLiM couldn't generate any offspring at all any more, and it would terminate after a million failed tries.

I have now fixed that bug and pushed the fix to GitHub.  So, the above code will work, but ONLY if you run it against the current GitHub head version of SLiM.  Sorry for the added complication.  Instructions for building from sources (both slim and SLiMgui) are in chapter 2 of the manual.  This bug fix will be released in SLiM 3.7, which will probably be out in a couple of weeks but no definite date has been chosen yet.

I hope this helps; happy modeling!

BY THE WAY: for anyone else reading this, I fixed another bug with reproductiveOutput as well; or at least it was arguably a bug.  When a parent generates an offspring through selfing or cloning, reproductiveOutput was incremented by *two*.  I think that was intentional, perhaps to represent the passing on of two chromosomes' worth of genetic material when you self/clone, as opposed to passing on just one chromosomes' worth when you produce an offspring through biparental mating.  However, I don't think it's the right behavior for most users, and I don't think it's likely to be what most people would expect when they hear the property name "reproductiveOutput"; most people think "how many offspring have I been the parent of?", however those offspring were generated.  So that's what the bahevior is now – selfing/cloning now increments the reproductiveOutput of the parent by 1, not 2.  This will break backward compatibility for anyone who was relying on it being 2 in this case, but my guess is very few people were using this at all since it was only added in SLiM 3.5.  If anyone has a strong objection to this change, please email me off-list to discuss it.  Thanks!

Cheers,
-B.

Benjamin C. Haller
Messer Lab
Cornell University


Olivia Johnson wrote on 10/26/21 8:10 AM:
--
SLiM forward genetic simulation: http://messerlab.org/slim/
---
You received this message because you are subscribed to the Google Groups "slim-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to slim-discuss...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/slim-discuss/32b9ab97-617c-41bf-b49b-15be1ad73ee9n%40googlegroups.com.

Ben Haller

unread,
Oct 26, 2021, 8:19:33 PM10/26/21
to slim-discuss
Hi all.  Just for the record: my decision, mentioned in my previous email, to change the way `reproductiveOutput` counts selfing and cloning (changing that from an increment of 2 to an increment of 1) has received some pushback.  It is a change that breaks backward compatibility, so caution is needed; and some argue that it is not the correct policy anyway, and that 2 was correct.  It clearly requires more thought, at a minimum.  I have backed out that change for now (while keeping the other change to `reproductiveOutput` that I mentioned – fixing the bug with it when modifyChild() rejects a proposed child).  Olivia, this latest change should not matter for you since your model does not appear to involve selfing/cloning anyway.  Again, if anyone has any thoughts regarding this change, please contact me off-list.  For now the change is backed out, and if that changes again, it will be announced when the change is published in the next version of SLiM, whenever that might happen.  Thanks, and sorry for the spam.

Cheers,
-B.

Benjamin C. Haller
Messer Lab
Cornell University


Olivia Johnson

unread,
Oct 27, 2021, 1:25:22 AM10/27/21
to slim-discuss
Thank you for this! I will download the GitHub version and give it a go!

Thanks
Olivia

Reply all
Reply to author
Forward
0 new messages