POMDPPlanners.tests.test_environments.test_pacman_native package
Submodules
POMDPPlanners.tests.test_environments.test_pacman_native.test_pacman_kernel_cache module
Per-action C++ kernel cache parity tests for PacManPOMDP.
These tests pin down the new per-action _trans_kernel_cache /
_obs_kernel_cache behaviour. They guarantee that:
_get_trans_kernel(action)/_get_obs_kernel(action)return the same Python object on repeated calls (cache hit).observation_log_probabilityproduces numerically identical results when routed through the cached kernel vs. a freshly constructed kernel (atol = 1e-12 — both paths execute the same C++ code).The env survives a pickle round-trip with the cache dropped, and the restored env behaves identically to the original on
sample_next_state,sample_observationandreward_batch.
- class POMDPPlanners.tests.test_environments.test_pacman_native.test_pacman_kernel_cache.TestObservationLogProbabilityCachedVsFresh[source]
Bases:
objectNumerical parity: cached path vs. freshly built kernel.
- test_observation_log_probability_matches_fresh_kernel()[source]
Test that the cached
observation_log_probabilityequals a freshly built kernel’s output.- Return type:
- Purpose: Validates that routing through the cached kernel gives
byte-equivalent log-probabilities (both paths execute the same C++ code).
- Given: A built env, a non-terminal next_state, and a 2-D batch of
candidate observations stacked from 16 sampled obs arrays.
- When:
env.observation_log_probability(next_state, action, obs_batch) is called using the cached kernel, and a freshly constructed
PacManObservationCppwith the same (next_state, action) is used to computenp.log(probability)directly.
Then: The two arrays are equal within atol=1e-12 for each action.
Test type: integration
- class POMDPPlanners.tests.test_environments.test_pacman_native.test_pacman_kernel_cache.TestPerActionKernelCache[source]
Bases:
objectCache hit + sample-driven warming behaviour.
- test_repeated_get_obs_kernel_returns_same_object()[source]
Test that
_get_obs_kernelis idempotent per action.- Return type:
- Purpose: Validates that the per-action observation kernel cache
returns the exact same Python object on a second call for the same action.
Given: A freshly constructed PacManPOMDP with empty caches. When:
_get_obs_kernel(a)is called twice for each action in{0, 1, 2, 3}.Then:
id()of the two returned kernels is equal for each action.Test type: unit
- test_repeated_get_trans_kernel_returns_same_object()[source]
Test that
_get_trans_kernelis idempotent per action.- Return type:
- Purpose: Validates that the per-action transition kernel cache
returns the exact same Python object on a second call for the same action, and distinct objects across actions.
Given: A freshly constructed PacManPOMDP with empty caches. When:
_get_trans_kernel(a)is called twice for each action in{0, 1, 2, 3}.- Then:
id()of the two returned kernels is equal for each action, and the four cached objects are pairwise distinct.
Test type: unit
- test_sample_next_state_warms_cache_once_per_action()[source]
Test that 100
sample_next_statecalls reuse the cached kernel.- Return type:
- Purpose: Validates the hot-path cache reuse — repeatedly sampling
should not rebuild the kernel.
Given: A freshly constructed env and a sampled initial state. When:
sample_next_state(state, action)is called 100 times foreach of the four actions.
- Then: After the first call for an action, the cached kernel is
identical to the one returned by
_get_trans_kerneland persists across all 100 calls.
Test type: unit
- class POMDPPlanners.tests.test_environments.test_pacman_native.test_pacman_kernel_cache.TestPickleRoundTrip[source]
Bases:
objectPickling drops kernels and rebuilds lazily.
- test_pickle_drops_caches_and_keeps_identical_behaviour()[source]
Test pickle round-trip preserves env behaviour while dropping kernel caches.
- Return type:
- Purpose: Validates that
__getstate__/__setstate__strip the (pybind11, non-picklable) kernels and the restored env behaves identically to the original on the env-level API.
- Given: A built env warmed by sampling once for action 0 (so its
transition cache holds one entry).
- When:
pickle.dumpsthenpickle.loadsruns on the env, and the restored env is queried with the same (state, action) under shared native and numpy seeds.
- Then: The restored env has empty caches,
sample_next_statereturns the same shape/values, and
reward_batchagrees byte-for-byte on a 4-particle batch.
Test type: integration
POMDPPlanners.tests.test_environments.test_pacman_native.test_pacman_native_equivalence module
Native↔Python equivalence tests for the PacMan POMDP C++ port.
These tests target the PacManTransitionCpp C++ kernel directly via the
PacManPOMDP env API (sample_next_state /
transition_log_probability / sample_observation /
observation_log_probability). The per-call Python wrapper classes
(PacManStateTransitionModel / PacManObservationModel) were
deleted in PR-D-Pacman together with the
state_transition_model / observation_model factory methods; the
env-level methods construct the native kernel directly.
- Run-time notes:
Each test that depends on reproducibility calls
_native.set_seed(...)at the top of the test, because each_native.soowns its own per-module RNG singleton and the test suite does not share a single source of randomness with numpy.
- class POMDPPlanners.tests.test_environments.test_pacman_native.test_pacman_native_equivalence.TestAggressiveDistribution[source]
Bases:
object- test_aggressive_ghost_empirical_matches_probability()[source]
Test empirical sample distribution matches transition_log_probability.
- Return type:
- Purpose: Validates that the softmax-sampled ghost move under the
aggressive strategy in C++ produces frequencies that match the analytic
transition_log_probabilityevaluation for the same transition.
Given: A 5x5 env with 1 aggressive ghost and no walls; seeded 0. When: 20_000 samples are drawn via env.sample_next_state; the
empirical per-next-state frequency is compared against
np.exp(env.transition_log_probability(state, action, unique_states)).Then: max |freq - prob| < 0.02 across the support.
Test type: integration
- class POMDPPlanners.tests.test_environments.test_pacman_native.test_pacman_native_equivalence.TestCollisionTerminal[source]
Bases:
object- test_pacman_walking_into_ghost_sets_terminal()[source]
Test that stepping onto a ghost sets the terminal flag.
Purpose: Validates the post-move collision check.
- Return type:
- Given: PacMan at (3, 2) with a ghost at (3, 3). Action east moves
PacMan to (3, 3) — the ghost may move away, but we repeat the test with a ghost the env is forced to stay in place: use the patrol strategy with an initial direction that blocks movement. For the simpler invariant here we seed many times and check at least one rollout yields a collision to terminal.
- When: env.sample_next_state is called up to 50 times with different
seeds until a transition produces a collision.
Then: At least one sample lands on terminal=True.
Test type: unit
- class POMDPPlanners.tests.test_environments.test_pacman_native.test_pacman_native_equivalence.TestNativeSampleAgainstBatchSample[source]
Bases:
objectTest per-particle native sample() and batch_sample() agree row-by-row.
- Return type:
- Purpose: Validates that the single-instance and batch entry points of
PacManTransitionCpp draw from the same RNG stream in the same order, so bearing the same seed they produce identical outputs.
- Given: A seeded native RNG and a batch of particles. The batch contains
5 copies of the initial state. The kernel is constructed directly via the env’s cached ctor kwargs.
- When: batch_sample is called on the 5-row batch via env.sample_next_state_batch,
and in a separate seeded run env.sample_next_state is called 5 times in a row on the same state.
Then: The two sequences of 5 ndarrays are equal row-for-row.
Test type: integration
- class POMDPPlanners.tests.test_environments.test_pacman_native.test_pacman_native_equivalence.TestPelletCollection[source]
Bases:
object- test_moving_onto_pellet_flips_mask_and_increments_score()[source]
Test that PacMan moving onto an active pellet collects it.
- Return type:
- Purpose: Validates the collection / score-update branch of the
transition kernel.
- Given: PacMan at (1, 0) with all 4 pellets active and score 0. Action
east moves PacMan to (1, 1) which is a registered pellet position.
When: env.sample_next_state is called once. Then: Pellet index 0 (the (1,1) pellet) flips from 1.0 to 0.0, and
the score increases by exactly
env.pellet_reward.Test type: unit
- class POMDPPlanners.tests.test_environments.test_pacman_native.test_pacman_native_equivalence.TestTerminalAbsorbing[source]
Bases:
object- test_terminal_state_is_absorbing()[source]
Test that sampling from a terminal state returns the state unchanged.
- Return type:
- Purpose: Validates the
if terminal return statefast path in apply_transition — terminal states are absorbing.
Given: A terminal state with terminal flag = 1.0. When: env.sample_next_state is called. Then: The returned state array equals the input byte-for-byte.
Test type: unit
- class POMDPPlanners.tests.test_environments.test_pacman_native.test_pacman_native_equivalence.TestWinCondition[source]
Bases:
object- test_collecting_last_pellet_sets_terminal()[source]
Test that collecting the last remaining pellet sets terminal=True.
Purpose: Validates the “no pellets remaining” terminal rule.
Given: PacMan at (1, 0) with only one pellet left at (1, 1). When: Action east moves PacMan onto (1, 1). Then: The next state has no active pellets and terminal=True.
Test type: unit
- Return type:
- POMDPPlanners.tests.test_environments.test_pacman_native.test_pacman_native_equivalence.test_scalar_obs_log_prob_un_floored_matches_batch_after_fix()[source]
Scalar obs log-prob below -690 floor matches the batch path post-fix.
- Return type:
- Purpose: Pins the post-fix contract for PacManPOMDP that
observation_log_probability(scalar) andobservation_log_probability_per_state(batch) agree on a moderate-density anchor whose analytic log-probability is well below the oldlog(p + 1e-300) ≈ -690.776floor but still above the kernel’s internal float64 underflow threshold. Pre-fix, the scalar path floored such values at ~-690.776 while the batch path returned the un-floored kernel log-likelihood — the asymmetry that motivated the env-wide log-prob floor removal.- Given: The shared 2-ghost env from
_build_env, a fresh initial state, action 0, and a 2-D ndarray observation
[[31, 31, 31, 31]](one row of 2*num_ghosts coordinates). At this offset the analytic 4-D Gaussian log-pdf for both ghosts is ≈ -710.187.- When: Both
observation_log_probability(with the 2-D ndarray fast path) and
observation_log_probability_per_stateare evaluated on the same (next_state, action, observation).- Then: Both return finite, equal values to within atol=1e-6, and
the common value is below -700 (past the old floor).
Test type: unit