sklears-core 0.1.1

Core traits, types, and utilities for sklears machine learning library
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
//! Plugin Factory and Configuration Builder
//!
//! This module provides factory patterns and builders for creating plugin instances
//! and configurations. It enables flexible plugin creation with configurable
//! parameters and runtime settings.

use super::core_traits::Plugin;
use super::types_config::{LogLevel, PluginConfig, PluginMetadata, PluginParameter};
use crate::error::Result;

/// Factory for creating plugin instances
///
/// The PluginFactory trait provides a standardized interface for creating
/// plugin instances with specific configurations. This enables dynamic
/// plugin creation and configuration management.
///
/// # Examples
///
/// ```rust,no_run
/// use sklears_core::plugin::{PluginFactory, Plugin, PluginConfig, PluginMetadata};
/// use sklears_core::error::Result;
///
/// struct LinearRegressionFactory;
///
/// impl PluginFactory for LinearRegressionFactory {
///     fn create_plugin(&self, config: &PluginConfig) -> Result<Box<dyn Plugin>> {
///         // Create and configure the plugin based on the provided config
///         // Box::new(LinearRegressionPlugin::new(config))
///         todo!("Implement plugin creation")
///     }
///
///     fn metadata(&self) -> PluginMetadata {
///         PluginMetadata {
///             name: "LinearRegression".to_string(),
///             version: "1.0.0".to_string(),
///             description: "Linear regression algorithm".to_string(),
///             ..Default::default()
///         }
///     }
///
///     fn validate_config(&self, config: &PluginConfig) -> Result<()> {
///         // Validate configuration parameters
///         Ok(())
///     }
/// }
/// ```
pub trait PluginFactory: Send + Sync {
    /// Create a new plugin instance
    ///
    /// This method creates a new plugin instance configured according to
    /// the provided configuration. The factory should validate the configuration
    /// and return an error if the plugin cannot be created with the given settings.
    ///
    /// # Arguments
    ///
    /// * `config` - The configuration for the plugin instance
    ///
    /// # Returns
    ///
    /// A boxed plugin instance, or an error if creation fails.
    fn create_plugin(&self, config: &PluginConfig) -> Result<Box<dyn Plugin>>;

    /// Get plugin metadata
    ///
    /// Returns metadata describing the plugins that this factory can create.
    /// This includes information about capabilities, supported types, and
    /// configuration requirements.
    ///
    /// # Returns
    ///
    /// Metadata for plugins created by this factory.
    fn metadata(&self) -> PluginMetadata;

    /// Validate configuration
    ///
    /// Validates that the provided configuration is suitable for creating
    /// a plugin instance. This should check parameter types, ranges, and
    /// any dependencies or requirements.
    ///
    /// # Arguments
    ///
    /// * `config` - The configuration to validate
    ///
    /// # Returns
    ///
    /// Ok(()) if the configuration is valid, or an error describing
    /// what is invalid.
    fn validate_config(&self, config: &PluginConfig) -> Result<()>;

    /// Get default configuration
    ///
    /// Returns a default configuration that can be used to create a plugin
    /// instance with sensible defaults. This provides a starting point for
    /// configuration customization.
    ///
    /// # Returns
    ///
    /// A default plugin configuration.
    fn default_config(&self) -> PluginConfig {
        PluginConfig::default()
    }

    /// Get configuration schema
    ///
    /// Returns information about the configuration parameters that this
    /// factory accepts, including their types, ranges, and descriptions.
    /// This can be used for automatic UI generation or documentation.
    ///
    /// # Returns
    ///
    /// A map of parameter names to their descriptions and constraints.
    fn config_schema(&self) -> std::collections::HashMap<String, String> {
        std::collections::HashMap::new()
    }
}

/// Builder for creating plugin configurations
///
/// The PluginConfigBuilder provides a fluent interface for constructing
/// plugin configurations with various parameters and runtime settings.
/// It ensures type safety and provides convenient methods for common
/// configuration patterns.
///
/// # Examples
///
/// ```rust
/// use sklears_core::plugin::{PluginConfigBuilder, PluginParameter, LogLevel};
///
/// let config = PluginConfigBuilder::new()
///     .with_parameter("learning_rate", PluginParameter::Float(0.01))
///     .with_parameter("max_iterations", PluginParameter::Int(1000))
///     .with_parameter("use_bias", PluginParameter::Bool(true))
///     .with_threads(4)
///     .with_memory_limit(1024 * 1024 * 1024) // 1GB
///     .with_timeout(30000) // 30 seconds
///     .with_gpu(true)
///     .with_log_level(LogLevel::Info)
///     .with_setting("backend", "cuda")
///     .build();
/// ```
#[derive(Debug, Clone)]
pub struct PluginConfigBuilder {
    /// The configuration being built
    config: PluginConfig,
}

