ripple-down-rules 0.6.23__tar.gz → 0.6.24__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 (153) hide show
  1. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/PKG-INFO +1 -1
  2. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/scripts/live_dot_server_client.py +1 -1
  3. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/src/ripple_down_rules/__init__.py +1 -1
  4. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/src/ripple_down_rules/rdr.py +48 -15
  5. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/src/ripple_down_rules/rdr_decorators.py +7 -6
  6. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/src/ripple_down_rules/rules.py +0 -3
  7. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/src/ripple_down_rules/utils.py +16 -6
  8. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/src/ripple_down_rules.egg-info/PKG-INFO +1 -1
  9. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/test/test_results/datasets_physical_object_is_a_robot/rdr_metadata/datasets_physical_object_is_a_robot.json +1 -1
  10. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/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
  11. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/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 +1 -1
  12. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/.github/workflows/build_and_deploy_doc.yml +0 -0
  13. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/.github/workflows/ci.yml +0 -0
  14. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/.github/workflows/publish-to-test-pypi.yml +0 -0
  15. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/.gitignore +0 -0
  16. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/.idea/shelf/Uncommitted_changes_before_Checkout_at_2_4_25,_6_32_PM_[Changes]/shelved.patch +0 -0
  17. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/.idea/shelf/Uncommitted_changes_before_Checkout_at_2_4_25,_6_32_PM_[Changes]1/shelved.patch +0 -0
  18. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/LICENSE +0 -0
  19. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/README.md +0 -0
  20. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/doc/_config.yml +0 -0
  21. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/doc/_toc.yml +0 -0
  22. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/doc/bibliography.md +0 -0
  23. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/doc/intro.md +0 -0
  24. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/doc/references.bib +0 -0
  25. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/doc/requirements.txt +0 -0
  26. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/examples/__init__.py +0 -0
  27. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/examples/animal_species.py +0 -0
  28. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/examples/part_containment_rdr/__init__.py +0 -0
  29. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/examples/part_containment_rdr/rdr_metadata/part_containment_rdr.json +0 -0
  30. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/examples/part_containment_rdr/robot_contained_objects_mcrdr.py +0 -0
  31. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/examples/part_containment_rdr/robot_contained_objects_mcrdr_defs.py +0 -0
  32. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/examples/part_containment_rdr/robot_rdr.py +0 -0
  33. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/examples/relational_example.py +0 -0
  34. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/images/scrdr.dot +0 -0
  35. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/images/scrdr.png +0 -0
  36. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/images/thinking_pr2.jpg +0 -0
  37. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/pyproject.toml +0 -0
  38. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/pytest.ini +0 -0
  39. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/requirements-dev-ci.txt +0 -0
  40. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/requirements-dev.txt +0 -0
  41. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/requirements-gui.txt +0 -0
  42. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/requirements-viz.txt +0 -0
  43. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/requirements.txt +0 -0
  44. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/results/complete_mcrdr_extra.dot +0 -0
  45. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/results/complete_mcrdr_extra.png +0 -0
  46. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/results/complete_mcrdr_stop_only.dot +0 -0
  47. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/results/complete_mcrdr_stop_only.png +0 -0
  48. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/results/complete_mcrdr_stop_plus_rule.dot +0 -0
  49. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/results/complete_mcrdr_stop_plus_rule.png +0 -0
  50. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/results/complete_scrdr.dot +0 -0
  51. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/results/complete_scrdr.png +0 -0
  52. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/results/complete_scrdr_2.dot +0 -0
  53. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/results/complete_scrdr_2.png +0 -0
  54. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/results/complete_scrdr_3.dot +0 -0
  55. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/results/complete_scrdr_3.png +0 -0
  56. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/results/grdr_Habitat.dot +0 -0
  57. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/results/grdr_Habitat.png +0 -0
  58. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/results/grdr_Species.dot +0 -0
  59. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/results/grdr_Species.png +0 -0
  60. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/results/mcrdr_extra.dot +0 -0
  61. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/results/mcrdr_extra.png +0 -0
  62. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/results/mcrdr_extra_classify.dot +0 -0
  63. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/results/mcrdr_extra_classify.png +0 -0
  64. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/results/mcrdr_stop_plus_rule_combined.dot +0 -0
  65. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/results/mcrdr_stop_plus_rule_combined.png +0 -0
  66. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/results/partial_mcrdr_extra.dot +0 -0
  67. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/results/partial_mcrdr_extra.png +0 -0
  68. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/results/relational_scrdr_classify.dot +0 -0
  69. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/results/relational_scrdr_classify.png +0 -0
  70. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/setup.cfg +0 -0
  71. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/src/ripple_down_rules/datastructures/__init__.py +0 -0
  72. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/src/ripple_down_rules/datastructures/callable_expression.py +0 -0
  73. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/src/ripple_down_rules/datastructures/case.py +0 -0
  74. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/src/ripple_down_rules/datastructures/dataclasses.py +0 -0
  75. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/src/ripple_down_rules/datastructures/enums.py +0 -0
  76. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/src/ripple_down_rules/experts.py +0 -0
  77. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/src/ripple_down_rules/helpers.py +0 -0
  78. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/src/ripple_down_rules/start-code-server.sh +0 -0
  79. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/src/ripple_down_rules/user_interface/__init__.py +0 -0
  80. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/src/ripple_down_rules/user_interface/gui.py +0 -0
  81. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/src/ripple_down_rules/user_interface/ipython_custom_shell.py +0 -0
  82. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/src/ripple_down_rules/user_interface/object_diagram.py +0 -0
  83. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/src/ripple_down_rules/user_interface/prompt.py +0 -0
  84. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/src/ripple_down_rules/user_interface/template_file_creator.py +0 -0
  85. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/src/ripple_down_rules.egg-info/SOURCES.txt +0 -0
  86. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/src/ripple_down_rules.egg-info/dependency_links.txt +0 -0
  87. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/src/ripple_down_rules.egg-info/requires.txt +0 -0
  88. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/src/ripple_down_rules.egg-info/top_level.txt +0 -0
  89. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/test/__init__.py +0 -0
  90. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/test/conf/__init__.py +0 -0
  91. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/test/conf/world/__init__.py +0 -0
  92. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/test/conf/world/base_config.py +0 -0
  93. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/test/conf/world/handles_and_containers.py +0 -0
  94. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/test/conftest.py +0 -0
  95. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/test/datasets.py +0 -0
  96. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/test/factories/__init__.py +0 -0
  97. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/test/factories/world/__init__.py +0 -0
  98. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/test/factories/world/handles_and_containers.py +0 -0
  99. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/test/test_expert_answers/correct_drawer_rdr_expert_answers_fit.json +0 -0
  100. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/test/test_expert_answers/drawer_cabinet_expert_answers_fit.json +0 -0
  101. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/test/test_expert_answers/grdr_expert_answers_classify.json +0 -0
  102. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/test/test_expert_answers/grdr_expert_answers_fit.json +0 -0
  103. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/test/test_expert_answers/grdr_expert_answers_fit_extra.json +0 -0
  104. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/test/test_expert_answers/grdr_expert_answers_fit_no_targets.json +0 -0
  105. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/test/test_expert_answers/mcrdr_expert_answers_classify.json +0 -0
  106. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/test/test_expert_answers/mcrdr_expert_answers_fit_no_targets.json +0 -0
  107. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/test/test_expert_answers/mcrdr_expert_answers_stop_only_fit.json +0 -0
  108. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/test/test_expert_answers/mcrdr_extra_expert_answers_classify.json +0 -0
  109. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/test/test_expert_answers/mcrdr_extra_expert_answers_fit.json +0 -0
  110. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/test/test_expert_answers/mcrdr_multi_line_expert_answers_fit.json +0 -0
  111. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/test/test_expert_answers/mcrdr_stop_only_answers_fit.json +0 -0
  112. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/test/test_expert_answers/mcrdr_stop_plus_rule_answers_fit.json +0 -0
  113. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/test/test_expert_answers/mcrdr_stop_plus_rule_combined_expert_answers_fit.json +0 -0
  114. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/test/test_expert_answers/mcrdr_stop_plus_rule_expert_answers_fit.json +0 -0
  115. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/test/test_expert_answers/mutagenic_expert_answers.json +0 -0
  116. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/test/test_expert_answers/relational_scrdr_expert_answers_classify.json +0 -0
  117. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/test/test_expert_answers/scrdr_expert_answers_classify.json +0 -0
  118. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/test/test_expert_answers/scrdr_expert_answers_fit.json +0 -0
  119. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/test/test_expert_answers/scrdr_expert_answers_fit_no_targets.json +0 -0
  120. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/test/test_expert_answers/scrdr_multi_line_expert_answers_fit.json +0 -0
  121. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/test/test_expert_answers/scrdr_world_expert_answers_fit.json +0 -0
  122. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/test/test_generated_rdrs/__init__.py +0 -0
  123. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/test/test_helpers/__init__.py +0 -0
  124. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/test/test_helpers/helpers.py +0 -0
  125. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/test/test_helpers/object_diagram_case_query.png +0 -0
  126. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/test/test_helpers/object_diagram_person.png +0 -0
  127. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/test/test_json_serialization.py +0 -0
  128. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/test/test_object_diagram.py +0 -0
  129. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/test/test_on_mutagenic.py +0 -0
  130. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/test/test_rdr.py +0 -0
  131. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/test/test_rdr_alchemy.py +0 -0
  132. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/test/test_rdr_decorators.py +0 -0
  133. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/test/test_rdr_helpers_rdrs.py +0 -0
  134. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/test/test_rdr_world/__init__.py +0 -0
  135. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/test/test_rdr_world/conftest.py +0 -0
  136. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/test/test_rdr_world/test_rdr_world.py +0 -0
  137. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/test/test_relational_rdr.py +0 -0
  138. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/test/test_relational_rdr_alchemy.py +0 -0
  139. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/test/test_results/datasets_physical_object_is_a_robot/__init__.py +0 -0
  140. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/test/test_results/datasets_physical_object_is_a_robot/physical_object_is_a_robot_output__scrdr.py +0 -0
  141. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/test/test_results/datasets_physical_object_is_a_robot/physical_object_is_a_robot_output__scrdr_defs.py +0 -0
  142. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/test/test_results/datasets_physical_object_is_a_robot/physical_object_is_a_robot_rdr.py +1 -1
  143. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/test/test_results/datasets_physical_object_select_objects_that_are_parts_of_robot/__init__.py +0 -0
  144. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/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 +0 -0
  145. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/test/test_results/datasets_physical_object_select_objects_that_are_parts_of_robot/physical_object_select_objects_that_are_parts_of_robot_rdr.py +1 -1
  146. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/test/test_sql_model.py +0 -0
  147. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/test/test_template_file_creator.py +0 -0
  148. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/test/test_user_interface/__init__.py +0 -0
  149. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/test/test_user_interface/test_ipython.py +0 -0
  150. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/test/test_user_interface/test_ipython_copilot.py +0 -0
  151. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/test/test_user_interface/test_prompt.py +0 -0
  152. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/test/test_user_interface/test_qt_gui_inline.py +0 -0
  153. {ripple_down_rules-0.6.23 → ripple_down_rules-0.6.24}/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.6.23
