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}