Skip to content

Commit a99ce0c

Browse files
committed
fix linter errors + rename consequence to consequent
1 parent e721bf2 commit a99ce0c

File tree

10 files changed

+130
-119
lines changed

10 files changed

+130
-119
lines changed

niaarm/association_rule.py

Lines changed: 57 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -74,55 +74,60 @@ def feature_position(self, feature):
7474
position = position + 2
7575
return position
7676

77-
def support_confidence(self, antecedent, consequence, transactions):
77+
def __match_antecedent(self, i, antecedent, transactions):
78+
match = 0
79+
for j in range(len(antecedent)):
80+
dtype = self.features[self.permutation[j]].dtype
81+
if dtype == 'float' or dtype == 'int':
82+
if antecedent[j] != 'NO':
83+
border = antecedent[j]
84+
if border[0] <= transactions[i, self.permutation[j]] <= border[1]:
85+
match = match + 1
86+
elif dtype == 'cat':
87+
if antecedent[j] != 'NO':
88+
ant = antecedent[j]
89+
if transactions[i, self.permutation[j]] == ant[0]:
90+
match = match + 1
91+
return match
92+
93+
def __match_consequent(self, i, antecedent, consequent, transactions):
94+
match = 0
95+
con_counter = 0
96+
for ll in range(len(antecedent), len(antecedent) + len(consequent)):
97+
dtype = self.features[self.permutation[ll]].dtype
98+
if dtype == 'float' or dtype == 'int':
99+
if consequent[con_counter] != 'NO':
100+
border = consequent[con_counter]
101+
if border[0] <= transactions[i, self.permutation[ll]] <= border[1]:
102+
match = match + 1
103+
elif dtype == 'cat':
104+
if consequent[con_counter] != 'NO':
105+
con = consequent[con_counter]
106+
107+
if transactions[i, self.permutation[ll]] == con[0]:
108+
match = match + 1
109+
110+
con_counter = con_counter + 1
111+
return match
112+
113+
def support_confidence(self, antecedent, consequent, transactions):
78114
supp = 0
79115
conf = 0
80116
conf_counter = 0
81117

82-
# firstly antecedent
83118
for i in range(len(transactions)):
84-
match1 = 0
85-
match2 = 0
86-
for j in range(len(antecedent)):
87-
dtype = self.features[self.permutation[j]].dtype
88-
if dtype == 'float' or dtype == 'int':
89-
if antecedent[j] != 'NO':
90-
border = antecedent[j]
91-
if border[0] <= transactions[i, self.permutation[j]] <= border[1]:
92-
match1 = match1 + 1
93-
elif dtype == 'cat':
94-
if antecedent[j] != 'NO':
95-
ant = antecedent[j]
96-
if transactions[i, self.permutation[j]] == ant[0]:
97-
match1 = match1 + 1
98-
99-
# secondly consequence
100-
con_counter = 0
101-
for ll in range(len(antecedent), len(antecedent) + len(consequence)):
102-
dtype = self.features[self.permutation[ll]].dtype
103-
if dtype == 'float' or dtype == 'int':
104-
if consequence[con_counter] != 'NO':
105-
border = consequence[con_counter]
106-
if border[0] <= transactions[i, self.permutation[ll]] <= border[1]:
107-
match2 = match2 + 1
108-
elif dtype == 'cat':
109-
if consequence[con_counter] != 'NO':
110-
con = consequence[con_counter]
111-
112-
if transactions[i, self.permutation[ll]] == con[0]:
113-
match2 = match2 + 1
114-
115-
con_counter = con_counter + 1
119+
match_antecedent = self.__match_antecedent(i, antecedent, transactions)
120+
match_consequent = self.__match_consequent(i, antecedent, consequent, transactions)
116121

117122
missing_ant = antecedent.count('NO')
118-
missing_con = consequence.count('NO')
123+
missing_con = consequent.count('NO')
119124

120-
if (missing_ant + match1) == len(antecedent):
125+
if (missing_ant + match_antecedent) == len(antecedent):
121126
conf_counter += 1
122-
if (missing_con + match2) == len(consequence):
127+
if (missing_con + match_consequent) == len(consequent):
123128
conf = conf + 1
124129

