Source code for phileas.iteration.random

import dataclasses
from dataclasses import dataclass

from phileas.iteration.base import ChildPath, DataTree, IterationTree


[docs] @dataclass(frozen=True) class Seed: """ Seed of a random iteration node, used by its RNG. """ #: Path of the node in the biggest tree that used it. path: ChildPath #: Salt value, to customize iteration independently of the shape of the #: iteration tree. salt: DataTree | None
[docs] def to_bytes(self) -> bytes: """ Convert the seed to bytes, for RNG seeding. """ salt = f":{self.salt}" if self.salt is not None else "" return ("/".join(map(str, self.path)) + salt).encode("utf-8")
[docs] @dataclass(frozen=True) class RandomTree: """ Additional base class of random iteration trees. """ #: Seed of the generator used by the random tree. It must be guaranteed that #: successive iteration values only depend on the seed value. #: #: For iteration to be possible, the seed must be set. If you don't want to #: manually specify the seed, you can use #: :py:func:`~phileas.iteration.utility.generate_seeds`. seed: Seed | None = None
[docs] def generate_seeds(tree: IterationTree, salt: DataTree | None = None) -> IterationTree: """ Populate the seeds of the random nodes and leaves of a tree, using the given salt value. """ def _generate_seed(tree: IterationTree, path: ChildPath) -> IterationTree: if isinstance(tree, RandomTree): new_seed = Seed(path, salt) return dataclasses.replace(tree, seed=new_seed) # type: ignore[call-arg] else: return tree return tree.depth_first_modify(_generate_seed)