I am currently writting a genetic algorithm in Haskell in which my chromosomes are rather complex structures representing executable systems.
In order for me to evaluate the fitness of my chromosomes I have to run an evolution function which performs one computational cycle of a given system. The fitness then is calculated just by counting how many times the evolution can be applied before there is no change in the system (in which case the system terminates).
The problem now is as follows: some systems can run infinitely long and will never terminate – I want to penalise those (by giving them little score). I could simply put a certain limit on number of steps but it does not solve another problem.
Some of my systems perform exponential computation (i.e. even for small values of evloution steps they grow to giant size) and they cause ERROR - Control stack overflow. For human observer it is clear that they will never terminate but the algorithm has no way of knowing so it runs and crushes.
My question is: is it possible to recover from such an error? I would like my algorithm to continue running after encountering this problem and just adjusting the chromosome score accordingly.
It seems to me like the best solution would be to tell the program: “Hey, try doing this, but if you fail don’t worry. I know how to handle it”. However I am not even sure if that’s possible. If not – are there any alternatives?
This will be hard to do reliably from inside Haskell — though under some conditions GHC will raise exceptions for these conditions. (You will need GHC 7).
If you really just want to catch stack overflows, this is possible, as this example shows:
Or catching any async exception (including heap exhaustion):
However, this is fragile.
Alternately, with GHC flags you can enforce maximum stack (or heap) size on a GHC-compiled process, causing it to be killed if it exceeds those limits (GHC appears to have no maximum stack limit these days).
If you compile your Haskell program with GHC (as is recommended), running it as:
the low heap limit below is enforced:
This requires GHC. (Again, you shouldn’t be using Hugs for this kind of work). Finally, you should ensure your programs don’t use excessive stack in the first place, via profiling in GHC.