use super::config::*;
use crate::OptimizerError as OptimError;
use crate::neural_architecture_search::ScheduleType;
use scirs2_core::ndarray::Array1;
use scirs2_core::numeric::Float;
use std::collections::{HashMap, VecDeque};
use std::fmt::Debug;
use std::time::{Duration, SystemTime};
type Result<T> = std::result::Result<T, OptimError>;
#[derive(Debug, Clone)]
pub struct OptimizationContext<T: Float + Debug + Send + Sync + Debug> {
pub state: OptimizationState<T>,
pub problem_characteristics: ProblemCharacteristics<T>,
pub resource_constraints: ResourceConstraints<T>,
pub time_constraints: TimeConstraints,
pub performance_history: Vec<T>,
pub current_phase: OptimizationPhase,
pub landscape_features: Option<LandscapeFeatures<T>>,
pub dimensionality: usize,
pub computational_budget: ComputationalBudget,
pub convergence_criteria: ConvergenceCriteria<T>,
pub metadata: HashMap<String, String>,
}
#[derive(Debug, Clone)]
pub struct OptimizationState<T: Float + Debug + Send + Sync + 'static> {
pub current_iteration: usize,
pub current_loss: T,
pub gradient_norm: T,
pub step_size: T,
pub convergence_measure: T,
pub current_parameters: Option<Array1<T>>,
pub velocity: Option<Array1<T>>,
pub adaptive_state: Option<AdaptiveState<T>>,
pub last_update: SystemTime,
pub statistics: OptimizationStatistics<T>,
}
#[derive(Debug, Clone)]
pub struct AdaptiveState<T: Float + Debug + Send + Sync + 'static> {
pub first_moment: Option<Array1<T>>,
pub second_moment: Option<Array1<T>>,
pub time_step: usize,
pub learning_rate_schedule: LearningRateSchedule<T>,
pub bias_correction: BiasCorrection<T>,
}
#[derive(Debug, Clone)]
pub struct LearningRateSchedule<T: Float + Debug + Send + Sync + 'static> {
pub schedule_type: ScheduleType,
pub base_lr: T,
pub current_lr: T,
pub parameters: HashMap<String, T>,
pub step_count: usize,
}
#[derive(Debug, Clone)]
pub struct BiasCorrection<T: Float + Debug + Send + Sync + 'static> {
pub beta1_correction: T,
pub beta2_correction: T,
pub power: usize,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ProblemType {
Unconstrained,
Constrained,
MultiObjective,
Stochastic,
Discrete,
MixedInteger,
}
impl Default for ProblemType {
fn default() -> Self {
ProblemType::Unconstrained
}
}
#[derive(Debug, Clone)]
pub struct ProblemCharacteristics<T: Float + Debug + Send + Sync + 'static> {
pub dimensionality: usize,
pub conditioning: T,
pub noise_level: T,
pub multimodality: T,
pub convexity: T,
pub separability: T,
pub smoothness: T,
pub sparsity: T,
pub problem_type: ProblemType,
pub domain_features: HashMap<String, T>,
}
#[derive(Debug, Clone)]
pub struct ResourceConstraints<T: Float + Debug + Send + Sync + 'static> {
pub max_memory: T,
pub max_compute: T,
pub max_time: Duration,
pub max_energy: T,
pub available_cores: usize,
pub available_gpus: usize,
pub network_bandwidth: T,
pub storage_limit: T,
}
#[derive(Debug, Clone)]
pub struct TimeConstraints {
pub deadline: Option<SystemTime>,
pub time_budget: Duration,
pub checkpoint_frequency: Duration,
pub step_timeout: Duration,
pub warmup_time: Duration,
pub cooldown_time: Duration,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum OptimizationPhase {
Initialization,
Exploration,
Exploitation,
Refinement,
Convergence,
Completion,
Error,
}
#[derive(Debug, Clone)]
pub struct StateTransition<T: Float + Debug + Send + Sync + 'static> {
pub from_phase: OptimizationPhase,
pub to_phase: OptimizationPhase,
pub transition_time: SystemTime,
pub trigger: String,
pub performance_delta: T,
pub duration: Duration,
pub reason: TransitionReason,
pub confidence: T,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum TransitionReason {
PerformanceThreshold,
TimeConstraint,
ResourceConstraint,
ConvergenceDetected,
StagnationDetected,
ExternalTrigger,
AutomaticProgression,
ErrorRecovery,
}
#[derive(Debug, Clone)]
pub struct LandscapeFeatures<T: Float + Debug + Send + Sync + 'static> {
pub curvature_info: CurvatureInfo<T>,
pub gradient_characteristics: GradientCharacteristics<T>,
pub local_geometry: LocalGeometry<T>,
pub global_structure: GlobalStructure<T>,
pub noise_characteristics: NoiseCharacteristics<T>,
pub trajectory_features: TrajectoryFeatures<T>,
pub extraction_time: SystemTime,
pub validity_duration: Duration,
}
#[derive(Debug, Clone)]
pub struct CurvatureInfo<T: Float + Debug + Send + Sync + 'static> {
pub mean_curvature: T,
pub max_curvature: T,
pub condition_number: T,
pub spectral_gap: T,
pub eigenvalue_distribution: EigenvalueDistribution<T>,
pub hessian_quality: T,
}
#[derive(Debug, Clone)]
pub struct EigenvalueDistribution<T: Float + Debug + Send + Sync + 'static> {
pub largest_eigenvalue: T,
pub smallest_eigenvalue: T,
pub mean_eigenvalue: T,
pub eigenvalue_variance: T,
pub negative_eigenvalues: usize,
pub spectral_density: Vec<T>,
}
#[derive(Debug, Clone)]
pub struct GradientCharacteristics<T: Float + Debug + Send + Sync + 'static> {
pub gradient_norm: T,
pub gradient_variance: T,
pub gradient_correlation: T,
pub directional_derivative: T,
pub gradient_predictability: T,
pub gradient_consistency: T,
pub signal_to_noise_ratio: T,
}
#[derive(Debug, Clone)]
pub struct LocalGeometry<T: Float + Debug + Send + Sync + 'static> {
pub local_minima_density: T,
pub saddle_point_density: T,
pub basin_width: T,
pub escape_difficulty: T,
pub local_convexity: T,
pub local_smoothness: T,
pub barrier_height: T,
}
#[derive(Debug, Clone)]
pub struct GlobalStructure<T: Float + Debug + Send + Sync + 'static> {
pub connectivity: T,
pub symmetry: T,
pub hierarchical_structure: T,
pub fractal_dimension: T,
pub global_convexity: T,
pub scale_separation: T,
pub modularity: T,
}
#[derive(Debug, Clone)]
pub struct NoiseCharacteristics<T: Float + Debug + Send + Sync + 'static> {
pub noise_level: T,
pub noise_type: NoiseType,
pub signal_to_noise_ratio: T,
pub noise_correlation: T,
pub noise_stationarity: T,
pub noise_predictability: T,
pub frequency_spectrum: Vec<T>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum NoiseType {
Gaussian,
Uniform,
Structured,
Adversarial,
Multiplicative,
TimeCorrelated,
}
#[derive(Debug, Clone)]
pub struct TrajectoryFeatures<T: Float + Debug + Send + Sync + 'static> {
pub path_length: T,
pub path_efficiency: T,
pub oscillation: T,
pub convergence_rate: T,
pub step_consistency: T,
pub direction_consistency: T,
pub progress_rate: T,
}
#[derive(Debug, Clone)]
pub struct OptimizationStatistics<T: Float + Debug + Send + Sync + 'static> {
pub total_iterations: usize,
pub total_evaluations: usize,
pub total_gradient_evaluations: usize,
pub best_objective: T,
pub current_objective: T,
pub improvement_rate: T,
pub convergence_history: VecDeque<ConvergenceRecord<T>>,
pub performance_metrics: PerformanceMetrics<T>,
pub time_statistics: TimeStatistics,
}
#[derive(Debug, Clone)]
pub struct ConvergenceRecord<T: Float + Debug + Send + Sync + 'static> {
pub iteration: usize,
pub objective: T,
pub gradient_norm: T,
pub step_size: T,
pub timestamp: SystemTime,
pub convergence_measure: T,
}
#[derive(Debug, Clone)]
pub struct PerformanceMetrics<T: Float + Debug + Send + Sync + 'static> {
pub convergence_speed: T,
pub final_accuracy: T,
pub robustness: T,
pub efficiency: T,
pub reliability: T,
pub adaptability: T,
}
#[derive(Debug, Clone)]
pub struct TimeStatistics {
pub total_time: Duration,
pub average_iteration_time: Duration,
pub time_per_evaluation: Duration,
pub setup_time: Duration,
pub cleanup_time: Duration,
pub idle_time: Duration,
}
#[derive(Debug, Clone)]
pub struct ComputationalBudget {
pub max_evaluations: usize,
pub used_evaluations: usize,
pub max_time: Duration,
pub elapsed_time: Duration,
pub max_memory: usize,
pub current_memory: usize,
pub available_cores: usize,
pub utilization_rate: f64,
}
#[derive(Debug, Clone)]
pub struct ConvergenceCriteria<T: Float + Debug + Send + Sync + 'static> {
pub function_tolerance: T,
pub parameter_tolerance: T,
pub gradient_tolerance: T,
pub max_iterations: usize,
pub stagnation_threshold: usize,
pub relative_improvement_threshold: T,
pub absolute_improvement_threshold: T,
pub target_objective: Option<T>,
}
#[derive(Debug)]
pub struct StateManager<T: Float + Debug + Send + Sync + Debug> {
pub current_context: OptimizationContext<T>,
pub transition_history: VecDeque<StateTransition<T>>,
pub phase_durations: HashMap<OptimizationPhase, Duration>,
pub state_snapshots: VecDeque<StateSnapshot<T>>,
pub validation_rules: Vec<StateValidationRule<T>>,
pub persistence_config: StatePersistenceConfig,
}
#[derive(Debug, Clone)]
pub struct StateSnapshot<T: Float + Debug + Send + Sync + 'static> {
pub timestamp: SystemTime,
pub state: OptimizationState<T>,
pub metrics: PerformanceMetrics<T>,
pub reason: SnapshotReason,
pub size: usize,
pub validation_hash: u64,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum SnapshotReason {
Periodic,
PhaseTransition,
PerformanceMilestone,
ErrorRecovery,
UserRequested,
AutomaticBackup,
}
pub struct StateValidationRule<T: Float + Debug + Send + Sync + Debug> {
pub name: String,
pub description: String,
pub validator: Box<dyn Fn(&OptimizationContext<T>) -> Result<bool> + Send + Sync>,
pub severity: ValidationSeverity,
pub enabled: bool,
}
impl<T: Float + Debug + Send + Sync + 'static> std::fmt::Debug for StateValidationRule<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("StateValidationRule")
.field("name", &self.name)
.field("description", &self.description)
.field("validator", &"<closure>")
.field("severity", &self.severity)
.field("enabled", &self.enabled)
.finish()
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ValidationSeverity {
Warning,
Error,
Critical,
}
#[derive(Debug, Clone)]
pub struct StatePersistenceConfig {
pub enabled: bool,
pub persistence_interval: Duration,
pub max_snapshots: usize,
pub compression_enabled: bool,
pub storage_path: String,
pub encryption_enabled: bool,
}
impl<T: Float + Debug + Send + Sync + 'static> StateManager<T> {
pub fn new(initial_context: OptimizationContext<T>) -> Self {
Self {
current_context: initial_context,
transition_history: VecDeque::new(),
phase_durations: HashMap::new(),
state_snapshots: VecDeque::new(),
validation_rules: Vec::new(),
persistence_config: StatePersistenceConfig::default(),
}
}
pub fn update_context(&mut self, new_context: OptimizationContext<T>) -> Result<()> {
self.validate_context(&new_context)?;
if new_context.current_phase != self.current_context.current_phase {
let transition = StateTransition {
from_phase: self.current_context.current_phase,
to_phase: new_context.current_phase,
transition_time: SystemTime::now(),
trigger: "context_update".to_string(),
performance_delta: T::zero(), duration: Duration::from_secs(0),
reason: TransitionReason::AutomaticProgression,
confidence: scirs2_core::numeric::NumCast::from(1.0).unwrap_or_else(|| T::zero()),
};
self.record_transition(transition)?;
}
self.current_context = new_context;
Ok(())
}
pub fn record_transition(&mut self, transition: StateTransition<T>) -> Result<()> {
self.transition_history.push_back(transition.clone());
if let Some(last_transition) = self.transition_history.iter().rev().nth(1) {
if last_transition.to_phase == transition.from_phase {
let duration = transition.transition_time
.duration_since(last_transition.transition_time)
.unwrap_or(Duration::from_secs(0));
*self.phase_durations.entry(transition.from_phase).or_insert(Duration::from_secs(0)) += duration;
}
}
if self.transition_history.len() > 1000 {
self.transition_history.pop_front();
}
Ok(())
}
pub fn create_snapshot(&mut self, reason: SnapshotReason) -> Result<()> {
let snapshot = StateSnapshot {
timestamp: SystemTime::now(),
state: self.current_context.state.clone(),
metrics: self.current_context.state.statistics.performance_metrics.clone(),
reason,
size: std::mem::size_of_val(&self.current_context.state),
validation_hash: self.compute_state_hash(&self.current_context.state)?,
};
self.state_snapshots.push_back(snapshot);
if self.state_snapshots.len() > self.persistence_config.max_snapshots {
self.state_snapshots.pop_front();
}
Ok(())
}
pub fn restore_from_snapshot(&mut self, snapshot_index: usize) -> Result<()> {
if let Some(snapshot) = self.state_snapshots.get(snapshot_index) {
let current_hash = self.compute_state_hash(&snapshot.state)?;
if current_hash != snapshot.validation_hash {
return Err(OptimError::ComputationError("Snapshot validation failed".to_string()));
}
self.current_context.state = snapshot.state.clone();
Ok(())
} else {
Err(OptimError::ComputationError("Snapshot not found".to_string()))
}
}
pub fn validate_context(&self, context: &OptimizationContext<T>) -> Result<()> {
for rule in &self.validation_rules {
if rule.enabled {
let is_valid = (rule.validator)(context)?;
if !is_valid {
match rule.severity {
ValidationSeverity::Warning => {
eprintln!("Warning: {}", rule.description);
}
ValidationSeverity::Error => {
return Err(OptimError::ComputationError(format!("Validation error: {}", rule.description)));
}
ValidationSeverity::Critical => {
return Err(OptimError::ComputationError(format!("Critical validation error: {}", rule.description)));
}
}
}
}
}
Ok(())
}
pub fn add_validation_rule(&mut self, rule: StateValidationRule<T>) {
self.validation_rules.push(rule);
}
pub fn get_state_statistics(&self) -> StateStatistics<T> {
StateStatistics {
total_transitions: self.transition_history.len(),
total_snapshots: self.state_snapshots.len(),
current_phase: self.current_context.current_phase,
time_in_current_phase: self.get_time_in_current_phase(),
average_phase_duration: self.compute_average_phase_duration(),
most_common_transition: self.get_most_common_transition(),
_phantom: std::marker::PhantomData,
}
}
fn compute_state_hash(&self, state: &OptimizationState<T>) -> Result<u64> {
let hash = state.current_iteration as u64
^ (state.current_loss.to_f64().unwrap_or(0.0) as u64)
^ state.last_update.duration_since(SystemTime::UNIX_EPOCH)
.unwrap_or(Duration::from_secs(0)).as_secs();
Ok(hash)
}
fn get_time_in_current_phase(&self) -> Duration {
if let Some(last_transition) = self.transition_history.back() {
if last_transition.to_phase == self.current_context.current_phase {
return SystemTime::now()
.duration_since(last_transition.transition_time)
.unwrap_or(Duration::from_secs(0));
}
}
Duration::from_secs(0)
}
fn compute_average_phase_duration(&self) -> Duration {
if self.phase_durations.is_empty() {
return Duration::from_secs(0);
}
let total_duration: Duration = self.phase_durations.values().sum();
total_duration / self.phase_durations.len() as u32
}
fn get_most_common_transition(&self) -> Option<(OptimizationPhase, OptimizationPhase)> {
let mut transition_counts: HashMap<(OptimizationPhase, OptimizationPhase), usize> = HashMap::new();
for transition in &self.transition_history {
*transition_counts.entry((transition.from_phase, transition.to_phase)).or_insert(0) += 1;
}
transition_counts.into_iter()
.max_by_key(|(_, count)| *count)
.map(|(transition, _)| transition)
}
}
#[derive(Debug, Clone)]
pub struct StateStatistics<T: Float + Debug + Send + Sync + 'static> {
pub total_transitions: usize,
pub total_snapshots: usize,
pub current_phase: OptimizationPhase,
pub time_in_current_phase: Duration,
pub average_phase_duration: Duration,
pub most_common_transition: Option<(OptimizationPhase, OptimizationPhase)>,
_phantom: std::marker::PhantomData<T>,
}
impl<T: Float + Debug + Send + Sync + 'static> Default for OptimizationContext<T> {
fn default() -> Self {
Self {
state: OptimizationState::default(),
problem_characteristics: ProblemCharacteristics::default(),
resource_constraints: ResourceConstraints::default(),
time_constraints: TimeConstraints::default(),
performance_history: Vec::new(),
current_phase: OptimizationPhase::Initialization,
landscape_features: None,
dimensionality: 100,
computational_budget: ComputationalBudget::default(),
convergence_criteria: ConvergenceCriteria::default(),
metadata: HashMap::new(),
}
}
}
impl<T: Float + Debug + Send + Sync + 'static> Default for OptimizationState<T> {
fn default() -> Self {
Self {
current_iteration: 0,
current_loss: T::zero(),
gradient_norm: T::zero(),
step_size: scirs2_core::numeric::NumCast::from(0.01).unwrap_or_else(|| T::zero()),
convergence_measure: T::zero(),
current_parameters: None,
velocity: None,
adaptive_state: None,
last_update: SystemTime::now(),
statistics: OptimizationStatistics::default(),
}
}
}
impl<T: Float + Debug + Send + Sync + 'static> Default for ProblemCharacteristics<T> {
fn default() -> Self {
Self {
dimensionality: 100,
conditioning: scirs2_core::numeric::NumCast::from(10.0).unwrap_or_else(|| T::zero()),
noise_level: scirs2_core::numeric::NumCast::from(0.01).unwrap_or_else(|| T::zero()),
multimodality: scirs2_core::numeric::NumCast::from(0.5).unwrap_or_else(|| T::zero()),
convexity: scirs2_core::numeric::NumCast::from(0.5).unwrap_or_else(|| T::zero()),
separability: scirs2_core::numeric::NumCast::from(0.5).unwrap_or_else(|| T::zero()),
smoothness: scirs2_core::numeric::NumCast::from(0.8).unwrap_or_else(|| T::zero()),
sparsity: scirs2_core::numeric::NumCast::from(0.1).unwrap_or_else(|| T::zero()),
problem_type: ProblemType::NonConvex,
domain_features: HashMap::new(),
}
}
}
impl<T: Float + Debug + Send + Sync + 'static> Default for ResourceConstraints<T> {
fn default() -> Self {
Self {
max_memory: scirs2_core::numeric::NumCast::from(8192.0).unwrap_or_else(|| T::zero()), max_compute: scirs2_core::numeric::NumCast::from(1.0).unwrap_or_else(|| T::zero()),
max_time: Duration::from_secs(3600), max_energy: scirs2_core::numeric::NumCast::from(1000.0).unwrap_or_else(|| T::zero()),
available_cores: num_cpus::get(),
available_gpus: 0,
network_bandwidth: scirs2_core::numeric::NumCast::from(1000.0).unwrap_or_else(|| T::zero()), storage_limit: scirs2_core::numeric::NumCast::from(100000.0).unwrap_or_else(|| T::zero()), }
}
}
impl Default for TimeConstraints {
fn default() -> Self {
Self {
deadline: None,
time_budget: Duration::from_secs(3600), checkpoint_frequency: Duration::from_secs(300), step_timeout: Duration::from_secs(60), warmup_time: Duration::from_secs(60),
cooldown_time: Duration::from_secs(30),
}
}
}
impl Default for ComputationalBudget {
fn default() -> Self {
Self {
max_evaluations: 10000,
used_evaluations: 0,
max_time: Duration::from_secs(3600), elapsed_time: Duration::from_secs(0),
max_memory: 1024 * 1024 * 1024, current_memory: 0,
available_cores: num_cpus::get(),
utilization_rate: 0.0,
}
}
}
impl<T: Float + Debug + Send + Sync + 'static> Default for ConvergenceCriteria<T> {
fn default() -> Self {
Self {
function_tolerance: scirs2_core::numeric::NumCast::from(1e-6).unwrap_or_else(|| T::zero()),
parameter_tolerance: scirs2_core::numeric::NumCast::from(1e-8).unwrap_or_else(|| T::zero()),
gradient_tolerance: scirs2_core::numeric::NumCast::from(1e-6).unwrap_or_else(|| T::zero()),
max_iterations: 1000,
stagnation_threshold: 50,
relative_improvement_threshold: scirs2_core::numeric::NumCast::from(1e-4).unwrap_or_else(|| T::zero()),
absolute_improvement_threshold: scirs2_core::numeric::NumCast::from(1e-6).unwrap_or_else(|| T::zero()),
target_objective: None,
}
}
}
impl<T: Float + Debug + Send + Sync + 'static> Default for OptimizationStatistics<T> {
fn default() -> Self {
Self {
total_iterations: 0,
total_evaluations: 0,
total_gradient_evaluations: 0,
best_objective: T::infinity(),
current_objective: T::infinity(),
improvement_rate: T::zero(),
convergence_history: VecDeque::new(),
performance_metrics: PerformanceMetrics::default(),
time_statistics: TimeStatistics::default(),
}
}
}
impl<T: Float + Debug + Send + Sync + 'static> Default for PerformanceMetrics<T> {
fn default() -> Self {
Self {
convergence_speed: T::zero(),
final_accuracy: T::zero(),
robustness: T::zero(),
efficiency: T::zero(),
reliability: T::zero(),
adaptability: T::zero(),
}
}
}
impl Default for TimeStatistics {
fn default() -> Self {
Self {
total_time: Duration::from_secs(0),
average_iteration_time: Duration::from_secs(0),
time_per_evaluation: Duration::from_secs(0),
setup_time: Duration::from_secs(0),
cleanup_time: Duration::from_secs(0),
idle_time: Duration::from_secs(0),
}
}
}
impl Default for StatePersistenceConfig {
fn default() -> Self {
Self {
enabled: true,
persistence_interval: Duration::from_secs(300), max_snapshots: 10,
compression_enabled: true,
storage_path: "/tmp/optimization_state".to_string(),
encryption_enabled: false,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_state_manager_creation() {
let context = OptimizationContext::<f32>::default();
let manager = StateManager::new(context);
assert_eq!(manager.current_context.current_phase, OptimizationPhase::Initialization);
}
#[test]
fn test_state_transition() {
let context = OptimizationContext::<f32>::default();
let mut manager = StateManager::new(context);
let transition = StateTransition {
from_phase: OptimizationPhase::Initialization,
to_phase: OptimizationPhase::Exploration,
transition_time: SystemTime::now(),
trigger: "test".to_string(),
performance_delta: 0.1,
duration: Duration::from_secs(1),
reason: TransitionReason::AutomaticProgression,
confidence: 0.9,
};
assert!(manager.record_transition(transition).is_ok());
assert_eq!(manager.transition_history.len(), 1);
}
#[test]
fn test_state_snapshot() {
let context = OptimizationContext::<f32>::default();
let mut manager = StateManager::new(context);
assert!(manager.create_snapshot(SnapshotReason::Periodic).is_ok());
assert_eq!(manager.state_snapshots.len(), 1);
}
#[test]
fn test_optimization_context_default() {
let context = OptimizationContext::<f64>::default();
assert_eq!(context.dimensionality, 100);
assert_eq!(context.current_phase, OptimizationPhase::Initialization);
assert!(context.performance_history.is_empty());
}
}