Skip to main content

microscope_memory/
heuristic_decision.rs

1//! Heuristic Decision Layer — gyors, heurisztikus döntéshozatal a kognitív modulok integrációjával.
2//!
3//! Ez a réteg egyesíti a salience (kiemelés), eureka (betekintés), meta_supervision (meta-felügyelet)
4//! és architecture_simulator modulokat egy egységes döntéshozó rendszerré.
5//! Képes mintázatfelismerésre, gyors heurisztikus döntésekre és folyamatos tanulásra.
6
7use std::collections::HashMap;
8use std::sync::{Arc, RwLock};
9use std::time::{SystemTime, UNIX_EPOCH};
10
11use crate::architecture_simulator::{ArchitectureSimulator, SimulationConfig, SimulationMetrics};
12use crate::eureka::EurekaLog;
13use crate::knowledge_base::KnowledgeBase;
14use crate::meta_supervision::MetaSupervisor;
15use crate::salience::SalienceState;
16
17// ─── Alap típusok ───────────────────────────────────────────────────────────
18
19/// Döntés típusa
20#[derive(Debug, Clone, PartialEq, Eq, Hash)]
21pub enum DecisionType {
22    /// Architektúra választás
23    ArchitectureSelection,
24    /// Erőforrás allokáció
25    ResourceAllocation,
26    /// Optimalizációs stratégia
27    OptimizationStrategy,
28    /// Kockázatkezelés
29    RiskManagement,
30    /// Tanulási stratégia
31    LearningStrategy,
32    /// Egyedi
33    Custom(String),
34}
35
36/// Döntési lehetőség
37#[derive(Debug, Clone)]
38pub struct DecisionOption {
39    pub id: String,
40    pub description: String,
41    pub decision_type: DecisionType,
42    /// Várható haszon (0.0 - 1.0)
43    pub expected_utility: f64,
44    /// Kockázati szint (0.0 - 1.0)
45    pub risk_level: f64,
46    /// Végrehajtási költség (0.0 - 1.0)
47    pub execution_cost: f64,
48    /// Bizonyossági szint (0.0 - 1.0)
49    pub confidence: f64,
50    /// Salience pontszám (a kiemelési hálózatból)
51    pub salience_score: f64,
52    /// Eureka pontszám (váratlan összefüggések)
53    pub eureka_score: f64,
54    /// Meta-felügyeleti pontszám
55    pub meta_score: f64,
56    /// Szimulációs előrejelzés (ha van)
57    pub simulation_prediction: Option<SimulationMetrics>,
58}
59
60/// Döntési eredmény
61#[derive(Debug, Clone)]
62pub struct Decision {
63    pub id: String,
64    pub timestamp: u64,
65    pub selected_option: DecisionOption,
66    pub alternatives: Vec<DecisionOption>,
67    pub reasoning: Vec<String>,
68    pub confidence_level: f64,
69    pub expected_outcome: String,
70}
71
72/// Heurisztikus minta
73#[derive(Debug, Clone)]
74pub struct HeuristicPattern {
75    pub id: String,
76    pub name: String,
77    pub pattern_type: String,
78    /// Milyen kontextusban érvényes
79    pub context: String,
80    /// Milyen gyakran hozott helyes döntést (0.0 - 1.0)
81    pub success_rate: f64,
82    /// Hányszor használtuk
83    pub usage_count: u64,
84    /// Utolsó használat időpontja
85    pub last_used: u64,
86    /// A minta súlya a döntéshozatalban
87    pub weight: f64,
88}
89
90/// Döntési napló bejegyzés
91#[derive(Debug, Clone)]
92pub struct DecisionLogEntry {
93    pub timestamp: u64,
94    pub decision_id: String,
95    pub decision_type: DecisionType,
96    pub selected_option: String,
97    pub outcome_score: f64,
98    pub reflection: String,
99}
100
101// ─── Heurisztikus Döntéshozó ─────────────────────────────────────────────────
102
103/// A fő heurisztikus döntéshozó rendszer
104pub struct HeuristicDecisionMaker {
105    /// Salience hálózat — kiemelés
106    salience: Arc<RwLock<SalienceState>>,
107    /// Eureka detektor — váratlan összefüggések
108    eureka: Arc<RwLock<EurekaLog>>,
109    /// Meta-felügyelet — teljesítményfigyelés
110    meta_supervisor: Arc<RwLock<MetaSupervisor>>,
111    /// Architektúra szimulátor
112    simulator: Arc<ArchitectureSimulator>,
113    /// Tudásbázis
114    knowledge_base: Arc<KnowledgeBase>,
115    /// Tanult heurisztikus minták
116    patterns: Arc<RwLock<HashMap<String, HeuristicPattern>>>,
117    /// Döntési napló
118    decision_log: Arc<RwLock<Vec<DecisionLogEntry>>>,
119    /// Döntési preferenciák (pl. "risk_averse", "aggressive", "balanced")
120    preference: String,
121    /// Tanulási ráta (0.0 - 1.0)
122    learning_rate: f64,
123}
124
125impl HeuristicDecisionMaker {
126    /// Létrehoz egy új döntéshozót
127    pub fn new(
128        salience: Arc<RwLock<SalienceState>>,
129        eureka: Arc<RwLock<EurekaLog>>,
130        meta_supervisor: Arc<RwLock<MetaSupervisor>>,
131        simulator: Arc<ArchitectureSimulator>,
132        knowledge_base: Arc<KnowledgeBase>,
133    ) -> Self {
134        Self {
135            salience,
136            eureka,
137            meta_supervisor,
138            simulator,
139            knowledge_base,
140            patterns: Arc::new(RwLock::new(HashMap::new())),
141            decision_log: Arc::new(RwLock::new(Vec::new())),
142            preference: "balanced".to_string(),
143            learning_rate: 0.1,
144        }
145    }
146
147    /// Beállítja a döntési preferenciát
148    pub fn set_preference(&mut self, preference: &str) {
149        self.preference = preference.to_string();
150    }
151
152    /// Beállítja a tanulási rátát
153    pub fn set_learning_rate(&mut self, rate: f64) {
154        self.learning_rate = rate.clamp(0.0, 1.0);
155    }
156
157    /// Döntési lehetőségek értékelése és rangsorolása
158    pub fn evaluate_options(&self, options: Vec<DecisionOption>) -> Vec<DecisionOption> {
159        let mut scored_options: Vec<(f64, DecisionOption)> = options
160            .into_iter()
161            .map(|opt| {
162                let score = self.calculate_option_score(&opt);
163                (score, opt)
164            })
165            .collect();
166
167        // Rendezés pontszám szerint csökkenő sorrendben
168        scored_options.sort_by(|a, b| b.0.total_cmp(&a.0));
169
170        scored_options.into_iter().map(|(_, opt)| opt).collect()
171    }
172
173    /// Kiszámítja egy opció összpontszámát
174    fn calculate_option_score(&self, option: &DecisionOption) -> f64 {
175        let mut score = 0.0;
176
177        // 1. Várható haszon
178        score += option.expected_utility * 0.25;
179
180        // 2. Kockázat kezelése preferencia szerint
181        let risk_factor = match self.preference.as_str() {
182            "risk_averse" => 1.0 - option.risk_level,
183            "aggressive" => option.risk_level,
184            _ => 0.5 + (0.5 - option.risk_level), // balanced
185        };
186        score += risk_factor * 0.15;
187
188        // 3. Végrehajtási költség (minél alacsonyabb, annál jobb)
189        score += (1.0 - option.execution_cost) * 0.1;
190
191        // 4. Bizonyosság
192        score += option.confidence * 0.1;
193
194        // 5. Salience pontszám (a kiemelési hálózatból)
195        // Valós idejű salience számítás a leírás alapján
196        let salience_score = {
197            let salience = crate::sync_guard::read_lock(&self.salience);
198            let hash = SalienceState::topic_hash(&option.description);
199            let computed = salience.compute_salience(0.5f32, 0.5f32, 0.5f32, hash);
200            computed as f64
201        };
202        score += salience_score;
203
204        // 6. Eureka pontszám (váratlan összefüggések)
205        // Az események insight_score-jának átlaga
206        let eureka_score = {
207            let eureka = crate::sync_guard::read_lock(&self.eureka);
208            let events = &eureka.events;
209            if events.is_empty() {
210                0.0
211            } else {
212                let total: f32 = events.iter().map(|e| e.insight_score()).sum();
213                (total / events.len() as f32) as f64
214            }
215        };
216        score += eureka_score * 0.1;
217
218        // 7. Meta-felügyeleti pontszám
219        let meta_score = {
220            let meta = crate::sync_guard::read_lock(&self.meta_supervisor);
221            let (current, _trend, _volatility) = meta.get_summary();
222            current as f64
223        };
224        score += meta_score * 0.1;
225
226        // 8. Szimulációs előrejelzés (ha van)
227        if let Some(ref sim) = option.simulation_prediction {
228            let stability_bonus = sim.stability_score * 0.05;
229            let resilience_bonus = sim.resilience_score * 0.05;
230            score += stability_bonus + resilience_bonus;
231        }
232
233        // 9. Tanult minták alapján korrekció
234        let pattern_correction = self.apply_learned_patterns(option);
235        score += pattern_correction * 0.1;
236
237        // 10. Tudásbázisból származó megerősítés
238        let kb_boost = {
239            let results = self.knowledge_base.search(&option.description, 3);
240            let boost: f64 = results
241                .iter()
242                .map(|r| r.entry.confidence * r.relevance_score.min(1.0) / 10.0)
243                .sum();
244            boost.min(0.2)
245        };
246        score += kb_boost;
247
248        score
249    }
250
251    /// Tanult minták alkalmazása egy opcióra
252    fn apply_learned_patterns(&self, option: &DecisionOption) -> f64 {
253        let patterns = crate::sync_guard::read_lock(&self.patterns);
254        let mut correction = 0.0;
255
256        for pattern in patterns.values() {
257            // Csak releváns mintákat alkalmazunk
258            if option.description.contains(&pattern.context)
259                || option
260                    .decision_type
261                    .to_string()
262                    .contains(&pattern.pattern_type)
263            {
264                let recency_factor = if pattern.last_used > 0 {
265                    let now = SystemTime::now()
266                        .duration_since(UNIX_EPOCH)
267                        .unwrap()
268                        .as_secs();
269                    let hours_since = (now - pattern.last_used) as f64 / 3600.0;
270                    (-hours_since / 24.0).exp() // exponenciális felejtés
271                } else {
272                    0.0
273                };
274
275                correction += pattern.success_rate * pattern.weight * recency_factor;
276            }
277        }
278
279        correction
280    }
281
282    /// Döntés meghozatala a legjobb opció kiválasztásával
283    pub fn make_decision(&self, options: Vec<DecisionOption>) -> Option<Decision> {
284        if options.is_empty() {
285            return None;
286        }
287
288        let ranked = self.evaluate_options(options);
289        let best = ranked.first().cloned()?;
290        let alternatives: Vec<DecisionOption> = ranked.into_iter().skip(1).collect();
291
292        // Indoklás generálása
293        let reasoning = self.generate_reasoning(&best);
294
295        let decision = Decision {
296            id: format!("decision_{}", rand::random::<u32>()),
297            timestamp: SystemTime::now()
298                .duration_since(UNIX_EPOCH)
299                .unwrap()
300                .as_secs(),
301            selected_option: best.clone(),
302            alternatives,
303            reasoning,
304            confidence_level: best.confidence,
305            expected_outcome: format!(
306                "Expected utility: {:.2}, Risk: {:.2}, Confidence: {:.2}",
307                best.expected_utility, best.risk_level, best.confidence
308            ),
309        };
310
311        // Döntés naplózása
312        self.log_decision(&decision);
313
314        Some(decision)
315    }
316
317    /// Indoklás generálása a döntéshez
318    fn generate_reasoning(&self, option: &DecisionOption) -> Vec<String> {
319        let mut reasoning = Vec::new();
320
321        reasoning.push(format!(
322            "Selected option: {} (type: {:?})",
323            option.description, option.decision_type
324        ));
325
326        if option.salience_score > 0.7 {
327            reasoning.push(format!(
328                "High salience detected ({:.2}) — option stands out from alternatives",
329                option.salience_score
330            ));
331        }
332
333        if option.eureka_score > 0.5 {
334            reasoning.push(format!(
335                "Eureka insight detected ({:.2}) — unexpected connection found",
336                option.eureka_score
337            ));
338        }
339
340        if let Some(ref sim) = option.simulation_prediction {
341            reasoning.push(format!(
342                "Simulation predicts: stability={:.2}, resilience={:.2}, bottleneck={}",
343                sim.stability_score,
344                sim.resilience_score,
345                sim.bottleneck_components.len()
346            ));
347        }
348
349        reasoning.push(format!(
350            "Risk/reward ratio: {:.2}",
351            option.expected_utility / (option.risk_level + 0.01)
352        ));
353
354        reasoning
355    }
356
357    /// Döntés naplózása
358    fn log_decision(&self, decision: &Decision) {
359        let mut log = crate::sync_guard::write_lock(&self.decision_log);
360        log.push(DecisionLogEntry {
361            timestamp: decision.timestamp,
362            decision_id: decision.id.clone(),
363            decision_type: decision.selected_option.decision_type.clone(),
364            selected_option: decision.selected_option.description.clone(),
365            outcome_score: 0.0, // kezdetben ismeretlen
366            reflection: String::new(),
367        });
368    }
369
370    /// Döntés utólagos értékelése (tanulás)
371    pub fn evaluate_decision_outcome(
372        &self,
373        decision_id: &str,
374        outcome_score: f64,
375        reflection: &str,
376    ) {
377        let mut log = crate::sync_guard::write_lock(&self.decision_log);
378
379        if let Some(entry) = log.iter_mut().find(|e| e.decision_id == decision_id) {
380            entry.outcome_score = outcome_score;
381            entry.reflection = reflection.to_string();
382
383            // Minta tanulása
384            self.learn_from_outcome(entry, outcome_score);
385        }
386    }
387
388    /// Tanulás a döntés kimeneteléből
389    fn learn_from_outcome(&self, entry: &DecisionLogEntry, outcome_score: f64) {
390        let mut patterns = crate::sync_guard::write_lock(&self.patterns);
391        let pattern_id = format!("pattern_{}", entry.decision_type);
392
393        let pattern = patterns.entry(pattern_id).or_insert(HeuristicPattern {
394            id: format!("pattern_{}", rand::random::<u32>()),
395            name: format!("{}_pattern", entry.decision_type),
396            pattern_type: entry.decision_type.to_string(),
397            context: entry.selected_option.clone(),
398            success_rate: 0.5,
399            usage_count: 0,
400            last_used: entry.timestamp,
401            weight: 0.5,
402        });
403
404        pattern.usage_count += 1;
405        pattern.last_used = entry.timestamp;
406
407        // Sikerráta frissítése (exponenciális mozgóátlag)
408        let learning = self.learning_rate;
409        pattern.success_rate = pattern.success_rate * (1.0 - learning) + outcome_score * learning;
410
411        // Súly frissítése a konzisztencia alapján
412        if outcome_score > 0.7 {
413            pattern.weight = (pattern.weight + learning).min(1.0);
414        } else if outcome_score < 0.3 {
415            pattern.weight = (pattern.weight - learning).max(0.0);
416        }
417    }
418
419    /// Architektúra ajánlás a szimulátor segítségével
420    pub fn recommend_architecture(&self, requirements: &str) -> Option<Decision> {
421        let architectures = self.simulator.list_architectures();
422
423        if architectures.is_empty() {
424            return None;
425        }
426
427        let options: Vec<DecisionOption> = architectures
428            .iter()
429            .map(|arch| {
430                // Szimuláció futtatása
431                let config = SimulationConfig {
432                    duration_secs: 30.0,
433                    time_step_ms: 100.0,
434                    max_concurrent_requests: 500,
435                    load_pattern: "sine".to_string(),
436                    peak_load: 0.7,
437                    enable_fault_injection: true,
438                    fault_rate: 0.01,
439                };
440
441                let sim_result = self.simulator.run_simulation(&arch.id, &config);
442
443                // Salience pontszám (valós salience számítás)
444                let salience_score = {
445                    let salience = crate::sync_guard::read_lock(&self.salience);
446                    let hash =
447                        SalienceState::topic_hash(&format!("{} {}", arch.name, requirements));
448                    salience.compute_salience(0.5f32, 0.5f32, 0.5f32, hash) as f64
449                };
450
451                // Eureka pontszám (insight score alapján)
452                let eureka_score = {
453                    let eureka = crate::sync_guard::read_lock(&self.eureka);
454                    let events = &eureka.events;
455                    if events.is_empty() {
456                        0.0
457                    } else {
458                        let total: f32 = events.iter().map(|e| e.insight_score()).sum();
459                        (total / events.len() as f32) as f64
460                    }
461                };
462
463                // Meta-felügyeleti pontszám
464                let meta_score = {
465                    let meta = crate::sync_guard::read_lock(&self.meta_supervisor);
466                    let (current, _trend, _volatility) = meta.get_summary();
467                    current as f64
468                };
469
470                DecisionOption {
471                    id: arch.id.clone(),
472                    description: format!("{}: {}", arch.name, arch.description),
473                    decision_type: DecisionType::ArchitectureSelection,
474                    expected_utility: arch.cohesion_score,
475                    risk_level: 1.0 - arch.cohesion_score,
476                    execution_cost: 0.3,
477                    confidence: 0.7,
478                    salience_score,
479                    eureka_score,
480                    meta_score,
481                    simulation_prediction: sim_result,
482                }
483            })
484            .collect();
485
486        self.make_decision(options)
487    }
488
489    /// Gyors heurisztikus döntés (időkorlátos)
490    pub fn quick_decision(
491        &self,
492        options: Vec<DecisionOption>,
493        time_budget_ms: u64,
494    ) -> Option<Decision> {
495        let start = std::time::Instant::now();
496
497        // Csak a legfontosabb tényezőket értékeljük
498        let scored: Vec<(f64, DecisionOption)> = options
499            .into_iter()
500            .map(|opt| {
501                let elapsed = start.elapsed().as_millis() as u64;
502                if elapsed > time_budget_ms {
503                    // Időkeret túllépve — csak a várható hasznot nézzük
504                    return (opt.expected_utility, opt);
505                }
506
507                // Gyorsított pontszámítás (kevesebb tényező)
508                let score = opt.expected_utility * 0.4
509                    + (1.0 - opt.risk_level) * 0.3
510                    + opt.confidence * 0.3;
511                (score, opt)
512            })
513            .collect();
514
515        let best = scored.into_iter().max_by(|a, b| a.0.total_cmp(&b.0))?;
516
517        Some(Decision {
518            id: format!("quick_decision_{}", rand::random::<u32>()),
519            timestamp: SystemTime::now()
520                .duration_since(UNIX_EPOCH)
521                .unwrap()
522                .as_secs(),
523            selected_option: best.1,
524            alternatives: Vec::new(),
525            reasoning: vec!["Quick decision — limited evaluation".to_string()],
526            confidence_level: 0.5,
527            expected_outcome: "Quick heuristic assessment".to_string(),
528        })
529    }
530
531    /// Mintázat felismerés a döntési naplóban
532    pub fn recognize_patterns(&self) -> Vec<HeuristicPattern> {
533        let log = crate::sync_guard::read_lock(&self.decision_log);
534        let mut pattern_map: HashMap<String, Vec<f64>> = HashMap::new();
535
536        for entry in log.iter() {
537            let key = format!("{:?}", entry.decision_type);
538            pattern_map
539                .entry(key)
540                .or_default()
541                .push(entry.outcome_score);
542        }
543
544        pattern_map
545            .into_iter()
546            .map(|(key, scores)| {
547                let avg_score = scores.iter().sum::<f64>() / scores.len() as f64;
548                HeuristicPattern {
549                    id: format!("recognized_{}", rand::random::<u32>()),
550                    name: format!("{}_pattern", key),
551                    pattern_type: key.clone(),
552                    context: "general".to_string(),
553                    success_rate: avg_score,
554                    usage_count: scores.len() as u64,
555                    last_used: SystemTime::now()
556                        .duration_since(UNIX_EPOCH)
557                        .unwrap()
558                        .as_secs(),
559                    weight: avg_score,
560                }
561            })
562            .collect()
563    }
564
565    /// Döntési statisztikák lekérdezése
566    pub fn get_statistics(&self) -> DecisionStatistics {
567        let log = crate::sync_guard::read_lock(&self.decision_log);
568        let patterns = crate::sync_guard::read_lock(&self.patterns);
569
570        let total_decisions = log.len() as u64;
571        let successful = log.iter().filter(|e| e.outcome_score > 0.7).count() as u64;
572        let failed = log.iter().filter(|e| e.outcome_score < 0.3).count() as u64;
573
574        DecisionStatistics {
575            total_decisions,
576            successful_decisions: successful,
577            failed_decisions: failed,
578            success_rate: if total_decisions > 0 {
579                successful as f64 / total_decisions as f64
580            } else {
581                0.0
582            },
583            learned_patterns: patterns.len() as u64,
584            current_preference: self.preference.clone(),
585            learning_rate: self.learning_rate,
586        }
587    }
588
589    /// Döntési napló exportálása
590    pub fn export_decision_log(&self) -> Vec<DecisionLogEntry> {
591        let log = crate::sync_guard::read_lock(&self.decision_log);
592        log.clone()
593    }
594
595    /// Tanult minták exportálása
596    pub fn export_patterns(&self) -> Vec<HeuristicPattern> {
597        let patterns = crate::sync_guard::read_lock(&self.patterns);
598        patterns.values().cloned().collect()
599    }
600}
601
602/// Döntési statisztikák
603#[derive(Debug, Clone)]
604pub struct DecisionStatistics {
605    pub total_decisions: u64,
606    pub successful_decisions: u64,
607    pub failed_decisions: u64,
608    pub success_rate: f64,
609    pub learned_patterns: u64,
610    pub current_preference: String,
611    pub learning_rate: f64,
612}
613
614// ─── Segédfüggvények ────────────────────────────────────────────────────────
615
616/// Létrehoz egy egyszerű döntési lehetőséget
617pub fn create_option(
618    description: &str,
619    decision_type: DecisionType,
620    expected_utility: f64,
621    risk_level: f64,
622) -> DecisionOption {
623    DecisionOption {
624        id: format!("opt_{}", rand::random::<u32>()),
625        description: description.to_string(),
626        decision_type,
627        expected_utility,
628        risk_level,
629        execution_cost: 0.5,
630        confidence: 0.7,
631        salience_score: 0.5,
632        eureka_score: 0.0,
633        meta_score: 0.5,
634        simulation_prediction: None,
635    }
636}
637
638/// Döntési típus stringgé alakítása
639impl std::fmt::Display for DecisionType {
640    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
641        match self {
642            DecisionType::ArchitectureSelection => write!(f, "architecture_selection"),
643            DecisionType::ResourceAllocation => write!(f, "resource_allocation"),
644            DecisionType::OptimizationStrategy => write!(f, "optimization_strategy"),
645            DecisionType::RiskManagement => write!(f, "risk_management"),
646            DecisionType::LearningStrategy => write!(f, "learning_strategy"),
647            DecisionType::Custom(s) => write!(f, "custom_{}", s),
648        }
649    }
650}
651
652#[cfg(test)]
653mod tests {
654    use super::*;
655    use crate::architecture_simulator::ArchitectureSimulator;
656    use crate::eureka::EurekaLog;
657    use crate::knowledge_base::KnowledgeBase;
658    use crate::meta_supervision::MetaSupervisor;
659    use crate::salience::SalienceState;
660    use std::path::Path;
661
662    fn create_test_decision_maker() -> HeuristicDecisionMaker {
663        let data_dir = Path::new("data");
664        let salience = Arc::new(RwLock::new(SalienceState::load_or_init(data_dir)));
665        let eureka = Arc::new(RwLock::new(EurekaLog::load_or_init(data_dir)));
666        let meta = Arc::new(RwLock::new(MetaSupervisor::new()));
667        let simulator = Arc::new(ArchitectureSimulator::new());
668        let kb = Arc::new(KnowledgeBase::new());
669
670        HeuristicDecisionMaker::new(salience, eureka, meta, simulator, kb)
671    }
672
673    #[test]
674    fn test_make_decision() {
675        let dm = create_test_decision_maker();
676
677        let options = vec![
678            create_option(
679                "Use microservices architecture",
680                DecisionType::ArchitectureSelection,
681                0.8,
682                0.3,
683            ),
684            create_option(
685                "Use monolithic architecture",
686                DecisionType::ArchitectureSelection,
687                0.5,
688                0.1,
689            ),
690            create_option(
691                "Use serverless architecture",
692                DecisionType::ArchitectureSelection,
693                0.6,
694                0.5,
695            ),
696        ];
697
698        let decision = dm.make_decision(options);
699        assert!(decision.is_some());
700        let decision = decision.unwrap();
701        assert!(!decision.reasoning.is_empty());
702        assert!(decision.confidence_level > 0.0);
703    }
704
705    #[test]
706    fn test_quick_decision() {
707        let dm = create_test_decision_maker();
708
709        let options = vec![
710            create_option("Option A", DecisionType::ResourceAllocation, 0.9, 0.2),
711            create_option("Option B", DecisionType::ResourceAllocation, 0.6, 0.4),
712        ];
713
714        let decision = dm.quick_decision(options, 100);
715        assert!(decision.is_some());
716    }
717
718    #[test]
719    fn test_learn_from_outcome() {
720        let dm = create_test_decision_maker();
721
722        let options = vec![create_option(
723            "Test option",
724            DecisionType::LearningStrategy,
725            0.7,
726            0.3,
727        )];
728
729        let decision = dm.make_decision(options).unwrap();
730        dm.evaluate_decision_outcome(&decision.id, 0.9, "Good decision");
731
732        let stats = dm.get_statistics();
733        assert!(stats.total_decisions > 0);
734        assert!(stats.success_rate > 0.0);
735    }
736
737    #[test]
738    fn test_pattern_recognition() {
739        let dm = create_test_decision_maker();
740
741        // Több döntés szimulálása
742        for i in 0..5 {
743            let options = vec![create_option(
744                &format!("Pattern option {}", i),
745                DecisionType::ArchitectureSelection,
746                0.7,
747                0.3,
748            )];
749            if let Some(decision) = dm.make_decision(options) {
750                dm.evaluate_decision_outcome(
751                    &decision.id,
752                    0.8 + (i as f64 * 0.02),
753                    "Consistent pattern",
754                );
755            }
756        }
757
758        let patterns = dm.recognize_patterns();
759        assert!(!patterns.is_empty());
760    }
761}