sklears_core/trait_explorer/
trait_registry.rs

1//! Comprehensive trait registry and exploration result types.
2//!
3//! This module provides the core infrastructure for managing and exploring traits within
4//! the sklears ecosystem. It includes trait registration, dependency analysis, performance
5//! analysis, and graph generation capabilities.
6//!
7//! # Key Components
8//!
9//! - [`TraitExplorationResult`] - Main result structure for trait exploration
10//! - [`TraitRegistry`] - Core registry for managing trait information
11//! - [`DependencyAnalysis`] - Analysis of trait dependencies and relationships
12//! - [`PerformanceAnalysis`] - Performance characteristics and optimization hints
13//! - [`TraitGraph`] - Visual graph representation of trait relationships
14//!
15//! # SciRS2 Compliance
16//!
17//! This module is fully compliant with SciRS2 policies, using:
18//! - `scirs2_core::ndarray` for unified array operations
19//! - `scirs2_core::random` for random number generation
20//! - `scirs2_core::error` for error handling
21//!
22//! # Examples
23//!
24//! ## Basic trait registry usage
25//!
26//! ```rust,ignore
27//! use sklears_core::trait_explorer::trait_registry::{TraitRegistry, TraitExplorationResult};
28//! use sklears_core::api_reference_generator::TraitInfo;
29//! use sklears_core::error::Result;
30//!
31//! // Create and populate a trait registry
32//! let mut registry = TraitRegistry::new();
33//! registry.load_sklears_traits()?;
34//!
35//! // Get trait information
36//! if let Some(estimator_trait) = registry.get_trait("Estimator") {
37//!     println!("Found trait: {}", estimator_trait.name);
38//!     let implementations = registry.get_implementations("Estimator");
39//!     println!("Implementations: {:?}", implementations);
40//! }
41//! # Ok::<(), sklears_core::error::SklearsError>(())
42//! ```
43//!
44//! ## Exploring trait relationships
45//!
46//! ```rust,ignore
47//! # use sklears_core::trait_explorer::trait_registry::*;
48//! # use sklears_core::error::Result;
49//! let mut registry = TraitRegistry::new();
50//! registry.load_sklears_traits()?;
51//!
52//! // Get all traits that a specific implementation supports
53//! let linear_reg_traits = registry.get_traits_for_implementation("LinearRegression");
54//! println!("LinearRegression implements: {:?}", linear_reg_traits);
55//!
56//! // List all available traits
57//! let all_traits = registry.get_all_trait_names();
58//! println!("Available traits: {:?}", all_traits);
59//! # Ok::<(), sklears_core::error::SklearsError>(())
60//! ```
61
62use crate::api_data_structures::{AssociatedType, MethodInfo, TraitInfo};
63use crate::error::{Result, SklearsError};
64use serde::{Deserialize, Serialize};
65use std::collections::HashMap;
66
67// SciRS2 Compliance - Use scirs2_core for unified functionality
68
69/// Comprehensive result structure for trait exploration operations.
70///
71/// This structure encapsulates all information discovered during trait exploration,
72/// including trait metadata, implementations, dependency analysis, performance
73/// characteristics, and visualization data.
74///
75/// # Fields
76///
77/// - `trait_name` - Name of the explored trait
78/// - `trait_info` - Complete trait information including methods and generics
79/// - `implementations` - Known implementations of this trait
80/// - `dependencies` - Dependency analysis including direct and transitive dependencies
81/// - `performance` - Performance characteristics and optimization hints
82/// - `complexity_score` - Complexity score (higher = more complex)
83/// - `graph` - Optional visual graph representation
84/// - `examples` - Usage examples for the trait
85/// - `related_traits` - List of related traits
86///
87/// # Examples
88///
89/// ```rust,ignore
90/// # use sklears_core::trait_explorer::trait_registry::*;
91/// # use sklears_core::api_reference_generator::TraitInfo;
92/// # use sklears_core::error::Result;
93/// // Typically obtained from trait exploration operations
94/// let result = TraitExplorationResult {
95///     trait_name: "Estimator".to_string(),
96///     trait_info: TraitInfo::default(),
97///     implementations: vec!["LinearRegression".to_string()],
98///     dependencies: DependencyAnalysis::default(),
99///     performance: PerformanceAnalysis::default(),
100///     complexity_score: 3.5,
101///     graph: None,
102///     examples: vec![],
103///     related_traits: vec!["Fit".to_string(), "Predict".to_string()],
104/// };
105///
106/// println!("Explored trait: {}", result.trait_name);
107/// println!("Complexity score: {}", result.complexity_score);
108/// ```
109#[derive(Debug, Clone, Serialize, Deserialize)]
110pub struct TraitExplorationResult {
111    /// Name of the explored trait
112    pub trait_name: String,
113    /// Complete trait information
114    pub trait_info: TraitInfo,
115    /// Known implementations of this trait
116    pub implementations: Vec<String>,
117    /// Dependency analysis
118    pub dependencies: DependencyAnalysis,
119    /// Performance characteristics
120    pub performance: PerformanceAnalysis,
121    /// Complexity score (higher = more complex)
122    pub complexity_score: f64,
123    /// Visual graph representation
124    pub graph: Option<TraitGraph>,
125    /// Usage examples
126    pub examples: Vec<UsageExample>,
127    /// Related traits
128    pub related_traits: Vec<String>,
129}
130
131impl Default for TraitExplorationResult {
132    fn default() -> Self {
133        Self {
134            trait_name: String::new(),
135            trait_info: TraitInfo::default(),
136            implementations: Vec::new(),
137            dependencies: DependencyAnalysis::default(),
138            performance: PerformanceAnalysis::default(),
139            complexity_score: 0.0,
140            graph: None,
141            examples: Vec::new(),
142            related_traits: Vec::new(),
143        }
144    }
145}
146
147/// Registry for managing trait information and relationships.
148///
149/// The `TraitRegistry` serves as a central repository for trait information,
150/// implementations, and their relationships. It provides efficient lookup
151/// and management capabilities for the trait exploration system.
152///
153/// # Architecture
154///
155/// The registry maintains three core data structures:
156/// - `traits` - Maps trait names to their complete information
157/// - `implementations` - Maps trait names to their known implementations
158/// - `implementation_traits` - Maps implementation names to the traits they implement
159///
160/// # Thread Safety
161///
162/// This registry is not thread-safe by default. For concurrent access,
163/// wrap it in appropriate synchronization primitives.
164///
165/// # Examples
166///
167/// ```rust,ignore
168/// use sklears_core::trait_explorer::trait_registry::TraitRegistry;
169/// use sklears_core::api_reference_generator::TraitInfo;
170/// use sklears_core::error::Result;
171///
172/// let mut registry = TraitRegistry::new();
173///
174/// // Load predefined sklears traits
175/// registry.load_sklears_traits()?;
176///
177/// // Add a custom trait
178/// let custom_trait = TraitInfo {
179///     name: "CustomTrait".to_string(),
180///     description: "A custom trait for testing".to_string(),
181///     path: "my_crate::CustomTrait".to_string(),
182///     generics: vec![],
183///     associated_types: vec![],
184///     methods: vec![],
185///     supertraits: vec![],
186///     implementations: vec!["MyImplementation".to_string()],
187/// };
188/// registry.add_trait(custom_trait);
189///
190/// // Query the registry
191/// assert!(registry.get_trait("CustomTrait").is_some());
192/// let implementations = registry.get_implementations("CustomTrait");
193/// assert_eq!(implementations, vec!["MyImplementation"]);
194/// # Ok::<(), sklears_core::error::SklearsError>(())
195/// ```
196#[derive(Debug)]
197pub struct TraitRegistry {
198    /// Maps trait names to their complete information
199    traits: HashMap<String, TraitInfo>,
200    /// Maps trait names to their known implementations
201    implementations: HashMap<String, Vec<String>>,
202    /// Maps implementation names to the traits they implement
203    implementation_traits: HashMap<String, Vec<String>>,
204}
205
206impl TraitRegistry {
207    /// Creates a new empty trait registry.
208    ///
209    /// # Examples
210    ///
211    /// ```rust,ignore
212    /// use sklears_core::trait_explorer::trait_registry::TraitRegistry;
213    ///
214    /// let registry = TraitRegistry::new();
215    /// assert_eq!(registry.get_all_trait_names().len(), 0);
216    /// ```
217    pub fn new() -> Self {
218        Self {
219            traits: HashMap::new(),
220            implementations: HashMap::new(),
221            implementation_traits: HashMap::new(),
222        }
223    }
224
225    /// Loads predefined sklears traits into the registry.
226    ///
227    /// This method populates the registry with the core traits used throughout
228    /// the sklears ecosystem: Estimator, Fit, Predict, and Transform.
229    ///
230    /// # Returns
231    ///
232    /// Returns `Ok(())` on success, or an error if trait loading fails.
233    ///
234    /// # Examples
235    ///
236    /// ```rust,ignore
237    /// use sklears_core::trait_explorer::trait_registry::TraitRegistry;
238    /// use sklears_core::error::Result;
239    ///
240    /// let mut registry = TraitRegistry::new();
241    /// registry.load_sklears_traits()?;
242    ///
243    /// // Verify core traits are loaded
244    /// assert!(registry.get_trait("Estimator").is_some());
245    /// assert!(registry.get_trait("Fit").is_some());
246    /// assert!(registry.get_trait("Predict").is_some());
247    /// assert!(registry.get_trait("Transform").is_some());
248    /// # Ok::<(), sklears_core::error::SklearsError>(())
249    /// ```
250    pub fn load_sklears_traits(&mut self) -> Result<()> {
251        // Load example trait data for sklears-core
252        let estimator_trait = TraitInfo {
253            name: "Estimator".to_string(),
254            description: "Base trait for all machine learning estimators".to_string(),
255            path: "sklears_core::traits::Estimator".to_string(),
256            generics: Vec::new(),
257            associated_types: vec![AssociatedType {
258                name: "Config".to_string(),
259                description: "Configuration type for the estimator".to_string(),
260                bounds: Vec::new(),
261            }],
262            methods: vec![MethodInfo {
263                name: "name".to_string(),
264                signature: "fn name(&self) -> &'static str".to_string(),
265                description: "Get the name of the estimator".to_string(),
266                parameters: Vec::new(),
267                return_type: "&'static str".to_string(),
268                required: true,
269            }],
270            supertraits: Vec::new(),
271            implementations: vec![
272                "LinearRegression".to_string(),
273                "LogisticRegression".to_string(),
274                "RandomForest".to_string(),
275            ],
276        };
277
278        let fit_trait = TraitInfo {
279            name: "Fit".to_string(),
280            description: "Trait for estimators that can be fitted to training data".to_string(),
281            path: "sklears_core::traits::Fit".to_string(),
282            generics: vec!["X".to_string(), "Y".to_string()],
283            associated_types: vec![AssociatedType {
284                name: "Fitted".to_string(),
285                description: "The type returned after fitting".to_string(),
286                bounds: vec!["Send".to_string(), "Sync".to_string()],
287            }],
288            methods: vec![MethodInfo {
289                name: "fit".to_string(),
290                signature: "fn fit(self, x: &X, y: &Y) -> Result<Self::Fitted>".to_string(),
291                description: "Fit the estimator to training data".to_string(),
292                parameters: Vec::new(),
293                return_type: "Result<Self::Fitted>".to_string(),
294                required: true,
295            }],
296            supertraits: vec!["Estimator".to_string()],
297            implementations: vec![
298                "LinearRegression".to_string(),
299                "LogisticRegression".to_string(),
300            ],
301        };
302
303        let predict_trait = TraitInfo {
304            name: "Predict".to_string(),
305            description: "Trait for making predictions on new data".to_string(),
306            path: "sklears_core::traits::Predict".to_string(),
307            generics: vec!["X".to_string()],
308            associated_types: vec![AssociatedType {
309                name: "Output".to_string(),
310                description: "The type of predictions made".to_string(),
311                bounds: Vec::new(),
312            }],
313            methods: vec![MethodInfo {
314                name: "predict".to_string(),
315                signature: "fn predict(&self, x: &X) -> Result<Self::Output>".to_string(),
316                description: "Make predictions on input data".to_string(),
317                parameters: Vec::new(),
318                return_type: "Result<Self::Output>".to_string(),
319                required: true,
320            }],
321            supertraits: Vec::new(),
322            implementations: vec![
323                "LinearRegression".to_string(),
324                "LogisticRegression".to_string(),
325                "RandomForest".to_string(),
326            ],
327        };
328
329        let transform_trait = TraitInfo {
330            name: "Transform".to_string(),
331            description: "Trait for data transformation operations".to_string(),
332            path: "sklears_core::traits::Transform".to_string(),
333            generics: vec!["X".to_string()],
334            associated_types: vec![AssociatedType {
335                name: "Output".to_string(),
336                description: "The type of transformed data".to_string(),
337                bounds: Vec::new(),
338            }],
339            methods: vec![MethodInfo {
340                name: "transform".to_string(),
341                signature: "fn transform(&self, x: &X) -> Result<Self::Output>".to_string(),
342                description: "Transform input data".to_string(),
343                parameters: Vec::new(),
344                return_type: "Result<Self::Output>".to_string(),
345                required: true,
346            }],
347            supertraits: Vec::new(),
348            implementations: vec![
349                "StandardScaler".to_string(),
350                "PCA".to_string(),
351                "MinMaxScaler".to_string(),
352            ],
353        };
354
355        // Register all traits
356        self.add_trait(estimator_trait);
357        self.add_trait(fit_trait);
358        self.add_trait(predict_trait);
359        self.add_trait(transform_trait);
360
361        Ok(())
362    }
363
364    /// Adds a trait to the registry.
365    ///
366    /// This method registers a trait and updates the implementation mappings
367    /// to maintain bidirectional relationships between traits and their implementations.
368    ///
369    /// # Arguments
370    ///
371    /// * `trait_info` - Complete information about the trait to add
372    ///
373    /// # Examples
374    ///
375    /// ```rust,ignore
376    /// use sklears_core::trait_explorer::trait_registry::TraitRegistry;
377    /// use sklears_core::api_reference_generator::TraitInfo;
378    ///
379    /// let mut registry = TraitRegistry::new();
380    /// let trait_info = TraitInfo {
381    ///     name: "MyTrait".to_string(),
382    ///     description: "A custom trait".to_string(),
383    ///     path: "my_crate::MyTrait".to_string(),
384    ///     generics: vec![],
385    ///     associated_types: vec![],
386    ///     methods: vec![],
387    ///     supertraits: vec![],
388    ///     implementations: vec!["MyImpl".to_string()],
389    /// };
390    ///
391    /// registry.add_trait(trait_info);
392    /// assert!(registry.get_trait("MyTrait").is_some());
393    /// assert_eq!(registry.get_implementations("MyTrait"), vec!["MyImpl"]);
394    /// ```
395    pub fn add_trait(&mut self, trait_info: TraitInfo) {
396        // Register implementations
397        for impl_name in &trait_info.implementations {
398            self.implementations
399                .entry(trait_info.name.clone())
400                .or_default()
401                .push(impl_name.clone());
402
403            self.implementation_traits
404                .entry(impl_name.clone())
405                .or_default()
406                .push(trait_info.name.clone());
407        }
408
409        self.traits.insert(trait_info.name.clone(), trait_info);
410    }
411
412    /// Retrieves trait information by name.
413    ///
414    /// # Arguments
415    ///
416    /// * `name` - The name of the trait to retrieve
417    ///
418    /// # Returns
419    ///
420    /// Returns `Some(&TraitInfo)` if the trait exists, `None` otherwise.
421    ///
422    /// # Examples
423    ///
424    /// ```rust,ignore
425    /// use sklears_core::trait_explorer::trait_registry::TraitRegistry;
426    /// use sklears_core::error::Result;
427    ///
428    /// let mut registry = TraitRegistry::new();
429    /// registry.load_sklears_traits()?;
430    ///
431    /// if let Some(estimator_trait) = registry.get_trait("Estimator") {
432    ///     println!("Found trait: {}", estimator_trait.name);
433    ///     println!("Description: {}", estimator_trait.description);
434    /// }
435    /// # Ok::<(), sklears_core::error::SklearsError>(())
436    /// ```
437    pub fn get_trait(&self, name: &str) -> Option<&TraitInfo> {
438        self.traits.get(name)
439    }
440
441    /// Gets all traits in the registry.
442    ///
443    /// # Returns
444    ///
445    /// Returns a vector of references to all trait information in the registry.
446    ///
447    /// # Examples
448    ///
449    /// ```rust,ignore
450    /// use sklears_core::trait_explorer::trait_registry::TraitRegistry;
451    /// use sklears_core::error::Result;
452    ///
453    /// let mut registry = TraitRegistry::new();
454    /// registry.load_sklears_traits()?;
455    ///
456    /// let all_traits = registry.get_all_traits();
457    /// println!("Registry contains {} traits", all_traits.len());
458    /// for trait_info in all_traits {
459    ///     println!("- {}: {}", trait_info.name, trait_info.description);
460    /// }
461    /// # Ok::<(), sklears_core::error::SklearsError>(())
462    /// ```
463    pub fn get_all_traits(&self) -> Vec<&TraitInfo> {
464        self.traits.values().collect()
465    }
466
467    /// Gets all trait names in the registry.
468    ///
469    /// # Returns
470    ///
471    /// Returns a vector of all trait names.
472    ///
473    /// # Examples
474    ///
475    /// ```rust,ignore
476    /// use sklears_core::trait_explorer::trait_registry::TraitRegistry;
477    /// use sklears_core::error::Result;
478    ///
479    /// let mut registry = TraitRegistry::new();
480    /// registry.load_sklears_traits()?;
481    ///
482    /// let trait_names = registry.get_all_trait_names();
483    /// assert!(trait_names.contains(&"Estimator".to_string()));
484    /// assert!(trait_names.contains(&"Fit".to_string()));
485    /// # Ok::<(), sklears_core::error::SklearsError>(())
486    /// ```
487    pub fn get_all_trait_names(&self) -> Vec<String> {
488        self.traits.keys().cloned().collect()
489    }
490
491    /// Gets all implementations of a specific trait.
492    ///
493    /// # Arguments
494    ///
495    /// * `trait_name` - The name of the trait
496    ///
497    /// # Returns
498    ///
499    /// Returns a vector of implementation names. Returns an empty vector
500    /// if the trait doesn't exist or has no implementations.
501    ///
502    /// # Examples
503    ///
504    /// ```rust,ignore
505    /// use sklears_core::trait_explorer::trait_registry::TraitRegistry;
506    /// use sklears_core::error::Result;
507    ///
508    /// let mut registry = TraitRegistry::new();
509    /// registry.load_sklears_traits()?;
510    ///
511    /// let estimator_impls = registry.get_implementations("Estimator");
512    /// assert!(estimator_impls.contains(&"LinearRegression".to_string()));
513    ///
514    /// let unknown_impls = registry.get_implementations("UnknownTrait");
515    /// assert!(unknown_impls.is_empty());
516    /// # Ok::<(), sklears_core::error::SklearsError>(())
517    /// ```
518    pub fn get_implementations(&self, trait_name: &str) -> Vec<String> {
519        self.implementations
520            .get(trait_name)
521            .cloned()
522            .unwrap_or_default()
523    }
524
525    /// Gets all traits implemented by a specific implementation.
526    ///
527    /// # Arguments
528    ///
529    /// * `implementation` - The name of the implementation
530    ///
531    /// # Returns
532    ///
533    /// Returns a vector of trait names that the implementation supports.
534    /// Returns an empty vector if the implementation doesn't exist.
535    ///
536    /// # Examples
537    ///
538    /// ```rust,ignore
539    /// use sklears_core::trait_explorer::trait_registry::TraitRegistry;
540    /// use sklears_core::error::Result;
541    ///
542    /// let mut registry = TraitRegistry::new();
543    /// registry.load_sklears_traits()?;
544    ///
545    /// let linear_reg_traits = registry.get_traits_for_implementation("LinearRegression");
546    /// assert!(linear_reg_traits.contains(&"Estimator".to_string()));
547    /// assert!(linear_reg_traits.contains(&"Fit".to_string()));
548    ///
549    /// let unknown_traits = registry.get_traits_for_implementation("UnknownImpl");
550    /// assert!(unknown_traits.is_empty());
551    /// # Ok::<(), sklears_core::error::SklearsError>(())
552    /// ```
553    pub fn get_traits_for_implementation(&self, implementation: &str) -> Vec<String> {
554        self.implementation_traits
555            .get(implementation)
556            .cloned()
557            .unwrap_or_default()
558    }
559
560    /// Checks if a trait exists in the registry.
561    ///
562    /// # Arguments
563    ///
564    /// * `trait_name` - The name of the trait to check
565    ///
566    /// # Returns
567    ///
568    /// Returns `true` if the trait exists, `false` otherwise.
569    ///
570    /// # Examples
571    ///
572    /// ```rust,ignore
573    /// use sklears_core::trait_explorer::trait_registry::TraitRegistry;
574    /// use sklears_core::error::Result;
575    ///
576    /// let mut registry = TraitRegistry::new();
577    /// registry.load_sklears_traits()?;
578    ///
579    /// assert!(registry.has_trait("Estimator"));
580    /// assert!(!registry.has_trait("NonExistentTrait"));
581    /// # Ok::<(), sklears_core::error::SklearsError>(())
582    /// ```
583    pub fn has_trait(&self, trait_name: &str) -> bool {
584        self.traits.contains_key(trait_name)
585    }
586
587    /// Checks if an implementation exists in the registry.
588    ///
589    /// # Arguments
590    ///
591    /// * `implementation` - The name of the implementation to check
592    ///
593    /// # Returns
594    ///
595    /// Returns `true` if the implementation exists, `false` otherwise.
596    ///
597    /// # Examples
598    ///
599    /// ```rust,ignore
600    /// use sklears_core::trait_explorer::trait_registry::TraitRegistry;
601    /// use sklears_core::error::Result;
602    ///
603    /// let mut registry = TraitRegistry::new();
604    /// registry.load_sklears_traits()?;
605    ///
606    /// assert!(registry.has_implementation("LinearRegression"));
607    /// assert!(!registry.has_implementation("NonExistentImpl"));
608    /// # Ok::<(), sklears_core::error::SklearsError>(())
609    /// ```
610    pub fn has_implementation(&self, implementation: &str) -> bool {
611        self.implementation_traits.contains_key(implementation)
612    }
613
614    /// Gets the total number of traits in the registry.
615    ///
616    /// # Returns
617    ///
618    /// Returns the count of registered traits.
619    ///
620    /// # Examples
621    ///
622    /// ```rust,ignore
623    /// use sklears_core::trait_explorer::trait_registry::TraitRegistry;
624    /// use sklears_core::error::Result;
625    ///
626    /// let mut registry = TraitRegistry::new();
627    /// assert_eq!(registry.trait_count(), 0);
628    ///
629    /// registry.load_sklears_traits()?;
630    /// assert!(registry.trait_count() > 0);
631    /// # Ok::<(), sklears_core::error::SklearsError>(())
632    /// ```
633    pub fn trait_count(&self) -> usize {
634        self.traits.len()
635    }
636
637    /// Gets the total number of unique implementations in the registry.
638    ///
639    /// # Returns
640    ///
641    /// Returns the count of unique implementations.
642    ///
643    /// # Examples
644    ///
645    /// ```rust,ignore
646    /// use sklears_core::trait_explorer::trait_registry::TraitRegistry;
647    /// use sklears_core::error::Result;
648    ///
649    /// let mut registry = TraitRegistry::new();
650    /// registry.load_sklears_traits()?;
651    ///
652    /// let impl_count = registry.implementation_count();
653    /// assert!(impl_count > 0);
654    /// # Ok::<(), sklears_core::error::SklearsError>(())
655    /// ```
656    pub fn implementation_count(&self) -> usize {
657        self.implementation_traits.len()
658    }
659}
660
661impl Default for TraitRegistry {
662    fn default() -> Self {
663        Self::new()
664    }
665}
666
667/// Analysis of trait dependencies and relationships.
668///
669/// This structure provides comprehensive information about how a trait
670/// relates to other traits in the system, including direct dependencies,
671/// transitive dependencies, and potential circular dependencies.
672///
673/// # Fields
674///
675/// - `direct_dependencies` - Immediate dependencies (supertraits, bounds)
676/// - `transitive_dependencies` - All dependencies through the dependency chain
677/// - `dependency_depth` - Maximum depth of the dependency chain
678/// - `circular_dependencies` - Any circular dependency cycles detected
679///
680/// # Examples
681///
682/// ```rust,ignore
683/// use sklears_core::trait_explorer::trait_registry::DependencyAnalysis;
684///
685/// let analysis = DependencyAnalysis {
686///     direct_dependencies: vec!["Send".to_string(), "Sync".to_string()],
687///     transitive_dependencies: vec!["Send".to_string(), "Sync".to_string()],
688///     dependency_depth: 1,
689///     circular_dependencies: vec![],
690/// };
691///
692/// assert_eq!(analysis.direct_dependencies.len(), 2);
693/// assert!(analysis.circular_dependencies.is_empty());
694/// ```
695#[derive(Debug, Clone, Default, Serialize, Deserialize)]
696pub struct DependencyAnalysis {
697    /// Direct dependencies (supertraits, bounds)
698    pub direct_dependencies: Vec<String>,
699    /// All transitive dependencies
700    pub transitive_dependencies: Vec<String>,
701    /// Maximum depth of dependency chain
702    pub dependency_depth: usize,
703    /// Circular dependency cycles detected
704    pub circular_dependencies: Vec<Vec<String>>,
705}
706
707/// Analysis of trait performance characteristics.
708///
709/// This structure provides detailed information about the performance
710/// implications of using a trait, including compilation impact, runtime
711/// overhead, memory footprint, and optimization suggestions.
712///
713/// # Fields
714///
715/// - `compilation_impact` - How the trait affects compilation time
716/// - `runtime_overhead` - Runtime performance characteristics
717/// - `memory_footprint` - Memory usage analysis
718/// - `optimization_hints` - Suggestions for performance optimization
719///
720/// # Examples
721///
722/// ```rust,ignore
723/// use sklears_core::trait_explorer::trait_registry::*;
724///
725/// let performance = PerformanceAnalysis {
726///     compilation_impact: CompilationImpact {
727///         estimated_compile_time_ms: 50,
728///         ..Default::default()
729///     },
730///     runtime_overhead: RuntimeOverhead {
731///         virtual_dispatch_cost: 10,
732///         stack_frame_size: 64,
733///         cache_pressure: "Low".to_string(),
734///     },
735///     memory_footprint: MemoryFootprint {
736///         vtable_size_bytes: 24,
737///         associated_data_size: 0,
738///         total_overhead: 24,
739///     },
740///     optimization_hints: vec![
741///         "Consider using static dispatch for performance-critical code".to_string()
742///     ],
743/// };
744///
745/// assert_eq!(performance.runtime_overhead.virtual_dispatch_cost, 10);
746/// ```
747#[derive(Debug, Clone, Default, Serialize, Deserialize)]
748pub struct PerformanceAnalysis {
749    /// Impact on compilation
750    pub compilation_impact: CompilationImpact,
751    /// Runtime performance characteristics
752    pub runtime_overhead: RuntimeOverhead,
753    /// Memory usage analysis
754    pub memory_footprint: MemoryFootprint,
755    /// Suggestions for optimization
756    pub optimization_hints: Vec<String>,
757}
758
759/// Compilation performance impact analysis.
760///
761/// This structure quantifies how a trait affects compilation performance,
762/// including estimated compile time impact and resource usage.
763#[derive(Debug, Clone, Default, Serialize, Deserialize)]
764pub struct CompilationImpact {
765    /// Estimated additional compile time in milliseconds
766    pub estimated_compile_time_ms: usize,
767    /// Generic instantiation impact
768    pub generic_instantiation_cost: usize,
769    /// Type checking complexity score
770    pub type_checking_complexity: f64,
771}
772
773/// Runtime performance overhead analysis.
774///
775/// This structure provides information about the runtime costs associated
776/// with using a trait, including virtual dispatch overhead and memory pressure.
777#[derive(Debug, Clone, Default, Serialize, Deserialize)]
778pub struct RuntimeOverhead {
779    /// Cost of virtual dispatch in nanoseconds
780    pub virtual_dispatch_cost: usize,
781    /// Stack frame size in bytes
782    pub stack_frame_size: usize,
783    /// Cache pressure level
784    pub cache_pressure: String,
785}
786
787/// Memory footprint analysis.
788///
789/// This structure analyzes the memory impact of using a trait,
790/// including vtable sizes and associated data overhead.
791#[derive(Debug, Clone, Default, Serialize, Deserialize)]
792pub struct MemoryFootprint {
793    /// Size of virtual function table
794    pub vtable_size_bytes: usize,
795    /// Memory used by associated data
796    pub associated_data_size: usize,
797    /// Total memory overhead
798    pub total_overhead: usize,
799}
800
801/// Visual graph representation of trait relationships.
802///
803/// This structure represents trait relationships as a directed graph,
804/// suitable for visualization and analysis tools.
805///
806/// # Fields
807///
808/// - `nodes` - All nodes in the graph (traits, implementations, etc.)
809/// - `edges` - Connections between nodes
810/// - `metadata` - Graph metadata including generation time and format
811///
812/// # Examples
813///
814/// ```rust,ignore
815/// use sklears_core::trait_explorer::trait_registry::*;
816/// use chrono::Utc;
817///
818/// let graph = TraitGraph {
819///     nodes: vec![
820///         TraitGraphNode {
821///             id: "Estimator".to_string(),
822///             label: "Estimator".to_string(),
823///             node_type: TraitNodeType::Trait,
824///             description: "Base estimator trait".to_string(),
825///             complexity: 2.0,
826///         }
827///     ],
828///     edges: vec![],
829///     metadata: TraitGraphMetadata {
830///         center_node: "Estimator".to_string(),
831///         generation_time: Utc::now(),
832///         export_format: GraphExportFormat::Dot,
833///     },
834/// };
835///
836/// let dot_output = graph.to_dot();
837/// assert!(dot_output.contains("digraph TraitGraph"));
838/// ```
839#[derive(Debug, Clone, Serialize, Deserialize)]
840pub struct TraitGraph {
841    /// Nodes in the graph
842    pub nodes: Vec<TraitGraphNode>,
843    /// Edges connecting nodes
844    pub edges: Vec<TraitGraphEdge>,
845    /// Graph metadata
846    pub metadata: TraitGraphMetadata,
847}
848
849impl TraitGraph {
850    /// Export graph to DOT format (Graphviz).
851    ///
852    /// # Returns
853    ///
854    /// Returns a string containing the graph in DOT format, suitable
855    /// for rendering with Graphviz tools.
856    ///
857    /// # Examples
858    ///
859    /// ```rust,ignore
860    /// use sklears_core::trait_explorer::trait_registry::*;
861    /// use chrono::Utc;
862    ///
863    /// let graph = TraitGraph {
864    ///     nodes: vec![
865    ///         TraitGraphNode {
866    ///             id: "Estimator".to_string(),
867    ///             label: "Estimator".to_string(),
868    ///             node_type: TraitNodeType::Trait,
869    ///             description: "Base trait".to_string(),
870    ///             complexity: 1.0,
871    ///         }
872    ///     ],
873    ///     edges: vec![],
874    ///     metadata: TraitGraphMetadata {
875    ///         center_node: "Estimator".to_string(),
876    ///         generation_time: Utc::now(),
877    ///         export_format: GraphExportFormat::Dot,
878    ///     },
879    /// };
880    ///
881    /// let dot = graph.to_dot();
882    /// assert!(dot.contains("Estimator"));
883    /// assert!(dot.contains("digraph TraitGraph"));
884    /// ```
885    pub fn to_dot(&self) -> String {
886        let mut dot = String::from("digraph TraitGraph {\n");
887        dot.push_str("  rankdir=TB;\n");
888        dot.push_str("  node [shape=box, style=rounded];\n");
889
890        // Add nodes
891        for node in &self.nodes {
892            let color = match node.node_type {
893                TraitNodeType::Trait => "lightblue",
894                TraitNodeType::Implementation => "lightgreen",
895                TraitNodeType::AssociatedType => "lightyellow",
896            };
897
898            dot.push_str(&format!(
899                "  \"{}\" [label=\"{}\" fillcolor={} style=\"filled,rounded\"];\n",
900                node.id, node.label, color
901            ));
902        }
903
904        // Add edges
905        for edge in &self.edges {
906            let style = match edge.edge_type {
907                EdgeType::Inherits => "solid",
908                EdgeType::Implements => "dashed",
909                EdgeType::AssociatedWith => "dotted",
910            };
911
912            dot.push_str(&format!(
913                "  \"{}\" -> \"{}\" [style={}];\n",
914                edge.from, edge.to, style
915            ));
916        }
917
918        dot.push_str("}\n");
919        dot
920    }
921
922    /// Export graph to JSON format.
923    ///
924    /// # Returns
925    ///
926    /// Returns a JSON string representation of the graph, suitable
927    /// for web-based visualization libraries.
928    pub fn to_json(&self) -> Result<String> {
929        serde_json::to_string_pretty(self)
930            .map_err(|e| SklearsError::Other(format!("Failed to serialize graph to JSON: {}", e)))
931    }
932}
933
934/// Node in the trait graph.
935///
936/// Represents an entity in the trait relationship graph, such as
937/// a trait, implementation, or associated type.
938#[derive(Debug, Clone, Serialize, Deserialize)]
939pub struct TraitGraphNode {
940    /// Unique identifier
941    pub id: String,
942    /// Display label
943    pub label: String,
944    /// Type of node
945    pub node_type: TraitNodeType,
946    /// Description text
947    pub description: String,
948    /// Complexity score for visual sizing
949    pub complexity: f64,
950}
951
952/// Edge in the trait graph.
953///
954/// Represents a relationship between two nodes in the trait graph.
955#[derive(Debug, Clone, Serialize, Deserialize)]
956pub struct TraitGraphEdge {
957    /// Source node ID
958    pub from: String,
959    /// Target node ID
960    pub to: String,
961    /// Type of relationship
962    pub edge_type: EdgeType,
963    /// Edge weight for layout
964    pub weight: f64,
965}
966
967/// Types of nodes in the trait graph.
968#[derive(Debug, Clone, Serialize, Deserialize)]
969pub enum TraitNodeType {
970    /// Main trait node
971    Trait,
972    /// Implementation node
973    Implementation,
974    /// Associated type node
975    AssociatedType,
976}
977
978/// Types of relationships between nodes.
979#[derive(Debug, Clone, Serialize, Deserialize)]
980pub enum EdgeType {
981    /// Inheritance relationship
982    Inherits,
983    /// Implementation relationship
984    Implements,
985    /// Associated with relationship
986    AssociatedWith,
987}
988
989/// Metadata for trait graphs.
990#[derive(Debug, Clone, Serialize, Deserialize)]
991pub struct TraitGraphMetadata {
992    /// Central node for focused graphs
993    pub center_node: String,
994    /// When the graph was generated
995    pub generation_time: chrono::DateTime<chrono::Utc>,
996    /// Export format used
997    pub export_format: GraphExportFormat,
998}
999
1000/// Available graph export formats.
1001#[derive(Debug, Clone, Serialize, Deserialize)]
1002pub enum GraphExportFormat {
1003    /// DOT format (Graphviz)
1004    Dot,
1005    /// JSON format
1006    Json,
1007    /// SVG format
1008    Svg,
1009}
1010
1011/// Usage example for a trait.
1012///
1013/// Provides practical examples of how to use a trait, including
1014/// code samples and explanations.
1015///
1016/// # Fields
1017///
1018/// - `title` - Brief title for the example
1019/// - `description` - Detailed description of what the example demonstrates
1020/// - `code` - Actual code content
1021/// - `category` - Category of the example (Implementation, Usage, etc.)
1022/// - `difficulty` - Difficulty level (Beginner, Intermediate, Advanced)
1023/// - `runnable` - Whether the example can be executed
1024///
1025/// # Examples
1026///
1027/// ```rust,ignore
1028/// use sklears_core::trait_explorer::trait_registry::*;
1029///
1030/// let example = UsageExample {
1031///     title: "Basic Estimator Implementation".to_string(),
1032///     description: "Shows how to implement the Estimator trait".to_string(),
1033///     code: r#"
1034/// impl Estimator for MyEstimator {
1035///     type Config = MyConfig;
1036///
1037///     fn name(&self) -> &'static str {
1038///         "MyEstimator"
1039///     }
1040/// }
1041/// "#.to_string(),
1042///     category: ExampleCategory::Implementation,
1043///     difficulty: ExampleDifficulty::Beginner,
1044///     runnable: true,
1045/// };
1046///
1047/// assert_eq!(example.difficulty, ExampleDifficulty::Beginner);
1048/// assert!(example.runnable);
1049/// ```
1050#[derive(Debug, Clone, Serialize, Deserialize)]
1051pub struct UsageExample {
1052    /// Title of the example
1053    pub title: String,
1054    /// Description of what the example shows
1055    pub description: String,
1056    /// Code content
1057    pub code: String,
1058    /// Category of example
1059    pub category: ExampleCategory,
1060    /// Difficulty level
1061    pub difficulty: ExampleDifficulty,
1062    /// Whether the example can be run
1063    pub runnable: bool,
1064}
1065
1066/// Categories of usage examples.
1067#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
1068pub enum ExampleCategory {
1069    /// How to implement the trait
1070    Implementation,
1071    /// How to use the trait
1072    Usage,
1073    /// Generic programming with the trait
1074    Generic,
1075    /// Advanced patterns
1076    Advanced,
1077}
1078
1079/// Difficulty levels for examples.
1080#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
1081pub enum ExampleDifficulty {
1082    Beginner,
1083    Intermediate,
1084    Advanced,
1085}
1086
1087#[allow(non_snake_case)]
1088#[cfg(test)]
1089mod tests {
1090    use super::*;
1091
1092    #[test]
1093    fn test_trait_registry_creation() {
1094        let registry = TraitRegistry::new();
1095        assert_eq!(registry.trait_count(), 0);
1096        assert_eq!(registry.implementation_count(), 0);
1097    }
1098
1099    #[test]
1100    fn test_load_sklears_traits() -> Result<()> {
1101        let mut registry = TraitRegistry::new();
1102        registry.load_sklears_traits()?;
1103
1104        // Verify core traits are loaded
1105        assert!(registry.has_trait("Estimator"));
1106        assert!(registry.has_trait("Fit"));
1107        assert!(registry.has_trait("Predict"));
1108        assert!(registry.has_trait("Transform"));
1109
1110        // Verify trait count
1111        assert_eq!(registry.trait_count(), 4);
1112
1113        Ok(())
1114    }
1115
1116    #[test]
1117    fn test_trait_retrieval() -> Result<()> {
1118        let mut registry = TraitRegistry::new();
1119        registry.load_sklears_traits()?;
1120
1121        let estimator_trait = registry.get_trait("Estimator").unwrap();
1122        assert_eq!(estimator_trait.name, "Estimator");
1123        assert_eq!(estimator_trait.path, "sklears_core::traits::Estimator");
1124
1125        assert!(registry.get_trait("NonExistent").is_none());
1126
1127        Ok(())
1128    }
1129
1130    #[test]
1131    fn test_implementation_mapping() -> Result<()> {
1132        let mut registry = TraitRegistry::new();
1133        registry.load_sklears_traits()?;
1134
1135        // Test trait -> implementations mapping
1136        let estimator_impls = registry.get_implementations("Estimator");
1137        assert!(estimator_impls.contains(&"LinearRegression".to_string()));
1138        assert!(estimator_impls.contains(&"LogisticRegression".to_string()));
1139        assert!(estimator_impls.contains(&"RandomForest".to_string()));
1140
1141        // Test implementation -> traits mapping
1142        let linear_reg_traits = registry.get_traits_for_implementation("LinearRegression");
1143        assert!(linear_reg_traits.contains(&"Estimator".to_string()));
1144        assert!(linear_reg_traits.contains(&"Fit".to_string()));
1145        assert!(linear_reg_traits.contains(&"Predict".to_string()));
1146
1147        Ok(())
1148    }
1149
1150    #[test]
1151    fn test_custom_trait_addition() {
1152        let mut registry = TraitRegistry::new();
1153
1154        let custom_trait = TraitInfo {
1155            name: "CustomTrait".to_string(),
1156            description: "A custom trait for testing".to_string(),
1157            path: "test::CustomTrait".to_string(),
1158            generics: vec!["T".to_string()],
1159            associated_types: vec![],
1160            methods: vec![],
1161            supertraits: vec![],
1162            implementations: vec!["CustomImpl".to_string()],
1163        };
1164
1165        registry.add_trait(custom_trait);
1166
1167        assert!(registry.has_trait("CustomTrait"));
1168        assert!(registry.has_implementation("CustomImpl"));
1169        assert_eq!(
1170            registry.get_implementations("CustomTrait"),
1171            vec!["CustomImpl"]
1172        );
1173        assert_eq!(
1174            registry.get_traits_for_implementation("CustomImpl"),
1175            vec!["CustomTrait"]
1176        );
1177    }
1178
1179    #[test]
1180    fn test_trait_exploration_result_default() {
1181        let result = TraitExplorationResult::default();
1182        assert!(result.trait_name.is_empty());
1183        assert_eq!(result.complexity_score, 0.0);
1184        assert!(result.implementations.is_empty());
1185        assert!(result.examples.is_empty());
1186        assert!(result.related_traits.is_empty());
1187    }
1188
1189    #[test]
1190    fn test_dependency_analysis_default() {
1191        let analysis = DependencyAnalysis::default();
1192        assert!(analysis.direct_dependencies.is_empty());
1193        assert!(analysis.transitive_dependencies.is_empty());
1194        assert_eq!(analysis.dependency_depth, 0);
1195        assert!(analysis.circular_dependencies.is_empty());
1196    }
1197
1198    #[test]
1199    fn test_performance_analysis_default() {
1200        let performance = PerformanceAnalysis::default();
1201        assert_eq!(performance.compilation_impact.estimated_compile_time_ms, 0);
1202        assert_eq!(performance.runtime_overhead.virtual_dispatch_cost, 0);
1203        assert_eq!(performance.memory_footprint.vtable_size_bytes, 0);
1204        assert!(performance.optimization_hints.is_empty());
1205    }
1206
1207    #[test]
1208    fn test_trait_graph_dot_export() {
1209        use chrono::Utc;
1210
1211        let graph = TraitGraph {
1212            nodes: vec![
1213                TraitGraphNode {
1214                    id: "Estimator".to_string(),
1215                    label: "Estimator".to_string(),
1216                    node_type: TraitNodeType::Trait,
1217                    description: "Base trait".to_string(),
1218                    complexity: 1.0,
1219                },
1220                TraitGraphNode {
1221                    id: "LinearRegression".to_string(),
1222                    label: "LinearRegression".to_string(),
1223                    node_type: TraitNodeType::Implementation,
1224                    description: "Linear regression implementation".to_string(),
1225                    complexity: 2.0,
1226                },
1227            ],
1228            edges: vec![TraitGraphEdge {
1229                from: "LinearRegression".to_string(),
1230                to: "Estimator".to_string(),
1231                edge_type: EdgeType::Implements,
1232                weight: 1.0,
1233            }],
1234            metadata: TraitGraphMetadata {
1235                center_node: "Estimator".to_string(),
1236                generation_time: Utc::now(),
1237                export_format: GraphExportFormat::Dot,
1238            },
1239        };
1240
1241        let dot = graph.to_dot();
1242        assert!(dot.contains("digraph TraitGraph"));
1243        assert!(dot.contains("Estimator"));
1244        assert!(dot.contains("LinearRegression"));
1245        assert!(dot.contains("lightblue")); // Trait color
1246        assert!(dot.contains("lightgreen")); // Implementation color
1247        assert!(dot.contains("dashed")); // Implements edge style
1248    }
1249
1250    #[test]
1251    fn test_trait_graph_json_export() -> Result<()> {
1252        use chrono::Utc;
1253
1254        let graph = TraitGraph {
1255            nodes: vec![TraitGraphNode {
1256                id: "Estimator".to_string(),
1257                label: "Estimator".to_string(),
1258                node_type: TraitNodeType::Trait,
1259                description: "Base trait".to_string(),
1260                complexity: 1.0,
1261            }],
1262            edges: vec![],
1263            metadata: TraitGraphMetadata {
1264                center_node: "Estimator".to_string(),
1265                generation_time: Utc::now(),
1266                export_format: GraphExportFormat::Json,
1267            },
1268        };
1269
1270        let json = graph.to_json()?;
1271        assert!(json.contains("\"nodes\""));
1272        assert!(json.contains("\"edges\""));
1273        assert!(json.contains("\"metadata\""));
1274        assert!(json.contains("Estimator"));
1275
1276        Ok(())
1277    }
1278
1279    #[test]
1280    fn test_usage_example_creation() {
1281        let example = UsageExample {
1282            title: "Basic Example".to_string(),
1283            description: "A simple usage example".to_string(),
1284            code: "println!(\"Hello, world!\");".to_string(),
1285            category: ExampleCategory::Usage,
1286            difficulty: ExampleDifficulty::Beginner,
1287            runnable: true,
1288        };
1289
1290        assert_eq!(example.category, ExampleCategory::Usage);
1291        assert_eq!(example.difficulty, ExampleDifficulty::Beginner);
1292        assert!(example.runnable);
1293    }
1294
1295    #[test]
1296    fn test_all_trait_names() -> Result<()> {
1297        let mut registry = TraitRegistry::new();
1298        registry.load_sklears_traits()?;
1299
1300        let trait_names = registry.get_all_trait_names();
1301        assert_eq!(trait_names.len(), 4);
1302        assert!(trait_names.contains(&"Estimator".to_string()));
1303        assert!(trait_names.contains(&"Fit".to_string()));
1304        assert!(trait_names.contains(&"Predict".to_string()));
1305        assert!(trait_names.contains(&"Transform".to_string()));
1306
1307        Ok(())
1308    }
1309
1310    #[test]
1311    fn test_all_traits() -> Result<()> {
1312        let mut registry = TraitRegistry::new();
1313        registry.load_sklears_traits()?;
1314
1315        let all_traits = registry.get_all_traits();
1316        assert_eq!(all_traits.len(), 4);
1317
1318        let trait_names: Vec<&str> = all_traits.iter().map(|t| t.name.as_str()).collect();
1319        assert!(trait_names.contains(&"Estimator"));
1320        assert!(trait_names.contains(&"Fit"));
1321        assert!(trait_names.contains(&"Predict"));
1322        assert!(trait_names.contains(&"Transform"));
1323
1324        Ok(())
1325    }
1326
1327    #[test]
1328    fn test_nonexistent_queries() {
1329        let registry = TraitRegistry::new();
1330
1331        assert!(!registry.has_trait("NonExistent"));
1332        assert!(!registry.has_implementation("NonExistent"));
1333        assert!(registry.get_implementations("NonExistent").is_empty());
1334        assert!(registry
1335            .get_traits_for_implementation("NonExistent")
1336            .is_empty());
1337    }
1338
1339    #[test]
1340    fn test_scirs2_compliance() {
1341        // Test that we can use SciRS2 components without issues
1342        use scirs2_core::random::prelude::*;
1343        use scirs2_core::random::Random;
1344
1345        let mut rng = Random::seed(42);
1346        let _random_value: f64 = rng.gen();
1347
1348        // Test array operations
1349        use scirs2_core::ndarray::{Array1, Array2};
1350        let _arr1: Array1<f64> = Array1::zeros(10);
1351        let _arr2: Array2<f64> = Array2::zeros((5, 5));
1352
1353        // This test passes if we can successfully use SciRS2 components
1354    }
1355
1356    #[test]
1357    fn test_registry_counts() -> Result<()> {
1358        let mut registry = TraitRegistry::new();
1359        assert_eq!(registry.trait_count(), 0);
1360        assert_eq!(registry.implementation_count(), 0);
1361
1362        registry.load_sklears_traits()?;
1363        assert_eq!(registry.trait_count(), 4);
1364        assert!(registry.implementation_count() > 0);
1365
1366        Ok(())
1367    }
1368}