ripple-down-rules 0.4.2__tar.gz → 0.4.3__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.
Files changed (39) hide show
  1. {ripple_down_rules-0.4.2 → ripple_down_rules-0.4.3}/PKG-INFO +14 -2
  2. {ripple_down_rules-0.4.2 → ripple_down_rules-0.4.3}/README.md +14 -2
  3. {ripple_down_rules-0.4.2 → ripple_down_rules-0.4.3}/pyproject.toml +1 -1
  4. {ripple_down_rules-0.4.2 → ripple_down_rules-0.4.3}/src/ripple_down_rules/rdr.py +19 -4
  5. {ripple_down_rules-0.4.2 → ripple_down_rules-0.4.3}/src/ripple_down_rules/user_interface/gui.py +55 -16
  6. {ripple_down_rules-0.4.2 → ripple_down_rules-0.4.3}/src/ripple_down_rules.egg-info/PKG-INFO +14 -2
  7. {ripple_down_rules-0.4.2 → ripple_down_rules-0.4.3}/LICENSE +0 -0
  8. {ripple_down_rules-0.4.2 → ripple_down_rules-0.4.3}/setup.cfg +0 -0
  9. {ripple_down_rules-0.4.2 → ripple_down_rules-0.4.3}/src/ripple_down_rules/__init__.py +0 -0
  10. {ripple_down_rules-0.4.2 → ripple_down_rules-0.4.3}/src/ripple_down_rules/datasets.py +0 -0
  11. {ripple_down_rules-0.4.2 → ripple_down_rules-0.4.3}/src/ripple_down_rules/datastructures/__init__.py +0 -0
  12. {ripple_down_rules-0.4.2 → ripple_down_rules-0.4.3}/src/ripple_down_rules/datastructures/callable_expression.py +0 -0
  13. {ripple_down_rules-0.4.2 → ripple_down_rules-0.4.3}/src/ripple_down_rules/datastructures/case.py +0 -0
  14. {ripple_down_rules-0.4.2 → ripple_down_rules-0.4.3}/src/ripple_down_rules/datastructures/dataclasses.py +0 -0
  15. {ripple_down_rules-0.4.2 → ripple_down_rules-0.4.3}/src/ripple_down_rules/datastructures/enums.py +0 -0
  16. {ripple_down_rules-0.4.2 → ripple_down_rules-0.4.3}/src/ripple_down_rules/experts.py +0 -0
  17. {ripple_down_rules-0.4.2 → ripple_down_rules-0.4.3}/src/ripple_down_rules/failures.py +0 -0
  18. {ripple_down_rules-0.4.2 → ripple_down_rules-0.4.3}/src/ripple_down_rules/helpers.py +0 -0
  19. {ripple_down_rules-0.4.2 → ripple_down_rules-0.4.3}/src/ripple_down_rules/rdr_decorators.py +0 -0
  20. {ripple_down_rules-0.4.2 → ripple_down_rules-0.4.3}/src/ripple_down_rules/rules.py +0 -0
  21. {ripple_down_rules-0.4.2 → ripple_down_rules-0.4.3}/src/ripple_down_rules/user_interface/__init__.py +0 -0
  22. {ripple_down_rules-0.4.2 → ripple_down_rules-0.4.3}/src/ripple_down_rules/user_interface/ipython_custom_shell.py +0 -0
  23. {ripple_down_rules-0.4.2 → ripple_down_rules-0.4.3}/src/ripple_down_rules/user_interface/object_diagram.py +0 -0
  24. {ripple_down_rules-0.4.2 → ripple_down_rules-0.4.3}/src/ripple_down_rules/user_interface/prompt.py +0 -0
  25. {ripple_down_rules-0.4.2 → ripple_down_rules-0.4.3}/src/ripple_down_rules/user_interface/template_file_creator.py +0 -0
  26. {ripple_down_rules-0.4.2 → ripple_down_rules-0.4.3}/src/ripple_down_rules/utils.py +0 -0
  27. {ripple_down_rules-0.4.2 → ripple_down_rules-0.4.3}/src/ripple_down_rules.egg-info/SOURCES.txt +0 -0
  28. {ripple_down_rules-0.4.2 → ripple_down_rules-0.4.3}/src/ripple_down_rules.egg-info/dependency_links.txt +0 -0
  29. {ripple_down_rules-0.4.2 → ripple_down_rules-0.4.3}/src/ripple_down_rules.egg-info/top_level.txt +0 -0
  30. {ripple_down_rules-0.4.2 → ripple_down_rules-0.4.3}/test/test_json_serialization.py +0 -0
  31. {ripple_down_rules-0.4.2 → ripple_down_rules-0.4.3}/test/test_object_diagram.py +0 -0
  32. {ripple_down_rules-0.4.2 → ripple_down_rules-0.4.3}/test/test_on_mutagenic.py +0 -0
  33. {ripple_down_rules-0.4.2 → ripple_down_rules-0.4.3}/test/test_rdr.py +0 -0
  34. {ripple_down_rules-0.4.2 → ripple_down_rules-0.4.3}/test/test_rdr_alchemy.py +0 -0
  35. {ripple_down_rules-0.4.2 → ripple_down_rules-0.4.3}/test/test_rdr_decorators.py +0 -0
  36. {ripple_down_rules-0.4.2 → ripple_down_rules-0.4.3}/test/test_rdr_world.py +0 -0
  37. {ripple_down_rules-0.4.2 → ripple_down_rules-0.4.3}/test/test_relational_rdr.py +0 -0
  38. {ripple_down_rules-0.4.2 → ripple_down_rules-0.4.3}/test/test_relational_rdr_alchemy.py +0 -0
  39. {ripple_down_rules-0.4.2 → ripple_down_rules-0.4.3}/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.4.2
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
- ```Python
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
+ ```
@@ -27,8 +27,9 @@ sudo apt-get install libxcb-cursor-dev
27
27
 
