Skip to main content

Crate atune_plugin_example

Crate atune_plugin_example 

Expand description

An out-of-tree sampler, written the way a plugin author would write one.

§Why this crate exists

Milestone M7’s exit 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. M7.D7 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 draws 1 - u for the same parameter. The pair straddles the middle of the support by construction, so a run of 2n trials cannot spend all of its budget on one side of a range the way 2n independent uniform draws sometimes do — the classic variance-reduction trick, and one that fits the seam exactly 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.

Structs§

Antithetic
Uniform sampling with antithetic pairs: trial 2k + 1 mirrors trial 2k.