Coverage for src/extratools_core/set/subset.py: 0%

24 statements  

« prev     ^ index     » next       coverage.py v7.8.1, created at 2025-05-23 02:35 -0700

1from collections.abc import Callable, Iterable 

2from collections.abc import Set as AbstractSet 

3 

4from ..seq.subseq import best_subseq_with_gaps, enumerate_subseqs_with_gaps 

5 

6 

7def enumerate_subsets[T](a: AbstractSet[T]) -> Iterable[AbstractSet[T]]: 

8 return map(frozenset, enumerate_subseqs_with_gaps(a)) 

9 

10 

11def best_subset[T]( 

12 a: set[T], 

13 score_func: Callable[[Iterable[T]], float], 

14) -> set[T]: 

15 return set(best_subseq_with_gaps(tuple(a), score_func)) 

16 

17 

18def set_cover[T]( 

19 whole: Iterable[T], 

20 covers: Iterable[AbstractSet[T]], 

21 *, 

22 score_func: Callable[[AbstractSet[T]], float] | None = None, 

23) -> Iterable[AbstractSet[T]]: 

24 local_score_func: Callable[[AbstractSet[T]], float] = score_func or len 

25 

26 whole_set: set[T] = set(whole) 

27 cover_sets: set[frozenset[T]] = {frozenset(x) for x in covers} 

28 

29 while whole_set and cover_sets: 

30 best_score: float | None 

31 best_set: frozenset[T] | None 

32 best_score, best_set = None, None 

33 

34 for curr in cover_sets: 

35 temp_set: frozenset[T] = curr & whole_set 

36 if temp_set: 

37 temp_score: float = local_score_func(temp_set) 

38 if not best_score or temp_score > best_score: 

39 best_score, best_set = temp_score, curr 

40 

41 if not best_set: 

42 return 

43 

44 yield best_set 

45 

46 whole_set.difference_update(best_set) 

47 cover_sets.remove(best_set)