rulelearn-ripper-interactive 0.2.3__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. rulelearn_ri/__init__.py +6 -0
  2. rulelearn_ri/algorithms/__init__.py +0 -0
  3. rulelearn_ri/algorithms/r2n/__init__.py +0 -0
  4. rulelearn_ri/algorithms/r2n/base.py +28 -0
  5. rulelearn_ri/algorithms/r2n/functions.py +25 -0
  6. rulelearn_ri/algorithms/r2n/mask.py +58 -0
  7. rulelearn_ri/algorithms/r2n/preprocessing_layers.py +192 -0
  8. rulelearn_ri/algorithms/r2n/r2n_algo.py +287 -0
  9. rulelearn_ri/algorithms/r2n/simple_rulenet.py +75 -0
  10. rulelearn_ri/algorithms/r2n/training.py +34 -0
  11. rulelearn_ri/algorithms/r2n/utilities.py +117 -0
  12. rulelearn_ri/algorithms/rbm/__init__.py +0 -0
  13. rulelearn_ri/algorithms/rbm/boolean_rule_cg.py +65 -0
  14. rulelearn_ri/algorithms/rbm/rbm/BRCG.py +69 -0
  15. rulelearn_ri/algorithms/rbm/rbm/GLRM.py +98 -0
  16. rulelearn_ri/algorithms/rbm/rbm/__init__.py +6 -0
  17. rulelearn_ri/algorithms/rbm/rbm/beam_search.py +302 -0
  18. rulelearn_ri/algorithms/rbm/rbm/boolean_rule_cg.py +245 -0
  19. rulelearn_ri/algorithms/rbm/rbm/features.py +544 -0
  20. rulelearn_ri/algorithms/rbm/rbm/linear_regression.py +393 -0
  21. rulelearn_ri/algorithms/rbm/rbm/logistic_regression.py +447 -0
  22. rulelearn_ri/algorithms/rbm/utils.py +13 -0
  23. rulelearn_ri/algorithms/ripper/__init__.py +10 -0
  24. rulelearn_ri/algorithms/ripper/base.py +81 -0
  25. rulelearn_ri/algorithms/ripper/binding.py +541 -0
  26. rulelearn_ri/algorithms/ripper/mdl.py +97 -0
  27. rulelearn_ri/algorithms/ripper/pruning.py +212 -0
  28. rulelearn_ri/algorithms/ripper/ripper.py +600 -0
  29. rulelearn_ri/algorithms/ripper/ripper_ruleset_generator.py +26 -0
  30. rulelearn_ri/algorithms/ripper/single_rule.py +425 -0
  31. rulelearn_ri/dise.py +64 -0
  32. rulelearn_ri/trxf/__init__.py +0 -0
  33. rulelearn_ri/trxf/classifier/__init__.py +0 -0
  34. rulelearn_ri/trxf/classifier/ruleset_classifier.py +153 -0
  35. rulelearn_ri/trxf/core/__init__.py +5 -0
  36. rulelearn_ri/trxf/core/boolean_evaluator.py +15 -0
  37. rulelearn_ri/trxf/core/conjunction.py +50 -0
  38. rulelearn_ri/trxf/core/dnf_ruleset.py +64 -0
  39. rulelearn_ri/trxf/core/feature.py +155 -0
  40. rulelearn_ri/trxf/core/predicate.py +98 -0
  41. rulelearn_ri/trxf/core/ruleset_generator.py +25 -0
  42. rulelearn_ri/trxf/core/utils.py +40 -0
  43. rulelearn_ri/trxf/metrics.py +98 -0
  44. rulelearn_ri/trxf/pmml_export/__init__.py +4 -0
  45. rulelearn_ri/trxf/pmml_export/__version__.py +1 -0
  46. rulelearn_ri/trxf/pmml_export/models/__init__.py +24 -0
  47. rulelearn_ri/trxf/pmml_export/models/attribute.py +24 -0
  48. rulelearn_ri/trxf/pmml_export/models/characteristics.py +20 -0
  49. rulelearn_ri/trxf/pmml_export/models/data_dictionary.py +53 -0
  50. rulelearn_ri/trxf/pmml_export/models/mining_schema.py +25 -0
  51. rulelearn_ri/trxf/pmml_export/models/pmml_ruleset_model.py +16 -0
  52. rulelearn_ri/trxf/pmml_export/models/predicate.py +42 -0
  53. rulelearn_ri/trxf/pmml_export/models/rule.py +26 -0
  54. rulelearn_ri/trxf/pmml_export/models/ruleset.py +28 -0
  55. rulelearn_ri/trxf/pmml_export/models/ruleset_model.py +16 -0
  56. rulelearn_ri/trxf/pmml_export/models/scorecard.py +35 -0
  57. rulelearn_ri/trxf/pmml_export/pmml_exporter.py +18 -0
  58. rulelearn_ri/trxf/pmml_export/reader/__init__.py +2 -0
  59. rulelearn_ri/trxf/pmml_export/reader/abstract_reader.py +16 -0
  60. rulelearn_ri/trxf/pmml_export/reader/trxf_reader.py +113 -0
  61. rulelearn_ri/trxf/pmml_export/serializer/__init__.py +2 -0
  62. rulelearn_ri/trxf/pmml_export/serializer/abstract_serializer.py +11 -0
  63. rulelearn_ri/trxf/pmml_export/serializer/nyoka_serializer.py +162 -0
  64. rulelearn_ri/trxf/scorecard/__init__.py +3 -0
  65. rulelearn_ri/trxf/scorecard/bins.py +253 -0
  66. rulelearn_ri/trxf/scorecard/partition.py +71 -0
  67. rulelearn_ri/trxf/scorecard/scorecard.py +78 -0
  68. rulelearn_ripper_interactive-0.2.3.dist-info/METADATA +164 -0
  69. rulelearn_ripper_interactive-0.2.3.dist-info/RECORD +73 -0
  70. rulelearn_ripper_interactive-0.2.3.dist-info/WHEEL +5 -0
  71. rulelearn_ripper_interactive-0.2.3.dist-info/licenses/LICENSE +201 -0
  72. rulelearn_ripper_interactive-0.2.3.dist-info/licenses/NOTICE +11 -0
  73. rulelearn_ripper_interactive-0.2.3.dist-info/top_level.txt +1 -0
