core.py 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. """ Generic SymPy-Independent Strategies """
  2. def identity(x):
  3. yield x
  4. def exhaust(brule):
  5. """ Apply a branching rule repeatedly until it has no effect """
  6. def exhaust_brl(expr):
  7. seen = {expr}
  8. for nexpr in brule(expr):
  9. if nexpr not in seen:
  10. seen.add(nexpr)
  11. yield from exhaust_brl(nexpr)
  12. if seen == {expr}:
  13. yield expr
  14. return exhaust_brl
  15. def onaction(brule, fn):
  16. def onaction_brl(expr):
  17. for result in brule(expr):
  18. if result != expr:
  19. fn(brule, expr, result)
  20. yield result
  21. return onaction_brl
  22. def debug(brule, file=None):
  23. """ Print the input and output expressions at each rule application """
  24. if not file:
  25. from sys import stdout
  26. file = stdout
  27. def write(brl, expr, result):
  28. file.write("Rule: %s\n" % brl.__name__)
  29. file.write("In: %s\nOut: %s\n\n" % (expr, result))
  30. return onaction(brule, write)
  31. def multiplex(*brules):
  32. """ Multiplex many branching rules into one """
  33. def multiplex_brl(expr):
  34. seen = set()
  35. for brl in brules:
  36. for nexpr in brl(expr):
  37. if nexpr not in seen:
  38. seen.add(nexpr)
  39. yield nexpr
  40. return multiplex_brl
  41. def condition(cond, brule):
  42. """ Only apply branching rule if condition is true """
  43. def conditioned_brl(expr):
  44. if cond(expr):
  45. yield from brule(expr)
  46. else:
  47. pass
  48. return conditioned_brl
  49. def sfilter(pred, brule):
  50. """ Yield only those results which satisfy the predicate """
  51. def filtered_brl(expr):
  52. yield from filter(pred, brule(expr))
  53. return filtered_brl
  54. def notempty(brule):
  55. def notempty_brl(expr):
  56. yielded = False
  57. for nexpr in brule(expr):
  58. yielded = True
  59. yield nexpr
  60. if not yielded:
  61. yield expr
  62. return notempty_brl
  63. def do_one(*brules):
  64. """ Execute one of the branching rules """
  65. def do_one_brl(expr):
  66. yielded = False
  67. for brl in brules:
  68. for nexpr in brl(expr):
  69. yielded = True
  70. yield nexpr
  71. if yielded:
  72. return
  73. return do_one_brl
  74. def chain(*brules):
  75. """
  76. Compose a sequence of brules so that they apply to the expr sequentially
  77. """
  78. def chain_brl(expr):
  79. if not brules:
  80. yield expr
  81. return
  82. head, tail = brules[0], brules[1:]
  83. for nexpr in head(expr):
  84. yield from chain(*tail)(nexpr)
  85. return chain_brl
  86. def yieldify(rl):
  87. """ Turn a rule into a branching rule """
  88. def brl(expr):
  89. yield rl(expr)
  90. return brl