Skip to main content

oxirs_core/consciousness/
intuitive_planner.rs

1//! Consciousness-Inspired Intuitive Query Planner
2//!
3//! This module implements artificial intuition for query optimization using
4//! pattern memory, gut feeling calculations, and creative optimization techniques.
5
6use crate::query::algebra::{AlgebraTriplePattern, TermPattern as AlgebraTermPattern};
7use crate::query::pattern_optimizer::IndexStats;
8use crate::OxirsError;
9use scirs2_core::random::{Random, RngExt};
10use serde::{Deserialize, Serialize};
11use std::collections::{HashMap, HashSet};
12use std::sync::{Arc, RwLock};
13
14/// Pattern memory for storing learned query patterns and their effectiveness
15#[derive(Debug, Clone, Serialize, Deserialize)]
16pub struct PatternMemory {
17    /// Historical pattern performance data
18    pub pattern_history: HashMap<String, PatternPerformance>,
19    /// Intuitive weights for different pattern characteristics
20    pub intuitive_weights: HashMap<PatternCharacteristic, f64>,
21    /// Successful pattern combinations
22    pub successful_combinations: Vec<PatternCombination>,
23}
24
25/// Performance metrics for a specific pattern
26#[derive(Debug, Clone, Serialize, Deserialize)]
27pub struct PatternPerformance {
28    /// Average execution time in microseconds
29    pub avg_execution_time: f64,
30    /// Success rate (0.0 to 1.0)
31    pub success_rate: f64,
32    /// Frequency of use
33    pub usage_count: usize,
34    /// Last used timestamp
35    pub last_used: std::time::SystemTime,
36    /// Intuitive effectiveness score
37    pub intuitive_score: f64,
38}
39
40/// Characteristics that influence intuitive decision making
41#[derive(Debug, Clone, Hash, PartialEq, Eq, Serialize, Deserialize)]
42pub enum PatternCharacteristic {
43    /// High selectivity patterns (few results)
44    HighSelectivity,
45    /// Join-heavy patterns
46    JoinIntensive,
47    /// Variable-heavy patterns
48    VariableRich,
49    /// Literal-bound patterns
50    LiteralBound,
51    /// Temporal patterns (time-based queries)
52    Temporal,
53    /// Hierarchical patterns (class/subclass)
54    Hierarchical,
55    /// Spatial patterns (geographic)
56    Spatial,
57    /// Numerical patterns (mathematical)
58    Numerical,
59}
60
61/// Successful pattern combination for learning
62#[derive(Debug, Clone, Serialize, Deserialize)]
63pub struct PatternCombination {
64    /// Patterns in the combination
65    pub patterns: Vec<String>,
66    /// Total effectiveness score
67    pub effectiveness: f64,
68    /// Context where this combination was successful
69    pub context: QueryContext,
70}
71
72/// Context information for query optimization
73#[derive(Debug, Clone, Serialize, Deserialize)]
74pub struct QueryContext {
75    /// Dataset size category
76    pub dataset_size: DatasetSize,
77    /// Query complexity level
78    pub complexity: ComplexityLevel,
79    /// Performance requirements
80    pub performance_req: PerformanceRequirement,
81    /// Domain type (e.g., scientific, business, social)
82    pub domain: String,
83}
84
85/// Dataset size categories
86#[derive(Debug, Clone, Serialize, Deserialize)]
87pub enum DatasetSize {
88    Small,     // < 1M triples
89    Medium,    // 1M - 100M triples
90    Large,     // 100M - 1B triples
91    VeryLarge, // > 1B triples
92}
93
94/// Query complexity levels
95#[derive(Debug, Clone, Serialize, Deserialize)]
96pub enum ComplexityLevel {
97    Simple,      // Single pattern queries
98    Moderate,    // 2-5 patterns with basic joins
99    Complex,     // 6-20 patterns with multiple joins
100    VeryComplex, // 20+ patterns with nested operations
101}
102
103/// Performance requirements
104#[derive(Debug, Clone, Serialize, Deserialize)]
105pub enum PerformanceRequirement {
106    Interactive, // < 100ms response time
107    Fast,        // < 1s response time
108    Balanced,    // Balanced performance/quality tradeoff
109    Batch,       // < 1min response time
110    Background,  // No strict time limit
111}
112
113/// Neural network simulation for intuitive decision making
114pub struct IntuitionNetwork {
115    /// Input weights for pattern characteristics
116    input_weights: HashMap<PatternCharacteristic, f64>,
117    /// Hidden layer connections
118    hidden_connections: Vec<Vec<f64>>,
119    /// Output layer for decision scoring
120    output_weights: Vec<f64>,
121    /// Learning rate for weight updates
122    learning_rate: f64,
123}
124
125impl Default for IntuitionNetwork {
126    fn default() -> Self {
127        Self::new()
128    }
129}
130
131impl IntuitionNetwork {
132    /// Create a new intuition network with random weights
133    pub fn new() -> Self {
134        let characteristics = vec![
135            PatternCharacteristic::HighSelectivity,
136            PatternCharacteristic::JoinIntensive,
137            PatternCharacteristic::VariableRich,
138            PatternCharacteristic::LiteralBound,
139            PatternCharacteristic::Temporal,
140            PatternCharacteristic::Hierarchical,
141            PatternCharacteristic::Spatial,
142            PatternCharacteristic::Numerical,
143        ];
144
145        let mut input_weights = HashMap::new();
146        for characteristic in characteristics {
147            input_weights.insert(
148                characteristic,
149                {
150                    let mut rng = Random::default();
151                    rng.random::<f64>()
152                } * 2.0
153                    - 1.0,
154            );
155        }
156
157        // Create hidden layer (8 inputs -> 5 hidden -> 1 output)
158        let hidden_connections = vec![
159            vec![
160                {
161                    let mut rng = Random::default();
162                    rng.random::<f64>()
163                } * 2.0
164                    - 1.0;
165                8
166            ], // Hidden neuron 1
167            vec![
168                {
169                    let mut rng = Random::default();
170                    rng.random::<f64>()
171                } * 2.0
172                    - 1.0;
173                8
174            ], // Hidden neuron 2
175            vec![
176                {
177                    let mut rng = Random::default();
178                    rng.random::<f64>()
179                } * 2.0
180                    - 1.0;
181                8
182            ], // Hidden neuron 3
183            vec![
184                {
185                    let mut rng = Random::default();
186                    rng.random::<f64>()
187                } * 2.0
188                    - 1.0;
189                8
190            ], // Hidden neuron 4
191            vec![
192                {
193                    let mut rng = Random::default();
194                    rng.random::<f64>()
195                } * 2.0
196                    - 1.0;
197                8
198            ], // Hidden neuron 5
199        ];
200
201        let output_weights = vec![
202            {
203                let mut rng = Random::default();
204                rng.random::<f64>()
205            } * 2.0
206                - 1.0;
207            5
208        ];
209
210        Self {
211            input_weights,
212            hidden_connections,
213            output_weights,
214            learning_rate: 0.01,
215        }
216    }
217
218    /// Calculate intuitive score for a pattern
219    pub fn calculate_intuitive_score(&self, characteristics: &[PatternCharacteristic]) -> f64 {
220        // Convert characteristics to input vector
221        let mut input_vector = [0.0; 8];
222        let characteristic_types = [
223            PatternCharacteristic::HighSelectivity,
224            PatternCharacteristic::JoinIntensive,
225            PatternCharacteristic::VariableRich,
226            PatternCharacteristic::LiteralBound,
227            PatternCharacteristic::Temporal,
228            PatternCharacteristic::Hierarchical,
229            PatternCharacteristic::Spatial,
230            PatternCharacteristic::Numerical,
231        ];
232
233        for (i, char_type) in characteristic_types.iter().enumerate() {
234            if characteristics.contains(char_type) {
235                input_vector[i] = 1.0;
236            }
237        }
238
239        // Forward pass through network
240        let mut hidden_activations = Vec::new();
241        for connections in &self.hidden_connections {
242            let mut activation = 0.0;
243            for (i, &weight) in connections.iter().enumerate() {
244                activation += input_vector[i] * weight;
245            }
246            hidden_activations.push(self.sigmoid(activation));
247        }
248
249        // Output layer
250        let mut output = 0.0;
251        for (i, &weight) in self.output_weights.iter().enumerate() {
252            output += hidden_activations[i] * weight;
253        }
254
255        self.sigmoid(output)
256    }
257
258    /// Sigmoid activation function
259    fn sigmoid(&self, x: f64) -> f64 {
260        1.0 / (1.0 + (-x).exp())
261    }
262
263    /// Update weights based on feedback
264    pub fn learn_from_feedback(
265        &mut self,
266        characteristics: &[PatternCharacteristic],
267        _expected_score: f64,
268        actual_performance: f64,
269    ) {
270        let predicted_score = self.calculate_intuitive_score(characteristics);
271        let error = actual_performance - predicted_score;
272
273        // Simple weight update (would be more sophisticated in real implementation)
274        for char_type in characteristics {
275            if let Some(weight) = self.input_weights.get_mut(char_type) {
276                *weight += self.learning_rate * error;
277            }
278        }
279    }
280}
281
282/// Gut feeling engine for making intuitive decisions
283#[allow(dead_code)]
284pub struct GutFeelingEngine {
285    /// Historical success patterns
286    success_patterns: HashMap<String, f64>,
287    /// Confidence thresholds for different decisions
288    confidence_thresholds: HashMap<String, f64>,
289    /// Emotional weighting factors
290    emotional_weights: HashMap<String, f64>,
291}
292
293impl Default for GutFeelingEngine {
294    fn default() -> Self {
295        Self::new()
296    }
297}
298
299impl GutFeelingEngine {
300    /// Create a new gut feeling engine
301    pub fn new() -> Self {
302        let mut confidence_thresholds = HashMap::new();
303        confidence_thresholds.insert("high_confidence".to_string(), 0.8);
304        confidence_thresholds.insert("medium_confidence".to_string(), 0.6);
305        confidence_thresholds.insert("low_confidence".to_string(), 0.4);
306
307        let mut emotional_weights = HashMap::new();
308        emotional_weights.insert("excitement".to_string(), 1.2); // Boost for novel patterns
309        emotional_weights.insert("caution".to_string(), 0.8); // Reduce for risky patterns
310        emotional_weights.insert("confidence".to_string(), 1.1); // Boost for familiar patterns
311
312        Self {
313            success_patterns: HashMap::new(),
314            confidence_thresholds,
315            emotional_weights,
316        }
317    }
318
319    /// Calculate gut feeling score for a decision
320    pub fn calculate_gut_feeling(&self, pattern_signature: &str, context: &QueryContext) -> f64 {
321        let base_confidence = self
322            .success_patterns
323            .get(pattern_signature)
324            .copied()
325            .unwrap_or(0.5);
326
327        // Apply contextual adjustments
328        let context_multiplier = match (&context.complexity, &context.performance_req) {
329            (ComplexityLevel::Simple, PerformanceRequirement::Interactive) => 1.2,
330            (ComplexityLevel::VeryComplex, PerformanceRequirement::Interactive) => 0.7,
331            (ComplexityLevel::Complex, PerformanceRequirement::Background) => 1.1,
332            _ => 1.0,
333        };
334
335        // Apply emotional weighting
336        let emotional_factor = if base_confidence > 0.8 {
337            self.emotional_weights
338                .get("confidence")
339                .copied()
340                .unwrap_or(1.0)
341        } else if pattern_signature.contains("novel") {
342            self.emotional_weights
343                .get("excitement")
344                .copied()
345                .unwrap_or(1.0)
346        } else {
347            self.emotional_weights
348                .get("caution")
349                .copied()
350                .unwrap_or(1.0)
351        };
352
353        (base_confidence * context_multiplier * emotional_factor).min(1.0)
354    }
355
356    /// Update gut feeling based on actual results
357    pub fn update_gut_feeling(&mut self, pattern_signature: String, success_rate: f64) {
358        let current = self
359            .success_patterns
360            .get(&pattern_signature)
361            .copied()
362            .unwrap_or(0.5);
363        // Exponential moving average
364        let updated = current * 0.8 + success_rate * 0.2;
365        self.success_patterns.insert(pattern_signature, updated);
366    }
367}
368
369/// Creativity engine for generating novel optimization strategies
370#[allow(dead_code)]
371pub struct CreativityEngine {
372    /// Repository of creative optimization techniques
373    techniques: Vec<CreativeTechnique>,
374    /// Randomness factor for exploration
375    exploration_factor: f64,
376    /// Combination history for avoiding repetition
377    combination_history: HashSet<String>,
378}
379
380/// Creative optimization techniques
381#[derive(Debug, Clone)]
382pub enum CreativeTechnique {
383    /// Reverse the usual optimization order
384    ReverseOptimization,
385    /// Try parallel execution paths
386    ParallelPaths,
387    /// Use predictive prefetching
388    PredictivePrefetch,
389    /// Apply genetic algorithm mutations
390    GeneticMutation,
391    /// Use chaos theory for exploration
392    ChaoticExploration,
393    /// Apply artistic principles (golden ratio, symmetry)
394    ArtisticPrinciples,
395    /// Use biomimetic approaches
396    BiomimeticOptimization,
397}
398
399impl Default for CreativityEngine {
400    fn default() -> Self {
401        Self::new()
402    }
403}
404
405impl CreativityEngine {
406    /// Create a new creativity engine
407    pub fn new() -> Self {
408        let techniques = vec![
409            CreativeTechnique::ReverseOptimization,
410            CreativeTechnique::ParallelPaths,
411            CreativeTechnique::PredictivePrefetch,
412            CreativeTechnique::GeneticMutation,
413            CreativeTechnique::ChaoticExploration,
414            CreativeTechnique::ArtisticPrinciples,
415            CreativeTechnique::BiomimeticOptimization,
416        ];
417
418        Self {
419            techniques,
420            exploration_factor: 0.1,
421            combination_history: HashSet::new(),
422        }
423    }
424
425    /// Generate creative optimization suggestions
426    pub fn generate_creative_optimizations(
427        &mut self,
428        _patterns: &[AlgebraTriplePattern],
429    ) -> Vec<CreativeOptimization> {
430        let mut optimizations = Vec::new();
431
432        // Apply each technique with some probability
433        for technique in &self.techniques {
434            if {
435                let mut rng = Random::default();
436                rng.random::<f64>()
437            } < self.exploration_factor
438            {
439                match technique {
440                    CreativeTechnique::ReverseOptimization => {
441                        optimizations.push(CreativeOptimization {
442                            technique: technique.clone(),
443                            description: "Try executing patterns in reverse selectivity order"
444                                .to_string(),
445                            confidence: 0.7,
446                            novelty: 0.8,
447                        });
448                    }
449                    CreativeTechnique::ParallelPaths => {
450                        optimizations.push(CreativeOptimization {
451                            technique: technique.clone(),
452                            description: "Execute independent patterns in parallel".to_string(),
453                            confidence: 0.9,
454                            novelty: 0.6,
455                        });
456                    }
457                    CreativeTechnique::ArtisticPrinciples => {
458                        optimizations.push(CreativeOptimization {
459                            technique: technique.clone(),
460                            description: "Apply golden ratio to join ordering".to_string(),
461                            confidence: 0.5,
462                            novelty: 0.95,
463                        });
464                    }
465                    _ => {
466                        // Other techniques would be implemented similarly
467                    }
468                }
469            }
470        }
471
472        optimizations
473    }
474}
475
476/// A creative optimization suggestion
477#[derive(Debug, Clone)]
478pub struct CreativeOptimization {
479    /// The technique used
480    pub technique: CreativeTechnique,
481    /// Human-readable description
482    pub description: String,
483    /// Confidence in this optimization (0.0 to 1.0)
484    pub confidence: f64,
485    /// Novelty factor (0.0 to 1.0)
486    pub novelty: f64,
487}
488
489/// Intuitive query planner that combines all consciousness-inspired components
490#[allow(dead_code)]
491pub struct IntuitiveQueryPlanner {
492    /// Pattern memory for learning
493    pattern_memory: Arc<RwLock<PatternMemory>>,
494    /// Neural network for intuitive scoring
495    intuition_network: Arc<RwLock<IntuitionNetwork>>,
496    /// Gut feeling engine
497    gut_feeling: Arc<RwLock<GutFeelingEngine>>,
498    /// Creativity engine
499    creativity: Arc<RwLock<CreativityEngine>>,
500    /// Traditional optimizer for baseline comparison
501    traditional_stats: Arc<IndexStats>,
502}
503
504impl IntuitiveQueryPlanner {
505    /// Create a new intuitive query planner
506    pub fn new(traditional_stats: Arc<IndexStats>) -> Self {
507        Self {
508            pattern_memory: Arc::new(RwLock::new(PatternMemory {
509                pattern_history: HashMap::new(),
510                intuitive_weights: HashMap::new(),
511                successful_combinations: Vec::new(),
512            })),
513            intuition_network: Arc::new(RwLock::new(IntuitionNetwork::new())),
514            gut_feeling: Arc::new(RwLock::new(GutFeelingEngine::new())),
515            creativity: Arc::new(RwLock::new(CreativityEngine::new())),
516            traditional_stats,
517        }
518    }
519
520    /// Plan query execution using intuitive optimization
521    pub fn plan_intuitive_execution(
522        &self,
523        patterns: &[AlgebraTriplePattern],
524        context: &QueryContext,
525    ) -> Result<IntuitiveExecutionPlan, OxirsError> {
526        // Extract pattern characteristics
527        let characteristics = self.extract_pattern_characteristics(patterns);
528
529        // Calculate intuitive scores
530        let intuitive_scores = match self.intuition_network.read() {
531            Ok(network) => patterns
532                .iter()
533                .enumerate()
534                .map(|(i, _)| network.calculate_intuitive_score(&characteristics[i]))
535                .collect::<Vec<_>>(),
536            _ => {
537                vec![0.5; patterns.len()]
538            }
539        };
540
541        // Get gut feeling assessment
542        let gut_feelings = match self.gut_feeling.read() {
543            Ok(gut) => patterns
544                .iter()
545                .map(|pattern| {
546                    let signature = format!("{pattern:?}");
547                    gut.calculate_gut_feeling(&signature, context)
548                })
549                .collect::<Vec<_>>(),
550            _ => {
551                vec![0.5; patterns.len()]
552            }
553        };
554
555        // Generate creative optimizations
556        let creative_opts = match self.creativity.write() {
557            Ok(mut creativity) => creativity.generate_creative_optimizations(patterns),
558            _ => Vec::new(),
559        };
560
561        // Combine all factors to create plan
562        let mut pattern_rankings = Vec::new();
563        for (i, pattern) in patterns.iter().enumerate() {
564            let combined_score = (intuitive_scores[i] + gut_feelings[i]) * 0.5;
565            pattern_rankings.push((i, pattern.clone(), combined_score));
566        }
567
568        // Sort by combined intuitive score
569        pattern_rankings.sort_by(|a, b| b.2.partial_cmp(&a.2).unwrap_or(std::cmp::Ordering::Equal));
570
571        Ok(IntuitiveExecutionPlan {
572            ordered_patterns: pattern_rankings,
573            creative_optimizations: creative_opts,
574            confidence_level: intuitive_scores.iter().sum::<f64>() / intuitive_scores.len() as f64,
575            gut_feeling_average: gut_feelings.iter().sum::<f64>() / gut_feelings.len() as f64,
576            context: context.clone(),
577        })
578    }
579
580    /// Extract pattern characteristics for intuitive analysis
581    fn extract_pattern_characteristics(
582        &self,
583        patterns: &[AlgebraTriplePattern],
584    ) -> Vec<Vec<PatternCharacteristic>> {
585        patterns
586            .iter()
587            .map(|pattern| {
588                let mut characteristics = Vec::new();
589
590                // Check for high selectivity (bound terms)
591                let bound_terms = [&pattern.subject, &pattern.predicate, &pattern.object]
592                    .iter()
593                    .filter(|term| !matches!(term, AlgebraTermPattern::Variable(_)))
594                    .count();
595
596                if bound_terms >= 2 {
597                    characteristics.push(PatternCharacteristic::HighSelectivity);
598                }
599
600                // Check for literal bounds
601                if matches!(pattern.object, AlgebraTermPattern::Literal(_)) {
602                    characteristics.push(PatternCharacteristic::LiteralBound);
603                }
604
605                // Count variables
606                let variable_count = [&pattern.subject, &pattern.predicate, &pattern.object]
607                    .iter()
608                    .filter(|term| matches!(term, AlgebraTermPattern::Variable(_)))
609                    .count();
610
611                if variable_count >= 2 {
612                    characteristics.push(PatternCharacteristic::VariableRich);
613                }
614
615                // Check for temporal patterns (basic heuristic)
616                if let AlgebraTermPattern::NamedNode(pred) = &pattern.predicate {
617                    if pred.as_str().contains("time") || pred.as_str().contains("date") {
618                        characteristics.push(PatternCharacteristic::Temporal);
619                    }
620                }
621
622                // Check for hierarchical patterns
623                if let AlgebraTermPattern::NamedNode(pred) = &pattern.predicate {
624                    if pred.as_str().contains("type") || pred.as_str().contains("subClass") {
625                        characteristics.push(PatternCharacteristic::Hierarchical);
626                    }
627                }
628
629                characteristics
630            })
631            .collect()
632    }
633
634    /// Learn from execution results to improve future planning
635    pub fn learn_from_execution(
636        &self,
637        plan: &IntuitiveExecutionPlan,
638        actual_performance: &ExecutionResults,
639    ) {
640        // Update pattern memory
641        if let Ok(mut memory) = self.pattern_memory.write() {
642            for (i, (_, pattern, predicted_score)) in plan.ordered_patterns.iter().enumerate() {
643                let signature = format!("{pattern:?}");
644                let actual_score = actual_performance
645                    .pattern_scores
646                    .get(&i)
647                    .copied()
648                    .unwrap_or(0.5);
649
650                let performance = PatternPerformance {
651                    avg_execution_time: actual_performance
652                        .execution_times
653                        .get(&i)
654                        .copied()
655                        .unwrap_or(1000.0),
656                    success_rate: actual_score,
657                    usage_count: memory
658                        .pattern_history
659                        .get(&signature)
660                        .map(|p| p.usage_count + 1)
661                        .unwrap_or(1),
662                    last_used: std::time::SystemTime::now(),
663                    intuitive_score: *predicted_score,
664                };
665
666                memory.pattern_history.insert(signature, performance);
667            }
668        }
669
670        // Update intuition network
671        if let Ok(mut network) = self.intuition_network.write() {
672            for (i, (_, pattern, predicted_score)) in plan.ordered_patterns.iter().enumerate() {
673                let characteristics =
674                    self.extract_pattern_characteristics(std::slice::from_ref(pattern))[0].clone();
675                let actual_score = actual_performance
676                    .pattern_scores
677                    .get(&i)
678                    .copied()
679                    .unwrap_or(0.5);
680
681                network.learn_from_feedback(&characteristics, *predicted_score, actual_score);
682            }
683        }
684
685        // Update gut feeling
686        if let Ok(mut gut) = self.gut_feeling.write() {
687            for (i, (_, pattern, _)) in plan.ordered_patterns.iter().enumerate() {
688                let signature = format!("{pattern:?}");
689                let success_rate = actual_performance
690                    .pattern_scores
691                    .get(&i)
692                    .copied()
693                    .unwrap_or(0.5);
694
695                gut.update_gut_feeling(signature, success_rate);
696            }
697        }
698    }
699}
700
701/// Execution plan generated by intuitive planner
702#[derive(Debug, Clone)]
703pub struct IntuitiveExecutionPlan {
704    /// Patterns ordered by intuitive ranking
705    pub ordered_patterns: Vec<(usize, AlgebraTriplePattern, f64)>,
706    /// Creative optimization suggestions
707    pub creative_optimizations: Vec<CreativeOptimization>,
708    /// Overall confidence in the plan
709    pub confidence_level: f64,
710    /// Average gut feeling score
711    pub gut_feeling_average: f64,
712    /// Context used for planning
713    pub context: QueryContext,
714}
715
716/// Results from executing an intuitive plan
717#[derive(Debug)]
718pub struct ExecutionResults {
719    /// Performance scores for each pattern (0.0 to 1.0)
720    pub pattern_scores: HashMap<usize, f64>,
721    /// Execution times in microseconds
722    pub execution_times: HashMap<usize, f64>,
723    /// Overall success rate
724    pub overall_success: f64,
725    /// Creative optimizations that were applied
726    pub applied_optimizations: Vec<CreativeTechnique>,
727}
728
729#[cfg(test)]
730mod tests {
731    use super::*;
732    use crate::{Literal, NamedNode, Variable};
733
734    #[test]
735    fn test_intuition_network_creation() {
736        let network = IntuitionNetwork::new();
737        assert_eq!(network.input_weights.len(), 8);
738        assert_eq!(network.hidden_connections.len(), 5);
739        assert_eq!(network.output_weights.len(), 5);
740    }
741
742    #[test]
743    fn test_gut_feeling_calculation() {
744        let engine = GutFeelingEngine::new();
745        let context = QueryContext {
746            dataset_size: DatasetSize::Medium,
747            complexity: ComplexityLevel::Simple,
748            performance_req: PerformanceRequirement::Interactive,
749            domain: "test".to_string(),
750        };
751
752        let score = engine.calculate_gut_feeling("test_pattern", &context);
753        assert!((0.0..=1.0).contains(&score));
754    }
755
756    #[test]
757    fn test_creativity_engine() {
758        let mut engine = CreativityEngine::new();
759        let patterns = vec![AlgebraTriplePattern::new(
760            AlgebraTermPattern::Variable(Variable::new("s").expect("valid variable name")),
761            AlgebraTermPattern::NamedNode(
762                NamedNode::new("http://example.org/pred").expect("valid IRI"),
763            ),
764            AlgebraTermPattern::Variable(Variable::new("o").expect("valid variable name")),
765        )];
766
767        let optimizations = engine.generate_creative_optimizations(&patterns);
768        // Should generate some optimizations based on exploration factor
769        assert!(optimizations.len() <= engine.techniques.len());
770    }
771
772    #[test]
773    fn test_pattern_characteristics_extraction() {
774        let stats = Arc::new(IndexStats::new());
775        let planner = IntuitiveQueryPlanner::new(stats);
776
777        let patterns = vec![AlgebraTriplePattern::new(
778            AlgebraTermPattern::NamedNode(
779                NamedNode::new("http://example.org/subj").expect("valid IRI"),
780            ),
781            AlgebraTermPattern::NamedNode(
782                NamedNode::new("http://example.org/type").expect("valid IRI"),
783            ),
784            AlgebraTermPattern::Literal(Literal::new("test")),
785        )];
786
787        let characteristics = planner.extract_pattern_characteristics(&patterns);
788        assert_eq!(characteristics.len(), 1);
789        assert!(characteristics[0].contains(&PatternCharacteristic::HighSelectivity));
790        assert!(characteristics[0].contains(&PatternCharacteristic::LiteralBound));
791    }
792}