Generalizing and benchmarking EC Recombination! Episode 66 of Unhindered by Coding
Channel: Unhindered by Coding!
Date: 27/01/2023

We continued to generalize (a generous term for rewrite) the EC `Recombinator` trait, and I added some benchmarking so we'd have some idea what impact these changes are having.

Before the stream I wrote some simple benchmarking for our `TwoPointXoWithMutate::make_child()`. With the right parameters, most of the effort here is in doing the recombination, and a lot of that is in the calls. It looks like adding the `Recombinator` trait _may_ slow things down a bit (maybe 10%), but this is on very fast calls (~500 ns), so it probably doesn't really matter much. The cost of doing all the fitness evaluations, especially for an interesting problem, or a bunch of lexicase selections will swamp the cost of this generalization.

We finishing switching over to the constant length array definition of recombinators by implementing `MutateWithOneOverLength`. That turned out to be a little weirder than I expected because we only know the length when `recombine` is called. I'd hoped to compute the mutation rate once and stash it, but here we end up computing it on every `recombine()` call, which is a little gross.

We then started implementing `Pipeline` with the understanding that this would likely turn up the issue of needing everyone to have the same type, thus breaking the ability to use fixed length arrays. And indeed it lead to a whole host of issues:

 - We had to change `Recombinator` to take a `&[&G]` of genomes instead of a fixed-length array since we need all the recombinators to have the same type.
 - The `Pipeline` then needed `Vec(dyn Recombinator)`, but that doesn't work because `dyn Recombinator`s won't always have the same size, and `Vec` requires all its items to have the same size.
 - So we went to `Vec(Box(dyn Recombinator))`, which seems to have worked. This means we get an extra indirection at every recombinator call, which is semi-annoying? I'll need to benchmark that to see what impact it has.
 - laundmo@Twitch (a new visitor) shared a lot, including a suggestion for a very nice VSCode extension called "Error Lens" which shows you errors right in the code. I'm definitely liking that.
 - I think that `Pipeline` "works", but it's rather fragile in that there's no way for the type checker to ensure that each recombinator outputs the desired number of parents for the next recombinator to take as input. This is essentially the problem of implementing function composition; we'll come back to that on the next `rust-ga` stream on Sunday.

================

In the first few months of 2023 (at least to mid-March) I'm streaming at https://twitch.tv/NicMcPhee four times a week:

* Tuesday: 10am-noon CST
* Wednesday: 7-9pm CST
* Saturday: 2-4pm CST
* Sunday: 10am-noon CST

The Tuesday and Sunday slots will be focusing on building the EC system in Rust and on the ice-repos webapp. The Wednesday and Saturday slots will be going through the Advent of Code 2022 puzzles/exercises.

Thanks for watching!