feat(library/simplifier): memoize intermediate results

Signed-off-by: Leonardo de Moura <leonardo@microsoft.com>
fix(library/expr_lt): use expression depth instead of size to obtain a monotonic total order on terms

It is not incorrect to use size, but it can easily overflow due to sharing.
The following script demonstrates the problem:

local f = Const("f")
local a = Const("a")
function mk_shared(d)
   if d == 0 then
      return a
   else
      local c = mk_shared(d-1)
      return f(c, c)
   end
end
print(mk_shared(33):size())

Signed-off-by: Leonardo de Moura <leonardo@microsoft.com>
fix(library/expr_lt): use expression depth instead of size to obtain a monotonic total order on terms