Initial add of the generic optimizer code

Before digging into this code, look at the Rules implemented at the bottom of DagOptimizer.

There are several TODOS here:

- [x] After I split the code into separate files, I started hitting a scala 2.9 compiler bug, that I don't hit in 2.10. I'll try to work around, or possibly hope that Twitter finally gets on 2.9 before we need this.

- [x] Tests tests tests. I played around at the repl, but clearly we need super hardcore tests for any optimization framework.

- [ ] Actually call this code from an existing platform.
My new idea on this is to consider the names to only apply to the "irreducibles", which are the literal functions, sources, sinks, services, stores and semigroups. So, step 1: build `Map[Any, List[String]]` which for each irreducible it gives you a `List[String]` of names that were applicable to it in the graph. Once those are built, we strip the names. Note, you can never delete irreducibles, they can only be combined (two functions into one flatMap). The IrreducibleContainer trait was added so we don't lose track of those.

I totally agree we need the names at all stages.