Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Combiner signature #78

Closed
wants to merge 1 commit into from
Closed

Combiner signature #78

wants to merge 1 commit into from

Conversation

rogiervandergeer
Copy link
Collaborator

@rogiervandergeer rogiervandergeer commented Mar 23, 2018

The combiner signature has been changed to combine(*parents, **kwargs)
to combine(parents, **kwargs). This was done mainly to prevent users accidentally passing too many parents. E.g., if one has a combiner function like:

def combiner(mom, dad, x=1, y=0):
    return (mom+dad)/x + y

and one passes three parents and no kwargs the function is called as combiner(*parents), which results in the third parent ending up as x. This only throws an error when x is also passed (and #76 is solved). Passing all parents as a sequence to a single argument solves this problem.

@rogiervandergeer
Copy link
Collaborator Author

@koaning can you check if the error messages you get with the new signature are any better?

@koaning
Copy link
Contributor

koaning commented Mar 28, 2018

import random 
from evol import Population, Evolution

pop = Population([i for i in range(100)], lambda x:x)
evo = (Evolution()
      .survive(n=4)
      .breed(parent_picker=lambda x: [random.choice(x)],
             combiner=lambda parents: (parents[0]+parents[1])/2))

pop.evolve(evo, n=10)

Results in

IndexError: tuple index out of range

Am thinking about what might be a nice change for offspring_generator in order to facilitate errors like this.

@koaning
Copy link
Contributor

koaning commented Mar 28, 2018

I mean ... we could do a try/catch here such that we can return a very descriptive error message. Something like

Something went wrong in the breed step. This is most likely due to the parent_picker that is passed does not have the number of parents picked that is required by the combiner. The parent_picker selected <X> parents when the error happened.

It feels like it might be a nice thing to do. When we resolve this we also need to re-generate the documentation.

@@ -101,23 +101,23 @@ class TestPopulationBreed:
def test_breed_amount_works(self, simple_chromosomes, simple_evaluation_function):
pop1 = Population(chromosomes=simple_chromosomes, eval_function=simple_evaluation_function)
pop1.survive(n=50).breed(parent_picker=lambda population: choices(population, k=2),
combiner=lambda mom, dad: (mom + dad) / 2)
combiner=lambda parents: sum(parents) / 2)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i actually prefer the resulting syntax too

@rogiervandergeer
Copy link
Collaborator Author

Catching (a subset of) exceptions thrown by the breeder and then raising another exception is tricky since you never know what went wrong inside the function. We could however augment the message from any exception thrown by adding a string like "the function was called with parents".

The generic combiners have a signature that does not match our expected
signature for combiners. While we expect a combiner to accept a number
of chromosomes, these combiners except individuals.

As I think that a combiner should solely combine two chromosomes, and
all logic related to the fitness of individuals selected for combining
should be handled by the picker, I've removed them.
# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants