import random
from enum import Enum
from typing import Any, Generic, TypeVar, List
from src.random_collections.random_collection_interface import IRandom
V = TypeVar('V', bound=Enum)
[docs]
class RandomCollection(Generic[V], IRandom[V]):
"""
Collection enabling weighted random selection of enum values with dynamic weight randomization.
Attributes:
_values (List[V]): List of enum members to choose from.
_weights (List[float]): Corresponding weights for each enum member.
randomization_factor (float): Multiplier range for weight perturbation.
"""
[docs]
def __init__(
self,
values: List[V],
weights: List[float],
randomization_factor: float = 1.5
):
"""
Initialize with lists of enum members and their base weights.
Args:
values (List[V]): Enum members available for selection.
weights (List[float]): Base weights for each member.
randomization_factor (float): Max multiplier for weight randomization.
"""
self._values: List[V] = values
self._weights: List[float] = weights
self.randomization_factor: float = randomization_factor
self._randomize_weights()
[docs]
def get_random_value(self, excluding: List[V] = None) -> V:
"""
Select a random enum member based on weights, excluding specified members.
Args:
excluding (List[V], optional): Members to skip. Defaults to None.
Returns:
V: Selected enum member.
"""
excluding = excluding or []
choice = random.choices(self._values, weights=self._weights, k=1)[0]
while choice in excluding:
choice = random.choices(self._values, weights=self._weights, k=1)[0]
return choice
def _randomize_weights(self) -> None:
"""
Apply random perturbation to each weight within [1, randomization_factor] range.
"""
self._weights = [
w * self._random_multiplier()
for w in self._weights
]
def _random_multiplier(self) -> float:
"""
Generate a random multiplier between 1 and `randomization_factor`.
Returns:
float: Random multiplier.
"""
return 1 + (self.randomization_factor - 1) * random.random()
[docs]
class RandomCollectionBuilder:
"""
Factory for creating RandomCollection instances from common data structures.
"""
[docs]
@staticmethod
def build_from_enum(enum_type: type[Enum]) -> RandomCollection[Enum]:
"""
Create a RandomCollection for enum members with equal base weights.
Args:
enum_type (type[Enum]): Enum class to build collection from.
Returns:
RandomCollection[Enum]: Collection with uniform weights.
"""
members = list(enum_type)
weights = [1.0] * len(members)
return RandomCollection(members, weights)
[docs]
@staticmethod
def build_from_value_weight_dict(value_weight_dict: dict[V, float]) -> RandomCollection[V]:
"""
Create a RandomCollection from a dict of values to weights.
Args:
value_weight_dict (dict[V, float]): Mapping of enum or values to base weights.
Returns:
RandomCollection[V]: Collection reflecting specified weights.
"""
values = list(value_weight_dict.keys())
weights = list(value_weight_dict.values())
return RandomCollection(values, weights)
[docs]
@staticmethod
def build_from_list_of_values(values: List[V]) -> RandomCollection[V]:
"""
Create a RandomCollection from a list of values using uniform weights.
Args:
values (List[V]): List of enum members or values.
Returns:
RandomCollection[V]: Collection with equal weights.
"""
weights = [1.0] * len(values)
return RandomCollection(values, weights)