Some of the recoverers (a word I think I've just coined) can use pre-calculated data to speed up their actions. Previously there was no sensible way for them to store this state, so they often calculate it over and over again. This PR first uses trait objects to allow different recoverers to store state, and then uses that facility to cache data. For the KimYi+ algorithm, on one of my standard examples, this reduces running time from ~3.5s to ~1.5s. That said, the speed improvement will heavily depend on the particular input: some examples will see no gains at all. However, I think it unlikely that any examples will slow down, so this is, overall, a win.
Each commit should stand alone, so I'd suggest reviewing each in isolation. [Notably, the 2nd commit -- which is a big part of the overall diff -- is mechanical and you may feel requires only a light review.]
Some of the recoverers (a word I think I've just coined) can use pre-calculated data to speed up their actions. Previously there was no sensible way for them to store this state, so they often calculate it over and over again. This PR first uses trait objects to allow different recoverers to store state, and then uses that facility to cache data. For the KimYi+ algorithm, on one of my standard examples, this reduces running time from ~3.5s to ~1.5s. That said, the speed improvement will heavily depend on the particular input: some examples will see no gains at all. However, I think it unlikely that any examples will slow down, so this is, overall, a win.
Each commit should stand alone, so I'd suggest reviewing each in isolation. [Notably, the 2nd commit -- which is a big part of the overall diff -- is mechanical and you may feel requires only a light review.]