Пример #1
0
 def build_tree_plan(self, pattern: Pattern, statistics: Dict):
     """
     Creates a tree-based evaluation plan for the given pattern.
     """
     statistics_copy = deepcopy(statistics)
     pattern_positive_args = pattern.get_top_level_structure_args(
         positive_only=True)
     pattern_positive_statistics = TreePlanBuilder.extract_positive_statistics(
         pattern, statistics_copy)
     if any(not isinstance(arg, PrimitiveEventStructure)
            for arg in pattern_positive_args):
         # the pattern contains nested parts and should be treated accordingly
         nested_topology, _ = self.__create_nested_topology(
             pattern, pattern_positive_statistics)
         positive_root = TreePlanBuilder.__adjust_nested_indices(
             pattern, nested_topology)
     else:
         # the pattern is entirely flat
         positive_root = self._create_tree_topology(
             pattern, pattern_positive_statistics,
             self.__init_tree_leaves(pattern))
     if isinstance(pattern.positive_structure, UnaryStructure):
         # an edge case where the topmost operator is a unary operator
         positive_root = self._instantiate_unary_node(
             pattern, positive_root)
     root = self.__negation_algorithm.handle_pattern_negation(
         pattern, statistics_copy, positive_root)
     pattern_condition = deepcopy(
         pattern.condition
     )  # copied since apply_condition modifies its input parameter
     root.apply_condition(pattern_condition)
     return TreePlan(root)
Пример #2
0
 def __create_selectivity_matrix_for_nested_operators(
         pattern: Pattern, statistics: Dict):
     """
     This function creates a selectivity matrix that fits the root operator (kind of flattening the selectivity
     of the nested operators, if exists).
     """
     selectivity_matrix = statistics[StatisticsTypes.SELECTIVITY_MATRIX]
     if pattern.count_primitive_events(
             positive_only=True) != len(selectivity_matrix):
         raise Exception("size mismatch")
     nested_selectivity_matrix = []
     primitive_sons_list = []
     # event_names are all the events in this pattern (including those under nested operators)
     event_names = [
         name for name in pattern.positive_structure.get_all_event_names()
     ]
     for arg in pattern.get_top_level_structure_args(positive_only=True):
         # This is a list with size of the number of args, where each entry in the list is the events' name of the
         # primitive events under this arg.
         primitive_sons_list.append(
             [name for name in arg.get_all_event_names()])
     for i, row_entry in enumerate(primitive_sons_list):
         nested_selectivity_matrix.append([])
         for col_entry in primitive_sons_list:
             # Building the new matrix, which is (#args x #args), where each entry is calculated based on the events
             # under the specific args respectively
             nested_selectivity = TreePlanBuilder.__calculate_nested_selectivity(
                 event_names, selectivity_matrix, row_entry, col_entry)
             nested_selectivity_matrix[i].append(nested_selectivity)
     return nested_selectivity_matrix
Пример #3
0
 def __init_tree_leaves(pattern: Pattern,
                        nested_topologies: List[TreePlanNode] = None,
                        nested_args: List[PatternStructure] = None,
                        nested_cost: List[float] = None):
     """
     Initializes the leaves of the tree plan. If the nested parameters are given, creates nested nodes instead of
     regular leaves where necessary.
     """
     leaves = []
     pattern_positive_args = pattern.get_top_level_structure_args(
         positive_only=True)
     for i, arg in enumerate(pattern_positive_args):
         if nested_topologies is None or nested_topologies[i] is None:
             # the current argument can either be a PrimitiveEventStructure or an UnaryOperator surrounding it
             event_structure = arg if isinstance(
                 arg, PrimitiveEventStructure) else arg.child
             new_leaf = TreePlanLeafNode(i, event_structure.type,
                                         event_structure.name)
         else:
             nested_topology = nested_topologies[i].sub_tree_plan \
                 if isinstance(nested_topologies[i], TreePlanNestedNode) else nested_topologies[i]
             new_leaf = TreePlanNestedNode(i, nested_topology,
                                           nested_args[i], nested_cost[i])
         if isinstance(arg, UnaryStructure):
             new_leaf = TreePlanBuilder._instantiate_unary_node(
                 TreePlanBuilder.__create_dummy_subpattern(pattern, arg),
                 new_leaf)
         leaves.append(new_leaf)
     return leaves
Пример #4
0
 def __adjust_nested_indices(pattern: Pattern, root, offset=0):
     """
     After building a tree plan, this function will correct the indexes of sub trees to continue the
     indices of the main tree, instead of restarting in each sub tree(which was important while building the plan)
     """
     for index, arg in enumerate(
             pattern.get_top_level_structure_args(positive_only=True)):
         node = TreePlanBuilder.__get_node_by_index(root, index)
         if isinstance(node, TreePlanLeafNode):
             node.event_index += offset
         elif isinstance(node, TreePlanNestedNode):
             nested_pattern = TreePlanBuilder.__create_dummy_subpattern(
                 pattern, arg)
             TreePlanBuilder.__adjust_nested_indices(
                 nested_pattern, node.sub_tree_plan,
                 node.nested_event_index + offset)
             offset += nested_pattern.count_primitive_events(
                 positive_only=True) - 1
     return root
Пример #5
0
 def __extract_nested_pattern(self, pattern: Pattern, statistics: Dict):
     """
     This function is done recursively, to support nested pattern's operators (i.e. And(Seq,Seq)).
     When encounters KleeneClosure or CompositeStructure, it computes this operator's tree plan (recursively...)
     and uses the returned tree plan's root as a new "simple" (primitive) event (with its statistics updated
     according to its subtree nodes), such that all nested Kleene/Composite operators can be treated as "simple"
     ones.
     For every "flat" pattern, it invokes an algorithm (to be implemented by subclasses) that builds an evaluation
     order of the operands, and converts it into a left-deep tree topology.
     """
     if isinstance(pattern.positive_structure, PrimitiveEventStructure):
         return pattern, statistics, None, None, None
     # a nested structure
     nested_topologies = []
     nested_args = []
     nested_cost = []
     nested_arrival_rates = []
     modified_statistics = {}
     if StatisticsTypes.SELECTIVITY_MATRIX in statistics:
         # If we have a selectivity matrix, than we need to create new one, that has the size of the "flat" root
         # operator and all its entries are computed according to the nested operators in each composite/kleene
         # structure.
         modified_statistics[StatisticsTypes.SELECTIVITY_MATRIX] = \
             TreePlanBuilder.__create_selectivity_matrix_for_nested_operators(pattern, statistics)
     for arg in pattern.get_top_level_structure_args(positive_only=True):
         # This loop creates (recursively) all the nested subtrees
         if not isinstance(arg, PrimitiveEventStructure):
             # If we are here than this structure is composite or unary.
             # And first create new pattern that fits the nested operator's stats and structure.
             pattern, nested_topologies, nested_arrival_rates, nested_cost, nested_args = \
                 self.__handle_nested_operator(arg, pattern, statistics, nested_topologies,
                                               nested_arrival_rates, nested_cost, nested_args)
         else:
             # If we are here, than this structure is primitive
             pattern, nested_topologies, nested_arrival_rates, nested_cost, nested_args = \
                 TreePlanBuilder.__handle_primitive_event(pattern, statistics, nested_topologies,
                                                          nested_arrival_rates, nested_cost, nested_args)
     modified_statistics[
         StatisticsTypes.ARRIVAL_RATES] = nested_arrival_rates
     return pattern, modified_statistics, nested_topologies, nested_args, nested_cost