#[allow(unused_imports)]
use crate::prelude::*;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum SearchMode {
Focused,
Diversification,
}
#[derive(Debug, Clone)]
pub struct StabilizationConfig {
pub focused_conflicts: u64,
pub diversification_conflicts: u64,
pub min_focused: u64,
pub max_focused: u64,
pub focused_phase_weight: f64,
pub diversification_phase_weight: f64,
pub focused_random_prob: f64,
pub diversification_random_prob: f64,
pub dynamic_adjustment: bool,
}
impl StabilizationConfig {
pub fn default_config() -> Self {
Self {
focused_conflicts: 5000,
diversification_conflicts: 1000,
min_focused: 1000,
max_focused: 100000,
focused_phase_weight: 0.95,
diversification_phase_weight: 0.5,
focused_random_prob: 0.01,
diversification_random_prob: 0.1,
dynamic_adjustment: true,
}
}
pub fn aggressive_focused() -> Self {
Self {
focused_conflicts: 10000,
diversification_conflicts: 500,
min_focused: 5000,
max_focused: 200000,
focused_phase_weight: 0.98,
diversification_phase_weight: 0.3,
focused_random_prob: 0.005,
diversification_random_prob: 0.15,
dynamic_adjustment: true,
}
}
pub fn balanced() -> Self {
Self::default_config()
}
}
impl Default for StabilizationConfig {
fn default() -> Self {
Self::default_config()
}
}
pub struct StabilizationManager {
mode: SearchMode,
config: StabilizationConfig,
conflicts_in_mode: u64,
total_focused_conflicts: u64,
total_diversification_conflicts: u64,
num_switches: u64,
progress_score: f64,
best_focused_progress: f64,
}
impl StabilizationManager {
pub fn new(config: StabilizationConfig) -> Self {
Self {
mode: SearchMode::Focused,
config,
conflicts_in_mode: 0,
total_focused_conflicts: 0,
total_diversification_conflicts: 0,
num_switches: 0,
progress_score: 0.0,
best_focused_progress: 0.0,
}
}
pub fn mode(&self) -> SearchMode {
self.mode
}
pub fn on_conflict(&mut self) -> bool {
self.conflicts_in_mode += 1;
match self.mode {
SearchMode::Focused => {
self.total_focused_conflicts += 1;
if self.conflicts_in_mode >= self.config.focused_conflicts {
self.switch_to_diversification();
return true;
}
}
SearchMode::Diversification => {
self.total_diversification_conflicts += 1;
if self.conflicts_in_mode >= self.config.diversification_conflicts {
self.switch_to_focused();
return true;
}
}
}
false
}
fn switch_to_focused(&mut self) {
self.mode = SearchMode::Focused;
self.conflicts_in_mode = 0;
self.num_switches += 1;
self.best_focused_progress = 0.0;
}
fn switch_to_diversification(&mut self) {
self.mode = SearchMode::Diversification;
self.conflicts_in_mode = 0;
self.num_switches += 1;
}
pub fn record_progress(&mut self, score: f64) {
self.progress_score = score;
if self.mode == SearchMode::Focused && score > self.best_focused_progress {
self.best_focused_progress = score;
if self.config.dynamic_adjustment {
let extension = (self.config.focused_conflicts as f64 * 0.1) as u64;
if self.config.focused_conflicts + extension <= self.config.max_focused {
self.config.focused_conflicts += extension;
}
}
}
}
pub fn phase_weight(&self) -> f64 {
match self.mode {
SearchMode::Focused => self.config.focused_phase_weight,
SearchMode::Diversification => self.config.diversification_phase_weight,
}
}
pub fn random_prob(&self) -> f64 {
match self.mode {
SearchMode::Focused => self.config.focused_random_prob,
SearchMode::Diversification => self.config.diversification_random_prob,
}
}
pub fn restart_multiplier(&self) -> f64 {
match self.mode {
SearchMode::Focused => 0.8, SearchMode::Diversification => 1.5, }
}
pub fn deletion_aggressiveness(&self) -> f64 {
match self.mode {
SearchMode::Focused => 0.5, SearchMode::Diversification => 1.5, }
}
pub fn force_mode(&mut self, mode: SearchMode) {
if self.mode != mode {
self.mode = mode;
self.conflicts_in_mode = 0;
self.num_switches += 1;
}
}
pub fn stats(&self) -> StabilizationStats {
StabilizationStats {
current_mode: self.mode,
conflicts_in_mode: self.conflicts_in_mode,
total_focused_conflicts: self.total_focused_conflicts,
total_diversification_conflicts: self.total_diversification_conflicts,
num_switches: self.num_switches,
progress_score: self.progress_score,
}
}
pub fn reset(&mut self) {
self.mode = SearchMode::Focused;
self.conflicts_in_mode = 0;
self.total_focused_conflicts = 0;
self.total_diversification_conflicts = 0;
self.num_switches = 0;
self.progress_score = 0.0;
self.best_focused_progress = 0.0;
}
}
impl Default for StabilizationManager {
fn default() -> Self {
Self::new(StabilizationConfig::default())
}
}
#[derive(Debug, Clone)]
pub struct StabilizationStats {
pub current_mode: SearchMode,
pub conflicts_in_mode: u64,
pub total_focused_conflicts: u64,
pub total_diversification_conflicts: u64,
pub num_switches: u64,
pub progress_score: f64,
}
impl StabilizationStats {
pub fn focused_ratio(&self) -> f64 {
let total = self.total_focused_conflicts + self.total_diversification_conflicts;
if total == 0 {
return 0.5;
}
self.total_focused_conflicts as f64 / total as f64
}
pub fn avg_conflicts_per_mode(&self) -> f64 {
if self.num_switches == 0 {
return 0.0;
}
let total = self.total_focused_conflicts + self.total_diversification_conflicts;
total as f64 / self.num_switches as f64
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_stabilization_basic() {
let config = StabilizationConfig::default_config();
let manager = StabilizationManager::new(config);
assert_eq!(manager.mode(), SearchMode::Focused);
}
#[test]
fn test_mode_switching() {
let config = StabilizationConfig {
focused_conflicts: 10,
diversification_conflicts: 5,
..StabilizationConfig::default_config()
};
let mut manager = StabilizationManager::new(config);
assert_eq!(manager.mode(), SearchMode::Focused);
for _ in 0..10 {
manager.on_conflict();
}
assert_eq!(manager.mode(), SearchMode::Diversification);
for _ in 0..5 {
manager.on_conflict();
}
assert_eq!(manager.mode(), SearchMode::Focused);
}
#[test]
fn test_phase_weight() {
let config = StabilizationConfig::default_config();
let manager = StabilizationManager::new(config.clone());
assert_eq!(manager.phase_weight(), config.focused_phase_weight);
let mut manager = StabilizationManager::new(config.clone());
manager.force_mode(SearchMode::Diversification);
assert_eq!(manager.phase_weight(), config.diversification_phase_weight);
}
#[test]
fn test_stats() {
let mut config = StabilizationConfig::default_config();
config.focused_conflicts = 5;
let mut manager = StabilizationManager::new(config);
for _ in 0..10 {
manager.on_conflict();
}
let stats = manager.stats();
assert!(stats.num_switches > 0);
assert!(stats.total_focused_conflicts > 0);
}
#[test]
fn test_progress_tracking() {
let config = StabilizationConfig::default_config();
let mut manager = StabilizationManager::new(config);
manager.record_progress(0.5);
assert_eq!(manager.progress_score, 0.5);
manager.record_progress(0.8);
assert_eq!(manager.progress_score, 0.8);
}
}