-
Notifications
You must be signed in to change notification settings - Fork 268
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Pass fitness function moran process #1198
Pass fitness function moran process #1198
Conversation
axelrod/moran.py
Outdated
def fitness_proportionate_selection(scores: List) -> int: | ||
def fitness_proportionate_selection( | ||
scores: List, fitness_function: FunctionType = None | ||
) -> int: | ||
"""Randomly selects an individual proportionally to score. | ||
|
||
Parameters |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Need to add fitness_function
to the docstring (similarly for MoranProcess.__init__
):
I suggest:
fitness_function: A function mapping a score to a (non-negative) float.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ah missed that. Fixing it
The failure is the same as on #1197:
|
This is a nice addition. Have you thought about making the transformation a property of the Moran process instead of an argument to fitness_proportionate_selection? Generally in the literature we have a payoff that is associated to a game and a total payoff vector As a point of comparison, if we were to add these transformations to the tournament class, where would they go? It feels more like a property of the tournament than the game itself -- you can imagine running the same tournament with different strengths of selection. In the same vein, we should think carefully about the names of these arguments. Applying Regardless, glad to have this in the library. I've used these a lot in my other work / libraries (see e.g. here). |
Hmm... I'm not sure it's a matter of undoing that change, since I made it in an effort to squash exactly this error (or it's reverse). It could be that I introduced some indeterminacy in #1196, but I haven't investigated yet. |
You're the expert here @marcharper and your suggestion makes sense to me. We could even do this without add anything at all and just passing a transformed game I guess? >>> R_f, P_f, S_f, T_f = some_transformation(R, P, S, T)
>>> game = axl.Game(R_f, P_f, S_f, T_f)
>>> mp = axl.MoranProcess(..., game=game...) (Similarly a user could wrap this for tournaments etc...)
Yeah 👍
If it's "simple" functional composition, does it need to be in the library at all? Perhaps just some documentation about applying a transformation to the game values? (Perhaps at the bottom of What do you reckon @marcharper? |
Yeah I noticed that @langner , strange :) I've opened #1200 and have a possible idea of a fix. @Nikoleta-v3 I suggest you wait to see first what Marc says about the overall idea and second for this to be fixed 👍 |
I think the naming choices I mentioned are ultimately the more important thing to get right for now. If we decide to refactor where the transform is applied later it's not that big of a deal. Personally it feels more like a composition to me (from a math perspective) rather than a kwarg or property of the Game (from a python perspective), but I can imagine arguments to the contrary. |
If you rebase on to master @Nikoleta-v3 this error is now fixed 👍 |
|
Fixed the type hint error 👍 |
axelrod/moran.py
Outdated
if j >= index: | ||
j += 1 | ||
else: | ||
j = fitness_proportionate_selection(scores) | ||
j = fitness_proportionate_selection( | ||
scores, fitness_function=self.fitness_function |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So this would be fitness_transformation=self.fitness_transformation
.
axelrod/moran.py
Outdated
"""Randomly selects an individual proportionally to score. | ||
|
||
Parameters | ||
---------- | ||
scores: Any sequence of real numbers | ||
fitness_function: A function mapping a score to a (non-negative) float |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Following @marcharper's suggestion can we change this to be fitness_transformation
as the variable name? Similarly in MoranProcess.__init__
and the docs 👍 :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM after fitness_function --> fitness_transformation
Thanks @Nikoleta-v3 👍 |
Using a fitness function that scales the utility for the Moran process is commonly used in the literature.
This
PR
implements that feature and now the Moran process has a new argument, thefitness_function
which is set asNone
as a default.I added a test which tests that cooperators can take over a population of defectors when the selection is weak. Also added an example in the documentations.
Please note that after chatting with @drvinceknight, I run
black
andisort
on the files(commit 4919dd2). This might make the diffs more complicated than needed, please let me know if you want me to undo that 👍 .