use crate::error::{OptimError, Result};
use scirs2_core::ndarray::{Array1, Array2};
use scirs2_core::numeric::{Float, ToPrimitive};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::fmt::Debug;
pub(crate) fn cast_scalar<T: Float, V: ToPrimitive + Copy + Debug>(value: V) -> Result<T> {
T::from(value).ok_or_else(|| {
OptimError::InvalidConfig(format!(
"{value:?} cannot be represented in this optimizer's scalar type"
))
})
}
pub(crate) fn cast_positive<T: Float, V: ToPrimitive + Copy + Debug>(
value: V,
what: &str,
) -> Result<T> {
let converted: T = cast_scalar(value)?;
if converted > T::zero() {
Ok(converted)
} else {
Err(OptimError::InsufficientData(format!(
"{what} must be positive, got {value:?}"
)))
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct LearnedOptimizerConfig {
pub learning_rate: f64,
pub meta_learning_rate: f64,
pub batch_size: usize,
pub max_steps: usize,
pub convergence_threshold: f64,
pub use_momentum: bool,
pub momentum_decay: f64,
pub weight_decay: f64,
pub hidden_size: usize,
pub attention_heads: usize,
pub gradient_history_size: usize,
pub input_features: usize,
pub output_features: usize,
pub num_layers: usize,
pub dropout_rate: f64,
pub use_attention: bool,
pub seed: Option<u64>,
}
impl Default for LearnedOptimizerConfig {
fn default() -> Self {
Self {
learning_rate: 0.001,
meta_learning_rate: 0.0001,
batch_size: 32,
max_steps: 1000,
convergence_threshold: 1e-6,
use_momentum: true,
momentum_decay: 0.9,
weight_decay: 1e-4,
hidden_size: 256,
attention_heads: 8,
gradient_history_size: 50,
input_features: 256,
output_features: 256,
num_layers: 3,
dropout_rate: 0.1,
use_attention: true,
seed: None,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub enum MetaOptimizationStrategy {
#[default]
FirstOrder,
SecondOrder,
MAML,
Reptile,
Custom {
inner_steps: usize,
outer_learning_rate: f64,
},
}
#[derive(Debug, Clone)]
pub struct OptimizerState<T: Float + Debug + Send + Sync + 'static> {
pub parameters: Array1<T>,
pub gradients: Array1<T>,
pub momentum: Option<Array1<T>>,
pub hidden_states: HashMap<String, Array1<T>>,
pub memory_buffers: HashMap<String, Array2<T>>,
pub step: usize,
pub step_count: usize,
pub loss: Option<T>,
pub learning_rate: T,
pub metadata: StateMetadata,
}
pub const DEFAULT_LEARNING_RATE: f64 = 0.001;
impl<T: Float + Debug + Send + Sync + 'static> OptimizerState<T> {
pub fn new(num_params: usize) -> Result<Self> {
Ok(Self {
parameters: Array1::zeros(num_params),
gradients: Array1::zeros(num_params),
momentum: None,
hidden_states: HashMap::new(),
memory_buffers: HashMap::new(),
step: 0,
step_count: 0,
loss: None,
learning_rate: cast_scalar(DEFAULT_LEARNING_RATE)?,
metadata: StateMetadata::default(),
})
}
}
#[derive(Debug, Clone)]
pub struct StateMetadata {
pub task_id: Option<String>,
pub optimizer_type: Option<String>,
pub version: String,
pub timestamp: std::time::SystemTime,
pub checksum: u64,
pub compression_level: u8,
pub custom_data: HashMap<String, String>,
}
impl Default for StateMetadata {
fn default() -> Self {
Self {
task_id: None,
optimizer_type: None,
version: "1.0".to_string(),
timestamp: std::time::SystemTime::now(),
checksum: 0,
compression_level: 0,
custom_data: HashMap::new(),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum NeuralOptimizerType {
Transformer,
LSTM,
MLP,
CNN,
}
#[derive(Debug, Clone)]
pub struct TaskContext<T: Float + Debug + Send + Sync + 'static> {
pub task_id: String,
pub initial_parameters: Array1<T>,
pub task_data: Array2<T>,
pub targets: Array1<T>,
pub difficulty: f64,
}
#[derive(Debug, Clone)]
pub struct NeuralOptimizerMetrics {
pub avg_loss: f64,
pub convergence_rate: f64,
pub steps_to_convergence: Option<usize>,
pub final_performance: f64,
pub training_time: f64,
}
#[derive(Debug, Clone)]
pub struct TaskPerformance {
pub task_id: String,
pub score: f64,
pub converged: bool,
pub steps_taken: usize,
pub final_loss: f64,
}