Skip to content
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

feat(GA): replacement module & BothParent operator #263

Merged
merged 6 commits into from
Dec 22, 2022

Conversation

kkafar
Copy link
Collaborator

@kkafar kkafar commented Dec 22, 2022

Description

First thing to note is that current solution is not really a "steady" replacement.

Currently I've introduced a separate replacement operator with the same approach as for other operators: trait + concrete types that implement that trait.

What makes it "not steady" is that this operator is passed to GA in the same way as any other operator, and thus it is called separately, after the crossover and there is need to iterate over whole population once again...

To make it "steady" we could pass replacement operator directly to the crossover operator as a parameter / construction parameter - and this is the thing I want your opinion on the most. Should we make the replacement a part of crossover process or should it be a standalone operator?

The second topic is that after ChromosomeWrapper was removed in #147 there is no option to define custom state on a individual, thus it makes some variants of replacement operator basically impossible to implement in a reasonable way (such as oldest individual replacement - as you would need to have a lifetime associated with the individual). Therefore I want to open a discussion whether we should bring back ChromosomeWrapper (or some improved version of this concept).

If I did not explain things clearly, please ask.

Linked issues

Resolves #58

Important implementation details

Described in previous sections.

@kkafar kkafar self-assigned this Dec 22, 2022
@kkafar kkafar added docs Improvements or additions to documentation feature New feature or request help-wanted Extra attention is needed question Further information is requested labels Dec 22, 2022
@kkafar kkafar changed the title feat(GA): replacement module & basic operators feat(GA): replacement module & BothParent operator Dec 22, 2022
@kkafar kkafar marked this pull request as ready for review December 22, 2022 13:15
@kkafar
Copy link
Collaborator Author

kkafar commented Dec 22, 2022

I'm gonna merge this PR right now & respond to any review in followup PR.

@kkafar kkafar merged commit d4923d4 into main Dec 22, 2022
@kkafar kkafar deleted the @kkafar/replacement-operator branch December 22, 2022 13:27
kkafar added a commit that referenced this pull request Dec 22, 2022
## Description

So I've just merged #263 skipping review process 🤦🏻‍♂️ and had to
immediately introduce some fixes;

1. I decided to take ownership of population & children, so that I can
modify it in the operator and avoid necessity of creating a copy.
2. Added `requires_children_fitness` method which indicated whether
children's fitness should be evaluated.
3. Fixed `BothParents` implementation
Copy link
Collaborator

@co012 co012 left a comment

Choose a reason for hiding this comment

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

LGTM.


/// # Replacement Operator
///
/// This trait defines common behavirou for crossover operators.
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
/// This trait defines common behavirou for crossover operators.
/// This trait defines common behaviour for replacement operators.

Copy link
Collaborator

@Garion9 Garion9 left a comment

Choose a reason for hiding this comment

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

As for the PR itself - LGTM.
As for concerns you mentioned in the description:

  1. Steady vs non-steady replacement - non-steady version kind of gives us more control over it, i.e. replacement operator is called no matter what implementation of crossover operator (including custom ones) is used. Also, iterating through population another time does increase time complexity, but it does not increase complexity class, so IMO it is acceptable.
  2. I'm not sure what sort of information such "state" would need, but in case of example given by you - "age" of an individual could be represented by its position in a collection that represents population, i.e. if new ones are only appended at the end, then those at the beginning must be the oldest. Therefore, maybe there is no real need for storing such a state, and this issue could be solved through clever implementation of replacement operators.

@kkafar
Copy link
Collaborator Author

kkafar commented Dec 23, 2022

Steady vs non-steady replacement - non-steady version kind of gives us more control over it, i.e. replacement operator is called no matter what implementation of crossover operator (including custom ones) is used. [..]

This is a valid point, but such approach introduces many difficulties. E.g. many of the replacement operators require knowledge of child's parents (i.e. for given child, we need to know which individuals are its parents) -- right now the only reasonable thing I came up with to realise this is to assume that crossover operator produces children at indices i, i+1 from individuals at i, i+1 positions from original population. But what happens if crossover operator breaks this contract?
My point is, that there already are such implicit dependencies in our code (I'm trying to point them out in code comments, so they are at least documented).

I've not decided what to do yet :D

[..] iterating through population another time does increase time complexity, but it does not increase complexity class, so IMO it is acceptable.

I must agree, I believe I'll leave it the way it is right now. But this approach will backfire once the population gets big enough. By "big enough" I mean like couple of hundreds of individuals, as this is a hot code called each iteration it will have serious impact.

But I guess we'll have to leave it this way for now as I do not have any other idea for now.

I'm not sure what sort of information such "state" would need, but in case of example given by you - "age" of an individual could be represented by its position in a collection that represents population, i.e. if new ones are only appended at the end, then those at the beginning must be the oldest

I believe this can not be done the way you described. Right now we assume that the population is of fixed size and the replacement happens in place (also shifting elements in a vector is a bad idea). Also I can not shuffle original population (not children) in any way, because I would lose any parentage information.

Such additional state, would allow to associate with given child e.g. a reference to parent individual or number of generations it has lasted up to given point in algorithm's time. W/o that I believe implementing "oldest individual" replacement operator will be impossible.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
docs Improvements or additions to documentation feature New feature or request help-wanted Extra attention is needed question Further information is requested
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[GA] Steady replacement - both parents
3 participants