28
28
  Fit the SCRDR to the data, then classify one of the data cases to check if its correct,
29
29
  and render the tree to a file:
30
+ ```
30
31
 
31
- ```Python
32
+ ```python
32
33
  from ripple_down_rules.datastructures.dataclasses import CaseQuery
33
34
  from ripple_down_rules.rdr import SingleClassRDR
34
35
  from ripple_down_rules.datasets import load_zoo_dataset
@@ -48,4 +49,15 @@ render_tree(scrdr.start_rule, use_dot_exporter=True, filename="scrdr")
48
49
 
49
50
  cat = scrdr.classify(all_cases[50])
50
51
  assert cat == targets[50]
51
- ```
52
+ ```
53
+
54
+ ## To Cite:
55
+
56
+ ```bib
57
+ @software{bassiouny2025rdr,
58
+ author = {Bassiouny, Abdelrhman},
59
+ title = {Ripple-Down-Rules},
60
+ url = {https://github.com/AbdelrhmanBassiouny/ripple_down_rules},
61
+ version = {0.4.1},
62
+ }
63
+ ```
@@ -6,7 +6,7 @@ build-backend = "setuptools.build_meta"
6
6
 
7
7
  [project]
8
8
  name = "ripple_down_rules"
9
- version = "0.4.2"
9
+ version = "0.4.3"
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" }]
@@ -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
- def __init__(self, parent=None):
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 = QHBoxLayout(button_widget)
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
- button_widget_layout.addWidget(accept_btn)
437
- button_widget_layout.addWidget(edit_btn)
438
- button_widget_layout.addWidget(load_btn)
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
- # self._control.setStyleSheet("""
599
- # background-color: #615f5f;
600
- # color: #3ba8e7;
601
- # selection-background-color: #006400;
602
- # selection-color: white;
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
- # self.syntax_style = 'monokai'
607
- self.set_default_style(colors='linux')
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.2
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
- ```Python
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
+ ```