125-
total = match1 + match2 + missing_ant + missing_con
130+
total = match_antecedent + match_consequent + missing_ant + missing_con
126131

127132
if total == len(self.features):
128133
supp = supp + 1
@@ -138,11 +143,11 @@ def support_confidence(self, antecedent, consequence, transactions):
138143

139144
return total_supp, total_conf
140145

141-
def coverage(self, antecedent, consequence):
142-
missing_total = antecedent.count("NO") + consequence.count("NO")
146+
def coverage(self, antecedent, consequent):
147+
missing_total = antecedent.count("NO") + consequent.count("NO")
143148
return 1 - missing_total / len(self.features)
144149

145-
def shrinkage(self, antecedent, consequence):
150+
def shrinkage(self, antecedent, consequent):
146151
differences = []
147152

148153
for i in range(len(antecedent)):
@@ -156,11 +161,11 @@ def shrinkage(self, antecedent, consequence):
156161
differences.append(diff)
157162

158163
con_counter = 0
159-
for ll in range(len(antecedent), len(antecedent) + len(consequence)):
164+
for ll in range(len(antecedent), len(antecedent) + len(consequent)):
160165
feature = self.features[self.permutation[ll]]
161166
if feature.dtype == 'float' or feature.dtype == 'int':
162-
if consequence[con_counter] != 'NO':
163-
borders = consequence[con_counter]
167+
if consequent[con_counter] != 'NO':
168+
borders = consequent[con_counter]
164169
diff_borders = borders[1] - borders[0]
165170
total_borders = feature.max_val - feature.min_val
166171
diff = diff_borders / total_borders
@@ -175,9 +180,9 @@ def shrinkage(self, antecedent, consequence):
175180
return 0.0
176181
return 1 - normalized
177182

178-
def format_rules(self, antecedent, consequence):
183+
def format_rules(self, antecedent, consequent):
179184
antecedent1 = []
180-
consequence1 = []
185+
consequent1 = []
181186

182187
for i in range(len(antecedent)):
183188
if antecedent[i] != "NO":
@@ -188,15 +193,15 @@ def format_rules(self, antecedent, consequence):
188193
rule = feature.name + "(" + str(antecedent[i]) + ")"
189194
antecedent1.append(rule)
190195

191-
for i in range(len(consequence)):
192-
if consequence[i] != "NO":
196+
for i in range(len(consequent)):
197+
if consequent[i] != "NO":
193198
feature = self.features[self.permutation[i + len(antecedent)]]
194199
if feature.dtype == "cat":
195-
rule = feature.name + "(" + str(consequence[i][0]) + ")"
200+
rule = feature.name + "(" + str(consequent[i][0]) + ")"
196201
else:
197-
rule = feature.name + "(" + str(consequence[i]) + ")"
198-
consequence1.append(rule)
199-
return antecedent1, consequence1
202+
rule = feature.name + "(" + str(consequent[i]) + ")"
203+
consequent1.append(rule)
204+
return antecedent1, consequent1
200205

201206

202207
def _normalize(value, actual_bounds, real_bounds):

niaarm/dataset.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ def __analyse_types(self):
4141
unique_categories = None
4242
else:
4343
dtype = "cat"
44-
unique_categories = sorted(col.astype('string').unique().tolist(), key=str.lower) # convert to str just in case
44+
unique_categories = sorted(col.astype('string').unique().tolist(), key=str.lower)
4545
min_value = None
4646
max_value = None
4747

niaarm/niaarm.py