3
+ Version: 0.6.24
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
@@ -52,7 +52,7 @@ def generate_html(dot_output="graph.html"):
52
52
  }}
53
53
 
54
54
  fetchAndRender();
55
- setInterval(fetchAndRender, 500); // Refresh every 2 seconds
55
+ setInterval(fetchAndRender, 100); // Refresh every 2 seconds
56
56
  </script>
57
57
  </body>
58
58
  </html>"""
@@ -1,4 +1,4 @@
1
- __version__ = "0.6.23"
1
+ __version__ = "0.6.24"
2
2
 
3
3
  import logging
4
4
  logger = logging.Logger("rdr")
@@ -4,7 +4,9 @@ import importlib
4
4
  import os
5
5
  from abc import ABC, abstractmethod
6
6
  from copy import copy
7
+ from dataclasses import is_dataclass
7
8
  from types import NoneType
9
+ import json
8
10
 
9
11
  from ripple_down_rules.datastructures.dataclasses import CaseFactoryMetaData
10
12
  from . import logger
@@ -36,7 +38,7 @@ except ImportError as e:
36
38
  RDRCaseViewer = None
37
39
  from .utils import draw_tree, make_set, SubclassJSONSerializer, make_list, get_type_from_string, \
38
40
  is_conflicting, extract_function_source, extract_imports, get_full_class_name, \
39
- is_iterable, str_to_snake_case, get_import_path_from_path, get_imports_from_types, render_tree
41
+ is_iterable, str_to_snake_case, get_import_path_from_path, get_imports_from_types, render_tree, table_rows_as_str
40
42
 
41
43
 
42
44
  class RippleDownRules(SubclassJSONSerializer, ABC):
@@ -97,11 +99,12 @@ class RippleDownRules(SubclassJSONSerializer, ABC):
97
99
  self.viewer = RDRCaseViewer.instances[0]
98
100
  logger.error("No viewer was provided, but there is already an existing viewer. "
99
101
  "Using the existing viewer.")
102
+ self.input_node: Optional[Rule] = None
100
103
 
101
104
  @property
102
105
  def viewer(self):
103
106
  return self._viewer
104
-
107
+
105
108
  @viewer.setter
106
109
  def viewer(self, value):
107
110
  self._viewer = value
@@ -110,23 +113,24 @@ class RippleDownRules(SubclassJSONSerializer, ABC):
110
113
 
111
114
  def render_evaluated_rule_tree(self, filename: str, show_full_tree: bool = False) -> None:
112
115
  if show_full_tree:
113
- render_tree(self.start_rule, use_dot_exporter=True, filename=filename)
116
+ start_rule = self.start_rule if self.input_node is None else self.input_node
117
+ render_tree(start_rule, use_dot_exporter=True, filename=filename)
114
118
  else:
115
119
  evaluated_rules = self.get_evaluated_rule_tree()
116
120
  if evaluated_rules is not None and len(evaluated_rules) > 0:
117
121
  render_tree(evaluated_rules[0], use_dot_exporter=True, filename=filename,
118
122
  only_nodes=evaluated_rules)
119
123
 
120
- def get_evaluated_rule_tree(self) -> List[Rule]:
124
+ def get_evaluated_rule_tree(self) -> Optional[List[Rule]]:
121
125
  """
