Crate atune_plugin_example
Expand description
An out-of-tree sampler and scheduler, written the way a plugin author would write them.
§Why this crate exists
A release criterion asks that “the guide’s example plugin crate compiles
against the frozen traits”. Nothing in the repository provisioned such a
crate: examples/rust/custom_sampler.rs is a workspace example binary,
compiled as part of atune with the facade and all its features in scope,
which is not the situation a plugin author is in. An earlier audit tested
the criterion by writing a crate outside the repository — it compiled, its
property test passed, and then it was gone, leaving nothing that keeps the
criterion met. This crate is that check, made standing: the workspace gate
compiles it on every run.
It is deliberately not a copy of custom_sampler.rs. A second copy of the
same sampler would prove only that the same code still compiles; a different
one — antithetic pairs rather than stratification — exercises a different part
of the seam and reads as an independent implementation, which is what the
criterion is really about.
§What it proves, and what it does not
cargo test -p atune_plugin_example proves the strong statement: the seams are
implementable with atune_core as the only dependency and its default
features off, because -p is what keeps cargo from unifying system back
in from the other workspace members. A workspace-wide cargo test compiles
this crate too, but with system unified on, so it proves the weaker “the
traits are usable from outside” — still worth having, and it is the run that
happens on every push.
The dispatch-only release-staging workflow adds a stronger package-boundary
check. It copies this crate unchanged into a disposable workspace, places the
extracted atune_core crate archive at this manifest’s relative path, proves
that no atune_core feature was enabled, then builds and runs these tests.
That is proof about the staged archive bytes, not a claim that a registry
publication exists; only a clean consumer resolving the published version can
close that final gap.
§The sampler
Antithetic is uniform random search with its draws mirrored in pairs. Trial
2k draws a unit coordinate u for each parameter; trial 2k + 1 uses
1 - u. Under a serial run, each completed pair covers both sides of the
unit interval. If the predecessor has not completed with its parameter
recorded, the odd trial falls back to its own uniform draw. This is a classic variance-reduction
trick that fits the seam because the framework hands a sampler the trial
number and a seed derived from it.
One property comes out of the trait’s own contract rather than from this
implementation being careful: per-name derivation, so a value survives
an edit to the search space. The seed for a parameter is
seed_for_name(trial seed, name), never the next number out
of one per-trial stream, which is what makes x keep its value when y is
added beside it.
§What writing it found out, and what it costs
An antithetic sampler needs trial 2k + 1 to know what trial 2k drew, and the
seam gives it no way to derive that: [TrialMeta::sampler_seed] is already
per-trial-number, so the two halves of a pair are handed unrelated seeds, and
[StudyView] exposes directions, the space and trial iterators but no study
seed. [Sampler::reseed], the natural place to receive one, is never called
outside tests. The only working route is the one below: read the predecessor’s
recorded value back out of the view and mirror that.
That is a real cost, stated here because a plugin author pays it too. It moves
this sampler off the stateless row of the seam’s own table — it is
history-dependent, like Tpe, so it promises single-worker determinism plus
replay rather than order-independence, and a two-worker run may pair trials
differently from a one-worker run. parallelism(1) is therefore part of the
contract of the test below, not an accident of it. Nothing is persisted
either way: [Sampler::state] stays None, because everything it needs is
already in the study’s own history.
§The scheduler
Ceiling prunes a trial whose first objective is worse than a fixed bound
from a given step on. It sits in the opposite corner of the seam from the
sampler: a decision reads only the report in front of it, so it is
stateless and order-independent, persists nothing, and accepts a multi-seed
fan’s aligned aggregate as just another report. Its tests run real studies in
both directions and check every trial’s fate against the rule.
The crate stops at these two seams. A storage backend proves itself against
the conformance suite, which atune_core exports only behind its
conformance feature, and the release-staging check above refuses any
atune_core feature in this manifest.
Structs§
- Antithetic
- Uniform sampling with antithetic pairs: trial
2k + 1mirrors trial2k. - Ceiling
- Prunes a trial whose first objective is worse than a fixed bound once it has reached a given step.