@@ -0,0 +1,253 @@
1
+ import abc
2
+ from numbers import Real
3
+ from typing import Dict, Set, Any, Optional
4
+ from rulelearn_ri.trxf.core import Feature
5
+
6
+
7
+ class Bin(abc.ABC):
8
+ """
9
+ Defines a set of values of interest for a particular feature along with an associated sub-score.
10
+ """
11
+
12
+ def __init__(self, feature: Feature):
13
+ """
14
+ @param feature: An instance of trxf.core.Feature. Specifies the feature with which this bin is associated.
15
+ """
16
+ self._feature = feature
17
+
18
+ @abc.abstractmethod
19
+ def evaluate(self, assignment: Dict[str, Any]) -> float:
20
+ """
21
+ Computes the sub-score for the bin based on the feature value.
22
+
23
+ @param assignment: dict mapping variable name to value
24
+ @return: float sub-score for the bin
25
+ """
26
+ raise NotImplementedError('Method evaluate in Bin not implemented')
27
+
28
+ @abc.abstractmethod
29
+ def contains(self, assignment: Dict[str, Any]) -> bool:
30
+ """
31
+ Checks if the value of the feature belongs to this bin or not.
32
+
33
+ @param assignment: dict mapping variable name to value
34
+ @return: bool, true if the feature value belongs to the bin and false otherwise
35
+ """
36
+ raise NotImplementedError('Method contains in Bin not implemented.')
37
+
38
+ @abc.abstractmethod
39
+ def overlaps(self, other: 'Bin') -> bool:
40
+ """
41
+ Checks whether this bin overlaps with the given other bin.
42
+
43
+ @param other: An instance of the same class as self specifying the other bin
44
+ @return: bool, true if the bins share at least one element and false otherwise
45
+ """
46
+ raise NotImplementedError('Method overlaps in Bin not implemented.')
47
+
48
+ @abc.abstractmethod
49
+ def __str__(self):
50
+ raise NotImplementedError('Method __str__ in Bin not implemented.')
51
+
52
+ @abc.abstractmethod
53
+ def __repr__(self):
54
+ raise NotImplementedError('Method __repr__ in Bin not implemented.')
55
+
56
+ @property
57
+ def feature(self) -> Feature:
58
+ return self._feature
59
+
60
+
61
+ class LinearIntervalBin(Bin):
62
+ """
63
+ Defines a Bin specified by a half-open interval [left_end, right_end) where the sub-score is calculated using
64
+ a linear function of the feature value (requires the feature to evaluate to a numerical value).
65
+ """
66
+
67
+ def __init__(self, feature: Feature, const_part: Real, linear_multiplier: Real, left_end: Optional[Real] = None,
68
+ right_end: Optional[Real] = None):
69
+ """
70
+ @param feature: An instance of trxf.core.Feature associated with this bin. This must be a numerical feature.
71
+ @param const_part: The constant additive part used in calculating the sub-score.
72
+ @param linear_multiplier: The sub-score will be calculated as linear_multiplier * feature_value + const_part
73
+ @param left_end: The left endpoint of the interval. Set to -infinity if not specified.
74
+ @param right_end: The right endpoint of the interval. Set to +infinity if not specified.
75
+ """
76
+ if left_end is None:
77
+ left_end = float('-inf')
78
+ if right_end is None:
79
+ right_end = float('inf')
80
+
81
+ if left_end >= right_end:
82
+ raise ValueError('Need left_end < right_end but left_end = "{}" and right_end = "{}"'
83
+ .format(left_end, right_end))
84
+
85
+ super(LinearIntervalBin, self).__init__(feature)
86
+ self._left_end = left_end
87
+ self._right_end = right_end
88
+ self._linear_multiplier = linear_multiplier
89
+ self._const_part = const_part
90
+
91
+ def evaluate(self, assignment: Dict[str, Any]) -> float:
92
+ """
93
+ Computes the sub-score for the bin based on the feature value. The sub-score is zero if the feature value lies
94
+ outside the bin and is given by linear_multiplier * feature_value + const_part otherwise.
95
+
96
+ @param assignment: dict mapping variable name to value
97
+ @return: float sub-score for the bin
98
+ """
99
+ if self.contains(assignment):
100
+ return self.linear_multiplier * self._get_feature_value(assignment) + self.const_part
101
+ return 0.0
102
+
103
+ def contains(self, assignment: Dict[str, Any]) -> bool:
104
+ """
105
+ Returns true if left_end <= feature_value < right_end for the given variable assignment.
106
+
107
+ @param assignment: dict mapping variable name to value
108
+ @return: bool True if the feature value belongs to the bin and False otherwise
109
+ """
110
+ return self.left_end <= self._get_feature_value(assignment) < self.right_end
111
+
112
+ def overlaps(self, other: 'LinearIntervalBin') -> bool:
113
+ """
114
+ Checks whether this bin overlaps with the given other bin.
115
+
116
+ @param other: An instance of LinearIntervalBin or a subclass thereof
117
+ @return: bool, true if the bins share at least one element and false otherwise
118
+ """
119
+ if not isinstance(other, LinearIntervalBin):
120
+ raise ValueError('other must be an instance of LinearIntervalBin or a subclass thereof but it'
121
+ 'is an instance of "{}"'.format(str(other.__class__)))
122
+ return (self.left_end < other.right_end) and (self.right_end > other.left_end)
123
+
124
+ def _get_feature_value(self, assignment: Dict[str, Any]) -> Real:
125
+ """
126
+ Evaluates the value of the feature for the specified variable assignment. Raises ValueError if the feature
127
+ evaluates to a non-numerical value.
128
+
129
+ @param assignment: dict mapping variable name to value
130
+ @return: float, value of the feature
131
+ """
132
+ feature_value = self.feature.evaluate(assignment)
133
+ if isinstance(feature_value, Real):
134
+ return feature_value
135
+ raise ValueError('Need the feature to evaluate to a numerical value but the type of returned value is "{}"'
136
+ .format(type(feature_value)))
137
+
138
+ def __str__(self):
139
+ return ' '.join([str(self.left_end), '<=', str(self.feature), '<', str(self.right_end), '->',
140
+ str(self.linear_multiplier), '*', 'x', '+', str(self.const_part)])
141
+
142
+ def __repr__(self):
143
+ return '%s(%r, [%r, %r), %r * x + %r)' % (self.__class__, self.feature, self.left_end, self.right_end,
144
+ self.linear_multiplier, self.const_part)
145
+
146
+ @property
147
+ def left_end(self) -> Real:
148
+ return self._left_end
149
+
150
+ @property
151
+ def right_end(self) -> Real:
152
+ return self._right_end
153
+
154
+ @property
155
+ def linear_multiplier(self) -> Real:
156
+ return self._linear_multiplier
157
+
158
+ @property
159
+ def const_part(self) -> Real:
160
+ return self._const_part
161
+
162
+
163
+ class IntervalBin(LinearIntervalBin):
164
+ """
165
+ Defines a bin specified by an interval [left_end, right_end) with a constant sub-score
166
+ """
167
+
168
+ def __init__(self, feature: Feature, sub_score: Real, left_end: Optional[Real] = None,
169
+ right_end: Optional[Real] = None):
170
+ """
171
+ @param feature: An instance of trxf.core.Feature. Specifies the feature to which this bin is associated.
172
+ @param sub_score: The constant sub-score associated with this bin
173
+ @param left_end: The left endpoint on the interval. Set to -infinity if not specified.
174
+ @param right_end: The right endpoint of the interval. Set to +infinity if not specified.
175
+ """
176
+ super(IntervalBin, self).__init__(feature, sub_score, 0.0, left_end, right_end)
177
+
178
+ def __str__(self):
179
+ return ' '.join([str(self.left_end), '<=', str(self.feature), '<', str(self.right_end), '->',
180
+ str(self.const_part)])
181
+
182
+ def __repr__(self):
183
+ return '%s(%r, [%r, %r), %r)' % (self.__class__, self.feature, self.left_end, self.right_end, self.const_part)
184
+
185
+ @property
186
+ def sub_score(self) -> Real:
187
+ return self.const_part
188
+
189
+
190
+ class SetBin(Bin):
191
+ """
192
+ Defines a Bin specified by a finite set of values and a constant sub-score
193
+ """
194
+
195
+ def __init__(self, feature: Feature, sub_score: Real, values: Set[Any]):
196
+ """
197
+ @param feature: An instance of trxf.core.Feature. Specifies the feature to which this bin is associated.
198
+ @param sub_score: The constant sub-score associated with this bin.
199
+ @param values: The set of values that belong to this bin
200
+ """
201
+ if len(values) == 0:
202
+ raise ValueError('Expected len(values) > 0, received len(values) == "{}"'.format(len(values)))
203
+
204
+ super(SetBin, self).__init__(feature)
205
+ self._values = values
206
+ self._sub_score = sub_score
207
+
208
+ def evaluate(self, assignment: Dict[str, Any]) -> float:
209
+ """
210
+ Computes the sub-score for the bin based on the feature value. The sub-score is zero if the feature value lies
211
+ outside the bin and is given by sub_score otherwise.
212
+
213
+ @param assignment: dict mapping variable name to value
214
+ @return: float sub-score for the bin
215
+ """
216
+ if self.contains(assignment):
217
+ return float(self.sub_score)
218
+ return 0.0
219
+
220
+ def contains(self, assignment: Dict[str, Any]) -> bool:
221
+ """
222
+ Returns true if the feature value belongs to the set of values in this bin and false otherwise
223
+
224
+ @param assignment: dict mapping variable name to value
225
+ @return: bool, true if the feature value belongs to the bin and false otherwise
226
+ """
227
+ return self.feature.evaluate(assignment) in self.values
228
+
229
+ def overlaps(self, other: 'SetBin') -> bool:
230
+ """
231
+ Checks whether this bin overlaps with the given other bin.
232
+
233
+ @param other: An instance of SetBin or a subclass thereof
234
+ @return: bool, true if the bins share at least one element and false otherwise
235
+ """
236
+ if not isinstance(other, SetBin):
237
+ raise ValueError('other must be an instance of SetBin or a subclass thereof but it'
238
+ 'is an instance of "{}"'.format(str(other.__class__)))
239
+ return len(self.values.intersection(other.values)) > 0
240
+
241
+ def __str__(self):
242
+ return ' '.join([str(self.feature), 'in', str(self.values), '->', str(self.sub_score)])
243
+
244
+ def __repr__(self):
245
+ return '%s(%r, %r, %r)' % (self.__class__, self.feature, self.values, self.sub_score)
246
+
247
+ @property
248
+ def values(self) -> Set[Any]:
249
+ return self._values
250
+
251
+ @property
252
+ def sub_score(self) -> Real:
253
+ return self._sub_score
@@ -0,0 +1,71 @@
1
+ from typing import List, Dict, Any
2
+ from rulelearn_ri.trxf.core import Feature
3
+ from rulelearn_ri.trxf.scorecard import Bin
4
+
5
+
6
+ class Partition(object):
7
+ """
8
+ A Partition is a set of non-overlapping bins of the same type associated with the same feature
9
+ """
10
+
11
+ def __init__(self, bins: List[Bin]):
12
+ """
13
+ @param bins: A list of instances of a subclass of GeneralizedBin. All elements must have the same type.
14
+ """
15
+ if len(bins) == 0:
16
+ raise ValueError('Need len(bins) > 0 but len(bins) = "{}"'.format(len(bins)))
17
+
18
+ # Check that all bins are associated with the same feature and have the same type
19
+ self._feature = bins[0].feature
20
+ bin_type = type(bins[0])
21
+ for idx, curr_bin in enumerate(bins):
22
+ if curr_bin.feature != self._feature:
23
+ raise ValueError('All bins must be associated with the same feature but bins[0] was associated with'
24
+ '"{}" whereas bins["{}"] was associated with "{}"'.format(self._feature, idx,
25
+ curr_bin.feature))
26
+ if type(curr_bin) != bin_type:
27
+ raise ValueError('All bins must have the same type but bins[0] has type "{}" while bins["{}"]'
28
+ 'has type "{}"'.format(bin_type, idx, type(curr_bin)))
29
+
30
+ # Check that bins do not overlap
31
+ for idx1 in range(len(bins)):
32
+ for idx2 in range(idx1 + 1, len(bins)):
33
+ if bins[idx1].overlaps(bins[idx2]):
34
+ raise ValueError('Bins must be non-overlapping but bin "{}" overlaps with bin "{}"'
35
+ .format(bins[idx1], bins[idx2]))
36
+
37
+ self._bins = bins
38
+
39
+ def evaluate(self, assignment: Dict[str, Any]) -> float:
40
+ """
41
+ Computes the sub-score for the feature associated with this partition. This score is given by the sub-score of
42
+ the first bin in the partition to which the feature value belongs. Raises ValueError if the feature value does
43
+ not belong to any of the bins.
44
+
45
+ @param assignment: dict mapping variable name to value
46
+ @return: float sub-score associated with this partition.
47
+ """
48
+ for curr_bin in self.bins:
49
+ if curr_bin.contains(assignment):
50
+ return curr_bin.evaluate(assignment)
51
+ raise ValueError('Value "{}" of the feature does not belong to any of the bins'
52
+ .format(self._feature.evaluate(assignment)))
53
+
54
+ def __str__(self):
55
+ return '\n'.join([str(self.feature)] + ['\t' + str(curr_bin) for curr_bin in self.bins])
56
+
57
+ def __repr__(self):
58
+ return '\n'.join([str(self.__class__)] + ['\t' + repr(self.feature)] +
59
+ ['\t' + repr(curr_bin) for curr_bin in self.bins])
60
+
61
+ @property
62
+ def num_bins(self) -> int:
63
+ return len(self.bins)
64
+
65
+ @property
66
+ def bins(self) -> List[Bin]:
67
+ return self._bins
68
+
69
+ @property
70
+ def feature(self) -> Feature:
71
+ return self._feature
@@ -0,0 +1,78 @@
1
+ from numbers import Real
2
+ from typing import List, Tuple, Dict, Any
3
+ from rulelearn_ri.trxf.core import Feature
4
+ from rulelearn_ri.trxf.scorecard import Partition
5
+
6
+
7
+ class Scorecard(object):
8
+ """
9
+ Defines the representation of a scorecard
10
+ """
11
+
12
+ def __init__(self, partitions: List[Partition], bias: Real = 0.0):
13
+ """
14
+ @param partitions: A list of instances of class Partition, each specifying the bins for a particular feature.
15
+ Elements in the list must correspond to distinct features.
16
+ @param bias: The global bias term used during scorecard evaluation
17
+ """
18
+ if len(partitions) == 0:
19
+ raise ValueError('Need len(partitions) > 0 but found len(partitions) == "{}"'.format(len(partitions)))
20
+
21
+ # Check that all partitions use different features
22
+ seen = []
23
+ for idx, partition in enumerate(partitions):
24
+ try:
25
+ prev_idx = seen.index(partition.feature)
26
+ except ValueError:
27
+ seen.append(partition.feature)
28
+ continue
29
+ raise ValueError('The instances in partitions must correspond to distinct features but the instance'
30
+ 'at index "{}" and "{}" use the same feature "{}"'
31
+ .format(prev_idx, idx, partition.feature))
32
+
33
+ self._partitions = partitions
34
+ self._bias = bias
35
+
36
+ def evaluate(self, assignment: Dict[str, Any]) -> float:
37
+ """
38
+ Computes the output of the scorecard for the given assignment of variables. This output is computed as the
39
+ sum of sub-scores for each partition in the scorecard and the bias term.
40
+
41
+ @param assignment: dict mapping variable names to values
42
+ @return: float score computed using the scorecard
43
+ """
44
+ score = self.bias
45
+ for partition in self.partitions:
46
+ score += partition.evaluate(assignment)
47
+ return float(score)
48
+
49
+ def __str__(self):
50
+ return '\n'.join([str(partition) for partition in self.partitions] + ['Bias="{}"'.format(self.bias)])
51
+
52
+ def __repr__(self):
53
+ return '\n'.join([str(self.__class__)] + [repr(partition) for partition in self.partitions] +
54
+ ['Bias="{}"'.format(self.bias)])
55
+
56
+ @property
57
+ def bias(self) -> Real:
58
+ return self._bias
59
+
60
+ @property
61
+ def partitions(self) -> List[Partition]:
62
+ return self._partitions
63
+
64
+ @property
65
+ def features(self) -> List[Feature]:
66
+ return [partition.feature for partition in self.partitions]
67
+
68
+ @property
69
+ def num_features(self) -> int:
70
+ return len(self.partitions)
71
+
72
+ @property
73
+ def bins_per_feature(self) -> List[Tuple[Feature, int]]:
74
+ return [(partition.feature, partition.num_bins) for partition in self.partitions]
75
+
76
+ @property
77
+ def total_bins(self) -> int:
78
+ return sum([partition.num_bins for partition in self.partitions])
@@ -0,0 +1,164 @@
1
+ Metadata-Version: 2.4
2
+ Name: rulelearn-ripper-interactive
3
+ Version: 0.2.3
4
+ Summary: Rule induction toolkit (fork of IBM rulelearn) with interactive, constrained single-rule RIPPER optimization
5
+ Author-email: Aaron Kurz <aaron.kurz@unisg.ch>, Hagen Voelzer <hagen.voelzer@unisg.ch>
6
+ License-Expression: Apache-2.0
7
+ Project-URL: Repository, https://github.com/aaronkurz/rulelearn-ripper-interactive
8
+ Project-URL: Upstream, https://github.com/IBM/rulelearn
9
+ Keywords: rule induction,ripper,interpretable machine learning,explainability,rule learning
10
+ Classifier: Development Status :: 4 - Beta
11
+ Classifier: Intended Audience :: Science/Research
12
+ Classifier: Operating System :: OS Independent
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3.10
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Programming Language :: Python :: 3.13
18
+ Classifier: Programming Language :: Python :: 3.14
19
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
20
+ Requires-Python: >=3.10
21
+ Description-Content-Type: text/markdown
22
+ License-File: LICENSE
23
+ License-File: NOTICE
24
+ Requires-Dist: numpy
25
+ Requires-Dist: pandas
26
+ Requires-Dist: scikit-learn
27
+ Requires-Dist: numba
28
+ Requires-Dist: nyoka==5.4.0
29
+ Provides-Extra: rbm
30
+ Requires-Dist: cvxpy; extra == "rbm"
31
+ Requires-Dist: ecos; extra == "rbm"
32
+ Requires-Dist: matplotlib; extra == "rbm"
33
+ Provides-Extra: r2n
34
+ Requires-Dist: torch; extra == "r2n"
35
+ Provides-Extra: all
36
+ Requires-Dist: rulelearn-ripper-interactive[r2n,rbm]; extra == "all"
37
+ Dynamic: license-file
38
+
39
+ # rulelearn-ripper-interactive
40
+
41
+ A rule induction toolkit for learning readable, editable rules from data. It is a fork of
42
+ [IBM's rulelearn](https://github.com/IBM/rulelearn) that adds **interactive, constrained
43
+ single-rule optimization** for RIPPER. You can grow and prune a single conjunctive rule
44
+ while forcing some features or predicates into it and keeping others out.
45
+
46
+ The package installs as `rulelearn_ri`, so it can be installed side by side with the
47
+ upstream `rulelearn` package.
48
+
49
+ ## Installation
50
+
51
+ ```bash
52
+ pip install rulelearn-ripper-interactive
53
+ ```
54
+
55
+ or, to add it to a [uv](https://docs.astral.sh/uv/) project:
56
+
57
+ ```bash
58
+ uv add rulelearn-ripper-interactive
59
+ ```
60
+
61
+ The core install covers RIPPER and TRXF (rule interchange, metrics and PMML export).
62
+ The other algorithms need heavier dependencies, available as extras:
63
+
64
+ ```bash
65
+ pip install "rulelearn-ripper-interactive[rbm]" # BRCG / GLRM (cvxpy, ecos, matplotlib)
66
+ pip install "rulelearn-ripper-interactive[r2n]" # Relational Rule Network (torch)
67
+ pip install "rulelearn-ripper-interactive[all]" # everything
68
+ ```
69
+
70
+ With uv, use `uv add "rulelearn-ripper-interactive[rbm]"` (or `[r2n]`, `[all]`) instead.
71
+
72
+ Requires Python 3.10 or newer.
73
+
74
+ ## Single-rule optimization
75
+
76
+ `optimize_single_rule` learns one conjunctive rule for a target label and returns it as a
77
+ TRXF `Conjunction`:
78
+
79
+ ```python
80
+ import pandas as pd
81
+ from rulelearn_ri.algorithms.ripper import optimize_single_rule
82
+
83
+ df = pd.DataFrame({
84
+ 'x': [1.0, 2.0, 3.0, 4.0],
85
+ 'target': ['True', 'True', 'False', 'False'],
86
+ })
87
+ X, y = df.drop(columns='target'), df['target']
88
+
89
+ rule = optimize_single_rule(X, y, target_label='True')
90
+ print(rule)
91
+ ```
92
+
93
+ Constraints let you steer the rule:
94
+
95
+ ```python
96
+ from rulelearn_ri.trxf.core import Feature, Predicate, Relation
97
+
98
+ # Force the feature `x` to appear in the rule (the boundary is still optimized)
99
+ optimize_single_rule(X, y, target_label='True', fixed_attributes=['x'])
100
+
101
+ # Force a specific predicate, with a fixed boundary, into the rule
102
+ optimize_single_rule(
103
+ X, y, target_label='True',
104
+ fixed_predicates=[Predicate(Feature('x'), Relation.LE, 2.5)],
105
+ )
106
+
107
+ # Keep a feature out of the rule (must not clash with any forced feature or predicate)
108
+ optimize_single_rule(X, y, target_label='True', forbidden_attributes=['x'])
109
+ ```
110
+
111
+ Further options: `pruning_threshold` (minimum number of instances for the grow/prune
112
+ split, default 20), `random_state` (seed for the split, default 0) and `ratio`
113
+ (fraction of the data used for growing, default 2/3).
114
+
115
+ ## Included algorithms
116
+
117
+ - Fast Effective Rule Induction (RIPPER) ([William W Cohen, 1995](http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.107.2612&rep=rep1&type=pdf)),
118
+ including the full rule-set learner `RipperExplainer`
119
+ - Boolean Decision Rules via Column Generation (Light Edition) ([Dash et al., 2018](https://papers.nips.cc/paper/7716-boolean-decision-rules-via-column-generation)), extra `rbm`
120
+ - Generalized Linear Rule Models ([Wei et al., 2019](http://proceedings.mlr.press/v97/wei19a.html)), extra `rbm`
121
+ - Relational Rule Network (R2N) ([Kusters et al., 2022](https://arxiv.org/abs/2201.06515)), extra `r2n`
122
+ - TRXF (Technical Rule Interchange Format): a common rule-set representation with evaluation tools
123
+ and PMML export
124
+
125
+ Example notebooks are in the [`examples/`](https://github.com/aaronkurz/rulelearn-ripper-interactive/tree/main/examples) directory of the repository.
126
+
127
+ ## Development
128
+
129
+ This project uses [uv](https://docs.astral.sh/uv/):
130
+
131
+ ```bash
132
+ git clone git@github.com:aaronkurz/rulelearn-ripper-interactive.git
133
+ cd rulelearn-ripper-interactive
134
+ uv sync --all-extras
135
+ uv run pytest
136
+ ```
137
+
138
+ ### Releasing
139
+
140
+ 1. Bump `version` in `pyproject.toml`.
141
+ 2. Build and check the distributions:
142
+ ```bash
143
+ rm -rf dist && uv build
144
+ uvx twine check --strict dist/*
145
+ ```
146
+ 3. Upload to TestPyPI first, then check it installs in a clean environment:
147
+ ```bash
148
+ uv publish --publish-url https://test.pypi.org/legacy/ --token <testpypi-token>
149
+ ```
150
+ 4. Upload to PyPI and tag the release:
151
+ ```bash
152
+ uv publish --token <pypi-token>
153
+ git tag v<version> && git push origin v<version>
154
+ ```
155
+
156
+ ## Acknowledgements
157
+
158
+ This package is derived from [rulelearn](https://github.com/IBM/rulelearn) by IBM,
159
+ originally released as part of [AI Explainability 360](https://github.com/Trusted-AI/AIX360).
160
+ See [NOTICE](https://github.com/aaronkurz/rulelearn-ripper-interactive/blob/main/NOTICE) for details.
161
+
162
+ ## License
163
+
164
+ Apache License 2.0. See [LICENSE](https://github.com/aaronkurz/rulelearn-ripper-interactive/blob/main/LICENSE).
@@ -0,0 +1,73 @@
1
+ rulelearn_ri/__init__.py,sha256=jNP9W3mpGoFFPe7vGg37q3mIj8dJr4NsRQUUXUkS-2g,163
2
+ rulelearn_ri/dise.py,sha256=kwQOoUQE6xqqInANdwD5X3KIMAhXuYaSWVMRZLzcsgk,1988
3
+ rulelearn_ri/algorithms/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
+ rulelearn_ri/algorithms/r2n/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
+ rulelearn_ri/algorithms/r2n/base.py,sha256=DoXsmM3t6PdEGDEWi5qrNnGn5b4gtq0HpTMleZNZw84,1017
6
+ rulelearn_ri/algorithms/r2n/functions.py,sha256=NqX1kcT1tUeBchfuA-SymD6ZGs1kTjKbtTIqGNAcJDs,682
7
+ rulelearn_ri/algorithms/r2n/mask.py,sha256=GWjw8oFQ2kFmbtCY3ozSU31Fk6GnUk4nnD-C3FWZmoI,1595
8
+ rulelearn_ri/algorithms/r2n/preprocessing_layers.py,sha256=8zYlw-T3d-CrugmqjVDfQf64cHG8omzZkP439WrIsuI,6971
9
+ rulelearn_ri/algorithms/r2n/r2n_algo.py,sha256=eGv1V6tAbGPTOwcupQL7Nmo-Fleh1F6HBiTm5RmEPPI,12690
10
+ rulelearn_ri/algorithms/r2n/simple_rulenet.py,sha256=GNHeSQoAXst2Do-AYxtl0a95sZuA0jY563VTNsLNeoM,2547
11
+ rulelearn_ri/algorithms/r2n/training.py,sha256=jxMDM_H6wipd8TF1wnEEjfbMWfcXIFKklR7gQtC3E4w,1085
12
+ rulelearn_ri/algorithms/r2n/utilities.py,sha256=E5wd3BW1umu4tlv8ENm1NAWbxzWCRvOSb_lTjNMzKdY,4251
13
+ rulelearn_ri/algorithms/rbm/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
14
+ rulelearn_ri/algorithms/rbm/boolean_rule_cg.py,sha256=ipntWEQt5_hFyLwCBjUcydVZB47vfP3Nt26Mtu-QKII,2224
15
+ rulelearn_ri/algorithms/rbm/utils.py,sha256=bluMLTwFTKd_ai1Pu2nBI6-hYC4Mqxuj-kXFEFq3r1c,315
16
+ rulelearn_ri/algorithms/rbm/rbm/BRCG.py,sha256=e8BfIEm9B9QIn8dlZs-4X2cXwfZoKoIHGunGTixXn74,2522
17
+ rulelearn_ri/algorithms/rbm/rbm/GLRM.py,sha256=tg_8C8HA5_bWQlX4p7xNNfVCFBw5xtdM4F49axrPqqI,3739
18
+ rulelearn_ri/algorithms/rbm/rbm/__init__.py,sha256=fMtOjJTkGbYsd8yOPDkgRzXx068O5eg7T1_UyK_Qye4,281
19
+ rulelearn_ri/algorithms/rbm/rbm/beam_search.py,sha256=KjKDw-ye5KiTveDIfUw60msmjJlmW9TFTPAnqNcLG6o,13057
20
+ rulelearn_ri/algorithms/rbm/rbm/boolean_rule_cg.py,sha256=x5pwI9k_Kri26Z8j3R85dADNvXMgb8hXd9bvI_3yqLY,9907
21
+ rulelearn_ri/algorithms/rbm/rbm/features.py,sha256=FtYZEYtlVrSd7sIIiZqQ0wIElQkyJWi2IE1i_CgENpw,24215
22
+ rulelearn_ri/algorithms/rbm/rbm/linear_regression.py,sha256=_-bZzAM8zg1OWb73xkeXemFxA9LUzKELapgLxaBO_A0,17602
23
+ rulelearn_ri/algorithms/rbm/rbm/logistic_regression.py,sha256=Omlpzj9diHMAmCNcV1sxYwzwmhodZeZBjNAJ1M2Gweo,19789
24
+ rulelearn_ri/algorithms/ripper/__init__.py,sha256=j4kVSsvxKRss9nMppbcQxpqD-fXibDTTwT9PdzIs8HM,228
25
+ rulelearn_ri/algorithms/ripper/base.py,sha256=2tS0hmm5E-EEJPouXrlln78zJoI8L2FR7NHD1ce0jGM,2764
26
+ rulelearn_ri/algorithms/ripper/binding.py,sha256=aAx70HKYFAIccA1j7KmEP_Xqvj0m4WgDyqQZxMknCWc,11920
27
+ rulelearn_ri/algorithms/ripper/mdl.py,sha256=Npg5ycPpWPk9JonMfPoezPrNsHL1osNdZo5tNwNchKk,2015
28
+ rulelearn_ri/algorithms/ripper/pruning.py,sha256=7Po1puPJpufREwY6sLfkS6FEaOj2rXRWzWpUrfgrTT8,4456
29
+ rulelearn_ri/algorithms/ripper/ripper.py,sha256=D3qCbwMWE7jkjwvp31k10T8nIieqbI4hey5ufCHu89Q,21564
30
+ rulelearn_ri/algorithms/ripper/ripper_ruleset_generator.py,sha256=Snz5gJ457m4JDx5d_FQAb_BPmopmtnNmpUv7QkltNuQ,902
31
+ rulelearn_ri/algorithms/ripper/single_rule.py,sha256=HEx_rITY100d15Xim9QIwdjPytSjwQjIPHWSIl0-O_w,16221
32
+ rulelearn_ri/trxf/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
33
+ rulelearn_ri/trxf/metrics.py,sha256=JEkfVrnxbeUAHqW5uZ-70iZ34e6vQqCTS63oMRS8o7c,4265
34
+ rulelearn_ri/trxf/classifier/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
35
+ rulelearn_ri/trxf/classifier/ruleset_classifier.py,sha256=6lLz8siaiaOJ6Ks9Z0l-RuoPt7_n0J2QLLT_L1AyOp4,6282
36
+ rulelearn_ri/trxf/core/__init__.py,sha256=jBMUQkndUnDU72BxsM49zh8JCb9gkepZcAhsxzlXsEA,193
37
+ rulelearn_ri/trxf/core/boolean_evaluator.py,sha256=MpDnozNaDoCd2cckawFW5AEzj78jgctgNmhPHlAsVTY,397
38
+ rulelearn_ri/trxf/core/conjunction.py,sha256=VaWUK7e5EmWhbpHiCmmnzjJBO4BsC5FmFKZO64QSW54,1539
39
+ rulelearn_ri/trxf/core/dnf_ruleset.py,sha256=QluNdrkL7r6BigXCsfc4gsVSutzW4T1alviXmAP74G0,2317
40
+ rulelearn_ri/trxf/core/feature.py,sha256=kQ8O1ECUubjNvr4mbQ6QgWdWP4M168rF-itZf6twXDk,5255
41
+ rulelearn_ri/trxf/core/predicate.py,sha256=KNChRF2Q5yy7iwTtMj_D7thijZgob68UyXLrbmbM2QM,3162
42
+ rulelearn_ri/trxf/core/ruleset_generator.py,sha256=DCF2PrbTgwCx0o06IFR3hBTKWxbLH5CkbmB7_bCCGaE,816
43
+ rulelearn_ri/trxf/core/utils.py,sha256=vqJXV0Tt8vQEcPOY065jCgQlzkpy6iuGt1OAsZsFU9A,1245
44
+ rulelearn_ri/trxf/pmml_export/__init__.py,sha256=6CZ_EJzb3kGIs7gpq5XAlHsVQFEF9r_UuBYqJXe_PmY,180
45
+ rulelearn_ri/trxf/pmml_export/__version__.py,sha256=p6UlmKJFsYomZzmxB_Ks3LTBru51FpBAY_hQw9_jogY,18
46
+ rulelearn_ri/trxf/pmml_export/pmml_exporter.py,sha256=h612wn9wzQC49T5me3lZg5lhQ8xxHHXZAtkvjCAkb80,782
47
+ rulelearn_ri/trxf/pmml_export/models/__init__.py,sha256=eKRbZhTx88mHsDGTI3QkR1D8RKulegYF5I-hniMWMGs,981
48
+ rulelearn_ri/trxf/pmml_export/models/attribute.py,sha256=-oI9pnx0vbnTlUzkIW1vBjnSa2D5ZYxeVIoN76vwIrE,617
49
+ rulelearn_ri/trxf/pmml_export/models/characteristics.py,sha256=5TWHHdfbrPvlL7h9BSUxfiN0y8VxUS3IZDj51onr3vE,381
50
+ rulelearn_ri/trxf/pmml_export/models/data_dictionary.py,sha256=tj7eGXqM3rg2LiiJEyL5SMPXOflwNo4QJxqZrcaCccs,1123
51
+ rulelearn_ri/trxf/pmml_export/models/mining_schema.py,sha256=riUUs2Z93NbxGt087VrNKmON79re2jsAwQjSDkx1fiw,554
52
+ rulelearn_ri/trxf/pmml_export/models/pmml_ruleset_model.py,sha256=6VZK4Acr0qzIOlS0QIxZT5hAbqbHEl-u9FeuyJQqx2g,435
53
+ rulelearn_ri/trxf/pmml_export/models/predicate.py,sha256=IHN9T3BjnUzABK3479wxzryu1LbnyB6Ly35QTvf5Nyg,965
54
+ rulelearn_ri/trxf/pmml_export/models/rule.py,sha256=SAgvKsv4R30eKeSJxskWtzKPCxPr2lazxLri4ZeNGfc,805
55
+ rulelearn_ri/trxf/pmml_export/models/ruleset.py,sha256=P3aBgYZ4p5EqWl4V7iu4RsICvoo7Gw4m35PtFh1yMu4,763
56
+ rulelearn_ri/trxf/pmml_export/models/ruleset_model.py,sha256=UsdesNQGj5NxK1HfNbN6HhsrJj2_nDhWYfPxO0-n23Y,396
57
+ rulelearn_ri/trxf/pmml_export/models/scorecard.py,sha256=cvJj6jPhSsSbJw-sQVP2kd1xZPEnb_SkPIsJosXox4Q,799
58
+ rulelearn_ri/trxf/pmml_export/reader/__init__.py,sha256=2woCITEi5QaUrmrCzVqcsEY6ntnLrYYXqciJo7U799c,80
59
+ rulelearn_ri/trxf/pmml_export/reader/abstract_reader.py,sha256=qPcbytFtzjZTQF4XFrAxS8AyKDcC5SCOw4Icw9hD3sE,311
60
+ rulelearn_ri/trxf/pmml_export/reader/trxf_reader.py,sha256=8sXWEKqBkObrj64s7dUt7nLT_XQXwO3Xn7JZqtKQi5M,5567
61
+ rulelearn_ri/trxf/pmml_export/serializer/__init__.py,sha256=NqjAw_feiNUUm0d4X2ZgjcMQzIO3F3xOyTkE00SH9B8,98
62
+ rulelearn_ri/trxf/pmml_export/serializer/abstract_serializer.py,sha256=qiNH4oYHnDzkUxYyLhRHfr92ln4rDfJ4Y3mQapcgeEM,246
63
+ rulelearn_ri/trxf/pmml_export/serializer/nyoka_serializer.py,sha256=NyWBDD3GTtjR9mNGLVrawNZsv3CN-TL4nVipA889Kks,8848
64
+ rulelearn_ri/trxf/scorecard/__init__.py,sha256=VeDCZDno8xpRrajbUt19ptz5egsdykjloy4oXhLaZT0,128
65
+ rulelearn_ri/trxf/scorecard/bins.py,sha256=Sm_hKfQcUSTfFJRkf-KX8WbNf-ajOBT4qKwHIQCCimc,10335
66
+ rulelearn_ri/trxf/scorecard/partition.py,sha256=4LyEZJvnenJmsb21NsyL5C9XiRFHlOyPNVdGkorSxjg,3097
67
+ rulelearn_ri/trxf/scorecard/scorecard.py,sha256=Y-Fa-5hrqEKcnIP4bCYdGxg3GQ9iio1tmaEBJy80LQI,2942
68
+ rulelearn_ripper_interactive-0.2.3.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
69
+ rulelearn_ripper_interactive-0.2.3.dist-info/licenses/NOTICE,sha256=BcNidS_aDOBStBdw7jUKMWqT56Md-7NEU8qDhPBWfRE,494
70
+ rulelearn_ripper_interactive-0.2.3.dist-info/METADATA,sha256=0ksyaCeKnfzYBvbaP5NS-mFbP7d_heIg4TCzouhh6sc,6116
71
+ rulelearn_ripper_interactive-0.2.3.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
72
+ rulelearn_ripper_interactive-0.2.3.dist-info/top_level.txt,sha256=Skh2-5pMO7dqQWvCJk_gDP3JkVz8EuX0cH5oLrfXiv8,13
73
+ rulelearn_ripper_interactive-0.2.3.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (84.0.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+