Depending on how you construct your predicates, you may be able to capture their composition... And then serialise that.
Could be represented as a list of those ranges [(l1,r1),(l2,r2),(l3,r3)]. Basically, instead of constructing a predicate function directly, you would assemble a data-structure representing the essence of the predicate, then convert that to both a function for evaluation, as well as a string for serialisation. This would also allow you to perform some "optimisation" before serialisation which could be fun.
Do you have some examples of what the predicates look like?
- Lyndon