1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
//! Association-rule generation from frequent itemsets: partition enumeration,
//! metric scoring, the metric-threshold filter, and the deterministic ordering.
//!
//! Split out of `mod.rs` to keep that file inside the project's 500-line `style.rs`
//! cap. The public entry point [`association_rules`] reproduces
//! `mlxtend.frequent_patterns.association_rules(frequent, metric, min_threshold)`:
//! every frequent itemset of size `≥ 2` is split into all non-empty antecedent /
//! consequent partitions, each scored with `support` / `confidence` / `lift` /
//! `leverage` / `conviction`, and emitted only when the chosen metric clears the
//! threshold. As a child module of `association`, this file can read the private
//! fields of the [`FrequentItemset`] and [`AssociationRule`] types declared in the
//! parent.
use BTreeMap;
use ;
/// Generates association rules from frequent itemsets, filtered by a metric
/// threshold.
///
/// Every frequent itemset of size `≥ 2` is split into all `2^m − 2` non-empty
/// antecedent / consequent partitions; each partition's `support`, `confidence`,
/// `lift`, `leverage`, and `conviction` are computed from the frequent-itemset
/// supports, and the rule is emitted only when the chosen `metric` is
/// `≥ min_threshold`. This mirrors
/// `mlxtend.frequent_patterns.association_rules(frequent, metric, min_threshold)`.
/// Rules are returned sorted by `(antecedent, consequent)` for determinism.
///
/// # Arguments
///
/// * `frequent` — frequent itemsets with supports, as returned by
/// [`apriori`](super::apriori); the single-item supports it contains are required
/// to score `lift` / `conviction`.
/// * `metric` — which metric the `min_threshold` filter applies to.
/// * `min_threshold` — the minimum value of `metric` a rule must reach; must be
/// finite.
///
/// # Returns
///
/// Every qualifying association rule with its metrics, deterministically ordered.
///
/// # Errors
///
/// Returns [`AssociationError::InvalidThreshold`] if `min_threshold` is not finite.
///
/// # Examples
///
/// ```
/// use stats_claw::algorithms::association::{apriori, association_rules, RuleMetric};
///
/// let t = vec![
/// vec![true, true],
/// vec![true, true],
/// vec![true, false],
/// vec![false, true],
/// ];
/// let frequent = apriori(&t, 0.25)?;
/// let rules = association_rules(&frequent, RuleMetric::Confidence, 0.5)?;
/// // {0} => {1} has confidence 2/3 ≥ 0.5, so it is emitted.
/// assert!(rules.iter().any(|r| r.antecedent() == [0] && r.consequent() == [1]));
/// # Ok::<(), stats_claw::algorithms::association::AssociationError>(())
/// ```
/// Scores a single antecedent ⇒ consequent partition into an [`AssociationRule`].
///
/// Applies the standard metric definitions from the three supports: the joint
/// support of the full itemset, the antecedent support, and the consequent support.
///
/// # Arguments
///
/// * `antecedent` — the ascending antecedent items.
/// * `consequent` — the ascending consequent items.
/// * `sup_union` — support of `antecedent ∪ consequent` (the parent itemset).
/// * `sup_a` — support of the antecedent alone.
/// * `sup_c` — support of the consequent alone.
///
/// # Returns
///
/// The fully-scored rule.
/// Returns the value of the selected `metric` for a scored rule.
///
/// The dispatch behind the [`association_rules`] threshold filter.
///
/// # Arguments
///
/// * `rule` — the scored rule.
/// * `metric` — which metric to read.
///
/// # Returns
///
/// The rule's value for that metric.
const
/// Enumerates the non-empty proper subsets of an ascending itemset.
///
/// Used to form every antecedent of an itemset's rules; each returned subset keeps
/// the items in ascending order, and the full set itself is excluded so the
/// consequent is always non-empty.
///
/// # Arguments
///
/// * `items` — the ascending itemset to split (length `m`, with `m ≤` machine word
/// bits, which always holds for realistic baskets).
///
/// # Returns
///
/// Each non-empty proper subset once, in ascending item order within each subset.
/// Sorts rules by ascending antecedent, then ascending consequent.
///
/// Gives a deterministic, reproducible ordering so the equivalence suite can sort
/// both sides to the same canonical order before comparing.
///
/// # Arguments
///
/// * `rules` — the rules to order in place.