122
126
  Get the evaluated rule tree of the classifier.
123
127
 
124
128
  :return: The evaluated rule tree.
125
129
  """
126
130
  if self.start_rule is None:
127
- return
128
- # raise ValueError("The start rule is not set. Please set the start rule before getting the evaluated rule tree.")
129
- evaluated_rule_tree = [r for r in [self.start_rule] + list(self.start_rule.descendants) if r.evaluated]
131
+ return None
132
+ start_rule = self.start_rule
133
+ evaluated_rule_tree = [r for r in [start_rule] + list(start_rule.descendants) if r.evaluated]
130
134
  return evaluated_rule_tree
131
135
 
132
136
  def save(self, save_dir: Optional[str] = None, model_name: Optional[str] = None,
@@ -260,9 +264,38 @@ class RippleDownRules(SubclassJSONSerializer, ABC):
260
264
  def __call__(self, case: Union[Case, SQLTable]) -> Union[CallableExpression, Dict[str, CallableExpression]]:
261
265
  return self.classify(case)
262
266
 
267
+ def classify(self, case: Union[Case, SQLTable], modify_case: bool = False, case_query: Optional[CaseQuery] = None) \
268
+ -> Optional[Union[CallableExpression, Dict[str, CallableExpression]]]:
269
+ """
270
+ Classify a case using the RDR classifier.
271
+
272
+ :param case: The case to classify.
273
+ :param modify_case: Whether to modify the original case attributes with the conclusion or not.
274
+ :param case_query: The case query containing the case to classify and the target category to compare the case with.
275
+ :return: The category that the case belongs to.
276
+ """
277
+ if self.start_rule is not None:
278
+ for rule in [self.start_rule] + list(self.start_rule.descendants):
279
+ rule.evaluated = False
280
+ rule.fired = False
281
+ if self.start_rule is not None and self.start_rule.parent is None:
282
+ if self.input_node is None:
283
+ self.input_node = type(self.start_rule)(parent=None, uid='0')
284
+ self.input_node.evaluated = False
285
+ self.input_node.fired = False
286
+ self.start_rule.parent = self.input_node
287
+ self.start_rule.weight = ""
288
+ if self.input_node is not None:
289
+ data = case.__dict__ if is_dataclass(case) else case
290
+ if hasattr(case, "items"):
291
+ self.input_node.name = json.dumps({k: str(v) for k, v in data.items()}, indent=4)
292
+ else:
293
+ self.input_node.name = str(data)
294
+ return self._classify(case, modify_case=modify_case, case_query=case_query)
295
+
263
296
  @abstractmethod
264
- def classify(self, case: Union[Case, SQLTable], modify_case: bool = False,
265
- case_query: Optional[CaseQuery] = None) \
297
+ def _classify(self, case: Union[Case, SQLTable], modify_case: bool = False,
298
+ case_query: Optional[CaseQuery] = None) \
266
299
  -> Optional[Union[CallableExpression, Dict[str, CallableExpression]]]:
267
300
  """
