- Replace Mutex<fastrand::Rng> with a stored seed + MurmurHash3 mixer
in RandomSampler, TpeSampler, and MotpeSampler so parallel workers
no longer serialize on a shared lock
- Add mix_seed() and distribution_fingerprint() to rng_util for
deterministic per-call RNG derivation from (seed, trial_id, distribution)
- Include an AtomicU64 call counter to disambiguate parameters that
share the same distribution within a trial
- Add blanket `impl Objective<V> for Fn(&mut Trial) -> Result<V, E>`
so closures work directly with `optimize`
- Rewrite optimize, optimize_async, optimize_parallel to accept
`impl Objective<V>` with before_trial/after_trial hooks
- Remove optimize_with, optimize_with_async, optimize_with_parallel
- Remove max_retries and retry logic from Objective trait
- Add explicit closure type annotations for HRTB inference
- Convert FnMut test closures to Fn via RefCell/Cell
fastrand is smaller, faster, and has no dependencies. Add rng_util
helper for f64 range generation since fastrand lacks a built-in
equivalent. Migrate all samplers, KDE modules, and fANOVA to use
fastrand's concrete Rng type instead of rand's trait-based generics.
Extend TPE to handle multi-objective optimization using Pareto-based
splitting. MOTPE uses non-dominated sorting to define "good" (front 0)
vs "bad" (dominated) regions for the KDE models, replacing the
single-objective gamma-based split.