Skip to main content

solverforge_config/
solver_config.rs

1use std::path::Path;
2use std::time::Duration;
3
4use serde::{Deserialize, Serialize};
5
6use crate::director::DirectorConfig;
7use crate::error::ConfigError;
8use crate::phase::PhaseConfig;
9use crate::termination::TerminationConfig;
10
11/// Main solver configuration.
12#[derive(Debug, Clone, Default, Deserialize, Serialize)]
13#[serde(rename_all = "snake_case")]
14pub struct SolverConfig {
15    /// Environment mode affecting reproducibility and assertions.
16    #[serde(default)]
17    pub environment_mode: EnvironmentMode,
18
19    /// Random seed for reproducible results.
20    #[serde(default)]
21    pub random_seed: Option<u64>,
22
23    /// Number of threads for parallel move evaluation.
24    #[serde(default)]
25    pub move_thread_count: MoveThreadCount,
26
27    /// Termination configuration.
28    #[serde(default)]
29    pub termination: Option<TerminationConfig>,
30
31    /// Score director configuration.
32    #[serde(default)]
33    pub score_director: Option<DirectorConfig>,
34
35    /// Phase configurations.
36    #[serde(default)]
37    pub phases: Vec<PhaseConfig>,
38}
39
40impl SolverConfig {
41    /// Creates a new default configuration.
42    pub fn new() -> Self {
43        Self::default()
44    }
45
46    /// Loads configuration from a TOML file.
47    ///
48    /// # Errors
49    ///
50    /// Returns error if file doesn't exist or contains invalid TOML.
51    pub fn load(path: impl AsRef<Path>) -> Result<Self, ConfigError> {
52        Self::from_toml_file(path)
53    }
54
55    /// Loads configuration from a TOML file.
56    pub fn from_toml_file(path: impl AsRef<Path>) -> Result<Self, ConfigError> {
57        let contents = std::fs::read_to_string(path)?;
58        Self::from_toml_str(&contents)
59    }
60
61    /// Parses configuration from a TOML string.
62    pub fn from_toml_str(s: &str) -> Result<Self, ConfigError> {
63        Ok(toml::from_str(s)?)
64    }
65
66    /// Loads configuration from a YAML file.
67    pub fn from_yaml_file(path: impl AsRef<Path>) -> Result<Self, ConfigError> {
68        let contents = std::fs::read_to_string(path)?;
69        Self::from_yaml_str(&contents)
70    }
71
72    /// Parses configuration from a YAML string.
73    pub fn from_yaml_str(s: &str) -> Result<Self, ConfigError> {
74        Ok(serde_yaml::from_str(s)?)
75    }
76
77    /// Sets the termination time limit.
78    pub fn with_termination_seconds(mut self, seconds: u64) -> Self {
79        self.termination = Some(TerminationConfig {
80            seconds_spent_limit: Some(seconds),
81            ..self.termination.unwrap_or_default()
82        });
83        self
84    }
85
86    /// Sets the random seed.
87    pub fn with_random_seed(mut self, seed: u64) -> Self {
88        self.random_seed = Some(seed);
89        self
90    }
91
92    /// Adds a phase configuration.
93    pub fn with_phase(mut self, phase: PhaseConfig) -> Self {
94        self.phases.push(phase);
95        self
96    }
97
98    /// Returns the termination time limit, if configured.
99    ///
100    /// Convenience method that delegates to `termination.time_limit()`.
101    ///
102    /// # Examples
103    ///
104    /// ```
105    /// use solverforge_config::SolverConfig;
106    /// use std::time::Duration;
107    ///
108    /// let config = SolverConfig::from_toml_str(r#"
109    ///     [termination]
110    ///     seconds_spent_limit = 30
111    /// "#).unwrap();
112    ///
113    /// assert_eq!(config.time_limit(), Some(Duration::from_secs(30)));
114    /// ```
115    pub fn time_limit(&self) -> Option<Duration> {
116        self.termination.as_ref().and_then(|t| t.time_limit())
117    }
118}
119
120/// Environment mode affecting solver behavior.
121#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Deserialize, Serialize)]
122#[serde(rename_all = "snake_case")]
123pub enum EnvironmentMode {
124    /// Non-reproducible mode with minimal overhead.
125    #[default]
126    NonReproducible,
127
128    /// Reproducible mode with deterministic behavior.
129    Reproducible,
130
131    /// Fast assert mode with basic assertions.
132    FastAssert,
133
134    /// Full assert mode with comprehensive assertions.
135    FullAssert,
136}
137
138/// Move thread count configuration.
139#[derive(Debug, Clone, Default, PartialEq, Eq, Deserialize, Serialize)]
140#[serde(rename_all = "snake_case")]
141pub enum MoveThreadCount {
142    /// Automatically determine thread count.
143    #[default]
144    Auto,
145
146    /// No parallel move evaluation.
147    None,
148
149    /// Specific number of threads.
150    Count(usize),
151}
152
153/// Runtime configuration overrides.
154#[derive(Debug, Clone, Default)]
155pub struct SolverConfigOverride {
156    /// Override termination configuration.
157    pub termination: Option<TerminationConfig>,
158}
159
160impl SolverConfigOverride {
161    /// Creates a new override with termination configuration.
162    pub fn with_termination(termination: TerminationConfig) -> Self {
163        SolverConfigOverride {
164            termination: Some(termination),
165        }
166    }
167}