268
301
  Classify a case.
@@ -703,8 +736,8 @@ class SingleClassRDR(RDRWithCodeWriter):
703
736
  expert.ask_for_conditions(case_query)
704
737
  self.start_rule = SingleClassRule.from_case_query(case_query)
705
738
 
706
- def classify(self, case: Case, modify_case: bool = False,
707
- case_query: Optional[CaseQuery] = None) -> Optional[Any]:
739
+ def _classify(self, case: Case, modify_case: bool = False,
740
+ case_query: Optional[CaseQuery] = None) -> Optional[Any]:
708
741
  """
709
742
  Classify a case by recursively evaluating the rules until a rule fires or the last rule is reached.
710
743
 
@@ -818,8 +851,8 @@ class MultiClassRDR(RDRWithCodeWriter):
818
851
  super(MultiClassRDR, self).__init__(start_rule, **kwargs)
819
852
  self.mode: MCRDRMode = mode
820
853
 
821
- def classify(self, case: Union[Case, SQLTable], modify_case: bool = False,
822
- case_query: Optional[CaseQuery] = None) -> Set[Any]:
854
+ def _classify(self, case: Union[Case, SQLTable], modify_case: bool = False,
855
+ case_query: Optional[CaseQuery] = None) -> Set[Any]:
823
856
  evaluated_rule = self.start_rule
824
857
  self.conclusions = []
825
858
  while evaluated_rule:
@@ -1064,8 +1097,8 @@ class GeneralRDR(RippleDownRules):
1064
1097
  def start_rules(self) -> List[Union[SingleClassRule, MultiClassTopRule]]:
1065
1098
  return [rdr.start_rule for rdr in self.start_rules_dict.values()]
1066
1099
 
1067
- def classify(self, case: Any, modify_case: bool = False,
1068
- case_query: Optional[CaseQuery] = None) -> Optional[Dict[str, Any]]:
1100
+ def _classify(self, case: Any, modify_case: bool = False,
1101
+ case_query: Optional[CaseQuery] = None) -> Optional[Dict[str, Any]]:
1069
1102
  """
