1use 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#[derive(Debug, Clone, Serialize, Deserialize)]
16pub struct PatternMemory {
17 pub pattern_history: HashMap<String, PatternPerformance>,
19 pub intuitive_weights: HashMap<PatternCharacteristic, f64>,
21 pub successful_combinations: Vec<PatternCombination>,
23}
24
25#[derive(Debug, Clone, Serialize, Deserialize)]
27pub struct PatternPerformance {
28 pub avg_execution_time: f64,
30 pub success_rate: f64,
32 pub usage_count: usize,
34 pub last_used: std::time::SystemTime,
36 pub intuitive_score: f64,
38}
39
40#[derive(Debug, Clone, Hash, PartialEq, Eq, Serialize, Deserialize)]
42pub enum PatternCharacteristic {
43 HighSelectivity,
45 JoinIntensive,
47 VariableRich,
49 LiteralBound,
51 Temporal,
53 Hierarchical,
55 Spatial,
57 Numerical,
59}
60
61#[derive(Debug, Clone, Serialize, Deserialize)]
63pub struct PatternCombination {
64 pub patterns: Vec<String>,
66 pub effectiveness: f64,
68 pub context: QueryContext,
70}
71
72#[derive(Debug, Clone, Serialize, Deserialize)]
74pub struct QueryContext {
75 pub dataset_size: DatasetSize,
77 pub complexity: ComplexityLevel,
79 pub performance_req: PerformanceRequirement,
81 pub domain: String,
83}
84
85#[derive(Debug, Clone, Serialize, Deserialize)]
87pub enum DatasetSize {
88 Small, Medium, Large, VeryLarge, }
93
94#[derive(Debug, Clone, Serialize, Deserialize)]
96pub enum ComplexityLevel {
97 Simple, Moderate, Complex, VeryComplex, }
102
103#[derive(Debug, Clone, Serialize, Deserialize)]
105pub enum PerformanceRequirement {
106 Interactive, Fast, Balanced, Batch, Background, }
112
113pub struct IntuitionNetwork {
115 input_weights: HashMap<PatternCharacteristic, f64>,
117 hidden_connections: Vec<Vec<f64>>,
119 output_weights: Vec<f64>,
121 learning_rate: f64,
123}
124
125impl Default for IntuitionNetwork {
126 fn default() -> Self {
127 Self::new()
128 }
129}
130
131impl IntuitionNetwork {
132 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 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 ], vec![
168 {
169 let mut rng = Random::default();
170 rng.random::<f64>()
171 } * 2.0
172 - 1.0;
173 8
174 ], vec![
176 {
177 let mut rng = Random::default();
178 rng.random::<f64>()
179 } * 2.0
180 - 1.0;
181 8
182 ], vec![
184 {
185 let mut rng = Random::default();
186 rng.random::<f64>()
187 } * 2.0
188 - 1.0;
189 8
190 ], vec![
192 {
193 let mut rng = Random::default();
194 rng.random::<f64>()
195 } * 2.0
196 - 1.0;
197 8
198 ], ];
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 pub fn calculate_intuitive_score(&self, characteristics: &[PatternCharacteristic]) -> f64 {
220 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 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 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 fn sigmoid(&self, x: f64) -> f64 {
260 1.0 / (1.0 + (-x).exp())
261 }
262
263 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 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#[allow(dead_code)]
284pub struct GutFeelingEngine {
285 success_patterns: HashMap<String, f64>,
287 confidence_thresholds: HashMap<String, f64>,
289 emotional_weights: HashMap<String, f64>,
291}
292
293impl Default for GutFeelingEngine {
294 fn default() -> Self {
295 Self::new()
296 }
297}
298
299impl GutFeelingEngine {
300 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); emotional_weights.insert("caution".to_string(), 0.8); emotional_weights.insert("confidence".to_string(), 1.1); Self {
313 success_patterns: HashMap::new(),
314 confidence_thresholds,
315 emotional_weights,
316 }
317 }
318
319 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 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 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 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 let updated = current * 0.8 + success_rate * 0.2;
365 self.success_patterns.insert(pattern_signature, updated);
366 }
367}
368
369#[allow(dead_code)]
371pub struct CreativityEngine {
372 techniques: Vec<CreativeTechnique>,
374 exploration_factor: f64,
376 combination_history: HashSet<String>,
378}
379
380#[derive(Debug, Clone)]
382pub enum CreativeTechnique {
383 ReverseOptimization,
385 ParallelPaths,
387 PredictivePrefetch,
389 GeneticMutation,
391 ChaoticExploration,
393 ArtisticPrinciples,
395 BiomimeticOptimization,
397}
398
399impl Default for CreativityEngine {
400 fn default() -> Self {
401 Self::new()
402 }
403}
404
405impl CreativityEngine {
406 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 pub fn generate_creative_optimizations(
427 &mut self,
428 _patterns: &[AlgebraTriplePattern],
429 ) -> Vec<CreativeOptimization> {
430 let mut optimizations = Vec::new();
431
432 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 }
468 }
469 }
470 }
471
472 optimizations
473 }
474}
475
476#[derive(Debug, Clone)]
478pub struct CreativeOptimization {
479 pub technique: CreativeTechnique,
481 pub description: String,
483 pub confidence: f64,
485 pub novelty: f64,
487}
488
489#[allow(dead_code)]
491pub struct IntuitiveQueryPlanner {
492 pattern_memory: Arc<RwLock<PatternMemory>>,
494 intuition_network: Arc<RwLock<IntuitionNetwork>>,
496 gut_feeling: Arc<RwLock<GutFeelingEngine>>,
498 creativity: Arc<RwLock<CreativityEngine>>,
500 traditional_stats: Arc<IndexStats>,
502}
503
504impl IntuitiveQueryPlanner {
505 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 pub fn plan_intuitive_execution(
522 &self,
523 patterns: &[AlgebraTriplePattern],
524 context: &QueryContext,
525 ) -> Result<IntuitiveExecutionPlan, OxirsError> {
526 let characteristics = self.extract_pattern_characteristics(patterns);
528
529 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 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 let creative_opts = match self.creativity.write() {
557 Ok(mut creativity) => creativity.generate_creative_optimizations(patterns),
558 _ => Vec::new(),
559 };
560
561 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 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 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 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 if matches!(pattern.object, AlgebraTermPattern::Literal(_)) {
602 characteristics.push(PatternCharacteristic::LiteralBound);
603 }
604
605 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 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 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 pub fn learn_from_execution(
636 &self,
637 plan: &IntuitiveExecutionPlan,
638 actual_performance: &ExecutionResults,
639 ) {
640 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 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 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#[derive(Debug, Clone)]
703pub struct IntuitiveExecutionPlan {
704 pub ordered_patterns: Vec<(usize, AlgebraTriplePattern, f64)>,
706 pub creative_optimizations: Vec<CreativeOptimization>,
708 pub confidence_level: f64,
710 pub gut_feeling_average: f64,
712 pub context: QueryContext,
714}
715
716#[derive(Debug)]
718pub struct ExecutionResults {
719 pub pattern_scores: HashMap<usize, f64>,
721 pub execution_times: HashMap<usize, f64>,
723 pub overall_success: f64,
725 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 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}