Coverage for src/extratools_core/settools.py: 0%

29 statements  

« prev     ^ index     » next       coverage.py v7.8.0, created at 2025-04-05 12:34 -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 add_to_set[T](s: set[T], x: T) -> bool: 

8 if x in s: 

9 return False 

10 

11 s.add(x) 

12 return True 

13 

14 

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

16 return map(frozenset, enumerate_subseqs_with_gaps(a)) 

17 

18 

19def best_subset[T]( 

20 a: set[T], 

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

22) -> set[T]: 

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

24 

25 

26def set_cover[T]( 

27 whole: Iterable[T], 

28 covers: Iterable[AbstractSet[T]], 

29 *, 

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

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

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

33 

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

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

36 

37 while whole_set and cover_sets: 

38 best_score: float | None 

39 best_set: frozenset[T] | None 

40 best_score, best_set = None, None 

41 

42 for curr in cover_sets: 

43 temp_set: frozenset[T] = curr & whole_set 

44 if temp_set: 

45 temp_score: float = local_score_func(temp_set) 

46 if not best_score or temp_score > best_score: 

47 best_score, best_set = temp_score, curr 

48 

49 if not best_set: 

50 return 

51 

52 yield best_set 

53 

54 whole_set.difference_update(best_set) 

55 cover_sets.remove(best_set)