Implement sharing of components in the evaluator

This addresses #306, sharing common components between multiple algorithm configurations.  It brings heavy refactoring of the train-test evaluator to accomplish this, including dependency-graph-based task execution.

It also starts using interruption to manage threads (#478).