Skip to content

Fix trim expansion loops testing the already-included cell - #102

Open
lispandfound wants to merge 1 commit into
mainfrom
fix/86-trim-expansion-boundary
Open

Fix trim expansion loops testing the already-included cell#102
lispandfound wants to merge 1 commit into
mainfrom
fix/86-trim-expansion-boundary

Conversation

@lispandfound

Copy link
Copy Markdown
Contributor

Fixes #86

Problem

The two expansion loops in trim_array_to_target_length tested a cell that is already inside the window rather than the candidate cell about to be absorbed:

# before
while left > 0 and slip_function[left] >= keep_threshold:            # left is already included
    left -= 1
while right < len(slip_function) and slip_function[right - 1] >= keep_threshold:  # right-1 already included
    right += 1

So whenever a boundary cell was above keep_threshold, the window swallowed its neighbour without ever checking that neighbour — typically a sub-threshold cell the shrink loop had just removed.

Measured impact

input target before after tolerance (±2*dx)
[1,1,9,1,1] 1 (0,4) len 4 (0,3) len 3 before violates (|4-1|=3 > 2)
[1,1,1,9,1,1,1] 1 (1,5) len 4 (1,4) len 3 before violates (|4-1|=3 > 2)
[0,0,9,0,0] 1 (2,3) (2,3) unchanged

Trace for the first case: the shrink loop correctly reaches (0, 3), then the second expansion loop sees slip_function[right - 1] == slip_function[2] == 9.0 >= 3.0 and grows right to 4, absorbing cell 3 whose value is 1.0 — below the threshold and never examined.

Correction to the issue as filed

Issue #86 cited [1,1,9,1,1] with target_length=3 returning (0, 5) — "the whole array" — as evidence. That result is actually within the documented target_length ± 2*dx tolerance (|5-3| = 2), so it is not by itself a defect; I have noted that on the issue. The tolerance violation at target_length=1 above is the real evidence, and it is what the new test asserts.

Cases where the absorbed cell is exactly zero are also not observable, because the zero-stripping loops further down clean them up. The bug only shows with sub-threshold but nonzero neighbours.

Changes

  • source_modelling/trim.py — test slip_function[left - 1] and slip_function[right], the cells actually being considered.
  • tests/test_trim.py — add test_trim_expansion_does_not_absorb_sub_threshold_cells, asserting both the exact window and the documented tolerance.

Verification

  • 2 of the 3 new parameters fail without the fix, all pass with it.
  • pytest tests/test_trim.py — 12 passed.
  • ruff check, ruff format, numpydoc lint clean.

Note this touches the same function as #88 (the bounds-guard ordering a few lines below), so those two branches will want a trivial rebase depending on merge order.

🤖 Generated with Claude Code

The two expansion loops in trim_array_to_target_length tested
slip_function[left] and slip_function[right - 1] -- cells already inside
the window -- rather than the candidate cells left - 1 and right. A
boundary cell above the keep threshold therefore pulled in its neighbour
without that neighbour ever being examined, widening the returned window
past the documented target_length +/- 2 * dx tolerance.

For [1, 1, 9, 1, 1] with target_length=1 and dx=1 the function returned
(0, 4) -- a 4-cell window for a 1-cell target, |4 - 1| = 3 > 2 -- where
it now returns (0, 3).

Fixes #86

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

trim.py: expansion loops test the already-included cell, undoing the trim

1 participant