1070
1103
  Classify a case by going through all RDRs and adding the categories that are classified, and then restarting
1071
1104
  the classification until no more categories can be added.
@@ -8,15 +8,16 @@ from functools import wraps
8
8
 
9
9
  from typing_extensions import Callable, Optional, Type, Tuple, Dict, Any, Self, get_type_hints, List, Union, Sequence
10
10
 
11
- from ripple_down_rules.datastructures.case import Case
12
- from ripple_down_rules.datastructures.dataclasses import CaseQuery
13
- from ripple_down_rules.experts import Expert, Human
14
- from ripple_down_rules.rdr import GeneralRDR
11
+ from .datastructures.case import Case
12
+ from .datastructures.dataclasses import CaseQuery
13
+ from .experts import Expert, Human
14
+ from .rdr import GeneralRDR
15
+ from . import logger
15
16
  try:
16
- from ripple_down_rules.user_interface.gui import RDRCaseViewer
17
+ from .user_interface.gui import RDRCaseViewer
17
18
  except ImportError:
18
19
  RDRCaseViewer = None
19
- from ripple_down_rules.utils import get_method_args_as_dict, get_func_rdr_model_name, make_set, \
20
+ from .utils import get_method_args_as_dict, get_func_rdr_model_name, make_set, \
20
21
  get_method_class_if_exists, str_to_snake_case
