Development documentation — 0.3.0a4 / main

This is the development branch, not a published stable release. Use the source installation guide. Functional checks cover Ubuntu, Windows and macOS; interpreter, artifact and optional-feature limits still apply. Read support, release gates and known limitations before relying on results.

IPR unchanged-block evaluation pruning

IPR now omits decoder/objective calls when assigning a guide block would leave the current chromosome's representation unchanged. It reuses the last completed cost of that current chromosome. This is local path bookkeeping, not a persistent fitness cache or phenotype-based deduplication.

Preserve path decisions, not redundant calls

The original block order, max(1,num_blocks-1) virtual steps, fixed-block bookkeeping and strict first-minimum tie decisions remain. An unchanged move still participates in selection at the known current cost and can consume a virtual step.

It would be incorrect to simply delete equal blocks and shorten the loop to different_blocks-1: that can change which meaningful candidates are explored, especially when all remaining genuine moves are worse or tied. Shared blocks also allow the existing path to reach the full guide early; that behavior is retained.

Only same-dtype, byte-identical blocks qualify. Signed-zero changes remain ordinary evaluations because a decoder can distinguish their signs. Different dtypes are handled conservatively through the existing assignment/callback path, even if a cast happens to leave numerical values unchanged. Partial final blocks and one-coordinate chromosomes remain covered. Caller parents remain detached.

Exact callback evidence

For the maintained 20-coordinate example, parents differ only in the first two-coordinate block and the guide improves a sum-of-squares objective:

Before After
Objective evaluations 55 2
Distinct evaluated vectors 2 2
Start evaluations 10 1
Guide evaluations 45 1
Returned chromosome Guide Same guide

An entirely representation-identical pair passed directly to the kernel evaluates the initial point once. Normal solve already backs off before relinking identical effective parents. A worse/tied genuine last-block move may still be evaluated repeatedly across virtual steps: removing those further repeats is not this change.

Independent scalar/list oracles run both legacy and pruned policies over identical, first/last/multiple changed blocks, better/worse/flat objectives and small/partial dimensions. For pure deterministic scoring they retain legacy result bits and costs, while actual callback traces exactly match the pruned oracle. Additional checks cover signed zero, mixed dtypes, original callback failures, an expired session before the next changed candidate, owned parent snapshots and the scalar copy-kernel benchmark control.

benchmarks/references/ipr-pruned-blocks-reference.jsonl repeats the bounded 36-case matrix at 1,024 completed objective evaluations each, charging all initialization. Pools remain unique and identical-parent selections remain zero. Pruning lets a fixed callback budget cover different numbers of paths and consume different RNG draws; this matrix is not an equal-path comparison or a timing measurement. Earlier pre-admission and unique-admission reference files remain unchanged historical data.

Callback and migration contract

Stateful or stochastic callbacks now run fewer times within a path. Reusing a known no-op cost does not reproduce fresh independent observations. Such objective trajectories and even results can change. No equivalence is promised for callbacks that depend on invocation count, time, mutation, random state or array identity. All changed candidates still pass through ordinary decoder/objective isolation, finite-result validation and cooperative deadline/error handling. No user callback is interrupted while executing.

Even for deterministic objectives, fixed-time/fixed-evaluation full searches can change trajectories because saved callbacks admit more path work. Pin 1a17524 to reproduce the preceding unpruned policy; no legacy flag or new dependency was added. The internal ipr-unchanged-block-pruning-v1 replay token marks old IPR incompatible with RNG-only replay, rather than mislabeling intentional work changes as isolation regressions.

benchmarks/algorithms/ipr.py::ScalarIPR now shares current pruning/virtual steps, varying only per-gene versus slice assignment. Do not compare an unpruned scalar kernel with a pruned solver and call the difference a block-copy speedup. Historical speed data retains its original source/policy scope; it is not a new measurement of this code.

This establishes reduced redundant callbacks in controlled paths, not measured whole-solver throughput, quality, feasibility, CPU/RSS/energy savings or C++ parity. No population-size default, native backend or active Knapsack benchmark was changed.