ripple-down-rules 0.5.58__tar.gz → 0.5.60__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 (139) hide show
  1. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/PKG-INFO +1 -1
  2. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/src/ripple_down_rules/__init__.py +1 -1
  3. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/src/ripple_down_rules/datastructures/callable_expression.py +2 -1
  4. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/src/ripple_down_rules/rdr.py +13 -6
  5. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/src/ripple_down_rules/rdr_decorators.py +6 -8
  6. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/src/ripple_down_rules/utils.py +21 -18
  7. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/src/ripple_down_rules.egg-info/PKG-INFO +1 -1
  8. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/test/test_helpers/helpers.py +9 -6
  9. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/test/test_rdr.py +12 -6
  10. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/test/test_rdr_world.py +1 -1
  11. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/test/test_results/datasets_physical_object_is_a_robot/rdr_metadata/datasets_physical_object_is_a_robot.json +4 -4
  12. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/test/test_results/datasets_physical_object_select_objects_that_are_parts_of_robot/physical_object_select_objects_that_are_parts_of_robot_output__mcrdr.py +1 -1
  13. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/test/test_results/datasets_physical_object_select_objects_that_are_parts_of_robot/rdr_metadata/datasets_physical_object_select_objects_that_are_parts_of_robot.json +6 -6
  14. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/.github/workflows/build_and_deploy_doc.yml +0 -0
  15. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/.github/workflows/ci.yml +0 -0
  16. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/.github/workflows/publish-to-test-pypi.yml +0 -0
  17. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/.idea/shelf/Uncommitted_changes_before_Checkout_at_2_4_25,_6_32_PM_[Changes]/shelved.patch +0 -0
  18. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/.idea/shelf/Uncommitted_changes_before_Checkout_at_2_4_25,_6_32_PM_[Changes]1/shelved.patch +0 -0
  19. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/LICENSE +0 -0
  20. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/README.md +0 -0
  21. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/doc/_config.yml +0 -0
  22. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/doc/_toc.yml +0 -0
  23. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/doc/bibliography.md +0 -0
  24. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/doc/intro.md +0 -0
  25. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/doc/references.bib +0 -0
  26. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/doc/requirements.txt +0 -0
  27. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/examples/__init__.py +0 -0
  28. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/examples/animal_species.py +0 -0
  29. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/examples/part_containment_rdr/__init__.py +0 -0
  30. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/examples/part_containment_rdr/rdr_metadata/part_containment_rdr.json +0 -0
  31. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/examples/part_containment_rdr/robot_contained_objects_mcrdr.py +0 -0
  32. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/examples/part_containment_rdr/robot_contained_objects_mcrdr_defs.py +0 -0
  33. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/examples/part_containment_rdr/robot_rdr.py +0 -0
  34. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/examples/relational_example.py +0 -0
  35. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/images/scrdr.dot +0 -0
  36. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/images/scrdr.png +0 -0
  37. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/images/thinking_pr2.jpg +0 -0
  38. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/pyproject.toml +0 -0
  39. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/pytest.ini +0 -0
  40. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/requirements-dev-ci.txt +0 -0
  41. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/requirements-dev.txt +0 -0
  42. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/requirements-gui.txt +0 -0
  43. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/requirements-viz.txt +0 -0
  44. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/requirements.txt +0 -0
  45. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/results/complete_mcrdr_extra.dot +0 -0
  46. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/results/complete_mcrdr_extra.png +0 -0
  47. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/results/complete_mcrdr_stop_only.dot +0 -0
  48. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/results/complete_mcrdr_stop_only.png +0 -0
  49. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/results/complete_mcrdr_stop_plus_rule.dot +0 -0
  50. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/results/complete_mcrdr_stop_plus_rule.png +0 -0
  51. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/results/complete_scrdr.dot +0 -0
  52. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/results/complete_scrdr.png +0 -0
  53. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/results/complete_scrdr_2.dot +0 -0
  54. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/results/complete_scrdr_2.png +0 -0
  55. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/results/complete_scrdr_3.dot +0 -0
  56. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/results/complete_scrdr_3.png +0 -0
  57. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/results/grdr_Habitat.dot +0 -0
  58. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/results/grdr_Habitat.png +0 -0
  59. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/results/grdr_Species.dot +0 -0
  60. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/results/grdr_Species.png +0 -0
  61. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/results/mcrdr_extra.dot +0 -0
  62. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/results/mcrdr_extra.png +0 -0
  63. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/results/mcrdr_extra_classify.dot +0 -0
  64. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/results/mcrdr_extra_classify.png +0 -0
  65. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/results/mcrdr_stop_plus_rule_combined.dot +0 -0
  66. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/results/mcrdr_stop_plus_rule_combined.png +0 -0
  67. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/results/partial_mcrdr_extra.dot +0 -0
  68. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/results/partial_mcrdr_extra.png +0 -0
  69. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/results/relational_scrdr_classify.dot +0 -0
  70. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/results/relational_scrdr_classify.png +0 -0
  71. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/setup.cfg +0 -0
  72. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/src/ripple_down_rules/datastructures/__init__.py +0 -0
  73. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/src/ripple_down_rules/datastructures/case.py +0 -0
  74. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/src/ripple_down_rules/datastructures/dataclasses.py +0 -0
  75. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/src/ripple_down_rules/datastructures/enums.py +0 -0
  76. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/src/ripple_down_rules/experts.py +0 -0
  77. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/src/ripple_down_rules/helpers.py +0 -0
  78. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/src/ripple_down_rules/rules.py +0 -0
  79. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/src/ripple_down_rules/start-code-server.sh +0 -0
  80. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/src/ripple_down_rules/user_interface/__init__.py +0 -0
  81. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/src/ripple_down_rules/user_interface/gui.py +0 -0
  82. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/src/ripple_down_rules/user_interface/ipython_custom_shell.py +0 -0
  83. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/src/ripple_down_rules/user_interface/object_diagram.py +0 -0
  84. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/src/ripple_down_rules/user_interface/prompt.py +0 -0
  85. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/src/ripple_down_rules/user_interface/template_file_creator.py +0 -0
  86. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/src/ripple_down_rules.egg-info/SOURCES.txt +0 -0
  87. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/src/ripple_down_rules.egg-info/dependency_links.txt +0 -0
  88. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/src/ripple_down_rules.egg-info/requires.txt +0 -0
  89. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/src/ripple_down_rules.egg-info/top_level.txt +0 -0
  90. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/test/datasets.py +0 -0
  91. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/test/test_expert_answers/correct_drawer_rdr_expert_answers_fit.json +0 -0
  92. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/test/test_expert_answers/grdr_expert_answers_classify.json +0 -0
  93. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/test/test_expert_answers/grdr_expert_answers_fit.json +0 -0
  94. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/test/test_expert_answers/grdr_expert_answers_fit_extra.json +0 -0
  95. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/test/test_expert_answers/grdr_expert_answers_fit_no_targets.json +0 -0
  96. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/test/test_expert_answers/mcrdr_expert_answers_classify.json +0 -0
  97. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/test/test_expert_answers/mcrdr_expert_answers_fit_no_targets.json +0 -0
  98. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/test/test_expert_answers/mcrdr_expert_answers_stop_only_fit.json +0 -0
  99. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/test/test_expert_answers/mcrdr_extra_expert_answers_classify.json +0 -0
  100. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/test/test_expert_answers/mcrdr_extra_expert_answers_fit.json +0 -0
  101. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/test/test_expert_answers/mcrdr_multi_line_expert_answers_fit.json +0 -0
  102. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/test/test_expert_answers/mcrdr_stop_only_answers_fit.json +0 -0
  103. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/test/test_expert_answers/mcrdr_stop_plus_rule_answers_fit.json +0 -0
  104. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/test/test_expert_answers/mcrdr_stop_plus_rule_combined_expert_answers_fit.json +0 -0
  105. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/test/test_expert_answers/mcrdr_stop_plus_rule_expert_answers_fit.json +0 -0
  106. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/test/test_expert_answers/mutagenic_expert_answers.json +0 -0
  107. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/test/test_expert_answers/relational_scrdr_expert_answers_classify.json +0 -0
  108. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/test/test_expert_answers/scrdr_expert_answers_classify.json +0 -0
  109. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/test/test_expert_answers/scrdr_expert_answers_fit.json +0 -0
  110. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/test/test_expert_answers/scrdr_expert_answers_fit_no_targets.json +0 -0
  111. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/test/test_expert_answers/scrdr_multi_line_expert_answers_fit.json +0 -0
  112. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/test/test_expert_answers/scrdr_world_expert_answers_fit.json +0 -0
  113. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/test/test_expert_answers/view_rdr_expert_answers_fit.json +0 -0
  114. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/test/test_generated_rdrs/__init__.py +0 -0
  115. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/test/test_helpers/__init__.py +0 -0
  116. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/test/test_helpers/object_diagram_case_query.png +0 -0
  117. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/test/test_helpers/object_diagram_person.png +0 -0
  118. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/test/test_json_serialization.py +0 -0
  119. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/test/test_object_diagram.py +0 -0
  120. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/test/test_on_mutagenic.py +0 -0
  121. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/test/test_rdr_alchemy.py +0 -0
  122. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/test/test_rdr_decorators.py +0 -0
  123. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/test/test_relational_rdr.py +0 -0
  124. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/test/test_relational_rdr_alchemy.py +0 -0
  125. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/test/test_results/datasets_physical_object_is_a_robot/__init__.py +0 -0
  126. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/test/test_results/datasets_physical_object_is_a_robot/physical_object_is_a_robot_output__scrdr.py +0 -0
  127. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/test/test_results/datasets_physical_object_is_a_robot/physical_object_is_a_robot_output__scrdr_defs.py +1 -1
  128. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/test/test_results/datasets_physical_object_is_a_robot/physical_object_is_a_robot_rdr.py +0 -0
  129. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/test/test_results/datasets_physical_object_select_objects_that_are_parts_of_robot/__init__.py +0 -0
  130. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/test/test_results/datasets_physical_object_select_objects_that_are_parts_of_robot/physical_object_select_objects_that_are_parts_of_robot_output__mcrdr_defs.py +2 -2
  131. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/test/test_results/datasets_physical_object_select_objects_that_are_parts_of_robot/physical_object_select_objects_that_are_parts_of_robot_rdr.py +0 -0
  132. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/test/test_sql_model.py +0 -0
  133. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/test/test_template_file_creator.py +0 -0
  134. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/test/test_user_interface/__init__.py +0 -0
  135. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/test/test_user_interface/test_ipython.py +0 -0
  136. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/test/test_user_interface/test_ipython_copilot.py +0 -0
  137. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/test/test_user_interface/test_prompt.py +0 -0
  138. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/test/test_user_interface/test_qt_gui_inline.py +0 -0
  139. {ripple_down_rules-0.5.58 → ripple_down_rules-0.5.60}/test/test_utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ripple_down_rules
