def _create_tree_topology(self, pattern: Pattern, statistics: Dict, leaves: List[TreePlanNode]): if StatisticsTypes.ARRIVAL_RATES in statistics and \ StatisticsTypes.SELECTIVITY_MATRIX in statistics and \ len(statistics) == 2: selectivity_matrix = statistics[StatisticsTypes.SELECTIVITY_MATRIX] arrival_rates = statistics[StatisticsTypes.ARRIVAL_RATES] else: raise MissingStatisticsException() order = self._get_initial_order(selectivity_matrix, arrival_rates) args_num = len(order) items = tuple(order) suborders = {(i, ): (TreePlanLeafNode(i), self._get_plan_cost(pattern, TreePlanLeafNode(i), statistics)) for i in items} tree_to_second_min_tree_map = {} invariants = ZStreamTreeInvariants(self._get_plan_cost) all_sub_trees = [] # iterate over suborders sizes for i in range(2, args_num + 1): # iterate over suborders of size i for j in range(args_num - i + 1): # create the suborder (slice) to find its optimum. suborder = tuple(order[t] for t in range(j, j + i)) # use first split of suborder as speculative best. order1_, order2_ = suborder[:1], suborder[1:] tree1_, _ = suborders[order1_] tree2_, _ = suborders[order2_] tree = TreePlanBuilder._instantiate_binary_node( pattern, tree1_, tree2_) cost = self._get_plan_cost(pattern, tree, statistics) suborders[suborder] = tree, cost second_prev_cost = cost second_min_tree = tree # iterate over splits of suborder for k in range(2, i): # find the optimal topology of this split, according to optimal topologies of subsplits. order1, order2 = suborder[:k], suborder[k:] tree1, _ = suborders[order1] tree2, _ = suborders[order2] _, prev_cost = suborders[suborder] new_tree = TreePlanBuilder._instantiate_binary_node( pattern, tree1, tree2) new_cost = self._get_plan_cost(pattern, new_tree, statistics) if new_cost < prev_cost: second_prev_cost = prev_cost second_min_tree = suborders[suborder][0] suborders[suborder] = new_tree, new_cost elif new_cost < second_prev_cost or second_min_tree == tree: second_prev_cost = new_cost second_min_tree = new_tree if i != 2: tree_to_second_min_tree_map[suborders[suborder] [0]] = second_min_tree # Eliminates all trees that are not in best tree from map_tree_to_second_min_tree InvariantAwareZStreamTreeBuilder.__get_relevant_sub_trees( suborders[items][0], all_sub_trees) for tree in all_sub_trees: invariants.add(Invariant(tree, tree_to_second_min_tree_map[tree])) # return the topology (index 0 at tuple) of the entire order, indexed to 'items' return suborders[items][0], invariants