POMDPPlanners.tests.test_planners.test_planners_utils package
Submodules
POMDPPlanners.tests.test_planners.test_planners_utils.test_cvar_exploration module
Tests for cvar_exploration LCB action selection.
- POMDPPlanners.tests.test_planners.test_planners_utils.test_cvar_exploration.test_sparse_sampling_lcb_falls_back_to_greedy_when_horizon_is_zero()[source]
At horizon=0 the LCB bound is undefined — fall back to greedy q-min.
- Purpose: Validates that the LCB action selector does not return a
systematic action-index-0 default when horizon=0. Without the fix, log(1 - belief_visits**0) = log(0) = -inf collapses every per-action score to NaN, and the comparison
score < best_scoreis False for NaN, so the kernel always returns index 0 — even when later actions have strictly lower q-values.- Given: A belief node with 3 visited action children, all with
visit_count=5; child[2] has the strictly lowest q_value (0.1 vs. 5.0 for the others).
- When: _sparse_sampling_guarantees_exploration_v2_arena is called
with horizon=0.
Then: Returns child[2] (lowest q), not child[0] by default.
Test type: unit
- POMDPPlanners.tests.test_planners.test_planners_utils.test_cvar_exploration.test_sparse_sampling_lcb_handles_overflow_at_deep_horizon_and_many_visits()[source]
LCB does not collapse to action-index-0 when belief_visits**horizon overflows.
- Purpose: Validates that the LCB action selector remains correct when
belief_visits ** horizonexceeds float64 max. With the naive formulax1 = 1 - belief_visits**horizonoverflows to -inf,x3 = log(x1 / x2)evaluates to +inf,boundevaluates to +inf, and every per-action score collapses to -inf. After the first iteration sets best_score=-inf the strict comparisonscore < best_scoreis False for all subsequent indices, so the kernel returns index 0 — even when later actions have strictly lower q-values. The fix must be a log-space rewrite that stays finite for any (belief_visits, horizon).- Given: A belief node with visit_count=10_000 and 3 visited action
children, all with visit_count=10; child[2] has the strictly lowest q_value (0.1 vs. 5.0 for the others). horizon=90 makes belief_visits**horizon = 10_000**90 = 1e360, which overflows float64 (max ≈ 1.8e308).
When: _sparse_sampling_guarantees_exploration_v2_arena is called. Then: Returns child[2] (lowest q-value), not child[0] by default.
Test type: unit
- POMDPPlanners.tests.test_planners.test_planners_utils.test_cvar_exploration.test_sparse_sampling_lcb_is_deterministic_when_no_unvisited_children()[source]
Picks lowest-LCB child when all action children have visit_count >= 1.
Purpose: Validates the LCB code path actually fires once every action child has been visited at least once. With a clear Q-value gap and a small exploration_constant, LCB selection is deterministic, so the same call under different RNG seeds must return the same child.
- Given: A belief node with 3 visited action children. Two have
q_value=5.0 and one has q_value=0.1; all share visit_count=10 so the per-child exploration term collapses to a constant. The lowest-Q child therefore has the lowest LCB.
- When: _sparse_sampling_guarantees_exploration_v2_arena is called
repeatedly under different np.random seeds.
Then: Every call returns the same child (the lowest-Q one).
Test type: unit
- POMDPPlanners.tests.test_planners.test_planners_utils.test_cvar_exploration.test_sparse_sampling_lcb_matches_log_space_formula_on_safe_inputs()[source]
LCB selection on inputs that do NOT overflow agrees with the log-space form.
- Purpose: Anchors the new log-space implementation against the
analytical formula on inputs where the original
belief_visits ** horizonform is safely representable in float64. This guards against the log-space rewrite silently changing the LCB ordering on the regime where the old code was already correct.- Given: A belief node with visit_count=20 and 3 visited action
children. q_values are spread enough that the LCB ordering is stable; visit counts differ to exercise the per-child bound. horizon=10 keeps 20**10 ≈ 1e13 well under float64 max.
- When: _sparse_sampling_guarantees_exploration_v2_arena is called and
the LCB is recomputed in log-space (
horizon * log(belief_visits) - log(delta * (belief_visits - 1))).
Then: The selector returns the index with the lowest analytic LCB.
Test type: unit
- POMDPPlanners.tests.test_planners.test_planners_utils.test_cvar_exploration.test_sparse_sampling_lcb_matches_paper_formula_at_small_horizon()[source]
LCB term inside the log is
(N_b^{T-t} - 1) / (delta * (N_b - 1)).Purpose: Pins the log-space expansion of the per-action confidence bound to the formula from Theorem 1 of the ICVaR paper:
sqrt(ln((N_b^{T-t} - 1) / (delta * (N_b - 1))) / (2 N_b)). Under that formula,log((N_b^{T-t} - 1) / (delta * (N_b - 1)))must be used — with the- 1in the numerator. A previous implementation dropped the- 1and usedlog(N_b^{T-t} / (delta (N_b - 1)))instead, which collapses toT-t * log(N_b)for small horizons and overstates the bound (e.g., forN_b = 2,T-t = 1, the term islog(2) ≈ 0.693instead of the correctlog(1/0.5) = log(2)— wait this is the same — let me redo: correct = log((2^1 - 1) / (0.5 * (2 - 1))) = log(2); buggy = log((2^1) / (0.5 * (2 - 1))) = log(4) = 2*log(2)). The 2x factor inside the sqrt is enough to flip the argmin between two action children with carefully chosenqand visit counts.- Given: A belief node with
visit_count = 2and two action children (A: q=0.0, visits=4; B: q=1.0, visits=1), with
alpha=1.0,delta=0.5,min_cost=-1,max_cost=1,horizon=1,exploration_constant=1.0.
When:
_sparse_sampling_guarantees_exploration_v2_arenais called. Then: Returns child A (q=0). Under the correct formulax3 = log(2), child A’s LCB ≈ -0.832 vs child B’s ≈ -0.665, so A wins. Under the buggyx3 = log(4)formula, child B’s LCB ≈ -1.354 vs child A’s ≈ -1.177, so B would (wrongly) win.Test type: unit
- Given: A belief node with
- POMDPPlanners.tests.test_planners.test_planners_utils.test_cvar_exploration.test_sparse_sampling_lcb_prefers_less_visited_child_when_q_tied()[source]
With Q-values tied, LCB selection favors the least-visited child.
Purpose: Validates that the per-child exploration bound (which scales with 1/sqrt(child_visits) inside the guarantees-bound formula) actually drives the choice toward less-visited children when Q is not a differentiator.
- Given: Three action children with identical q_value=1.0 but visit
counts [50, 10, 100]; child[1] is the least visited.
- When: _sparse_sampling_guarantees_exploration_v2_arena is called
with a large exploration_constant so the bonus dominates.
Then: Every call returns child[1] regardless of RNG seed.
Test type: unit