expr - pyll Apply instance to be evaluated memo - optional dictionary of values to use for particular nodes deepcopy_inputs - deepcopy inputs to every node prior to calling that node's function on those inputs. If this leads to a different return value, then some funct
(
expr,
deepcopy_inputs=False,
memo=None,
max_program_len=None,
memo_gc=True,
print_trace=False,
print_node_on_error=True,
)
| 764 | |
| 765 | |
| 766 | def rec_eval( |
| 767 | expr, |
| 768 | deepcopy_inputs=False, |
| 769 | memo=None, |
| 770 | max_program_len=None, |
| 771 | memo_gc=True, |
| 772 | print_trace=False, |
| 773 | print_node_on_error=True, |
| 774 | ): |
| 775 | """ |
| 776 | expr - pyll Apply instance to be evaluated |
| 777 | |
| 778 | memo - optional dictionary of values to use for particular nodes |
| 779 | |
| 780 | deepcopy_inputs - deepcopy inputs to every node prior to calling that |
| 781 | node's function on those inputs. If this leads to a different return |
| 782 | value, then some function (XXX add more complete DebugMode |
| 783 | functionality) in your graph is modifying its inputs and causing |
| 784 | mis-calculation. XXX: This is not a fully-functional DebugMode because |
| 785 | if the offender happens on account of the toposort order to be the last |
| 786 | user of said input, then it will not be detected as a potential |
| 787 | problem. |
| 788 | |
| 789 | """ |
| 790 | if max_program_len == None: |
| 791 | max_program_len = DEFAULT_MAX_PROGRAM_LEN |
| 792 | |
| 793 | if deepcopy_inputs not in (0, 1, False, True): |
| 794 | # -- I've been calling rec_eval(expr, memo) by accident a few times |
| 795 | # this error would have been appreciated. |
| 796 | raise ValueError("deepcopy_inputs should be bool", deepcopy_inputs) |
| 797 | |
| 798 | node = as_apply(expr) |
| 799 | topnode = node |
| 800 | |
| 801 | if memo is None: |
| 802 | memo = {} |
| 803 | else: |
| 804 | memo = dict(memo) |
| 805 | |
| 806 | # -- hack for speed |
| 807 | # since the inputs are constant during rec_eval |
| 808 | # but not constant in general |
| 809 | node_inputs = {} |
| 810 | node_list = [] |
| 811 | dfs(node, node_list, seqset=node_inputs) |
| 812 | |
| 813 | # TODO: optimize dfs to not recurse past the items in memo |
| 814 | # this is especially important for evaluating Lambdas |
| 815 | # which cause rec_eval to recurse |
| 816 | # |
| 817 | # N.B. that Lambdas may expand the graph during the evaluation |
| 818 | # so that this iteration may be an incomplete |
| 819 | if memo_gc: |
| 820 | clients = {} |
| 821 | for aa in node_list: |
| 822 | clients.setdefault(aa, set()) |
| 823 | for ii in node_inputs[aa]: |