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
« 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
4from .seq.subseq import best_subseq_with_gaps, enumerate_subseqs_with_gaps
7def add_to_set[T](s: set[T], x: T) -> bool:
8 if x in s:
9 return False
11 s.add(x)
12 return True
15def enumerate_subsets[T](a: AbstractSet[T]) -> Iterable[AbstractSet[T]]:
16 return map(frozenset, enumerate_subseqs_with_gaps(a))
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))
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
34 whole_set: set[T] = set(whole)
35 cover_sets: set[frozenset[T]] = {frozenset(x) for x in covers}
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
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
49 if not best_set:
50 return
52 yield best_set
54 whole_set.difference_update(best_set)
55 cover_sets.remove(best_set)