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_score is 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 ** horizon exceeds float64 max. With the naive formula x1 = 1 - belief_visits**horizon overflows to -inf, x3 = log(x1 / x2) evaluates to +inf, bound evaluates to +inf, and every per-action score collapses to -inf. After the first iteration sets best_score=-inf the strict comparison score < best_score is 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 ** horizon form 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 - 1 in the numerator. A previous implementation dropped the - 1 and used log(N_b^{T-t} / (delta (N_b - 1))) instead, which collapses to T-t * log(N_b) for small horizons and overstates the bound (e.g., for N_b = 2, T-t = 1, the term is log(2) 0.693 instead of the correct log(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 chosen q and visit counts.

Given: A belief node with visit_count = 2 and 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_arena is called. Then: Returns child A (q=0). Under the correct formula

x3 = log(2), child A’s LCB ≈ -0.832 vs child B’s ≈ -0.665, so A wins. Under the buggy x3 = log(4) formula, child B’s LCB ≈ -1.354 vs child A’s ≈ -1.177, so B would (wrongly) win.

Test type: unit

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

POMDPPlanners.tests.test_planners.test_planners_utils.test_dpw module

POMDPPlanners.tests.test_planners.test_planners_utils.test_rollout module