21
22
 
22
23
 
@@ -116,9 +116,6 @@ class Rule(NodeMixin, SubclassJSONSerializer, ABC):
116
116
  :param x: The case to evaluate the rule on.
117
117
  :return: The rule that fired or the last evaluated rule if no rule fired.
118
118
  """
119
- if self.root is self:
120
- for descendant in self.descendants:
121
- descendant.evaluated = False
122
119
  self.evaluated = True
123
120
  if not self.conditions:
124
121
  raise ValueError("Rule has no conditions")
@@ -21,6 +21,7 @@ from subprocess import check_call
21
21
  from tempfile import NamedTemporaryFile
22
22
  from textwrap import dedent
23
23
  from types import NoneType
24
+ import shutil
24
25
 
25
26
  import six
26
27
  from sqlalchemy.exc import NoInspectionAvailable
@@ -50,6 +51,7 @@ from sqlalchemy.orm import Mapped, registry, class_mapper, DeclarativeBase as SQ
50
51
  from tabulate import tabulate
51
52
  from typing_extensions import Callable, Set, Any, Type, Dict, TYPE_CHECKING, get_type_hints, \
52
53
  get_origin, get_args, Tuple, Optional, List, Union, Self, ForwardRef, Iterable
54
+ from . import logger
53
55
 
54
56
  if TYPE_CHECKING:
55
57
  from .datastructures.case import Case
@@ -1408,7 +1410,11 @@ def table_rows_as_str(row_dicts: List[Dict[str, Any]], columns_per_row: int = 20
1408
1410
  row_values = [list(map(lambda v: v[:max_line_sze] + '...' if len(v) > max_line_sze else v, row)) for row in
1409
1411
  row_values]
1410
1412
  row_values = [list(map(lambda v: v.lower() if v in ["True", "False"] else v, row)) for row in row_values]
1411
- table = tabulate(row_values, tablefmt='simple_grid', maxcolwidths=[max_line_sze] * 2)
1413
+ # Step 1: Get terminal size
1414
+ terminal_width = shutil.get_terminal_size((80, 20)).columns
1415
+ # Step 2: Dynamically calculate max width per column (simple approximation)
1416
+ max_col_width = terminal_width // len(row_values[0])
1417
+ table = tabulate(row_values, tablefmt='simple_grid', maxcolwidths=max_col_width)#[max_line_sze] * 2)
1412
1418
  all_table_rows.append(table)
1413
1419
  return "\n".join(all_table_rows)
1414
1420
 
@@ -1628,7 +1634,7 @@ def edge_attr_setter(parent, child):
1628
1634
  """
1629
1635
  Set the edge attributes for the dot exporter.
