feat: эвристическое отсечение (pruning) в explode_callgraph_branches
Добавлены параметры для 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 <qwen-coder@alibabacloud.com>
This commit is contained in:
@@ -111,18 +111,36 @@ class GraphWalker:
|
|||||||
return head
|
return head
|
||||||
|
|
||||||
@classmethod
|
@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
|
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:
|
if cache_key in cls._explode_cache:
|
||||||
return cls._explode_cache[cache_key]
|
return cls._explode_cache[cache_key]
|
||||||
|
|
||||||
# Вычисляем лениво через generator
|
# Вычисляем лениво через 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
|
cls._explode_cache[cache_key] = variants
|
||||||
@@ -130,22 +148,46 @@ class GraphWalker:
|
|||||||
return variants
|
return variants
|
||||||
|
|
||||||
@classmethod
|
@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:
|
Yields:
|
||||||
CallgraphVariant: Варианты преобразований по одному
|
CallgraphVariant: Варианты преобразований по одному
|
||||||
"""
|
"""
|
||||||
for variant in g.variants:
|
for variant in g.variants:
|
||||||
if len(variant.subgraphs) == 0:
|
if len(variant.subgraphs) == 0:
|
||||||
|
# Pruning: проверяем порог приоритета
|
||||||
|
variant_priority = variant.injector.priority if isinstance(variant.injector.priority, (int, float)) else 0.0
|
||||||
|
if variant_priority >= priority_threshold:
|
||||||
yield variant
|
yield variant
|
||||||
continue
|
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 = []
|
subg_iterators = []
|
||||||
for subg in variant.subgraphs:
|
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:
|
if len(combinations) == 0:
|
||||||
subg_iterators.append([None])
|
subg_iterators.append([None])
|
||||||
else:
|
else:
|
||||||
|
|||||||
Reference in New Issue
Block a user