3
- Version: 0.5.58
3
+ Version: 0.5.60
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
@@ -1,4 +1,4 @@
1
- __version__ = "0.5.58"
1
+ __version__ = "0.5.60"
2
2
 
3
3
  import logging
4
4
  logger = logging.Logger("rdr")
@@ -259,7 +259,8 @@ class CallableExpression(SubclassJSONSerializer):
259
259
  "conclusion_type": [get_full_class_name(t) for t in self.conclusion_type]
260
260
  if self.conclusion_type is not None else None,
261
261
  "scope": {k: get_full_class_name(v) for k, v in self.scope.items()
262
- if hasattr(v, '__module__') and hasattr(v, '__name__')},
262
+ if hasattr(v, '__module__') and hasattr(v, '__name__')
263
+ and v.__module__ is not None and v.__name__ is not None},
263
264
  "conclusion": conclusion_to_json(self.conclusion),
264
265
  "mutually_exclusive": self.mutually_exclusive,
265
266
  }
@@ -78,7 +78,7 @@ class RippleDownRules(SubclassJSONSerializer, ABC):
78
78
  """
79
79
 
80
80
  def __init__(self, start_rule: Optional[Rule] = None, viewer: Optional[RDRCaseViewer] = None,
81
- save_dir: Optional[str] = None, ask_always: bool = True, model_name: Optional[str] = None):
81
+ save_dir: Optional[str] = None, ask_always: bool = False, model_name: Optional[str] = None):
82
82
  """
