TrajectoryBranchNoveltyUtilityConfiguration
Cell score for branch (transition) novelty: traffic × (1 − branch_coverage), floored.
Coverage objectives mark a cell done once it leads somewhere good, so they go blind to an un-taken branch at an already-good, high-traffic cell — the rut the policy pours through but always exits the same way (the step before a never-crossed jump). This utility targets branches, not cells: branch_coverage = distinct_successors / (distinct_successors + branch_half) is low exactly where few distinct successor cells have been tried, so a heavily-trafficked cell with one habitual exit scores high. Restarts land there and the random-episode fraction tries the untaken branch, discovering the jump's downstream. "Explore everywhere" = explore every branch.
traffic = visits / (visits + visit_half) saturates to 1 for heavily-visited cells so it balances against (1 − branch_coverage) ∈ [0, 1] instead of being dominated by raw counts.
floor keeps every reachable (visited at least once) cell at a minimum score forever, so exploration never fully abandons a solved region — pairs with the branch term to keep coverage from collapsing to zero once a cell looks done.
Properties
is_cell_scoring
is_cell_scoring: booluses_cell_key_grouping
uses_cell_key_grouping: boolValues
branch_half
branch_half: float = Field(default=2.0, gt=0.0)Distinct-successor count at which branch coverage reaches 0.5.
floor
floor: float = Field(default=0.0, ge=0.0)Minimum score for any cell visited at least once, so solved regions keep a restart trickle.
kind
kind: Literal['branch_novelty'] = 'branch_novelty'visit_half
visit_half: float = Field(default=1000.0, gt=0.0)Visit count at which the traffic factor reaches 0.5.