Support custom LPE symbols from the user

This has been requested so light path expressions can use
custom symbols for events and scatterings in addition to the
builtin C, L, D, etc ...
Optiization: Be less conservative in implementation of unread_after().

It was really implemented as if it were "unread AT OR after". It's used
to determine whether it's safe to elide assignments to variables that
aren't subsequently use. But sometimes the assignment is a function
where the variable assigned to is also one of the arguments. For
example,
    x = func(x,y)
x is read on that op, but not AFTER. But because of how the unread_after
also discounted elision if used on that op, it was less aggressive than it
could have been in eliminating statements like this.