def match_leaf(self, yield_func, leaf, rest_leaves, rest_expression, vars, expression, attributes, evaluation, leaf_index=1, leaf_count=None, first=False, fully=True, depth=1, wrap_oneid=True): if rest_expression is None: rest_expression = ([], []) evaluation.check_stopped() match_count = leaf.get_match_count(vars) leaf_candidates = leaf.get_match_candidates( rest_expression[1], # leaf.candidates, expression, attributes, evaluation, vars) if len(leaf_candidates) < match_count[0]: return # STRANGE: candidate in leaf_candidates causes BusError for # Real ^ Integer (e.g. 2.0^3) when not converted to a set! leaf_candidates = set(leaf_candidates) candidates = rest_expression[1] # "Artificially" only use more leaves than specified for some kind # of pattern. # TODO: This could be further optimized! try_flattened = ('Flat' in attributes) and (leaf.get_head_name() in ( 'Pattern', 'PatternTest', 'Condition', 'Optional', 'Blank', 'BlankSequence', 'BlankNullSequence', 'Alternatives', 'OptionsPattern', 'Repeated', 'RepeatedNull')) if try_flattened: set_lengths = (match_count[0], None) else: set_lengths = match_count # try_flattened is used later to decide whether wrapping of leaves # into one operand may occur. # This can of course also be when flat and same head. try_flattened = try_flattened or (( 'Flat' in attributes) and leaf.get_head() == expression.head) less_first = len(rest_leaves) > 0 if 'Orderless' in attributes: sets = None if leaf.get_head_name() == 'Pattern': varname = leaf.leaves[0].get_name() existing = vars.get(varname, None) if existing is not None: head = existing.get_head() if (head.get_name() == 'Sequence' or ( 'Flat' in attributes and head == expression.get_head())): needed = existing.leaves else: needed = [existing] available = candidates[:] for needed_leaf in needed: if (needed_leaf in available and # nopep8 needed_leaf in leaf_candidates): available.remove(needed_leaf) else: return sets = [(needed, ([], available))] if sets is None: sets = subsets(candidates, included=leaf_candidates, less_first=less_first, *set_lengths) else: sets = subranges(candidates, flexible_start=first and not fully, included=leaf_candidates, less_first=less_first, *set_lengths) # print "Match %s in %s" % (leaf, expression) if rest_leaves: next_leaf = rest_leaves[0] next_rest_leaves = rest_leaves[1:] next_depth = depth + 1 next_index = leaf_index + 1 for items, items_rest in sets: # try: # print (u" " + u", ".join(unicode(item) # for item in items)).encode('utf-8') # except # Include wrappings like Plus[a, b] only if not all items taken # - in that case we would match the same expression over and over. include_flattened = (try_flattened and 0 < len(items) < len(expression.leaves)) # Don't try flattened when the expression would remain the same! def leaf_yield(next_vars, next_rest): # if next_rest is None: # next_rest = ([], []) # yield_func(next_vars, (rest_expression[0] + items_rest[0], # next_rest[1])) if next_rest is None: yield_func( next_vars, (rest_expression[0] + items_rest[0], [])) else: yield_func( next_vars, (rest_expression[0] + items_rest[0], next_rest[1])) def match_yield(new_vars, _): if rest_leaves: self.match_leaf( leaf_yield, next_leaf, next_rest_leaves, items_rest, new_vars, expression, attributes, evaluation, fully=fully, depth=next_depth, leaf_index=next_index, leaf_count=leaf_count, wrap_oneid=wrap_oneid) else: if not fully or (not items_rest[0] and not items_rest[1]): yield_func(new_vars, items_rest) def yield_wrapping(item): leaf.match(match_yield, item, vars, evaluation, fully=True, head=expression.head, leaf_index=leaf_index, leaf_count=leaf_count, wrap_oneid=wrap_oneid) self.get_wrappings( yield_wrapping, items, match_count[1], expression, attributes, include_flattened=include_flattened)
def match_leaf(self, yield_func, leaf, rest_leaves, rest_expression, vars, expression, attributes, evaluation, leaf_index=1, leaf_count=None, first=False, fully=True, depth=1, wrap_oneid=True): if rest_expression is None: rest_expression = ([], []) evaluation.check_stopped() match_count = leaf.get_match_count(vars) leaf_candidates = leaf.get_match_candidates( rest_expression[1], # leaf.candidates, expression, attributes, evaluation, vars) if len(leaf_candidates) < match_count[0]: return candidates = rest_expression[1] # "Artificially" only use more leaves than specified for some kind # of pattern. # TODO: This could be further optimized! try_flattened = (('System`Flat' in attributes) and (leaf.get_head_name() in (system_symbols( 'Pattern', 'PatternTest', 'Condition', 'Optional', 'Blank', 'BlankSequence', 'BlankNullSequence', 'Alternatives', 'OptionsPattern', 'Repeated', 'RepeatedNull')))) if try_flattened: set_lengths = (match_count[0], None) else: set_lengths = match_count # try_flattened is used later to decide whether wrapping of leaves # into one operand may occur. # This can of course also be when flat and same head. try_flattened = try_flattened or (('System`Flat' in attributes) and leaf.get_head() == expression.head) less_first = len(rest_leaves) > 0 if 'System`Orderless' in attributes: # we only want leaf_candidates to be a set if we're orderless. # otherwise, constructing a set() is very slow for large lists. # performance test case: # x = Range[100000]; Timing[Combinatorica`BinarySearch[x, 100]] leaf_candidates = set(leaf_candidates) # for fast lookup sets = None if leaf.get_head_name() == 'System`Pattern': varname = leaf.leaves[0].get_name() existing = vars.get(varname, None) if existing is not None: head = existing.get_head() if (head.get_name() == 'System`Sequence' or ('System`Flat' in attributes and head == expression.get_head())): needed = existing.leaves else: needed = [existing] available = candidates[:] for needed_leaf in needed: if (needed_leaf in available and # nopep8 needed_leaf in leaf_candidates): available.remove(needed_leaf) else: return sets = [(needed, ([], available))] if sets is None: sets = subsets(candidates, included=leaf_candidates, less_first=less_first, *set_lengths) else: sets = subranges(candidates, flexible_start=first and not fully, included=leaf_candidates, less_first=less_first, *set_lengths) if rest_leaves: next_leaf = rest_leaves[0] next_rest_leaves = rest_leaves[1:] next_depth = depth + 1 next_index = leaf_index + 1 for items, items_rest in sets: # Include wrappings like Plus[a, b] only if not all items taken # - in that case we would match the same expression over and over. include_flattened = (try_flattened and 0 < len(items) < len(expression.leaves)) # Don't try flattened when the expression would remain the same! def leaf_yield(next_vars, next_rest): # if next_rest is None: # next_rest = ([], []) # yield_func(next_vars, (rest_expression[0] + items_rest[0], # next_rest[1])) if next_rest is None: yield_func(next_vars, (rest_expression[0] + items_rest[0], [])) else: yield_func( next_vars, (rest_expression[0] + items_rest[0], next_rest[1])) def match_yield(new_vars, _): if rest_leaves: self.match_leaf(leaf_yield, next_leaf, next_rest_leaves, items_rest, new_vars, expression, attributes, evaluation, fully=fully, depth=next_depth, leaf_index=next_index, leaf_count=leaf_count, wrap_oneid=wrap_oneid) else: if not fully or (not items_rest[0] and not items_rest[1]): yield_func(new_vars, items_rest) def yield_wrapping(item): leaf.match(match_yield, item, vars, evaluation, fully=True, head=expression.head, leaf_index=leaf_index, leaf_count=leaf_count, wrap_oneid=wrap_oneid) self.get_wrappings(yield_wrapping, items, match_count[1], expression, attributes, include_flattened=include_flattened)
def match_leaf(self, yield_func, leaf, rest_leaves, rest_expression, vars, expression, attributes, evaluation, leaf_index=1, leaf_count=None, first=False, fully=True, depth=1, wrap_oneid=True): if rest_expression is None: rest_expression = ([], []) evaluation.check_stopped() match_count = leaf.get_match_count(vars) leaf_candidates = leaf.get_match_candidates( rest_expression[1], # leaf.candidates, expression, attributes, evaluation, vars) if len(leaf_candidates) < match_count[0]: return # STRANGE: candidate in leaf_candidates causes BusError for # Real ^ Integer (e.g. 2.0^3) when not converted to a set! leaf_candidates = set(leaf_candidates) candidates = rest_expression[1] # "Artificially" only use more leaves than specified for some kind # of pattern. # TODO: This could be further optimized! try_flattened = ('Flat' in attributes) and (leaf.get_head_name() in ( 'Pattern', 'PatternTest', 'Condition', 'Optional', 'Blank', 'BlankSequence', 'BlankNullSequence', 'Alternatives', 'OptionsPattern', 'Repeated', 'RepeatedNull')) if try_flattened: set_lengths = (match_count[0], None) else: set_lengths = match_count # try_flattened is used later to decide whether wrapping of leaves # into one operand may occur. # This can of course also be when flat and same head. try_flattened = try_flattened or ( ('Flat' in attributes) and leaf.get_head() == expression.head) less_first = len(rest_leaves) > 0 if 'Orderless' in attributes: sets = None if leaf.get_head_name() == 'Pattern': varname = leaf.leaves[0].get_name() existing = vars.get(varname, None) if existing is not None: head = existing.get_head() if (head.get_name() == 'Sequence' or ('Flat' in attributes and head == expression.get_head())): needed = existing.leaves else: needed = [existing] available = candidates[:] for needed_leaf in needed: if (needed_leaf in available and # nopep8 needed_leaf in leaf_candidates): available.remove(needed_leaf) else: return sets = [(needed, ([], available))] if sets is None: sets = subsets(candidates, included=leaf_candidates, less_first=less_first, *set_lengths) else: sets = subranges(candidates, flexible_start=first and not fully, included=leaf_candidates, less_first=less_first, *set_lengths) # print "Match %s in %s" % (leaf, expression) if rest_leaves: next_leaf = rest_leaves[0] next_rest_leaves = rest_leaves[1:] next_depth = depth + 1 next_index = leaf_index + 1 for items, items_rest in sets: # try: # print (u" " + u", ".join(unicode(item) # for item in items)).encode('utf-8') # except # Include wrappings like Plus[a, b] only if not all items taken # - in that case we would match the same expression over and over. include_flattened = (try_flattened and 0 < len(items) < len(expression.leaves)) # Don't try flattened when the expression would remain the same! def leaf_yield(next_vars, next_rest): # if next_rest is None: # next_rest = ([], []) # yield_func(next_vars, (rest_expression[0] + items_rest[0], # next_rest[1])) if next_rest is None: yield_func(next_vars, (rest_expression[0] + items_rest[0], [])) else: yield_func( next_vars, (rest_expression[0] + items_rest[0], next_rest[1])) def match_yield(new_vars, _): if rest_leaves: self.match_leaf(leaf_yield, next_leaf, next_rest_leaves, items_rest, new_vars, expression, attributes, evaluation, fully=fully, depth=next_depth, leaf_index=next_index, leaf_count=leaf_count, wrap_oneid=wrap_oneid) else: if not fully or (not items_rest[0] and not items_rest[1]): yield_func(new_vars, items_rest) def yield_wrapping(item): leaf.match(match_yield, item, vars, evaluation, fully=True, head=expression.head, leaf_index=leaf_index, leaf_count=leaf_count, wrap_oneid=wrap_oneid) self.get_wrappings(yield_wrapping, items, match_count[1], expression, attributes, include_flattened=include_flattened)
def match_leaf(self, yield_func, leaf, rest_leaves, rest_expression, vars, expression, attributes, evaluation, leaf_index=1, leaf_count=None, first=False, fully=True, depth=1, wrap_oneid=True): if rest_expression is None: rest_expression = ([], []) evaluation.check_stopped() match_count = leaf.get_match_count(vars) leaf_candidates = leaf.get_match_candidates( rest_expression[1], # leaf.candidates, expression, attributes, evaluation, vars) if len(leaf_candidates) < match_count[0]: return candidates = rest_expression[1] # "Artificially" only use more leaves than specified for some kind # of pattern. # TODO: This could be further optimized! try_flattened = (('System`Flat' in attributes) and (leaf.get_head_name() in ( system_symbols( 'Pattern', 'PatternTest', 'Condition', 'Optional', 'Blank', 'BlankSequence', 'BlankNullSequence', 'Alternatives', 'OptionsPattern', 'Repeated', 'RepeatedNull')))) if try_flattened: set_lengths = (match_count[0], None) else: set_lengths = match_count # try_flattened is used later to decide whether wrapping of leaves # into one operand may occur. # This can of course also be when flat and same head. try_flattened = try_flattened or (( 'System`Flat' in attributes) and leaf.get_head() == expression.head) less_first = len(rest_leaves) > 0 if 'System`Orderless' in attributes: # we only want leaf_candidates to be a set if we're orderless. # otherwise, constructing a set() is very slow for large lists. # performance test case: # x = Range[100000]; Timing[Combinatorica`BinarySearch[x, 100]] leaf_candidates = set(leaf_candidates) # for fast lookup sets = None if leaf.get_head_name() == 'System`Pattern': varname = leaf.leaves[0].get_name() existing = vars.get(varname, None) if existing is not None: head = existing.get_head() if (head.get_name() == 'System`Sequence' or ( 'System`Flat' in attributes and head == expression.get_head())): needed = existing.leaves else: needed = [existing] available = candidates[:] for needed_leaf in needed: if (needed_leaf in available and # nopep8 needed_leaf in leaf_candidates): available.remove(needed_leaf) else: return sets = [(needed, ([], available))] if sets is None: sets = subsets(candidates, included=leaf_candidates, less_first=less_first, *set_lengths) else: sets = subranges(candidates, flexible_start=first and not fully, included=leaf_candidates, less_first=less_first, *set_lengths) if rest_leaves: next_leaf = rest_leaves[0] next_rest_leaves = rest_leaves[1:] next_depth = depth + 1 next_index = leaf_index + 1 for items, items_rest in sets: # Include wrappings like Plus[a, b] only if not all items taken # - in that case we would match the same expression over and over. include_flattened = (try_flattened and 0 < len(items) < len(expression.leaves)) # Don't try flattened when the expression would remain the same! def leaf_yield(next_vars, next_rest): # if next_rest is None: # next_rest = ([], []) # yield_func(next_vars, (rest_expression[0] + items_rest[0], # next_rest[1])) if next_rest is None: yield_func( next_vars, (rest_expression[0] + items_rest[0], [])) else: yield_func( next_vars, (rest_expression[0] + items_rest[0], next_rest[1])) def match_yield(new_vars, _): if rest_leaves: self.match_leaf( leaf_yield, next_leaf, next_rest_leaves, items_rest, new_vars, expression, attributes, evaluation, fully=fully, depth=next_depth, leaf_index=next_index, leaf_count=leaf_count, wrap_oneid=wrap_oneid) else: if not fully or (not items_rest[0] and not items_rest[1]): yield_func(new_vars, items_rest) def yield_wrapping(item): leaf.match(match_yield, item, vars, evaluation, fully=True, head=expression.head, leaf_index=leaf_index, leaf_count=leaf_count, wrap_oneid=wrap_oneid) self.get_wrappings( yield_wrapping, items, match_count[1], expression, attributes, include_flattened=include_flattened)