1630
1636
  """
1631
- if child and hasattr(child, "weight") and child.weight:
1637
+ if child and hasattr(child, "weight") and child.weight is not None:
1632
1638
  return f'style="bold", label=" {child.weight}"'
1633
1639
  return ""
1634
1640
 
@@ -1913,7 +1919,7 @@ class FilteredDotExporter(object):
1913
1919
 
1914
1920
 
1915
1921
  def render_tree(root: Node, use_dot_exporter: bool = False,
1916
- filename: str = "scrdr", only_nodes: List[Node] = None):
1922
+ filename: str = "scrdr", only_nodes: List[Node] = None, show_in_console: bool = False):
1917
1923
  """
1918
1924
  Render the tree using the console and optionally export it to a dot file.
1919
1925
 
@@ -1921,12 +1927,16 @@ def render_tree(root: Node, use_dot_exporter: bool = False,
1921
1927
  :param use_dot_exporter: Whether to export the tree to a dot file.
1922
1928
  :param filename: The name of the file to export the tree to.
1923
1929
  :param only_nodes: A list of nodes to include in the dot export.
1930
+ :param show_in_console: Whether to print the tree to the console.
1924
1931
  """
1925
1932
  if not root:
1926
- logging.warning("No rules to render")
1933
+ logger.warning("No rules to render")
1927
1934
  return
1928
- # for pre, _, node in RenderTree(root):
1929
- # print(f"{pre}{node.weight if hasattr(node, 'weight') and node.weight else ''} {node.__str__()}")
1935
+ if show_in_console:
1936
+ for pre, _, node in RenderTree(root):
1937
+ if only_nodes is not None and node not in only_nodes:
1938
+ continue
1939
+ print(f"{pre}{node.weight if hasattr(node, 'weight') and node.weight else ''} {node.__str__()}")
1930
1940
  if use_dot_exporter:
1931
1941
  unique_node_names = get_unique_node_names_func(root)
1932
1942
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ripple_down_rules
3
- Version: 0.6.23
3
+ Version: 0.6.24
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
@@ -55,7 +55,7 @@
55
55
  "_name": "PhysicalObject_is_a_robot"
56
56
  },
57
57
  "conclusion_name": "output_",
58
- "weight": null,
58
+ "weight": "",
59
59
  "uid": "226969243620390858682731042391766665817",
60
60
  "refinement": null,
61
61
  "alternative": null
@@ -5,7 +5,7 @@ from .physical_object_select_objects_that_are_parts_of_robot_output__mcrdr_defs
5
5
 
6
6
 
7
7
  attribute_name = 'output_'
8
- conclusion_type = (set, list, PhysicalObject,)
8
+ conclusion_type = (set, PhysicalObject, list,)
9
9
  mutually_exclusive = False
10
10
 
11
11
 
@@ -64,7 +64,7 @@
64
64
  "_name": "PhysicalObject_select_objects_that_are_parts_of_robot"
65
65
  },
66
66
  "conclusion_name": "output_",
67
- "weight": "next",
67
+ "weight": "",
68
68
  "uid": "164855806603893754507167918997373216146",
69
69
  "refinement": null,
70
70
  "alternative": null
@@ -1,6 +1,6 @@
1
+ from ripple_down_rules.datastructures.case import Case, create_case
1
2
  from ripple_down_rules.helpers import general_rdr_classify
2
3
  from typing_extensions import Any, Dict
3
- from ripple_down_rules.datastructures.case import Case, create_case
4
4
  from . import physical_object_is_a_robot_output__scrdr as output__classifier
5
5
 
6
6
  classifiers_dict = dict()
@@ -1,6 +1,6 @@
1
+ from ripple_down_rules.datastructures.case import Case, create_case
1
2
  from ripple_down_rules.helpers import general_rdr_classify
2
3
  from typing_extensions import Any, Dict
3
- from ripple_down_rules.datastructures.case import Case, create_case
4
4
  from . import physical_object_select_objects_that_are_parts_of_robot_output__mcrdr as output__classifier
5
5
 
6
6
  classifiers_dict = dict()