From 10f9672577e60e8537ad75ba45007ac000b3d75d Mon Sep 17 00:00:00 2001 From: Qwen Code Assistant Date: Sat, 28 Mar 2026 17:46:31 +0000 Subject: [PATCH] =?UTF-8?q?feat:=20=D1=8D=D0=B2=D1=80=D0=B8=D1=81=D1=82?= =?UTF-8?q?=D0=B8=D1=87=D0=B5=D1=81=D0=BA=D0=BE=D0=B5=20=D0=BE=D1=82=D1=81?= =?UTF-8?q?=D0=B5=D1=87=D0=B5=D0=BD=D0=B8=D0=B5=20(pruning)=20=D0=B2=20exp?= =?UTF-8?q?lode=5Fcallgraph=5Fbranches?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Добавлены параметры для pruning: - priority_threshold: минимальный приоритет для рассмотрения - min_consumed_types: минимальное количество consumed_types Pruning применяется в: - _explode_callgraph_branches_lazy(): отсечение по приоритету и consumed_types - explode_callgraph_branches(): передача параметров pruning По умолчанию pruning отключён (priority_threshold=-1e9, min_consumed_types=0) для обратной совместимости. Файлы: - graph_walker.py: параметры pruning в explode и _explode_lazy Co-authored-by: Qwen-Coder --- src/breakshaft/graph_walker.py | 56 +++++++++++++++++++++++++++++----- 1 file changed, 49 insertions(+), 7 deletions(-) diff --git a/src/breakshaft/graph_walker.py b/src/breakshaft/graph_walker.py index 9e8c627..7a08af4 100644 --- a/src/breakshaft/graph_walker.py +++ b/src/breakshaft/graph_walker.py @@ -111,18 +111,36 @@ class GraphWalker: return head @classmethod - def explode_callgraph_branches(cls, g: Callgraph, from_types: frozenset[type]) -> list[CallgraphVariant]: + def explode_callgraph_branches(cls, g: Callgraph, from_types: frozenset[type], + priority_threshold: float = -1e9, + min_consumed_types: int = 0) -> list[CallgraphVariant]: + """ + Взрыв графа преобразований с pruning. + + Args: + g: Граф преобразований + from_types: Исходные типы + priority_threshold: Минимальный приоритет для рассмотрения (pruning) + min_consumed_types: Минимальное количество consumed_types (pruning) + + Returns: + list[CallgraphVariant]: Варианты преобразований + """ # Кэширование: создаём хэш графа # Хэш графа = хэш всех вариантов g_hash = hash(frozenset(g.variants)) if g.variants else 0 - cache_key = (g_hash, hash(from_types)) + cache_key = (g_hash, hash(from_types), hash(priority_threshold), hash(min_consumed_types)) # Проверяем кэш if cache_key in cls._explode_cache: return cls._explode_cache[cache_key] # Вычисляем лениво через generator - variants = list(cls._explode_callgraph_branches_lazy(g, from_types)) + variants = list(cls._explode_callgraph_branches_lazy( + g, from_types, + priority_threshold=priority_threshold, + min_consumed_types=min_consumed_types + )) # Сохраняем в кэш cls._explode_cache[cache_key] = variants @@ -130,22 +148,46 @@ class GraphWalker: return variants @classmethod - def _explode_callgraph_branches_lazy(cls, g: Callgraph, from_types: frozenset[type]): + def _explode_callgraph_branches_lazy(cls, g: Callgraph, from_types: frozenset[type], + priority_threshold: float = -1e9, + min_consumed_types: int = 0): """ - Ленивая версия explode_callgraph_branches (generator). + Ленивая версия explode_callgraph_branches (generator) с pruning. + + Args: + g: Граф преобразований + from_types: Исходные типы + priority_threshold: Минимальный приоритет для рассмотрения (pruning) + min_consumed_types: Минимальное количество consumed_types (pruning) Yields: CallgraphVariant: Варианты преобразований по одному """ for variant in g.variants: if len(variant.subgraphs) == 0: - yield variant + # Pruning: проверяем порог приоритета + variant_priority = variant.injector.priority if isinstance(variant.injector.priority, (int, float)) else 0.0 + if variant_priority >= priority_threshold: + yield variant + continue + + # Pruning: проверяем consumed_types + if len(variant.consumed_from_types) < min_consumed_types: + continue + + # Pruning: проверяем приоритет + variant_priority = variant.injector.priority if isinstance(variant.injector.priority, (int, float)) else 0.0 + if variant_priority < priority_threshold: continue # Собираем ленивые итераторы для подграфов subg_iterators = [] for subg in variant.subgraphs: - combinations = list(cls._explode_callgraph_branches_lazy(subg, from_types)) + combinations = list(cls._explode_callgraph_branches_lazy( + subg, from_types, + priority_threshold=priority_threshold, + min_consumed_types=min_consumed_types + )) if len(combinations) == 0: subg_iterators.append([None]) else: