ripple-down-rules 0.0.11__tar.gz → 0.0.13__tar.gz
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.
- {ripple_down_rules-0.0.11 → ripple_down_rules-0.0.13}/PKG-INFO +1 -1
- {ripple_down_rules-0.0.11 → ripple_down_rules-0.0.13}/pyproject.toml +1 -1
- {ripple_down_rules-0.0.11 → ripple_down_rules-0.0.13}/src/ripple_down_rules/rdr.py +21 -16
- {ripple_down_rules-0.0.11 → ripple_down_rules-0.0.13}/src/ripple_down_rules/rules.py +11 -4
- {ripple_down_rules-0.0.11 → ripple_down_rules-0.0.13}/src/ripple_down_rules.egg-info/PKG-INFO +1 -1
- {ripple_down_rules-0.0.11 → ripple_down_rules-0.0.13}/test/test_json_serialization.py +11 -14
- {ripple_down_rules-0.0.11 → ripple_down_rules-0.0.13}/test/test_rdr.py +9 -29
- {ripple_down_rules-0.0.11 → ripple_down_rules-0.0.13}/LICENSE +0 -0
- {ripple_down_rules-0.0.11 → ripple_down_rules-0.0.13}/README.md +0 -0
- {ripple_down_rules-0.0.11 → ripple_down_rules-0.0.13}/setup.cfg +0 -0
- {ripple_down_rules-0.0.11 → ripple_down_rules-0.0.13}/src/ripple_down_rules/__init__.py +0 -0
- {ripple_down_rules-0.0.11 → ripple_down_rules-0.0.13}/src/ripple_down_rules/datasets.py +0 -0
- {ripple_down_rules-0.0.11 → ripple_down_rules-0.0.13}/src/ripple_down_rules/datastructures/__init__.py +0 -0
- {ripple_down_rules-0.0.11 → ripple_down_rules-0.0.13}/src/ripple_down_rules/datastructures/callable_expression.py +0 -0
- {ripple_down_rules-0.0.11 → ripple_down_rules-0.0.13}/src/ripple_down_rules/datastructures/case.py +0 -0
- {ripple_down_rules-0.0.11 → ripple_down_rules-0.0.13}/src/ripple_down_rules/datastructures/dataclasses.py +0 -0
- {ripple_down_rules-0.0.11 → ripple_down_rules-0.0.13}/src/ripple_down_rules/datastructures/enums.py +0 -0
- {ripple_down_rules-0.0.11 → ripple_down_rules-0.0.13}/src/ripple_down_rules/experts.py +0 -0
- {ripple_down_rules-0.0.11 → ripple_down_rules-0.0.13}/src/ripple_down_rules/failures.py +0 -0
- {ripple_down_rules-0.0.11 → ripple_down_rules-0.0.13}/src/ripple_down_rules/prompt.py +0 -0
- {ripple_down_rules-0.0.11 → ripple_down_rules-0.0.13}/src/ripple_down_rules/utils.py +0 -0
- {ripple_down_rules-0.0.11 → ripple_down_rules-0.0.13}/src/ripple_down_rules.egg-info/SOURCES.txt +0 -0
- {ripple_down_rules-0.0.11 → ripple_down_rules-0.0.13}/src/ripple_down_rules.egg-info/dependency_links.txt +0 -0
- {ripple_down_rules-0.0.11 → ripple_down_rules-0.0.13}/src/ripple_down_rules.egg-info/top_level.txt +0 -0
- {ripple_down_rules-0.0.11 → ripple_down_rules-0.0.13}/test/test_rdr_alchemy.py +0 -0
- {ripple_down_rules-0.0.11 → ripple_down_rules-0.0.13}/test/test_relational_rdr.py +0 -0
- {ripple_down_rules-0.0.11 → ripple_down_rules-0.0.13}/test/test_relational_rdr_alchemy.py +0 -0
- {ripple_down_rules-0.0.11 → ripple_down_rules-0.0.13}/test/test_sql_model.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: ripple_down_rules
|
3
|
-
Version: 0.0.
|
3
|
+
Version: 0.0.13
|
4
4
|
Summary: Implements the various versions of Ripple Down Rules (RDR) for knowledge representation and reasoning.
|
5
5
|
Author-email: Abdelrhman Bassiouny <abassiou@uni-bremen.de>
|
6
6
|
License: GNU GENERAL PUBLIC LICENSE
|
@@ -6,7 +6,7 @@ build-backend = "setuptools.build_meta"
|
|
6
6
|
|
7
7
|
[project]
|
8
8
|
name = "ripple_down_rules"
|
9
|
-
version = "0.0.
|
9
|
+
version = "0.0.13"
|
10
10
|
description = "Implements the various versions of Ripple Down Rules (RDR) for knowledge representation and reasoning."
|
11
11
|
readme = "README.md"
|
12
12
|
authors = [{ name = "Abdelrhman Bassiouny", email = "abassiou@uni-bremen.de" }]
|
@@ -17,7 +17,7 @@ from .utils import draw_tree, make_set, get_attribute_by_type, copy_case, \
|
|
17
17
|
get_hint_for_attribute, SubclassJSONSerializer, is_iterable, make_list
|
18
18
|
|
19
19
|
|
20
|
-
class RippleDownRules(ABC):
|
20
|
+
class RippleDownRules(SubclassJSONSerializer, ABC):
|
21
21
|
"""
|
22
22
|
The abstract base class for the ripple down rules classifiers.
|
23
23
|
"""
|
@@ -175,10 +175,7 @@ class RippleDownRules(ABC):
|
|
175
175
|
return conclusion_type in case
|
176
176
|
|
177
177
|
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
class RDRWithCodeWriter(RDR, ABC):
|
178
|
+
class RDRWithCodeWriter(RippleDownRules, ABC):
|
182
179
|
|
183
180
|
@abstractmethod
|
184
181
|
def write_rules_as_source_code_to_file(self, rule: Rule, file, parent_indent: str = ""):
|
@@ -199,7 +196,7 @@ class RDRWithCodeWriter(RDR, ABC):
|
|
199
196
|
"""
|
200
197
|
func_def = f"def classify(case: {self.case_type.__name__}) -> {self._get_conclusion_type_hint()}:\n"
|
201
198
|
with open(file_path + f"/{self.generated_python_file_name}.py", "w") as f:
|
202
|
-
f.write(self._get_imports())
|
199
|
+
f.write(self._get_imports() + "\n\n")
|
203
200
|
f.write(func_def)
|
204
201
|
f.write(f"{' '*4}if not isinstance(case, Case):\n"
|
205
202
|
f"{' '*4} case = create_case(case, recursion_idx=3)\n""")
|
@@ -222,7 +219,6 @@ class RDRWithCodeWriter(RDR, ABC):
|
|
222
219
|
if self.conclusion_type.__module__ != "builtins":
|
223
220
|
imports += f"from {self.conclusion_type.__module__} import {self.conclusion_type.__name__}\n"
|
224
221
|
imports += "from ripple_down_rules.datastructures import Case, create_case\n"
|
225
|
-
imports += "\n\n"
|
226
222
|
return imports
|
227
223
|
|
228
224
|
def get_rdr_classifier_from_python_file(self, package_name) -> Callable[[Any], Any]:
|
@@ -261,7 +257,7 @@ class RDRWithCodeWriter(RDR, ABC):
|
|
261
257
|
return type(self.start_rule.conclusion)
|
262
258
|
|
263
259
|
|
264
|
-
class SingleClassRDR(RDRWithCodeWriter
|
260
|
+
class SingleClassRDR(RDRWithCodeWriter):
|
265
261
|
|
266
262
|
def fit_case(self, case_query: CaseQuery, expert: Optional[Expert] = None, **kwargs) \
|
267
263
|
-> Union[CaseAttribute, CallableExpression]:
|
@@ -354,17 +350,15 @@ class MultiClassRDR(RDRWithCodeWriter):
|
|
354
350
|
The conditions of the stopping rule if needed.
|
355
351
|
"""
|
356
352
|
|
357
|
-
def __init__(self,
|
353
|
+
def __init__(self, start_rule: Optional[Rule] = None,
|
358
354
|
mode: MCRDRMode = MCRDRMode.StopOnly, session: Optional[Session] = None):
|
359
355
|
"""
|
360
|
-
:param
|
361
|
-
and are always checked, in contrast to the refinement and alternative rules which are only checked if the
|
362
|
-
starting rules fire or not.
|
356
|
+
:param start_rule: The starting rules for the classifier.
|
363
357
|
:param mode: The mode of the classifier, either StopOnly or StopPlusRule, or StopPlusRuleCombined.
|
364
358
|
:param session: The sqlalchemy orm session.
|
365
359
|
"""
|
366
|
-
|
367
|
-
super(MultiClassRDR, self).__init__(
|
360
|
+
start_rule = MultiClassTopRule() if not start_rule else start_rule
|
361
|
+
super(MultiClassRDR, self).__init__(start_rule, session=session)
|
368
362
|
self.mode: MCRDRMode = mode
|
369
363
|
|
370
364
|
def classify(self, case: Union[Case, SQLTable]) -> List[Any]:
|
@@ -452,8 +446,8 @@ class MultiClassRDR(RDRWithCodeWriter):
|
|
452
446
|
return f"Set[{self.conclusion_type.__name__}]"
|
453
447
|
|
454
448
|
def _get_imports(self) -> str:
|
455
|
-
imports = super()._get_imports()
|
456
|
-
imports += "
|
449
|
+
imports = super()._get_imports()
|
450
|
+
imports += "from typing_extensions import Set\n"
|
457
451
|
return imports
|
458
452
|
|
459
453
|
def update_start_rule(self, case: Union[Case, SQLTable], target: Any, expert: Expert):
|
@@ -615,6 +609,17 @@ class MultiClassRDR(RDRWithCodeWriter):
|
|
615
609
|
"""
|
616
610
|
self.start_rule.alternative = MultiClassTopRule(conditions, conclusion, corner_case=corner_case)
|
617
611
|
|
612
|
+
def _to_json(self) -> Dict[str, Any]:
|
613
|
+
return {"start_rule": self.start_rule.to_json()}
|
614
|
+
|
615
|
+
@classmethod
|
616
|
+
def _from_json(cls, data: Dict[str, Any]) -> Self:
|
617
|
+
"""
|
618
|
+
Create an instance of the class from a json
|
619
|
+
"""
|
620
|
+
start_rule = SingleClassRule.from_json(data["start_rule"])
|
621
|
+
return cls(start_rule)
|
622
|
+
|
618
623
|
|
619
624
|
class GeneralRDR(RippleDownRules):
|
620
625
|
"""
|
@@ -265,14 +265,17 @@ class MultiClassStopRule(Rule, HasAlternativeRule):
|
|
265
265
|
|
266
266
|
def _to_json(self) -> Dict[str, Any]:
|
267
267
|
self.json_serialization = {**Rule._to_json(self),
|
268
|
-
"top_rule": self.top_rule.to_json(),
|
269
268
|
"alternative": self.alternative.to_json() if self.alternative is not None else None}
|
270
269
|
return self.json_serialization
|
271
270
|
|
272
271
|
@classmethod
|
273
272
|
def _from_json(cls, data: Dict[str, Any]) -> MultiClassStopRule:
|
274
|
-
loaded_rule =
|
275
|
-
|
273
|
+
loaded_rule = super(MultiClassStopRule, cls)._from_json(data)
|
274
|
+
# The following is done to prevent re-initialization of the top rule,
|
275
|
+
# so the top rule that is already initialized is passed in the data instead of its json serialization.
|
276
|
+
loaded_rule.top_rule = data['top_rule']
|
277
|
+
if data['alternative'] is not None:
|
278
|
+
data['alternative']['top_rule'] = data['top_rule']
|
276
279
|
loaded_rule.alternative = MultiClassStopRule.from_json(data["alternative"])
|
277
280
|
return loaded_rule
|
278
281
|
|
@@ -312,7 +315,11 @@ class MultiClassTopRule(Rule, HasRefinementRule, HasAlternativeRule):
|
|
312
315
|
|
313
316
|
@classmethod
|
314
317
|
def _from_json(cls, data: Dict[str, Any]) -> MultiClassTopRule:
|
315
|
-
loaded_rule =
|
318
|
+
loaded_rule = super(MultiClassTopRule, cls)._from_json(data)
|
319
|
+
# The following is done to prevent re-initialization of the top rule,
|
320
|
+
# so the top rule that is already initialized is passed in the data instead of its json serialization.
|
321
|
+
if data['refinement'] is not None:
|
322
|
+
data['refinement']['top_rule'] = loaded_rule
|
316
323
|
loaded_rule.refinement = MultiClassStopRule.from_json(data["refinement"])
|
317
324
|
loaded_rule.alternative = MultiClassTopRule.from_json(data["alternative"])
|
318
325
|
return loaded_rule
|
{ripple_down_rules-0.0.11 → ripple_down_rules-0.0.13}/src/ripple_down_rules.egg-info/PKG-INFO
RENAMED
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: ripple_down_rules
|
3
|
-
Version: 0.0.
|
3
|
+
Version: 0.0.13
|
4
4
|
Summary: Implements the various versions of Ripple Down Rules (RDR) for knowledge representation and reasoning.
|
5
5
|
Author-email: Abdelrhman Bassiouny <abassiou@uni-bremen.de>
|
6
6
|
License: GNU GENERAL PUBLIC LICENSE
|
@@ -6,7 +6,9 @@ from typing_extensions import List
|
|
6
6
|
from ripple_down_rules.datasets import load_zoo_dataset
|
7
7
|
from ripple_down_rules.datastructures import CaseQuery, Case
|
8
8
|
from ripple_down_rules.experts import Human
|
9
|
-
from ripple_down_rules.rdr import SingleClassRDR
|
9
|
+
from ripple_down_rules.rdr import SingleClassRDR, MultiClassRDR
|
10
|
+
from ripple_down_rules.utils import make_set
|
11
|
+
from test_helpers.helpers import get_fit_mcrdr, get_fit_scrdr
|
10
12
|
|
11
13
|
|
12
14
|
class TestJSONSerialization(TestCase):
|
@@ -20,7 +22,7 @@ class TestJSONSerialization(TestCase):
|
|
20
22
|
cls.all_cases, cls.targets = load_zoo_dataset(cls.cache_dir + "/zoo_dataset.pkl")
|
21
23
|
|
22
24
|
def test_scrdr_json_serialization(self):
|
23
|
-
scrdr = self.
|
25
|
+
scrdr = get_fit_scrdr(self.all_cases, self.targets)
|
24
26
|
filename = f"{self.cache_dir}/scrdr.json"
|
25
27
|
scrdr.save(filename)
|
26
28
|
scrdr = SingleClassRDR.load(filename)
|
@@ -28,16 +30,11 @@ class TestJSONSerialization(TestCase):
|
|
28
30
|
cat = scrdr.classify(case)
|
29
31
|
self.assertEqual(cat, target)
|
30
32
|
|
31
|
-
def
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
scrdr = SingleClassRDR()
|
37
|
-
case_queries = [CaseQuery(case, target=target) for case, target in zip(self.all_cases, self.targets)]
|
38
|
-
scrdr.fit(case_queries, expert=expert,
|
39
|
-
animate_tree=draw_tree)
|
33
|
+
def test_mcrdr_json_serialization(self):
|
34
|
+
mcrdr = get_fit_mcrdr(self.all_cases, self.targets)
|
35
|
+
filename = f"{self.cache_dir}/mcrdr.json"
|
36
|
+
mcrdr.save(filename)
|
37
|
+
mcrdr = MultiClassRDR.load(filename)
|
40
38
|
for case, target in zip(self.all_cases, self.targets):
|
41
|
-
cat =
|
42
|
-
self.assertEqual(cat, target)
|
43
|
-
return scrdr
|
39
|
+
cat = mcrdr.classify(case)
|
40
|
+
self.assertEqual(make_set(cat), make_set(target))
|
@@ -11,6 +11,7 @@ from ripple_down_rules.datastructures import Case, MCRDRMode, \
|
|
11
11
|
from ripple_down_rules.experts import Human
|
12
12
|
from ripple_down_rules.rdr import SingleClassRDR, MultiClassRDR, GeneralRDR
|
13
13
|
from ripple_down_rules.utils import render_tree, get_all_subclasses, make_set
|
14
|
+
from test_helpers.helpers import get_fit_scrdr, get_fit_mcrdr
|
14
15
|
|
15
16
|
|
16
17
|
class TestRDR(TestCase):
|
@@ -71,7 +72,7 @@ class TestRDR(TestCase):
|
|
71
72
|
expert.save_answers(file)
|
72
73
|
|
73
74
|
def test_write_scrdr_to_python_file(self):
|
74
|
-
scrdr = self.
|
75
|
+
scrdr = get_fit_scrdr(self.all_cases,self.targets)
|
75
76
|
scrdr.write_to_python_file(self.generated_rdrs_dir)
|
76
77
|
classify_species_scrdr = scrdr.get_rdr_classifier_from_python_file(self.generated_rdrs_dir)
|
77
78
|
for case, target in zip(self.all_cases, self.targets):
|
@@ -79,13 +80,12 @@ class TestRDR(TestCase):
|
|
79
80
|
self.assertEqual(cat, target)
|
80
81
|
|
81
82
|
def test_write_mcrdr_to_python_file(self):
|
82
|
-
mcrdr = self.
|
83
|
+
mcrdr = get_fit_mcrdr(self.all_cases, self.targets)
|
83
84
|
mcrdr.write_to_python_file(self.generated_rdrs_dir)
|
84
85
|
classify_species_mcrdr = mcrdr.get_rdr_classifier_from_python_file(self.generated_rdrs_dir)
|
85
|
-
for case in self.all_cases:
|
86
|
-
|
87
|
-
|
88
|
-
self.assertEqual(make_set(cat_1), make_set(cat_2))
|
86
|
+
for case, target in zip(self.all_cases, self.targets):
|
87
|
+
cat = classify_species_mcrdr(case)
|
88
|
+
self.assertEqual(make_set(cat), make_set(target))
|
89
89
|
|
90
90
|
def test_classify_mcrdr(self):
|
91
91
|
use_loaded_answers = True
|
@@ -115,7 +115,7 @@ class TestRDR(TestCase):
|
|
115
115
|
expert.load_answers(filename)
|
116
116
|
mcrdr = MultiClassRDR()
|
117
117
|
case_queries = [CaseQuery(case, target=target) for case, target in zip(self.all_cases, self.targets)]
|
118
|
-
mcrdr.fit(case_queries, expert=expert, animate_tree=draw_tree
|
118
|
+
mcrdr.fit(case_queries, expert=expert, animate_tree=draw_tree)
|
119
119
|
render_tree(mcrdr.start_rule, use_dot_exporter=True,
|
120
120
|
filename=self.test_results_dir + f"/mcrdr_stop_only")
|
121
121
|
cats = mcrdr.classify(self.all_cases[50])
|
@@ -259,7 +259,7 @@ class TestRDR(TestCase):
|
|
259
259
|
if use_loaded_answers:
|
260
260
|
expert.load_answers(filename)
|
261
261
|
|
262
|
-
fit_scrdr = self.
|
262
|
+
fit_scrdr = get_fit_scrdr(self.all_cases, self.targets, draw_tree=False)
|
263
263
|
|
264
264
|
grdr = GeneralRDR({type(fit_scrdr.start_rule.conclusion): fit_scrdr})
|
265
265
|
|
@@ -310,7 +310,7 @@ class TestRDR(TestCase):
|
|
310
310
|
if use_loaded_answers:
|
311
311
|
expert.load_answers(filename)
|
312
312
|
|
313
|
-
fit_scrdr = self.
|
313
|
+
fit_scrdr = get_fit_scrdr(self.all_cases, self.targets, draw_tree=False)
|
314
314
|
|
315
315
|
grdr = GeneralRDR({type(fit_scrdr.start_rule.conclusion): fit_scrdr})
|
316
316
|
|
@@ -327,23 +327,3 @@ class TestRDR(TestCase):
|
|
327
327
|
cwd = os.getcwd()
|
328
328
|
file = os.path.join(cwd, filename)
|
329
329
|
expert.save_answers(file)
|
330
|
-
|
331
|
-
def get_fit_scrdr(self, draw_tree=False) -> SingleClassRDR:
|
332
|
-
filename = self.expert_answers_dir + "/scrdr_expert_answers_fit"
|
333
|
-
expert = Human(use_loaded_answers=True)
|
334
|
-
expert.load_answers(filename)
|
335
|
-
|
336
|
-
scrdr = SingleClassRDR()
|
337
|
-
case_queries = [CaseQuery(case, target=target) for case, target in zip(self.all_cases, self.targets)]
|
338
|
-
scrdr.fit(case_queries, expert=expert,
|
339
|
-
animate_tree=draw_tree)
|
340
|
-
return scrdr
|
341
|
-
|
342
|
-
def get_fit_mcrdr(self, draw_tree: bool = False):
|
343
|
-
filename = self.expert_answers_dir + "/mcrdr_expert_answers_stop_only_fit"
|
344
|
-
expert = Human(use_loaded_answers=True)
|
345
|
-
expert.load_answers(filename)
|
346
|
-
mcrdr = MultiClassRDR()
|
347
|
-
case_queries = [CaseQuery(case, target=target) for case, target in zip(self.all_cases, self.targets)]
|
348
|
-
mcrdr.fit(case_queries, expert=expert, animate_tree=draw_tree, n_iter=1)
|
349
|
-
return mcrdr
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{ripple_down_rules-0.0.11 → ripple_down_rules-0.0.13}/src/ripple_down_rules/datastructures/case.py
RENAMED
File without changes
|
File without changes
|
{ripple_down_rules-0.0.11 → ripple_down_rules-0.0.13}/src/ripple_down_rules/datastructures/enums.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{ripple_down_rules-0.0.11 → ripple_down_rules-0.0.13}/src/ripple_down_rules.egg-info/SOURCES.txt
RENAMED
File without changes
|
File without changes
|
{ripple_down_rules-0.0.11 → ripple_down_rules-0.0.13}/src/ripple_down_rules.egg-info/top_level.txt
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|