83
83
  :param start_rule: The starting rule for the classifier.
84
84
  :param viewer: The viewer gui to use for the classifier. If None, no viewer is used.
@@ -241,12 +241,18 @@ class RippleDownRules(SubclassJSONSerializer, ABC):
241
241
  self.case_type = case_query.case_type if self.case_type is None else self.case_type
242
242
  self.case_name = case_query.case_name if self.case_name is None else self.case_name
243
243
 
244
- expert = expert or Human(answers_save_path=self.save_dir + '/expert_answers' if self.save_dir else None)
244
+ expert = expert or Human(viewer=self.viewer,
245
+ answers_save_path=self.save_dir + '/expert_answers'
246
+ if self.save_dir else None)
245
247
 
246
248
  if case_query.target is None:
247
249
  case_query_cp = copy(case_query)
248
250
  conclusions = self.classify(case_query_cp.case, modify_case=True)
249
- if self.ask_always or conclusions is None or is_iterable(conclusions) and len(conclusions) == 0:
251
+ if (self.ask_always or conclusions is None
252
+ or is_iterable(conclusions) and len(conclusions) == 0
253
+ or (isinstance(conclusions, dict) and (case_query_cp.attribute_name not in conclusions
254
+ or not any(type(c) in case_query_cp.core_attribute_type
255
+ for c in make_list(conclusions[case_query_cp.attribute_name]))))):
250
256
  expert.ask_for_conclusion(case_query_cp)
