Coverage for src/extratools_core/set/subset.py: 0%
24 statements
« prev ^ index » next coverage.py v7.8.1, created at 2025-05-23 01:16 -0700
« prev ^ index » next coverage.py v7.8.1, created at 2025-05-23 01:16 -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 enumerate_subsets[T](a: AbstractSet[T]) -> Iterable[AbstractSet[T]]:
8 return map(frozenset, enumerate_subseqs_with_gaps(a))
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))
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
26 whole_set: set[T] = set(whole)
27 cover_sets: set[frozenset[T]] = {frozenset(x) for x in covers}
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
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
41 if not best_set:
42 return
44 yield best_set
46 whole_set.difference_update(best_set)
47 cover_sets.remove(best_set)