optirs_nas/lib.rs
1//! # OptiRS NAS - Neural Architecture Search
2//!
3//! **Version:** 0.3.2
4//! **Status:** Research-grade implementations; APIs may still change between releases
5//!
6//! ⚠️ **Warning:** Architecture search is compute-heavy and the search-space / objective
7//! APIs are still evolving. Validate a discovered architecture against your own baselines
8//! before relying on it in production.
9//!
10//! `optirs-nas` provides neural architecture search and automated optimizer discovery
11//! built on [SciRS2](https://github.com/cool-japan/scirs).
12//!
13//! ## Dependencies
14//!
15//! - `scirs2-core` 0.6.5 - required foundation (arrays, RNG, numeric traits)
16//!
17//! This crate has **no intra-workspace dependencies**: `optirs-core` and
18//! `optirs-learned` were declared once but never referenced, and were removed so
19//! `optirs-nas` builds and tests standalone. The benchmark harness in
20//! [`evaluation::BenchmarkSuite`] implements its optimizer update rules directly, which
21//! also makes NAS scores reproducible independently of sibling-crate changes.
22//!
23//! ## Implementation Status (v0.3.2)
24//!
25//! - ✅ Bayesian optimization ([`search_strategies::bayesian`] - Gaussian-process surrogate search)
26//! - ✅ Hyperparameter search ([`hyperparameter`] - grid enumeration, TPE, a GP-free
27//! kernel-regression surrogate, and evolutionary search)
28//! - ✅ Evolutionary algorithms ([`search_strategies::evolutionary`] - population-based search)
29//! - ✅ RL-based search ([`search_strategies::rl_search`] - neural-controller sampling)
30//! - ✅ Differentiable search ([`search_strategies::differentiable`] - DARTS-style gradient search)
31//! - ✅ Multi-objective optimization ([`multi_objective`] - NSGA-II, NSGA-III, MOEA/D,
32//! weighted-sum, Pareto frontier, exact hypervolume)
33//! - ✅ Hardware-aware cost modeling ([`hardware_cost`] - latency/memory/energy estimation)
34//! - ✅ AutoML pipeline coordination ([`automl_pipeline`]), cross-domain transfer, few-shot and
35//! progressive search
36//! - 📝 Real, tested algorithms throughout - still labeled research-grade because search-space
37//! and objective APIs may change across releases
38//!
39//! ## Features
40//!
41//! ### Search Strategies
42//! - **Bayesian Optimization** - Gaussian processes for efficient search
43//! - **Evolutionary Algorithms** - Population-based architecture evolution
44//! - **Reinforcement Learning** - Neural controller for architecture sampling
45//! - **Gradient-Based** - DARTS and differentiable NAS
46//!
47//! ### Multi-Objective Optimization
48//! - **Pareto Frontier** - Balance accuracy, speed, memory
49//! - **Weighted Sum** - Customizable objective functions
50//! - **NSGA-II** - Non-dominated sorting genetic algorithm
51//! - **NSGA-III** - Reference-point-based many-objective sorting
52//! - **MOEA/D** - Decomposition-based optimization (Tchebycheff/PBI/ASF/weighted-sum)
53//! - Interactive preference articulation and Pareto-level constraint handling
54//! (`MultiObjectiveConfig::user_preferences`/`constraint_handling`) are declared
55//! but not yet consulted by any optimizer; hard resource limits are enforced
56//! separately by [`nas_engine::resources::ResourceMonitor`], not by the
57//! multi-objective layer.
58//!
59//! ### Progressive Search
60//! - **Start Simple** - Begin with small architectures
61//! - **Gradual Complexity** - Incrementally increase depth/width
62//! - **Early Stopping** - Prune unpromising architectures
63//! - **Transfer Learning** - Reuse knowledge from previous searches
64//!
65//! ### Hardware-Aware NAS
66//! - **Latency Prediction** - Model inference time on target hardware
67//! - **Memory Estimation** - Predict GPU/TPU memory usage
68//! - **Energy Consumption** - Optimize for mobile/edge devices
69//! - **Cost Optimization** - Minimize cloud compute costs
70//!
71//! ## Example Usage
72//!
73//! The engine type is [`nas_engine::NeuralArchitectureSearch`], configured with a
74//! [`nas_engine::NASConfig`]. This example compiles and runs as a doctest, so it
75//! cannot drift away from the real API.
76//!
77//! ```rust
78//! use optirs_nas::nas_engine::resources::SystemResourceTracker;
79//! use optirs_nas::nas_engine::telemetry::{FixedTelemetry, TelemetrySample};
80//! use optirs_nas::nas_engine::{
81//! create_minimal_nas_config, NeuralArchitectureSearch, SearchStrategyType,
82//! };
83//! use std::time::Duration;
84//!
85//! # fn main() -> Result<(), optirs_nas::error::OptimError> {
86//! // A small, ready-made configuration: a populated search space, a Random
87//! // strategy and a tiny budget.
88//! let mut config = create_minimal_nas_config::<f64>();
89//! config.search_strategy = SearchStrategyType::Evolutionary;
90//! config.search_budget = 2;
91//! config.population_size = 4;
92//!
93//! let mut engine = NeuralArchitectureSearch::new(config)?;
94//! // The engine reports which strategy is *actually* running, not just what was
95//! // requested.
96//! assert_eq!(engine.search_strategy_name(), "EvolutionaryStrategy");
97//!
98//! // Pin the telemetry so this example's outcome does not depend on how much
99//! // memory the host happens to have free. `resource_monitor_mut` is the supported
100//! // injection point for real telemetry too.
101//! engine.resource_monitor_mut().set_trackers(vec![Box::new(
102//! SystemResourceTracker::with_telemetry(
103//! "example".to_string(),
104//! Duration::from_secs(5),
105//! Box::new(FixedTelemetry::new("example", TelemetrySample::unknown())),
106//! ),
107//! )]);
108//!
109//! // A short search: two generations against the built-in evaluator.
110//! let results = engine.run_search()?;
111//! assert!(!results.search_history.is_empty());
112//! # Ok(())
113//! # }
114//! ```
115//!
116//! Hyperparameter search is independent of the engine and can be driven directly:
117//!
118//! ```rust
119//! use optirs_nas::hyperparameter::{
120//! DistributionType, HyperparameterOptimizer, HyperparameterSpace,
121//! OptimizationStrategy, ParameterRange,
122//! };
123//!
124//! # fn main() -> Result<(), optirs_nas::error::OptimError> {
125//! let mut space: HyperparameterSpace<f64> = HyperparameterSpace::new();
126//! space.add_parameter(
127//! "learning_rate".to_string(),
128//! ParameterRange {
129//! name: "learning_rate".to_string(),
130//! min_value: 1e-5,
131//! max_value: 1e-1,
132//! distribution: DistributionType::Uniform,
133//! log_scale: true,
134//! discrete_values: None,
135//! },
136//! );
137//!
138//! // Grid search enumerates the grid; it does not sample at random.
139//! let mut optimizer =
140//! HyperparameterOptimizer::with_seed(space, OptimizationStrategy::Grid, 7);
141//! optimizer.set_grid_resolution(4);
142//! assert_eq!(optimizer.grid_size(), Some(4));
143//!
144//! let suggestion = optimizer.suggest_configuration()?;
145//! let learning_rate = suggestion.parameters["learning_rate"];
146//! assert!((1e-5..=1e-1).contains(&learning_rate));
147//! # Ok(())
148//! # }
149//! ```
150//!
151//! ## Supported Search Spaces
152//!
153//! - **Optimizer Selection** - Choose between SGD, Adam, RMSprop, etc.
154//! - **Hyperparameters** - Learning rates, momentum, weight decay
155//! - **Learning Rate Schedules** - Warmup, decay, cosine annealing
156//! - **Regularization** - L1/L2, dropout rates, gradient clipping
157//! - **Architecture Components** - Optimizer composition and ensembles
158//!
159//! ## Architecture
160//!
161//! Every algorithm in this crate is implemented here; `scirs2-core` supplies the
162//! numeric substrate only:
163//!
164//! - **Arrays**: `scirs2_core::ndarray` ([`scirs2_core::ndarray::Array1`] / `Array2` / `Array3`)
165//! - **Numeric traits**: `scirs2_core::numeric` ([`scirs2_core::numeric::Float`], `NumCast`)
166//! - **RNG**: `scirs2_core::random` (`Random`, `Rng`)
167//!
168//! The search machinery itself lives in this crate:
169//! - **Search space**: [`nas_engine::SearchSpaceConfig`]
170//! - **Engine**: [`nas_engine::NeuralArchitectureSearch`]
171//! - **Strategies**: [`search_strategies`]
172//! - **Multi-objective**: [`multi_objective`]
173//!
174//! (Earlier revisions of this document referenced
175//! `scirs2_core::neural_architecture_search` and
176//! `scirs2_core::quantum_optimization`; neither module exists.)
177//!
178//! ## References
179//!
180//! - DARTS: Differentiable Architecture Search (Liu et al., 2019)
181//! - EfficientNet: Rethinking Model Scaling for CNNs (Tan & Le, 2019)
182//! - Once-for-All: Train One Network and Specialize it for Efficient Deployment (Cai et al., 2020)
183//!
184//! ## Contributing
185//!
186//! Research contributions welcome! Follow SciRS2 integration guidelines.
187
188/// Compiles and runs every `rust` code block in `README.md` as a doctest, so the
189/// README cannot drift away from the API.
190///
191/// The previous README documented roughly twenty types that do not exist
192/// (`NASEngine`, `BayesianOptimizer`, `ProgressiveNAS::new().with_initial_depth(..)`,
193/// `HardwareAwareNAS`, `DistributedNAS`, ...) and `.await`ed every call in a crate
194/// with no `async fn` at all. Nothing caught it because nothing compiled it.
195///
196/// `#[cfg(doctest)]` keeps this out of the published documentation and out of
197/// normal builds; it exists only so `cargo test --doc` picks the file up.
198#[cfg(doctest)]
199#[doc = include_str!("../README.md")]
200struct ReadmeDoctests;
201
202pub mod architecture;
203pub mod architecture_embedding;
204pub mod architecture_knowledge_graph;
205pub mod automl_pipeline;
206pub mod cross_domain_transfer;
207pub mod domain_specific_nas;
208pub mod error;
209pub mod evaluation;
210pub mod few_shot_architecture;
211pub mod hardware_cost;
212pub mod hyperparameter;
213pub mod multi_objective;
214pub mod multimodal_nas;
215pub mod nas_engine;
216pub(crate) mod numeric;
217pub mod progressive;
218pub mod search_strategies;
219pub mod speech_nas;
220
221pub use architecture::ArchitectureSpace;
222pub use architecture_embedding::{AggregationMethod, ArchitectureEmbedder};
223pub use architecture_knowledge_graph::{
224 ArchKnowledgeEdge, ArchKnowledgeNode, ArchitectureKnowledgeGraph, NodeId, PerformanceRecord,
225 RelationType,
226};
227pub use automl_pipeline::{
228 AutomlPipelineConfig, AutomlPipelineCoordinator, CandidateModel, EnsembleStrategy,
229 FeatureEngineeringStep, PipelineEvaluation, PreprocessingStep, ScoredPipeline, SvmKernel,
230 TrainValSplit,
231};
232pub use cross_domain_transfer::{
233 CrossDomainTransferEngine, DomainProfile, DomainSimilarityMetric, DomainSimilarityReport,
234 TransferRecommendation, TransferabilityWeights,
235};
236pub use domain_specific_nas::{
237 DomainNASEngine, DomainSearchSpace, DomainType as NASDomainType, NASConstraint,
238};
239pub use error::{OptimError, Result};
240pub use few_shot_architecture::{
241 ArchitectureExample, DistanceMetric, FewShotAlgorithm, FewShotArchitectureOptimizer,
242 FewShotConfig, FewShotPrediction,
243};
244pub use hardware_cost::{
245 ActivationKind, Bottleneck, CostReport, HardwareCostModel, HardwareProfile, LatencyLookupTable,
246 LatencyPrediction, LatencySource, LayerKind, LayerSignature, LayerSpec, PerLayerCost, PoolKind,
247 RooflineResult,
248};
249pub use multimodal_nas::{
250 FusionOp, Modality, ModalityEncoder, MultimodalArchitecture, MultimodalEvaluation,
251 MultimodalLayer, MultimodalNasEngine, MultimodalSearchSpace, MultimodalValidationError,
252};
253pub use search_strategies::SearchStrategy;
254pub use speech_nas::{
255 layer_position_constraint, LayerPositionConstraint, SpeechLayerType, SpeechModelConfig,
256 SpeechModelEvaluation, SpeechNasEngine, SpeechSearchSpace,
257};
258
259// Re-export key types
260use serde::{Deserialize, Serialize};
261
262/// Evaluation configuration for architecture search
263#[derive(Debug, Clone, Serialize, Deserialize)]
264pub struct EvaluationConfig {
265 /// Number of epochs for evaluation
266 pub epochs: u32,
267 /// Batch size for training
268 pub batch_size: usize,
269 /// Learning rate for evaluation
270 pub learning_rate: f64,
271 /// Use performance prediction
272 pub performance_prediction: bool,
273}
274
275/// Evaluation metrics for architectures
276#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
277pub enum EvaluationMetric {
278 /// Final performance metric
279 FinalPerformance,
280 /// Convergence speed metric
281 ConvergenceSpeed,
282 /// Model stability metric
283 Stability,
284 /// Robustness metric
285 Robustness,
286 /// Efficiency metric
287 Efficiency,
288 /// Generalization metric
289 Generalization,
290 /// Memory usage metric
291 MemoryUsage,
292 /// Computation time metric
293 ComputationTime,
294 /// Training stability metric
295 TrainingStability,
296 /// Memory efficiency metric
297 MemoryEfficiency,
298 /// Computational efficiency metric
299 ComputationalEfficiency,
300 /// Accuracy metric
301 Accuracy,
302 /// Training time metric
303 TrainingTime,
304}
305
306// ---------------------------------------------------------------------------
307// Canonical result / architecture types
308// ---------------------------------------------------------------------------
309//
310// The generic, element-type-parameterised definitions in
311// [`nas_engine::results`] are the single source of truth for architectures,
312// evaluation results and resource accounting. They are re-exported here so
313// `optirs_nas::OptimizerArchitecture<T>` and
314// `nas_engine::results::OptimizerArchitecture<T>` name the *same* type. Earlier
315// releases carried a second, `f64`-only copy of each of these structs at the
316// crate root; those duplicates are gone.
317
318pub use nas_engine::config::NASConfig;
319pub use nas_engine::results::{
320 BenchmarkResult, CrossValidationResults, EvaluationResults, OptimizerArchitecture,
321 ResourceUsage, TrainingSnapshot,
322};
323
324impl Default for EvaluationConfig {
325 fn default() -> Self {
326 Self {
327 epochs: 20,
328 batch_size: 32,
329 learning_rate: 1e-3,
330 performance_prediction: false,
331 }
332 }
333}
334
335impl EvaluationConfig {
336 /// Derive an evaluation configuration from the richer, generic
337 /// [`nas_engine::config::EvaluationConfig`] carried by [`NASConfig`].
338 ///
339 /// The engine-level configuration describes budgets and statistical
340 /// testing; the evaluation subsystem only needs the step budget, batch size
341 /// and base learning rate, plus whether performance prediction is enabled.
342 /// `max_epochs` is clamped to at least one step so an evaluation always
343 /// performs real work.
344 pub fn from_engine_config<T>(config: &nas_engine::config::EvaluationConfig<T>) -> Self
345 where
346 T: scirs2_core::numeric::Float + std::fmt::Debug + Send + Sync + 'static,
347 {
348 Self {
349 epochs: config.evaluation_budget.max_epochs.max(1) as u32,
350 batch_size: 32,
351 learning_rate: 1e-3,
352 performance_prediction: false,
353 }
354 }
355}