Lines changed: 32 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,15 @@ class NiaARM(Problem):
1111
Reference:
1212
The implementation is composed of ideas found in the following papers:
1313
14-
I. Fister Jr., A. Iglesias, A. Gálvez, J. Del Ser, E. Osaba, I Fister. [Differential evolution for association rule mining using categorical and numerical attributes](http://www.iztok-jr-fister.eu/static/publications/231.pdf) In: Intelligent data engineering and automated learning - IDEAL 2018, pp. 79-88, 2018.
14+
I. Fister Jr., A. Iglesias, A. Gálvez, J. Del Ser, E. Osaba, I Fister.
15+
[Differential evolution for association rule mining using categorical and numerical attributes]
16+
(http://www.iztok-jr-fister.eu/static/publications/231.pdf)
17+
In: Intelligent data engineering and automated learning - IDEAL 2018, pp. 79-88, 2018.
1518
16-
I. Fister Jr., V. Podgorelec, I. Fister. Improved Nature-Inspired Algorithms for Numeric Association Rule Mining. In: Vasant P., Zelinka I., Weber GW. (eds) Intelligent Computing and Optimization. ICO 2020. Advances in Intelligent Systems and Computing, vol 1324. Springer, Cham.
19+
I. Fister Jr., V. Podgorelec, I. Fister.
20+
Improved Nature-Inspired Algorithms for Numeric Association Rule Mining.
21+
In: Vasant P., Zelinka I., Weber GW. (eds) Intelligent Computing and Optimization. ICO 2020.
22+
Advances in Intelligent Systems and Computing, vol 1324. Springer, Cham.
1723
1824
Attributes:
1925
features (list[Feature]): List of features.
@@ -39,10 +45,10 @@ def __init__(self, dimension, features, transactions, alpha=0.0, beta=0.0, gamma
3945
self.rules = []
4046
super().__init__(dimension, 0.0, 1.0)
4147

42-
def rule_exists(self, antecedent, consequence):
48+
def rule_exists(self, antecedent, consequent):
4349
r"""Check if association rule already exists."""
4450
for rule in self.rules:
45-
if rule.antecedent == antecedent and rule.consequence == consequence:
51+
if rule.antecedent == antecedent and rule.consequent == consequent:
4652
return True
4753
return False
4854

@@ -52,11 +58,11 @@ def export_rules(self, path):
5258
writer = csv.writer(f)
5359

5460
# write header
55-
writer.writerow(["Antecedent", "Consequence", "Fitness", "Support", "Confidence", "Coverage", "Shrinkage"])
61+
writer.writerow(["Antecedent", "consequent", "Fitness", "Support", "Confidence", "Coverage", "Shrinkage"])
5662

5763
for rule in self.rules:
5864
writer.writerow(
59-
[rule.antecedent, rule.consequence, rule.fitness, rule.support, rule.confidence, rule.coverage,
65+
[rule.antecedent, rule.consequent, rule.fitness, rule.support, rule.confidence, rule.coverage,
6066
rule.shrink])
6167
print(f"Rules exported to {path}")
6268

@@ -74,41 +80,41 @@ def _evaluate(self, sol):
7480

7581
rule = arm.build_rule(solution)
7682

77-
# get antecedent and consequence of rule
83+
# get antecedent and consequent of rule
7884
antecedent = rule[:cut]
79-
consequence = rule[cut:]
85+
consequent = rule[cut:]
8086

8187
# check if rule is feasible
82-
if _rule_feasible(antecedent, consequence):
88+
if _rule_feasible(antecedent, consequent):
8389
# get support and confidence of rule
84-
support, confidence = arm.support_confidence(antecedent, consequence, self.transactions)
90+
support, confidence = arm.support_confidence(antecedent, consequent, self.transactions)
8591

8692
if self.gamma == 0.0:
8793
shrinkage = 0
8894
else:
89-
shrinkage = arm.shrinkage(antecedent, consequence)
95+
shrinkage = arm.shrinkage(antecedent, consequent)
9096

9197
if self.delta == 0.0:
9298
coverage = 0
9399
else:
94-
coverage = arm.coverage(antecedent, consequence)
100+
coverage = arm.coverage(antecedent, consequent)
95101

96102
fitness = ((self.alpha * support) + (self.beta * confidence) + (self.gamma * shrinkage) +
97103
(self.delta * coverage)) / (self.alpha + self.beta + self.gamma + self.delta)
98104

99-
# in case no attributes were selected for antecedent or consequence
100-
if antecedent.count("NO") == len(antecedent) or consequence.count("NO") == len(consequence):
105+
# in case no attributes were selected for antecedent or consequent
106+
if antecedent.count("NO") == len(antecedent) or consequent.count("NO") == len(consequent):
101107
fitness = 0.0
102108

103109
if support > 0.0 and confidence > 0.0:
104-
antecedent, consequence = _fix_border(antecedent, consequence)
110+
antecedent, consequent = _fix_border(antecedent, consequent)
105111
# format rule; remove NO; add name of features
106-
antecedent1, consequence1 = arm.format_rules(antecedent, consequence)
112+
antecedent1, consequent1 = arm.format_rules(antecedent, consequent)
107113

108114
# save feasible rule
109-
if not self.rule_exists(antecedent1, consequence1):
115+
if not self.rule_exists(antecedent1, consequent1):
110116
self.rules.append(
111-
Rule(antecedent1, consequence1, fitness, support, confidence, coverage, shrinkage))
117+
Rule(antecedent1, consequent1, fitness, support, confidence, coverage, shrinkage))
112118

113119
if fitness > self.best_fitness:
114120
self.best_fitness = fitness
@@ -119,26 +125,26 @@ def _evaluate(self, sol):
119125
return -1.0
120126

121127

122-
def _fix_border(antecedent, consequence):
128+
def _fix_border(antecedent, consequent):
123129
r"""In case lower and upper bounds of interval are the same.
124130
We need this in order to provide clean output.
125131
126132
Arguments:
127133
antecedent (np.ndarray): .
128-
consequence (np.ndarray): .
134+
consequent (np.ndarray): .
129135
130136
Returns:
131137
antecedent (array):
132-
consequence (array):
138+
consequent (array):
133139
"""
134140
for i in range(len(antecedent)):
135141
if len(antecedent[i]) > 1:
136142
if antecedent[i][0] == antecedent[i][1]:
137143
antecedent[i] = antecedent[i][0]
138144

139-
for i in range(len(consequence)):
140-
if len(consequence[i]) > 1:
141-
if consequence[i][0] == consequence[i][1]:
142-
consequence[i] = consequence[i][0]
145+
for i in range(len(consequent)):
146+
if len(consequent[i]) > 1:
147+
if consequent[i][0] == consequent[i][1]:
148+
consequent[i] = consequent[i][0]
143149

144-
return antecedent, consequence
150+
return antecedent, consequent

niaarm/rule.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ class Rule:
88
99
Attributes:
1010
antecedent (list[str]): A list of antecedents of association rule.
11-
consequence (list[str]): A list of consequents of association rule.
11+
consequent (list[str]): A list of consequents of association rule.
1212
fitness (float): Value of fitness function.
1313
support (float): Value of support.
1414
confidence (float): Value of confidence.
@@ -18,7 +18,7 @@ class Rule:
1818
"""
1919

2020
antecedent: list[str]
21-
consequence: list[str]
21+
consequent: list[str]
2222
fitness: float
2323
support: float
2424
confidence: float

niaarm/stats.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,4 +41,4 @@ def avg_ant_len(self):
4141

4242
@property
4343
def avg_con_len(self):
44-
return np.mean([len(rule.consequence) for rule in self.rules])
44+
return np.mean([len(rule.consequent) for rule in self.rules])

niaarm/tests/test_coverage.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,22 +15,22 @@ def test_a(self):
1515
# Rule: A => 0
1616
antecedent = [['A']]
1717

18-
consequence = [[0, 0]]
18+
consequent = [[0, 0]]
1919

2020
oper = AssociationRule(self.features)
2121

22-
coverage = oper.coverage(antecedent, consequence)
22+
coverage = oper.coverage(antecedent, consequent)
2323

2424
self.assertEqual(coverage, 1)
2525

2626
def test_b(self):
2727
# Rule: NO => 0
2828
antecedent = ["NO"]
2929

30-
consequence = [[0, 0]]
30+
consequent = [[0, 0]]
3131

3232
oper = AssociationRule(self.features)
3333

34-
coverage = oper.coverage(antecedent, consequence)
34+
coverage = oper.coverage(antecedent, consequent)
3535

3636
self.assertEqual(coverage, 0.5)

0 commit comments

Comments
 (0)