1use serde::{Deserialize, Serialize};
2use std::time::Duration;
3
4pub type ItemSet = Vec<String>;
6
7#[derive(Debug, Clone, Serialize, Deserialize)]
9pub struct FrequentItemset {
10 pub items: ItemSet,
11 pub support: f64,
12}
13
14#[derive(Debug, Clone, Serialize, Deserialize)]
16pub struct AssociationRule {
17 pub antecedent: ItemSet,
18 pub consequent: ItemSet,
19 pub metrics: PatternMetrics,
20}
21
22#[derive(Debug, Clone, Serialize, Deserialize)]
24pub struct SequentialPattern {
25 pub sequence: Vec<ItemSet>,
26 pub time_gaps: Vec<Duration>,
27 pub support: f64,
28}
29
30#[derive(Debug, Clone, Serialize, Deserialize)]
32pub struct PatternMetrics {
33 pub confidence: f64,
36
37 pub support: f64,
40
41 pub lift: f64,
44
45 pub conviction: f64,
48
49 #[serde(skip_serializing_if = "Option::is_none")]
51 pub avg_time_gap: Option<Duration>,
52
53 #[serde(skip_serializing_if = "Option::is_none")]
54 pub time_variance: Option<Duration>,
55}
56
57#[derive(Debug, Clone, Serialize, Deserialize)]
59pub struct Pattern {
60 pub pattern_type: PatternType,
61 pub items: Vec<String>,
62 pub metrics: PatternMetrics,
63 pub evidence: Vec<String>, }
65
66#[derive(Debug, Clone, Serialize, Deserialize)]
67pub enum PatternType {
68 FrequentItemset,
70
71 Sequential { time_constraints: Vec<Duration> },
73
74 AssociationRule {
76 antecedent: Vec<String>,
77 consequent: Vec<String>,
78 },
79}
80
81impl AssociationRule {
82 pub fn quality_score(&self) -> f64 {
84 self.metrics.confidence * 0.5 + self.metrics.lift * 0.3 + self.metrics.support * 0.2
86 }
87}
88
89#[cfg(test)]
90mod tests {
91 use super::*;
92
93 #[test]
94 fn test_quality_score() {
95 let rule = AssociationRule {
96 antecedent: vec!["A".to_string()],
97 consequent: vec!["B".to_string()],
98 metrics: PatternMetrics {
99 confidence: 0.8,
100 support: 0.6,
101 lift: 1.5,
102 conviction: 2.0,
103 avg_time_gap: None,
104 time_variance: None,
105 },
106 };
107
108 let score = rule.quality_score();
109 assert!(score > 0.0 && score <= 1.0);
110 }
111}