-
Notifications
You must be signed in to change notification settings - Fork 59
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
Separated out functionalities from initPopulation #36
Conversation
ca6dd41
to
e38537b
Compare
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.
I am not convinced that an introduction of a new creation
parameter provides better design. Now you have to reconcile type differences between initPopulation
values and values generated by creation
.
mutation::Function = ((r,m)->r), | ||
smutation::Function = (s->s), | ||
termination::Function = (x->false), | ||
creation::Function = (n -> rand(n)), |
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.
Now, the creation
function could generate vector with the type different from initPolulation
if only initPolulation
parameter passed.
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.
My intent here is that either a creation function or an initPopulation vector is passed, and if both are passed, the creation function is not called. Unfortunately Julia functions are not parameterised by argument or return types, so we cannot enforce creation (or for that matter, any other function used) to accept or return compatible types.
The reason I created this PR is because I was primarily working towards my second PR #37 which addresses my issue #35, and I was having difficulty accommodating the existing initialisation system. Specifically, for populations with individuals which aren't Vector{T} (eg. object individuals or higher dimension individuals), Matrix{T} is not appropriate for initialising a group of individuals. Hence, I changed it to Vector{I}, which could be Vector{Vector{T}}, Vector{Object} or Vector{Array{T, N}} accordingly. With regards to adding a creation function, I added this because it felt weird to me for initPopulation to be a vector or a function. Also, having separate parameters means that, in future, additional functionality could easily be implemented for passing partial initial populations: for an initPopulation of length less than N, the creation function could be used to generate the remaining individuals. |
The I like a separate parameter for a creation function, so I think it would be better to set a following initialization procedure for population as follows:
In the above initialization procedure, there is no need match types between initial population parameter and creation function output. |
I don't quite follow. In this PR, there is no need to match types between initial population and creation function either. The creation function is never called if a value is provided for initial population. |
Clearly, we got some misunderstanding. Let's get to the beginning. So, what do you think initial population parameter should be? |
For my project, I am working off aahaselgrove/Evolutionary.jl@0cd421d, in which the function signature for Lines 1 to 31 in 0cd421d
Hence, default behaviour is for the initial population to be generated by the default creation function |
The creation function
Can you update only GA at this point? I want to try specify different API for ES function. |
I like that in your |
Here is my take on initialization:
In that way, population initialization is moved out of the main algorithm, and the new interface would allow to provide special initialization functions for custom population creation procedure. |
I like the multiple dispatch approach for population initialization - it feels appropriate to the language. I still have problems with the initialisation options you provide for the reasons I outlined above.
I believe the existing method of creation also only works only if T is primitive. I don't think it's feasible to be generic enough to cover all kinds of population, and it is reasonable to require the user to perform initialisation for more complex types. However, I could certainly see it being appropriate to throw an error if the user tries to run ga with a more complex individual without defining a creation function or passing an initial population. |
Also, can |
Really, I thought they are functional. Anyway, leave them for future development.
Surely, the default
That's why the Matrix or Vector{Vector} population parameters were provided - to initialize whole population in advance. |
I think I've hit an effective compromise now. Initialisation can still be completed by passing a vector representing the search space or a matrix, but this is no longer part of the core algorithm, but more like helper functions for common initialisation patterns. The core algorithm is to first use any individuals passed in with the |
I think it's a good thing to move out initialization out of core algorithm. Do not stop in half way move all initializations into the separate function.
Mixing two types of the population initialization isn't a very nice thing. It could create ambiguities down the line. |
Do you have any examples of how this would be an issue? MATLAB's |
Well, you can have population values type-incompatible with the creation function produced individuals. I looked at MATLAB Nevertheless, could you move any initialization code out of the Do not bother to change ES code. I've already started working on it. |
Population values could also be incompatible with
I'll take a look at this. |
`initPopulation` was a heavily overloaded parameter, with a variety of types corresponding to a range of possible behaviours. This commit: - Move the option to pass a vector representing the search space or a matrix into separate wrapper functions. - Restricts `population` to be a vector of individuals (where an individual is a single member of the population) - Adds a new parameter `creation` to represent a function to create an individual. Default behaviour has not been changed, but is now represented by a creation function.
Implemented in new api, see Docs/Dev/Population |
initPopulation
was a heavily overloaded parameter, with a variety oftypes corresponding to a range of possible behaviours. This commit:
This is specific and unclear, and behaviour can easily be easily
represented by one of the other options
initPopulation
to be a vector of individuals (where anindividual is a single member of the population)
creation
to represent a function to create anindividual.
Default behaviour has not been changed, but is now represented by a
creation function.