Added a linear solver mutator.

This PR has been split out of the specialize_branched_loops branch for easier review. I have added a class that implements a linear solver mutation on expressions. The idea is that you provide an equality or inequality expression, a variable you want to solve for, and a list of free variables that may appear in the expression. The solver then attempts to mutate the expression such that the variable you are solving for appears alone on the left hand side of the equation. If the solve does not succeed, e.g. because the expression was not linear, then the expression is returned unmutated. This solver is used extensively in the specialize_branched_loops optimization pass.
So, I could very easily be convinced that this is a bad idea, but I'm going to toss this out there anyways:

It looks like the logic in visit_sym_cmp is nearly a subset of the logic in visit_asym_cmp, and there's a lot of nearly duplicated code. Would it be worth trying to handle the visit_sym_case in this function too?