ripple-down-rules 0.4.2__py3-none-any.whl → 0.4.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.
- ripple_down_rules/rdr.py +19 -4
- ripple_down_rules/user_interface/gui.py +55 -16
- {ripple_down_rules-0.4.2.dist-info → ripple_down_rules-0.4.3.dist-info}/METADATA +14 -2
- {ripple_down_rules-0.4.2.dist-info → ripple_down_rules-0.4.3.dist-info}/RECORD +7 -7
- {ripple_down_rules-0.4.2.dist-info → ripple_down_rules-0.4.3.dist-info}/WHEEL +1 -1
- {ripple_down_rules-0.4.2.dist-info → ripple_down_rules-0.4.3.dist-info}/licenses/LICENSE +0 -0
- {ripple_down_rules-0.4.2.dist-info → ripple_down_rules-0.4.3.dist-info}/top_level.txt +0 -0
ripple_down_rules/rdr.py
CHANGED
@@ -16,9 +16,10 @@ from .datastructures.callable_expression import CallableExpression
|
|
16
16
|
from .datastructures.case import Case, CaseAttribute, create_case
|
17
17
|
from .datastructures.dataclasses import CaseQuery
|
18
18
|
from .datastructures.enums import MCRDRMode
|
19
|
-
from .experts import Expert
|
19
|
+
from .experts import Expert, Human
|
20
20
|
from .helpers import is_matching
|
21
21
|
from .rules import Rule, SingleClassRule, MultiClassTopRule, MultiClassStopRule
|
22
|
+
from .user_interface.gui import RDRCaseViewer
|
22
23
|
from .utils import draw_tree, make_set, copy_case, \
|
23
24
|
SubclassJSONSerializer, make_list, get_type_from_string, \
|
24
25
|
is_conflicting, update_case, get_imports_from_scope, extract_function_source
|
@@ -41,12 +42,25 @@ class RippleDownRules(SubclassJSONSerializer, ABC):
|
|
41
42
|
The name of the generated python file.
|
42
43
|
"""
|
43
44
|
|
44
|
-
def __init__(self, start_rule: Optional[Rule] = None):
|
45
|
+
def __init__(self, start_rule: Optional[Rule] = None, viewer: Optional[RDRCaseViewer] = None):
|
45
46
|
"""
|
46
47
|
:param start_rule: The starting rule for the classifier.
|
47
48
|
"""
|
48
49
|
self.start_rule = start_rule
|
49
50
|
self.fig: Optional[plt.Figure] = None
|
51
|
+
self.viewer: Optional[RDRCaseViewer] = viewer
|
52
|
+
if self.viewer is not None:
|
53
|
+
self.viewer.set_save_function(self.save)
|
54
|
+
|
55
|
+
def set_viewer(self, viewer: RDRCaseViewer):
|
56
|
+
"""
|
57
|
+
Set the viewer for the classifier.
|
58
|
+
|
59
|
+
:param viewer: The viewer to set.
|
60
|
+
"""
|
61
|
+
self.viewer = viewer
|
62
|
+
if self.viewer is not None:
|
63
|
+
self.viewer.set_save_function(self.save)
|
50
64
|
|
51
65
|
def fit(self, case_queries: List[CaseQuery],
|
52
66
|
expert: Optional[Expert] = None,
|
@@ -703,7 +717,8 @@ class GeneralRDR(RippleDownRules):
|
|
703
717
|
gets called when the final rule fires.
|
704
718
|
"""
|
705
719
|
|
706
|
-
def __init__(self, category_rdr_map: Optional[Dict[str, Union[SingleClassRDR, MultiClassRDR]]] = None
|
720
|
+
def __init__(self, category_rdr_map: Optional[Dict[str, Union[SingleClassRDR, MultiClassRDR]]] = None,
|
721
|
+
**kwargs):
|
707
722
|
"""
|
708
723
|
:param category_rdr_map: A map of case attribute names to ripple down rules classifiers,
|
709
724
|
where each category is a parent category that has a set of mutually exclusive (in case of SCRDR) child
|
@@ -715,7 +730,7 @@ class GeneralRDR(RippleDownRules):
|
|
715
730
|
"""
|
716
731
|
self.start_rules_dict: Dict[str, Union[SingleClassRDR, MultiClassRDR]] \
|
717
732
|
= category_rdr_map if category_rdr_map else {}
|
718
|
-
super(GeneralRDR, self).__init__()
|
733
|
+
super(GeneralRDR, self).__init__(**kwargs)
|
719
734
|
self.all_figs: List[plt.Figure] = [sr.fig for sr in self.start_rules_dict.values()]
|
720
735
|
|
721
736
|
def add_rdr(self, rdr: Union[SingleClassRDR, MultiClassRDR], attribute_name: Optional[str] = None):
|
@@ -12,7 +12,7 @@ from PyQt6.QtWidgets import (
|
|
12
12
|
)
|
13
13
|
from qtconsole.inprocess import QtInProcessKernelManager
|
14
14
|
from qtconsole.rich_jupyter_widget import RichJupyterWidget
|
15
|
-
from typing_extensions import Optional, Any, List, Dict
|
15
|
+
from typing_extensions import Optional, Any, List, Dict, Callable
|
16
16
|
|
17
17
|
from ..datastructures.dataclasses import CaseQuery
|
18
18
|
from ..datastructures.enums import PromptFor
|
@@ -275,9 +275,13 @@ class RDRCaseViewer(QMainWindow):
|
|
275
275
|
main_obj: Optional[Dict[str, Any]] = None
|
276
276
|
user_input: Optional[str] = None
|
277
277
|
attributes_widget: Optional[QWidget] = None
|
278
|
+
save_function: Optional[Callable[str], None] = None
|
278
279
|
|
279
|
-
|
280
|
+
|
281
|
+
def __init__(self, parent=None, save_file: Optional[str] = None):
|
280
282
|
super().__init__(parent)
|
283
|
+
self.save_file = save_file
|
284
|
+
|
281
285
|
self.setWindowTitle("RDR Case Viewer")
|
282
286
|
|
283
287
|
self.setBaseSize(1600, 600) # or your preferred initial size
|
@@ -316,6 +320,15 @@ class RDRCaseViewer(QMainWindow):
|
|
316
320
|
main_layout.addWidget(middle_widget, stretch=2)
|
317
321
|
main_layout.addWidget(self.obj_diagram_viewer, stretch=2)
|
318
322
|
|
323
|
+
def set_save_function(self, save_function: Callable[[str], None]) -> None:
|
324
|
+
"""
|
325
|
+
Set the function to save the file.
|
326
|
+
|
327
|
+
:param save_function: The function to save the file.
|
328
|
+
"""
|
329
|
+
self.save_function = save_function
|
330
|
+
self.save_btn.clicked.connect(lambda: self.save_function(self.save_file))
|
331
|
+
|
319
332
|
def print(self, msg):
|
320
333
|
"""
|
321
334
|
Print a message to the console.
|
@@ -406,9 +419,9 @@ class RDRCaseViewer(QMainWindow):
|
|
406
419
|
self.expand_collapse_all(item.widget(), expand=False)
|
407
420
|
|
408
421
|
def expand_collapse_all(self, widget, expand=True, curr_depth=0, max_depth=2):
|
409
|
-
widget.toggle_button.setChecked(expand)
|
410
|
-
widget.toggle()
|
411
422
|
if expand and curr_depth < max_depth:
|
423
|
+
widget.toggle_button.setChecked(expand)
|
424
|
+
widget.toggle()
|
412
425
|
# do it for recursive children
|
413
426
|
for i in range(widget.content_layout.count()):
|
414
427
|
item = widget.content_layout.itemAt(i)
|
@@ -419,7 +432,14 @@ class RDRCaseViewer(QMainWindow):
|
|
419
432
|
|
420
433
|
def create_buttons_widget(self):
|
421
434
|
button_widget = QWidget()
|
422
|
-
button_widget_layout =
|
435
|
+
button_widget_layout = QVBoxLayout(button_widget)
|
436
|
+
|
437
|
+
row_1_button_widget = QWidget()
|
438
|
+
row_1_button_widget_layout = QHBoxLayout(row_1_button_widget)
|
439
|
+
row_2_button_widget = QWidget()
|
440
|
+
row_2_button_widget_layout = QHBoxLayout(row_2_button_widget)
|
441
|
+
button_widget_layout.addWidget(row_1_button_widget)
|
442
|
+
button_widget_layout.addWidget(row_2_button_widget)
|
423
443
|
|
424
444
|
accept_btn = QPushButton("Accept")
|
425
445
|
accept_btn.clicked.connect(self._accept)
|
@@ -433,9 +453,13 @@ class RDRCaseViewer(QMainWindow):
|
|
433
453
|
load_btn.clicked.connect(self._load)
|
434
454
|
load_btn.setStyleSheet(f"background-color: {color_name_to_html('b')}; color: white;") # Blue button
|
435
455
|
|
436
|
-
|
437
|
-
|
438
|
-
|
456
|
+
self.save_btn = QPushButton("Save")
|
457
|
+
self.save_btn.setStyleSheet(f"background-color: {color_name_to_html('b')}; color: white;") # Blue button
|
458
|
+
|
459
|
+
row_1_button_widget_layout.addWidget(edit_btn)
|
460
|
+
row_1_button_widget_layout.addWidget(load_btn)
|
461
|
+
row_1_button_widget_layout.addWidget(accept_btn)
|
462
|
+
row_2_button_widget_layout.addWidget(self.save_btn)
|
439
463
|
return button_widget
|
440
464
|
|
441
465
|
def _accept(self):
|
@@ -595,16 +619,31 @@ class IPythonConsole(RichJupyterWidget):
|
|
595
619
|
self._control.setPalette(palette)
|
596
620
|
|
597
621
|
# Override the stylesheet to force background and text colors
|
598
|
-
|
599
|
-
|
600
|
-
|
601
|
-
|
602
|
-
|
603
|
-
|
622
|
+
self.style_sheet = '''\
|
623
|
+
QPlainTextEdit, QTextEdit {
|
624
|
+
background-color: %(bgcolor)s;
|
625
|
+
background-clip: padding;
|
626
|
+
color: %(fgcolor)s;
|
627
|
+
selection-background-color: %(select)s;
|
628
|
+
}
|
629
|
+
.inverted {
|
630
|
+
background-color: %(fgcolor)s;
|
631
|
+
color: %(bgcolor)s;
|
632
|
+
}
|
633
|
+
.error { color: red; }
|
634
|
+
.in-prompt-number { font-weight: bold; color: %(in_prompt_number_color)s} }
|
635
|
+
.in-prompt { font-weight: bold; color: %(in_prompt_color)s }
|
636
|
+
.out-prompt-number { font-weight: bold; color: %(out_prompt_number_color)s }
|
637
|
+
.out-prompt { font-weight: bold; color: %(out_prompt_color)s }
|
638
|
+
'''%dict(
|
639
|
+
bgcolor='#0b0d0b', fgcolor='#47d9cc', select="#555",
|
640
|
+
in_prompt_number_color='lime', in_prompt_color='lime',
|
641
|
+
out_prompt_number_color='red', out_prompt_color='red'
|
642
|
+
)
|
604
643
|
|
605
644
|
# Use a dark syntax style like monokai
|
606
|
-
|
607
|
-
self.set_default_style(colors='
|
645
|
+
self.syntax_style = 'monokai'
|
646
|
+
# self.set_default_style(colors='lightbg')
|
608
647
|
|
609
648
|
self.exit_requested.connect(self.stop)
|
610
649
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: ripple_down_rules
|
3
|
-
Version: 0.4.
|
3
|
+
Version: 0.4.3
|
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
|
@@ -714,8 +714,9 @@ sudo apt-get install libxcb-cursor-dev
|
|
714
714
|
|
715
715
|
Fit the SCRDR to the data, then classify one of the data cases to check if its correct,
|
716
716
|
and render the tree to a file:
|
717
|
+
```
|
717
718
|
|
718
|
-
```
|
719
|
+
```python
|
719
720
|
from ripple_down_rules.datastructures.dataclasses import CaseQuery
|
720
721
|
from ripple_down_rules.rdr import SingleClassRDR
|
721
722
|
from ripple_down_rules.datasets import load_zoo_dataset
|
@@ -736,3 +737,14 @@ render_tree(scrdr.start_rule, use_dot_exporter=True, filename="scrdr")
|
|
736
737
|
cat = scrdr.classify(all_cases[50])
|
737
738
|
assert cat == targets[50]
|
738
739
|
```
|
740
|
+
|
741
|
+
## To Cite:
|
742
|
+
|
743
|
+
```bib
|
744
|
+
@software{bassiouny2025rdr,
|
745
|
+
author = {Bassiouny, Abdelrhman},
|
746
|
+
title = {Ripple-Down-Rules},
|
747
|
+
url = {https://github.com/AbdelrhmanBassiouny/ripple_down_rules},
|
748
|
+
version = {0.4.1},
|
749
|
+
}
|
750
|
+
```
|
@@ -3,7 +3,7 @@ ripple_down_rules/datasets.py,sha256=fJbZ7V-UUYTu5XVVpFinTbuzN3YePCnUB01L3AyZVM8
|
|
3
3
|
ripple_down_rules/experts.py,sha256=S-d1EZP0SK0Ab_pMzgkOcLvZFLMdSm8_C0u3AgfouUc,6468
|
4
4
|
ripple_down_rules/failures.py,sha256=E6ajDUsw3Blom8eVLbA7d_Qnov2conhtZ0UmpQ9ZtSE,302
|
5
5
|
ripple_down_rules/helpers.py,sha256=TvTJU0BA3dPcAyzvZFvAu7jZqsp8Lu0HAAwvuizlGjg,2018
|
6
|
-
ripple_down_rules/rdr.py,sha256=
|
6
|
+
ripple_down_rules/rdr.py,sha256=cO5QUtrKDaOk75GUnBwxzq-ZYzFbJhgycX6BKeLEVtM,44258
|
7
7
|
ripple_down_rules/rdr_decorators.py,sha256=VdmE0JrE8j89b6Af1R1tLZiKfy3h1VCvhAUefN_FLLQ,6753
|
8
8
|
ripple_down_rules/rules.py,sha256=QQy7NBG6mKiowxVG_LjQJBxLTDW2hMyx5zAgwUxdCMM,17183
|
9
9
|
ripple_down_rules/utils.py,sha256=kJEqmKuq3NxM8gY7MrXSps2Xvf1FsYFgTMo3PSYZJY8,49098
|
@@ -13,13 +13,13 @@ ripple_down_rules/datastructures/case.py,sha256=oC8OSdhXvHE-Zx1IIQlad-fsKzQQqr6M
|
|
13
13
|
ripple_down_rules/datastructures/dataclasses.py,sha256=GWnUF4h4zfNHSsyBIz3L9y8sLkrXRv0FK_OxzzLc8L8,8183
|
14
14
|
ripple_down_rules/datastructures/enums.py,sha256=ce7tqS0otfSTNAOwsnXlhsvIn4iW_Y_N3TNebF3YoZs,5700
|
15
15
|
ripple_down_rules/user_interface/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
16
|
-
ripple_down_rules/user_interface/gui.py,sha256=
|
16
|
+
ripple_down_rules/user_interface/gui.py,sha256=GlVUYGpMRikrd-FjYCAamdKFAuTAeiq21ZzQvjVKJ4g,27588
|
17
17
|
ripple_down_rules/user_interface/ipython_custom_shell.py,sha256=tc7ms80iPNElm9AYC6i1FlfMKkqHLT8wmOEXg_k9yAU,6275
|
18
18
|
ripple_down_rules/user_interface/object_diagram.py,sha256=84JlEH0nQmtGmP8Su5iRX3ZfqByYHbVwd0BQYYPuckY,4436
|
19
19
|
ripple_down_rules/user_interface/prompt.py,sha256=tQyIrRno1YuS3K0c4p48FVTdDJGG0HCE63WHVKpSJ1I,7976
|
20
20
|
ripple_down_rules/user_interface/template_file_creator.py,sha256=PegwW_g8UScjEF2GGe1eV0VoWUzxPhA27L9ExbL7Y_E,12610
|
21
|
-
ripple_down_rules-0.4.
|
22
|
-
ripple_down_rules-0.4.
|
23
|
-
ripple_down_rules-0.4.
|
24
|
-
ripple_down_rules-0.4.
|
25
|
-
ripple_down_rules-0.4.
|
21
|
+
ripple_down_rules-0.4.3.dist-info/licenses/LICENSE,sha256=ixuiBLtpoK3iv89l7ylKkg9rs2GzF9ukPH7ynZYzK5s,35148
|
22
|
+
ripple_down_rules-0.4.3.dist-info/METADATA,sha256=gT-m0t8DxQkY2a7qqne4CxS-6WnobM0LGBa4dBlMOwo,42875
|
23
|
+
ripple_down_rules-0.4.3.dist-info/WHEEL,sha256=zaaOINJESkSfm_4HQVc5ssNzHCPXhJm0kEUakpsEHaU,91
|
24
|
+
ripple_down_rules-0.4.3.dist-info/top_level.txt,sha256=VeoLhEhyK46M1OHwoPbCQLI1EifLjChqGzhQ6WEUqeM,18
|
25
|
+
ripple_down_rules-0.4.3.dist-info/RECORD,,
|
File without changes
|
File without changes
|