251
257
  case_query.target = case_query_cp.target
252
258
  if case_query.target is None:
@@ -493,7 +499,8 @@ class RDRWithCodeWriter(RippleDownRules, ABC):
493
499
  return self.start_rule.conclusion_name
494
500
 
495
501
  def _to_json(self) -> Dict[str, Any]:
496
- return {"start_rule": self.start_rule.to_json(), "generated_python_file_name": self.generated_python_file_name,
502
+ return {"start_rule": self.start_rule.to_json(),
503
+ "generated_python_file_name": self.generated_python_file_name,
497
504
  "name": self.name,
498
505
  "case_type": get_full_class_name(self.case_type) if self.case_type is not None else None,
499
506
  "case_name": self.case_name}
@@ -645,12 +652,12 @@ class MultiClassRDR(RDRWithCodeWriter):
645
652
  """
646
653
 
647
654
  def __init__(self, start_rule: Optional[MultiClassTopRule] = None,
648
- mode: MCRDRMode = MCRDRMode.StopOnly):
655
+ mode: MCRDRMode = MCRDRMode.StopOnly, **kwargs):
649
656
  """
650
657
  :param start_rule: The starting rules for the classifier.
651
658
  :param mode: The mode of the classifier, either StopOnly or StopPlusRule, or StopPlusRuleCombined.
652
659
  """
653
- super(MultiClassRDR, self).__init__(start_rule)
660
+ super(MultiClassRDR, self).__init__(start_rule, **kwargs)
654
661
  self.mode: MCRDRMode = mode
655
662
 
656
663
  def classify(self, case: Union[Case, SQLTable], modify_case: bool = False) -> Set[Any]:
@@ -24,7 +24,6 @@ class RDRDecorator:
24
24
  def __init__(self, models_dir: str,
25
25
  output_type: Tuple[Type],
26
26
  mutual_exclusive: bool,
27
- python_dir: Optional[str] = None,
28
27
  output_name: str = "output_",
29
28
  fit: bool = True,
30
29
  expert: Optional[Expert] = None):
@@ -32,7 +31,6 @@ class RDRDecorator:
32
31
  :param models_dir: The directory to save/load the RDR models.
33
32
  :param output_type: The type of the output. This is used to create the RDR model.
34
33
  :param mutual_exclusive: If True, the output types are mutually exclusive.
35
- :param python_dir: The directory to save the RDR model as a python file.
36
34
  If None, the RDR model will not be saved as a python file.
37
35
  :param output_name: The name of the output. This is used to create the RDR model.
38
36
  :param fit: If True, the function will be in fit mode. This means that the RDR will prompt the user for the
@@ -47,7 +45,6 @@ class RDRDecorator:
47
45
  self.output_type = output_type
48
46
  self.parsed_output_type: List[Type] = []
49
47
  self.mutual_exclusive = mutual_exclusive
50
- self.rdr_python_path: Optional[str] = python_dir
51
48
  self.output_name = output_name
52
49
  self.fit: bool = fit
53
50
  self.expert: Optional[Expert] = expert
@@ -64,8 +61,6 @@ class RDRDecorator:
64
61
  self.initialize_rdr_model_name_and_load(func)
65
62
 
66
63
  if self.fit:
67
- expert_answers_path = os.path.join(self.rdr_models_dir, self.model_name, "expert_answers")
68
- self.expert = self.expert or Human(answers_save_path=expert_answers_path)
69
64
  case_query = self.create_case_query_from_method(func, self.parsed_output_type,
70
65
  self.mutual_exclusive, self.output_name,
71
66
  *args, **kwargs)
@@ -148,9 +143,12 @@ class RDRDecorator:
148
143
  """
149
144
  Load the RDR model from the specified directory.
150
145
  """
151
- if self.model_name is not None and os.path.exists(os.path.join(self.rdr_models_dir, self.model_name)):
152
- self.rdr = GeneralRDR.load(self.rdr_models_dir, self.model_name)
153
- else:
146
+ self.rdr = None
147
+ if self.model_name is not None:
148
+ model_path = os.path.join(self.rdr_models_dir, self.model_name + f"/rdr_metadata/{self.model_name}.json")
149
+ if os.path.exists(os.path.join(self.rdr_models_dir, model_path)):
150
+ self.rdr = GeneralRDR.load(self.rdr_models_dir, self.model_name)
151
+ if self.rdr is None:
154
152
  self.rdr = GeneralRDR(save_dir=self.rdr_models_dir, model_name=self.model_name)
155
153
 
156
154
  def update_from_python(self):
@@ -497,21 +497,8 @@ def serialize_dataclass(obj: Any, seen=None) -> Any:
497
497
  value = getattr(obj, f.name)
498
498
  result['fields'][f.name] = serialize_dataclass(value, seen)
499
499
  return result
500
- elif isinstance(obj, list):
501
- return [serialize_dataclass(v, seen) for v in obj]
502
- elif isinstance(obj, dict):
503
- serialized_dict = {}
504
- for k, v in obj.items():
505
- if not isinstance(k, (str, int, bool, float, type(None))):
506
- continue
507
- serialized_dict[k] = serialize_dataclass(v, seen)
508
- return serialized_dict
509
500
  else:
510
- try:
511
- json.dumps(obj) # Check if the object is JSON serializable
512
- return obj
513
- except TypeError:
514
- return None
501
+ return SubclassJSONSerializer.to_json_static(obj, seen)
515
502
 
516
503
 
517
504
  def deserialize_dataclass(data: Any, refs: Optional[Dict[str, Any]] = None) -> Any:
@@ -875,10 +862,26 @@ class SubclassJSONSerializer:
875
862
  return data
876
863
 
877
864
  @staticmethod
878
- def to_json_static(obj) -> Dict[str, Any]:
879
- if is_dataclass(obj):
880
- return serialize_dataclass(obj)
881
- return {"_type": get_full_class_name(obj.__class__), **obj._to_json()}
865
+ def to_json_static(obj, seen=None) -> Any:
866
+ if isinstance(obj, SubclassJSONSerializer):
867
+ return {"_type": get_full_class_name(obj.__class__), **obj._to_json()}
868
+ elif is_dataclass(obj):
869
+ return serialize_dataclass(obj, seen)
870
+ elif isinstance(obj, list):
871
+ return [SubclassJSONSerializer.to_json_static(v, seen) for v in obj]
872
+ elif isinstance(obj, dict):
873
+ serialized_dict = {}
874
+ for k, v in obj.items():
875
+ if not isinstance(k, (str, int, bool, float, type(None))):
876
+ continue
877
+ serialized_dict[k] = SubclassJSONSerializer.to_json_static(v, seen)
878
+ return serialized_dict
879
+ else:
880
+ try:
881
+ json.dumps(obj) # Check if the object is JSON serializable
882
+ return obj
883
+ except TypeError:
884
+ return None
882
885
 
883
886
  def to_json(self) -> Dict[str, Any]:
884
887
  return self.to_json_static(self)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ripple_down_rules
3
- Version: 0.5.58
3
+ Version: 0.5.60
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
@@ -17,14 +17,15 @@ def get_fit_scrdr(cases: List[Any], targets: List[Any], attribute_name: str = "s
17
17
  expert_answers_file: str = "scrdr_expert_answers_fit",
18
18
  draw_tree: bool = False,
19
19
  load_answers: bool = True,
20
- save_answers: bool = False) -> Tuple[SingleClassRDR, List[CaseQuery]]:
20
+ save_answers: bool = False,
21
+ ask_always: bool = False) -> Tuple[SingleClassRDR, List[CaseQuery]]:
21
22
  filename = os.path.join(os.getcwd(), expert_answers_dir, expert_answers_file)
22
23
  expert = Human(use_loaded_answers=load_answers)
23
24
  if load_answers:
24
25
  expert.load_answers(filename)
25
26
 
26
27
  targets = [None for _ in cases] if targets is None or len(targets) == 0 else targets
27
- scrdr = SingleClassRDR()
28
+ scrdr = SingleClassRDR(ask_always=ask_always)
28
29
  case_queries = [CaseQuery(case, attribute_name, (attribute_type,), True, _target=target)
29
30
  for case, target in zip(cases, targets)]
30
31
  scrdr.fit(case_queries, expert=expert, animate_tree=draw_tree)
@@ -43,13 +44,14 @@ def get_fit_mcrdr(cases: List[Any], targets: List[Any], attribute_name: str = "s
43
44
  expert_answers_file: str = "mcrdr_expert_answers_stop_only_fit",
44
45
  draw_tree: bool = False,
45
46
  load_answers: bool = True,
46
- save_answers: bool = False) -> MultiClassRDR:
47
+ save_answers: bool = False,
48
+ ask_always: bool = False) -> MultiClassRDR:
47
49
  filename = os.path.join(os.getcwd(), expert_answers_dir, expert_answers_file)
48
50
  expert = Human(use_loaded_answers=load_answers)
49
51
  if load_answers:
50
52
  expert.load_answers(filename)
51
53
  targets = [None for _ in cases] if targets is None or len(targets) == 0 else targets
52
- mcrdr = MultiClassRDR()
54
+ mcrdr = MultiClassRDR(ask_always=ask_always)
53
55
  case_queries = [CaseQuery(case, attribute_name, (attribute_type,), mutually_exclusive, _target=target)
54
56
  for case, target in zip(cases, targets)]
55
57
  mcrdr.fit(case_queries, expert=expert, animate_tree=draw_tree)
@@ -66,7 +68,8 @@ def get_fit_grdr(cases: List[Any], targets: List[Any], expert_answers_dir: str =
66
68
  load_answers: bool = True,
67
69
  save_answers: bool = False,
68
70
  append: bool = False,
69
- no_targets: bool = False) -> Tuple[GeneralRDR, List[dict]]:
71
+ no_targets: bool = False,
72
+ ask_always: bool = False) -> Tuple[GeneralRDR, List[dict]]:
70
73
  filename = os.path.join(os.path.dirname(__file__), '..', expert_answers_dir, expert_answers_file)
71
74
  expert = Human(use_loaded_answers=load_answers, append=append)
72
75
  if load_answers:
@@ -74,7 +77,7 @@ def get_fit_grdr(cases: List[Any], targets: List[Any], expert_answers_dir: str =
74
77
 
75
78
  fit_scrdr, _ = get_fit_scrdr(cases, targets, draw_tree=False)
76
79
 
77
- grdr = GeneralRDR()
80
+ grdr = GeneralRDR(ask_always=ask_always)
78
81
  grdr.add_rdr(fit_scrdr)
79
82
 
80
83
  n = 20
@@ -125,7 +125,8 @@ class TestRDR(TestCase):
125
125
  expert_answers_dir=self.expert_answers_dir,
126
126
  expert_answers_file="scrdr_expert_answers_fit_no_targets",
127
127
  load_answers=True,
128
- save_answers=False)
128
+ save_answers=False,
129
+ ask_always=True)
129
130
  if draw:
130
131
  render_tree(scrdr.start_rule, use_dot_exporter=True,
131
132
  filename=self.test_results_dir + f"/scrdr_no_targets")
@@ -135,7 +136,8 @@ class TestRDR(TestCase):
135
136
  scrdr, case_queries = get_fit_scrdr(self.all_cases[:20], [], draw_tree=False,
136
137
  expert_answers_dir=self.expert_answers_dir,
137
138
  expert_answers_file="scrdr_expert_answers_fit_no_targets",
138
- load_answers=True, save_answers=False)
139
+ load_answers=True, save_answers=False,
140
+ ask_always=True)
139
141
  model_dir = self.generated_rdrs_dir + '/scrdr_no_targets'
140
142
  os.makedirs(model_dir, exist_ok=True)
141
143
  scrdr._write_to_python(model_dir)
@@ -150,7 +152,8 @@ class TestRDR(TestCase):
150
152
  expert_answers_dir=self.expert_answers_dir,
151
153
  expert_answers_file="mcrdr_expert_answers_fit_no_targets",
152
154
  load_answers=True,
153
- save_answers=False)
155
+ save_answers=False,
156
+ ask_always=True)
154
157
  # render_tree(mcrdr.start_rule, use_dot_exporter=True,
155
158
  # filename=self.test_results_dir + f"/mcrdr_no_targets")
156
159
  for case, target in zip(self.all_cases[:20], self.targets[:20]):
@@ -162,7 +165,8 @@ class TestRDR(TestCase):
162
165
  mcrdr = get_fit_mcrdr(self.all_cases[:20], [], draw_tree=False,
163
166
  expert_answers_dir=self.expert_answers_dir,
164
167
  expert_answers_file="mcrdr_expert_answers_fit_no_targets",
165
- load_answers=True, save_answers=False)
168
+ load_answers=True, save_answers=False,
169
+ ask_always=True)
166
170
  model_dir = self.generated_rdrs_dir + '/mcrdr_no_targets'
167
171
  os.makedirs(model_dir, exist_ok=True)
168
172
  mcrdr._write_to_python(model_dir)
@@ -178,7 +182,8 @@ class TestRDR(TestCase):
178
182
  grdr, all_targets = get_fit_grdr(self.all_cases, self.targets, draw_tree=draw_tree,
179
183
  expert_answers_dir=self.expert_answers_dir,
180
184
  expert_answers_file="grdr_expert_answers_fit_no_targets",
181
- load_answers=True, save_answers=False, append=False, no_targets=True)
185
+ load_answers=True, save_answers=False, append=False, no_targets=True,
186
+ ask_always=True)
182
187
  if draw_tree:
183
188
  for conclusion_name, rdr in grdr.start_rules_dict.items():
184
189
  render_tree(rdr.start_rule, use_dot_exporter=True,
@@ -194,7 +199,8 @@ class TestRDR(TestCase):
194
199
  grdr, all_targets = get_fit_grdr(self.all_cases, self.targets, draw_tree=False,
195
200
  expert_answers_dir=self.expert_answers_dir,
196
201
  expert_answers_file="grdr_expert_answers_fit_no_targets",
197
- load_answers=True, save_answers=False, append=False, no_targets=True)
202
+ load_answers=True, save_answers=False, append=False, no_targets=True,
203
+ ask_always=True)
198
204
  model_dir = self.generated_rdrs_dir + '/grdr_no_targets'
199
205
  grdr._write_to_python(model_dir)
200
206
  classify_species_grdr = grdr.get_rdr_classifier_from_python_file(model_dir)
@@ -182,7 +182,7 @@ class TestRDRWorld(TestCase):
182
182
  filename = os.path.join(os.getcwd(), "test_expert_answers/correct_drawer_rdr_expert_answers_fit")
183
183
  if use_loaded_answers:
184
184
  expert.load_answers(filename)
185
- rdr = GeneralRDR()
185
+ rdr = GeneralRDR(ask_always=True)
186
186
  rdr.fit(self.drawer_case_queries, expert=expert, animate_tree=False)
187
187
  if save_answers:
188
188
  expert.save_answers(filename)
@@ -12,9 +12,9 @@
12
12
  "builtins.bool"
13
13
  ],
14
14
  "scope": {
15
- "PhysicalObject": "datasets.PhysicalObject",
15
+ "Dict": "typing.Dict",
16
16
  "Robot": "datasets.Robot",
17
- "Dict": "typing.Dict"
17
+ "PhysicalObject": "datasets.PhysicalObject"
18
18
  },
19
19
  "conclusion": {
20
20
  "_type": "builtins.NoneType",
@@ -29,9 +29,9 @@
29
29
  "builtins.bool"
30
30
  ],
31
31
  "scope": {
32
- "PhysicalObject": "datasets.PhysicalObject",
32
+ "Dict": "typing.Dict",
33
33
  "Robot": "datasets.Robot",
34
- "Dict": "typing.Dict"
34
+ "PhysicalObject": "datasets.PhysicalObject"
35
35
  },
36
36
  "conclusion": {
37
37
  "_type": "builtins.NoneType",
@@ -6,7 +6,7 @@ from ripple_down_rules.rdr import MultiClassRDR
6
6
 
7
7
 
8
8
  attribute_name = 'output_'
9
- conclusion_type = (set, list, PhysicalObject,)
9
+ conclusion_type = (PhysicalObject, list, set,)
10
10
  type_ = MultiClassRDR
11
11
 
12
12
 
@@ -12,11 +12,11 @@
12
12
  "builtins.bool"
13
13
  ],
14
14
  "scope": {
15
- "Robot": "datasets.Robot",
16
15
  "Dict": "typing.Dict",
17
- "PhysicalObject": "datasets.PhysicalObject",
16
+ "Union": "typing.Union",
17
+ "Robot": "datasets.Robot",
18
18
  "List": "typing.List",
19
- "Union": "typing.Union"
19
+ "PhysicalObject": "datasets.PhysicalObject"
20
20
  },
21
21
  "conclusion": {
22
22
  "_type": "builtins.NoneType",
@@ -33,11 +33,11 @@
33
33
  "builtins.list"
34
34
  ],
35
35
  "scope": {
36
- "Robot": "datasets.Robot",
37
36
  "Dict": "typing.Dict",
38
- "PhysicalObject": "datasets.PhysicalObject",
37
+ "Union": "typing.Union",
38
+ "Robot": "datasets.Robot",
39
39
  "List": "typing.List",
40
- "Union": "typing.Union"
40
+ "PhysicalObject": "datasets.PhysicalObject"
41
41
  },
42
42
  "conclusion": {
43
43
  "_type": "builtins.NoneType",
@@ -1,6 +1,6 @@
1
- from datasets import PhysicalObject
2
1
  from datasets import Robot
3
2
  from typing import Dict
3
+ from datasets import PhysicalObject
4
4
 
5
5
 
6
6
  def conditions_226969243620390858682731042391766665817(case):
@@ -1,8 +1,8 @@
1
- from typing import List
2
1
  from datasets import Robot
3
- from datasets import PhysicalObject
2
+ from typing import List
4
3
  from typing import Union
5
4
  from typing import Dict
5
+ from datasets import PhysicalObject
6
6
  from typing_extensions import Union
7
7
 
8
8