impl PluginConfigBuilder {
    /// Create a new config builder
    ///
    /// Initializes a new builder with default configuration values.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use sklears_core::plugin::PluginConfigBuilder;
    ///
    /// let builder = PluginConfigBuilder::new();
    /// let config = builder.build();
    /// ```
    pub fn new() -> Self {
        Self {
            config: PluginConfig::default(),
        }
    }

    /// Add a parameter to the configuration
    ///
    /// Adds a named parameter with the specified value to the configuration.
    /// This method can be chained to add multiple parameters.
    ///
    /// # Arguments
    ///
    /// * `key` - The parameter name
    /// * `value` - The parameter value
    ///
    /// # Examples
    ///
    /// ```rust
    /// use sklears_core::plugin::{PluginConfigBuilder, PluginParameter};
    ///
    /// let config = PluginConfigBuilder::new()
    ///     .with_parameter("learning_rate", PluginParameter::Float(0.01))
    ///     .with_parameter("regularization", PluginParameter::Float(0.001))
    ///     .build();
    /// ```
    pub fn with_parameter(mut self, key: &str, value: PluginParameter) -> Self {
        self.config.parameters.insert(key.to_string(), value);
        self
    }

    /// Add multiple parameters at once
    ///
    /// Convenience method for adding multiple parameters from a map.
    ///
    /// # Arguments
    ///
    /// * `params` - Map of parameter names to values
    pub fn with_parameters(
        mut self,
        params: std::collections::HashMap<String, PluginParameter>,
    ) -> Self {
        self.config.parameters.extend(params);
        self
    }

    /// Set the number of threads to use
    ///
    /// Configures the number of threads that the plugin should use for
    /// parallel processing. If not set, the plugin will use its default
    /// threading behavior.
    ///
    /// # Arguments
    ///
    /// * `threads` - Number of threads to use
    ///
    /// # Examples
    ///
    /// ```rust
    /// use sklears_core::plugin::PluginConfigBuilder;
    ///
    /// let config = PluginConfigBuilder::new()
    ///     .with_threads(8)
    ///     .build();
    /// ```
    pub fn with_threads(mut self, threads: usize) -> Self {
        self.config.runtime_settings.num_threads = Some(threads);
        self
    }

    /// Set memory limit in bytes
    ///
    /// Configures the maximum amount of memory that the plugin should use.
    /// This can help prevent out-of-memory errors in resource-constrained
    /// environments.
    ///
    /// # Arguments
    ///
    /// * `limit` - Memory limit in bytes
    ///
    /// # Examples
    ///
    /// ```rust
    /// use sklears_core::plugin::PluginConfigBuilder;
    ///
    /// let config = PluginConfigBuilder::new()
    ///     .with_memory_limit(2 * 1024 * 1024 * 1024) // 2GB
    ///     .build();
    /// ```
    pub fn with_memory_limit(mut self, limit: usize) -> Self {
        self.config.runtime_settings.memory_limit = Some(limit);
        self
    }

    /// Set timeout in milliseconds
    ///
    /// Configures the maximum time that plugin operations should take
    /// before timing out. This can help prevent hanging operations.
    ///
    /// # Arguments
    ///
    /// * `timeout_ms` - Timeout in milliseconds
    ///
    /// # Examples
    ///
    /// ```rust
    /// use sklears_core::plugin::PluginConfigBuilder;
    ///
    /// let config = PluginConfigBuilder::new()
    ///     .with_timeout(60000) // 1 minute
    ///     .build();
    /// ```
    pub fn with_timeout(mut self, timeout_ms: u64) -> Self {
        self.config.runtime_settings.timeout_ms = Some(timeout_ms);
        self
    }

    /// Enable or disable GPU acceleration
    ///
    /// Configures whether the plugin should use GPU acceleration if available.
    ///
    /// # Arguments
    ///
    /// * `use_gpu` - Whether to use GPU acceleration
    ///
    /// # Examples
    ///
    /// ```rust
    /// use sklears_core::plugin::PluginConfigBuilder;
    ///
    /// let config = PluginConfigBuilder::new()
    ///     .with_gpu(true)
    ///     .build();
    /// ```
    pub fn with_gpu(mut self, use_gpu: bool) -> Self {
        self.config.runtime_settings.use_gpu = use_gpu;
        self
    }

    /// Set logging level
    ///
    /// Configures the verbosity of logging output from the plugin.
    ///
    /// # Arguments
    ///
    /// * `level` - The logging level to use
    ///
    /// # Examples
    ///
    /// ```rust
    /// use sklears_core::plugin::{PluginConfigBuilder, LogLevel};
    ///
    /// let config = PluginConfigBuilder::new()
    ///     .with_log_level(LogLevel::Debug)
    ///     .build();
    /// ```
    pub fn with_log_level(mut self, level: LogLevel) -> Self {
        self.config.runtime_settings.log_level = level;
        self
    }

