| """ Generic SymPy-Independent Strategies """ | |
| def identity(x): | |
| yield x | |
| def exhaust(brule): | |
| """ Apply a branching rule repeatedly until it has no effect """ | |
| def exhaust_brl(expr): | |
| seen = {expr} | |
| for nexpr in brule(expr): | |
| if nexpr not in seen: | |
| seen.add(nexpr) | |
| yield from exhaust_brl(nexpr) | |
| if seen == {expr}: | |
| yield expr | |
| return exhaust_brl | |
| def onaction(brule, fn): | |
| def onaction_brl(expr): | |
| for result in brule(expr): | |
| if result != expr: | |
| fn(brule, expr, result) | |
| yield result | |
| return onaction_brl | |
| def debug(brule, file=None): | |
| """ Print the input and output expressions at each rule application """ | |
| if not file: | |
| from sys import stdout | |
| file = stdout | |
| def write(brl, expr, result): | |
| file.write("Rule: %s\n" % brl.__name__) | |
| file.write("In: %s\nOut: %s\n\n" % (expr, result)) | |
| return onaction(brule, write) | |
| def multiplex(*brules): | |
| """ Multiplex many branching rules into one """ | |
| def multiplex_brl(expr): | |
| seen = set() | |
| for brl in brules: | |
| for nexpr in brl(expr): | |
| if nexpr not in seen: | |
| seen.add(nexpr) | |
| yield nexpr | |
| return multiplex_brl | |
| def condition(cond, brule): | |
| """ Only apply branching rule if condition is true """ | |
| def conditioned_brl(expr): | |
| if cond(expr): | |
| yield from brule(expr) | |
| else: | |
| pass | |
| return conditioned_brl | |
| def sfilter(pred, brule): | |
| """ Yield only those results which satisfy the predicate """ | |
| def filtered_brl(expr): | |
| yield from filter(pred, brule(expr)) | |
| return filtered_brl | |
| def notempty(brule): | |
| def notempty_brl(expr): | |
| yielded = False | |
| for nexpr in brule(expr): | |
| yielded = True | |
| yield nexpr | |
| if not yielded: | |
| yield expr | |
| return notempty_brl | |
| def do_one(*brules): | |
| """ Execute one of the branching rules """ | |
| def do_one_brl(expr): | |
| yielded = False | |
| for brl in brules: | |
| for nexpr in brl(expr): | |
| yielded = True | |
| yield nexpr | |
| if yielded: | |
| return | |
| return do_one_brl | |
| def chain(*brules): | |
| """ | |
| Compose a sequence of brules so that they apply to the expr sequentially | |
| """ | |
| def chain_brl(expr): | |
| if not brules: | |
| yield expr | |
| return | |
| head, tail = brules[0], brules[1:] | |
| for nexpr in head(expr): | |
| yield from chain(*tail)(nexpr) | |
| return chain_brl | |
| def yieldify(rl): | |
| """ Turn a rule into a branching rule """ | |
| def brl(expr): | |
| yield rl(expr) | |
| return brl | |