    /// Add a plugin-specific setting
    ///
    /// Adds a custom setting that is specific to the plugin being configured.
    /// These settings are typically used for plugin-specific configuration
    /// that doesn't fit into the standard parameter system.
    ///
    /// # Arguments
    ///
    /// * `key` - The setting name
    /// * `value` - The setting value
    ///
    /// # Examples
    ///
    /// ```rust
    /// use sklears_core::plugin::PluginConfigBuilder;
    ///
    /// let config = PluginConfigBuilder::new()
    ///     .with_setting("backend", "tensorflow")
    ///     .with_setting("device", "/gpu:0")
    ///     .build();
    /// ```
    pub fn with_setting(mut self, key: &str, value: &str) -> Self {
        self.config
            .plugin_settings
            .insert(key.to_string(), value.to_string());
        self
    }

    /// Add multiple settings at once
    ///
    /// Convenience method for adding multiple plugin-specific settings.
    ///
    /// # Arguments
    ///
    /// * `settings` - Map of setting names to values
    pub fn with_settings(mut self, settings: std::collections::HashMap<String, String>) -> Self {
        self.config.plugin_settings.extend(settings);
        self
    }

    /// Build the final configuration
    ///
    /// Consumes the builder and returns the constructed configuration.
    ///
    /// # Returns
    ///
    /// The configured PluginConfig instance.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use sklears_core::plugin::{PluginConfigBuilder, PluginParameter};
    ///
    /// let config = PluginConfigBuilder::new()
    ///     .with_parameter("learning_rate", PluginParameter::Float(0.01))
    ///     .with_threads(4)
    ///     .build();
    /// ```
    pub fn build(self) -> PluginConfig {
        self.config
    }

    /// Get a reference to the current configuration
    ///
    /// Returns a reference to the configuration being built without
    /// consuming the builder. This can be useful for inspecting the
    /// current state during construction.
    ///
    /// # Returns
    ///
    /// A reference to the current configuration.
    pub fn config(&self) -> &PluginConfig {
        &self.config
    }

    /// Validate the current configuration
    ///
    /// Validates the current configuration state without building it.
    /// This can be useful for checking configuration validity during
    /// the building process.
    ///
    /// # Returns
    ///
    /// Ok(()) if the configuration is valid, or an error describing
    /// what is invalid.
    pub fn validate(&self) -> Result<()> {
        // Basic validation - can be extended
        if self.config.runtime_settings.num_threads == Some(0) {
            return Err(crate::error::SklearsError::InvalidOperation(
                "Number of threads cannot be zero".to_string(),
            ));
        }

        if let Some(timeout) = self.config.runtime_settings.timeout_ms {
            if timeout == 0 {
                return Err(crate::error::SklearsError::InvalidOperation(
                    "Timeout cannot be zero".to_string(),
                ));
            }
        }

        Ok(())
    }

    /// Clone the builder
    ///
    /// Creates a copy of the current builder state, allowing for
    /// branching configuration construction.
    ///
    /// # Returns
    ///
    /// A cloned builder with the same configuration state.
    pub fn clone_builder(&self) -> Self {
        self.clone()
    }
}

impl Default for PluginConfigBuilder {
    fn default() -> Self {
        Self::new()
    }
}

/// Convenience functions for common plugin configurations
impl PluginConfigBuilder {
    /// Create a configuration optimized for CPU-intensive tasks
    ///
    /// Sets up a configuration with appropriate threading and resource
    /// settings for CPU-bound algorithms.
    pub fn cpu_optimized() -> Self {
        Self::new()
            .with_threads(num_cpus::get())
            .with_gpu(false)
            .with_log_level(LogLevel::Info)
    }

    /// Create a configuration optimized for GPU acceleration
    ///
    /// Sets up a configuration with GPU acceleration enabled and
    /// appropriate resource settings.
    pub fn gpu_optimized() -> Self {
        Self::new()
            .with_gpu(true)
            .with_threads(2) // Fewer CPU threads when using GPU
            .with_log_level(LogLevel::Info)
    }

    /// Create a configuration for development/debugging
    ///
    /// Sets up a configuration with verbose logging and longer timeouts
    /// suitable for development environments.
    pub fn development() -> Self {
        Self::new()
            .with_log_level(LogLevel::Debug)
            .with_timeout(300000) // 5 minutes
            .with_threads(1) // Single-threaded for easier debugging
    }

    /// Create a configuration for production environments
    ///
    /// Sets up a configuration with optimized settings for production use,
    /// including appropriate resource limits and logging levels.
    pub fn production() -> Self {
        Self::new()
            .with_log_level(LogLevel::Warn)
            .with_timeout(30000) // 30 seconds
            .with_memory_limit(4 * 1024 * 1024 * 1024) // 4GB
            .with_threads(num_cpus::get())
    }
}