ripple-down-rules 0.6.24__tar.gz → 0.6.25__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/PKG-INFO +1 -1
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/src/ripple_down_rules/__init__.py +1 -1
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/src/ripple_down_rules/datastructures/callable_expression.py +3 -2
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/src/ripple_down_rules/datastructures/dataclasses.py +2 -2
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/src/ripple_down_rules/datastructures/enums.py +4 -1
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/src/ripple_down_rules/experts.py +2 -2
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/src/ripple_down_rules/helpers.py +28 -7
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/src/ripple_down_rules/rdr.py +68 -22
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/src/ripple_down_rules/rules.py +160 -53
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/src/ripple_down_rules/user_interface/prompt.py +6 -3
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/src/ripple_down_rules/utils.py +16 -11
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/src/ripple_down_rules.egg-info/PKG-INFO +1 -1
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/test/test_json_serialization.py +8 -3
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/test/test_results/datasets_physical_object_is_a_robot/rdr_metadata/datasets_physical_object_is_a_robot.json +4 -4
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/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 +3 -2
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/test/test_user_interface/test_qt_gui_inline.py +3 -2
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/.github/workflows/build_and_deploy_doc.yml +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/.github/workflows/ci.yml +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/.github/workflows/publish-to-test-pypi.yml +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/.gitignore +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/.idea/shelf/Uncommitted_changes_before_Checkout_at_2_4_25,_6_32_PM_[Changes]/shelved.patch +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/.idea/shelf/Uncommitted_changes_before_Checkout_at_2_4_25,_6_32_PM_[Changes]1/shelved.patch +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/LICENSE +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/README.md +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/doc/_config.yml +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/doc/_toc.yml +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/doc/bibliography.md +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/doc/intro.md +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/doc/references.bib +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/doc/requirements.txt +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/examples/__init__.py +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/examples/animal_species.py +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/examples/part_containment_rdr/__init__.py +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/examples/part_containment_rdr/rdr_metadata/part_containment_rdr.json +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/examples/part_containment_rdr/robot_contained_objects_mcrdr.py +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/examples/part_containment_rdr/robot_contained_objects_mcrdr_defs.py +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/examples/part_containment_rdr/robot_rdr.py +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/examples/relational_example.py +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/images/scrdr.dot +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/images/scrdr.png +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/images/thinking_pr2.jpg +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/pyproject.toml +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/pytest.ini +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/requirements-dev-ci.txt +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/requirements-dev.txt +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/requirements-gui.txt +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/requirements-viz.txt +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/requirements.txt +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/results/complete_mcrdr_extra.dot +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/results/complete_mcrdr_extra.png +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/results/complete_mcrdr_stop_only.dot +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/results/complete_mcrdr_stop_only.png +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/results/complete_mcrdr_stop_plus_rule.dot +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/results/complete_mcrdr_stop_plus_rule.png +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/results/complete_scrdr.dot +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/results/complete_scrdr.png +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/results/complete_scrdr_2.dot +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/results/complete_scrdr_2.png +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/results/complete_scrdr_3.dot +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/results/complete_scrdr_3.png +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/results/grdr_Habitat.dot +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/results/grdr_Habitat.png +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/results/grdr_Species.dot +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/results/grdr_Species.png +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/results/mcrdr_extra.dot +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/results/mcrdr_extra.png +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/results/mcrdr_extra_classify.dot +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/results/mcrdr_extra_classify.png +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/results/mcrdr_stop_plus_rule_combined.dot +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/results/mcrdr_stop_plus_rule_combined.png +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/results/partial_mcrdr_extra.dot +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/results/partial_mcrdr_extra.png +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/results/relational_scrdr_classify.dot +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/results/relational_scrdr_classify.png +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/scripts/live_dot_server_client.py +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/setup.cfg +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/src/ripple_down_rules/datastructures/__init__.py +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/src/ripple_down_rules/datastructures/case.py +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/src/ripple_down_rules/rdr_decorators.py +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/src/ripple_down_rules/start-code-server.sh +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/src/ripple_down_rules/user_interface/__init__.py +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/src/ripple_down_rules/user_interface/gui.py +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/src/ripple_down_rules/user_interface/ipython_custom_shell.py +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/src/ripple_down_rules/user_interface/object_diagram.py +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/src/ripple_down_rules/user_interface/template_file_creator.py +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/src/ripple_down_rules.egg-info/SOURCES.txt +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/src/ripple_down_rules.egg-info/dependency_links.txt +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/src/ripple_down_rules.egg-info/requires.txt +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/src/ripple_down_rules.egg-info/top_level.txt +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/test/__init__.py +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/test/conf/__init__.py +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/test/conf/world/__init__.py +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/test/conf/world/base_config.py +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/test/conf/world/handles_and_containers.py +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/test/conftest.py +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/test/datasets.py +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/test/factories/__init__.py +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/test/factories/world/__init__.py +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/test/factories/world/handles_and_containers.py +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/test/test_expert_answers/correct_drawer_rdr_expert_answers_fit.json +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/test/test_expert_answers/drawer_cabinet_expert_answers_fit.json +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/test/test_expert_answers/grdr_expert_answers_classify.json +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/test/test_expert_answers/grdr_expert_answers_fit.json +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/test/test_expert_answers/grdr_expert_answers_fit_extra.json +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/test/test_expert_answers/grdr_expert_answers_fit_no_targets.json +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/test/test_expert_answers/mcrdr_expert_answers_classify.json +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/test/test_expert_answers/mcrdr_expert_answers_fit_no_targets.json +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/test/test_expert_answers/mcrdr_expert_answers_stop_only_fit.json +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/test/test_expert_answers/mcrdr_extra_expert_answers_classify.json +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/test/test_expert_answers/mcrdr_extra_expert_answers_fit.json +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/test/test_expert_answers/mcrdr_multi_line_expert_answers_fit.json +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/test/test_expert_answers/mcrdr_stop_only_answers_fit.json +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/test/test_expert_answers/mcrdr_stop_plus_rule_answers_fit.json +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/test/test_expert_answers/mcrdr_stop_plus_rule_combined_expert_answers_fit.json +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/test/test_expert_answers/mcrdr_stop_plus_rule_expert_answers_fit.json +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/test/test_expert_answers/mutagenic_expert_answers.json +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/test/test_expert_answers/relational_scrdr_expert_answers_classify.json +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/test/test_expert_answers/scrdr_expert_answers_classify.json +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/test/test_expert_answers/scrdr_expert_answers_fit.json +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/test/test_expert_answers/scrdr_expert_answers_fit_no_targets.json +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/test/test_expert_answers/scrdr_multi_line_expert_answers_fit.json +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/test/test_expert_answers/scrdr_world_expert_answers_fit.json +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/test/test_generated_rdrs/__init__.py +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/test/test_helpers/__init__.py +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/test/test_helpers/helpers.py +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/test/test_helpers/object_diagram_case_query.png +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/test/test_helpers/object_diagram_person.png +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/test/test_object_diagram.py +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/test/test_on_mutagenic.py +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/test/test_rdr.py +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/test/test_rdr_alchemy.py +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/test/test_rdr_decorators.py +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/test/test_rdr_helpers_rdrs.py +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/test/test_rdr_world/__init__.py +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/test/test_rdr_world/conftest.py +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/test/test_rdr_world/test_rdr_world.py +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/test/test_relational_rdr.py +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/test/test_relational_rdr_alchemy.py +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/test/test_results/datasets_physical_object_is_a_robot/__init__.py +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/test/test_results/datasets_physical_object_is_a_robot/physical_object_is_a_robot_output__scrdr.py +1 -1
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/test/test_results/datasets_physical_object_is_a_robot/physical_object_is_a_robot_output__scrdr_defs.py +1 -1
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/test/test_results/datasets_physical_object_is_a_robot/physical_object_is_a_robot_rdr.py +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/test/test_results/datasets_physical_object_select_objects_that_are_parts_of_robot/__init__.py +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/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
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/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
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/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 +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/test/test_sql_model.py +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/test/test_template_file_creator.py +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/test/test_user_interface/__init__.py +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/test/test_user_interface/test_ipython.py +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/test/test_user_interface/test_ipython_copilot.py +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/test/test_user_interface/test_prompt.py +0 -0
- {ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/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.
|
3
|
+
Version: 0.6.25
|
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
|
@@ -95,7 +95,7 @@ class CallableExpression(SubclassJSONSerializer):
|
|
95
95
|
encapsulating_function_name: str = "_get_value"
|
96
96
|
|
97
97
|
def __init__(self, user_input: Optional[str] = None,
|
98
|
-
conclusion_type: Optional[Tuple[Type]] = None,
|
98
|
+
conclusion_type: Optional[Tuple[Type, ...]] = None,
|
99
99
|
expression_tree: Optional[AST] = None,
|
100
100
|
scope: Optional[Dict[str, Any]] = None,
|
101
101
|
conclusion: Optional[Any] = None,
|
@@ -176,7 +176,8 @@ class CallableExpression(SubclassJSONSerializer):
|
|
176
176
|
new_user_input = (f"{cond1_user_input}\n"
|
177
177
|
f"{cond2_user_input}\n"
|
178
178
|
f"return _cond1(case) and _cond2(case)")
|
179
|
-
return CallableExpression(new_user_input, conclusion_type=self.conclusion_type
|
179
|
+
return CallableExpression(new_user_input, conclusion_type=self.conclusion_type,
|
180
|
+
mutually_exclusive=self.mutually_exclusive)
|
180
181
|
|
181
182
|
def update_user_input_from_file(self, file_path: str, function_name: str):
|
182
183
|
"""
|
@@ -31,7 +31,7 @@ class CaseQuery:
|
|
31
31
|
"""
|
32
32
|
The name of the attribute.
|
33
33
|
"""
|
34
|
-
_attribute_types: Tuple[Type]
|
34
|
+
_attribute_types: Tuple[Type, ...]
|
35
35
|
"""
|
36
36
|
The type(s) of the attribute.
|
37
37
|
"""
|
@@ -139,7 +139,7 @@ class CaseQuery:
|
|
139
139
|
attribute_types_str = f"Union[{', '.join([t.__name__ for t in self.core_attribute_type])}]"
|
140
140
|
else:
|
141
141
|
attribute_types_str = self.core_attribute_type[0].__name__
|
142
|
-
if
|
142
|
+
if not self.mutually_exclusive:
|
143
143
|
return f"List[{attribute_types_str}]"
|
144
144
|
else:
|
145
145
|
return attribute_types_str
|
{ripple_down_rules-0.6.24 → ripple_down_rules-0.6.25}/src/ripple_down_rules/datastructures/enums.py
RENAMED
@@ -196,7 +196,10 @@ class RDREdge(Enum):
|
|
196
196
|
"""
|
197
197
|
Next edge, the edge that represents the next rule to be evaluated.
|
198
198
|
"""
|
199
|
-
|
199
|
+
Filter = "filter if"
|
200
|
+
"""
|
201
|
+
Filter edge, the edge that represents the filter condition.
|
202
|
+
"""
|
200
203
|
|
201
204
|
class ValueType(Enum):
|
202
205
|
Unary = auto()
|
@@ -41,14 +41,14 @@ class Expert(ABC):
|
|
41
41
|
A flag to indicate if the expert should use loaded answers or not.
|
42
42
|
"""
|
43
43
|
|
44
|
-
def __init__(self, use_loaded_answers: bool =
|
44
|
+
def __init__(self, use_loaded_answers: bool = False,
|
45
45
|
append: bool = False,
|
46
46
|
answers_save_path: Optional[str] = None):
|
47
47
|
self.all_expert_answers = []
|
48
48
|
self.use_loaded_answers = use_loaded_answers
|
49
49
|
self.append = append
|
50
50
|
self.answers_save_path = answers_save_path
|
51
|
-
if answers_save_path is not None:
|
51
|
+
if answers_save_path is not None and os.path.exists(answers_save_path + '.py'):
|
52
52
|
if use_loaded_answers:
|
53
53
|
self.load_answers(answers_save_path)
|
54
54
|
else:
|
@@ -2,15 +2,14 @@ from __future__ import annotations
|
|
2
2
|
|
3
3
|
import os
|
4
4
|
from types import ModuleType
|
5
|
+
from typing import Tuple
|
5
6
|
|
6
|
-
from ripple_down_rules.datastructures.dataclasses import CaseFactoryMetaData
|
7
|
-
|
8
|
-
from .datastructures.case import create_case
|
9
|
-
from .datastructures.dataclasses import CaseQuery
|
10
7
|
from typing_extensions import Type, Optional, Callable, Any, Dict, TYPE_CHECKING, Union
|
11
8
|
|
12
|
-
from .
|
9
|
+
from .datastructures.case import create_case, Case
|
10
|
+
from .datastructures.dataclasses import CaseQuery
|
13
11
|
from .utils import calculate_precision_and_recall
|
12
|
+
from .utils import get_func_rdr_model_name, copy_case, make_set, update_case
|
14
13
|
|
15
14
|
if TYPE_CHECKING:
|
16
15
|
from .rdr import RippleDownRules
|
@@ -55,12 +54,14 @@ def general_rdr_classify(classifiers_dict: Dict[str, Union[ModuleType, RippleDow
|
|
55
54
|
if attribute_name in new_conclusions:
|
56
55
|
temp_case_query = CaseQuery(case_cp, attribute_name, rdr.conclusion_type, rdr.mutually_exclusive)
|
57
56
|
update_case(temp_case_query, new_conclusions)
|
58
|
-
if len(new_conclusions) == 0 or len(classifiers_dict) == 1 and list(classifiers_dict.values())[
|
57
|
+
if len(new_conclusions) == 0 or len(classifiers_dict) == 1 and list(classifiers_dict.values())[
|
58
|
+
0].mutually_exclusive:
|
59
59
|
break
|
60
60
|
return conclusions
|
61
61
|
|
62
62
|
|
63
|
-
def is_matching(classifier: Callable[[Any], Any], case_query: CaseQuery,
|
63
|
+
def is_matching(classifier: Callable[[Any], Any], case_query: CaseQuery,
|
64
|
+
pred_cat: Optional[Dict[str, Any]] = None) -> bool:
|
64
65
|
"""
|
65
66
|
:param classifier: The RDR classifier to check the prediction of.
|
66
67
|
:param case_query: The case query to check.
|
@@ -95,3 +96,23 @@ def load_or_create_func_rdr_model(func, model_dir: str, rdr_type: Type[RippleDow
|
|
95
96
|
else:
|
96
97
|
rdr = rdr_type(**rdr_kwargs)
|
97
98
|
return rdr
|
99
|
+
|
100
|
+
|
101
|
+
def get_an_updated_case_copy(case: Case, conclusion: Callable, attribute_name: str, conclusion_type: Tuple[Type, ...],
|
102
|
+
mutually_exclusive: bool) -> Case:
|
103
|
+
"""
|
104
|
+
:param case: The case to copy and update.
|
105
|
+
:param conclusion: The conclusion to add to the case.
|
106
|
+
:param attribute_name: The name of the attribute to update.
|
107
|
+
:param conclusion_type: The type of the conclusion to update.
|
108
|
+
:param mutually_exclusive: Whether the rule belongs to a mutually exclusive RDR.
|
109
|
+
:return: A copy of the case updated with the given conclusion.
|
110
|
+
"""
|
111
|
+
case_cp = copy_case(case)
|
112
|
+
temp_case_query = CaseQuery(case_cp, attribute_name, conclusion_type,
|
113
|
+
mutually_exclusive=mutually_exclusive)
|
114
|
+
output = conclusion(case_cp)
|
115
|
+
if not isinstance(output, Dict):
|
116
|
+
output = {attribute_name: output}
|
117
|
+
update_case(temp_case_query, output)
|
118
|
+
return case_cp
|
@@ -1,12 +1,12 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
|
3
3
|
import importlib
|
4
|
+
import json
|
4
5
|
import os
|
5
6
|
from abc import ABC, abstractmethod
|
6
7
|
from copy import copy
|
7
8
|
from dataclasses import is_dataclass
|
8
9
|
from types import NoneType
|
9
|
-
import json
|
10
10
|
|
11
11
|
from ripple_down_rules.datastructures.dataclasses import CaseFactoryMetaData
|
12
12
|
from . import logger
|
@@ -29,16 +29,17 @@ from .datastructures.case import Case, CaseAttribute, create_case
|
|
29
29
|
from .datastructures.dataclasses import CaseQuery
|
30
30
|
from .datastructures.enums import MCRDRMode
|
31
31
|
from .experts import Expert, Human
|
32
|
-
from .helpers import is_matching, general_rdr_classify
|
33
|
-
from .rules import Rule, SingleClassRule, MultiClassTopRule, MultiClassStopRule
|
32
|
+
from .helpers import is_matching, general_rdr_classify, get_an_updated_case_copy
|
33
|
+
from .rules import Rule, SingleClassRule, MultiClassTopRule, MultiClassStopRule, MultiClassRefinementRule, \
|
34
|
+
MultiClassFilterRule
|
34
35
|
|
35
36
|
try:
|
36
37
|
from .user_interface.gui import RDRCaseViewer
|
37
38
|
except ImportError as e:
|
38
39
|
RDRCaseViewer = None
|
39
40
|
from .utils import draw_tree, make_set, SubclassJSONSerializer, make_list, get_type_from_string, \
|
40
|
-
|
41
|
-
is_iterable, str_to_snake_case, get_import_path_from_path, get_imports_from_types, render_tree
|
41
|
+
is_value_conflicting, extract_function_source, extract_imports, get_full_class_name, \
|
42
|
+
is_iterable, str_to_snake_case, get_import_path_from_path, get_imports_from_types, render_tree
|
42
43
|
|
43
44
|
|
44
45
|
class RippleDownRules(SubclassJSONSerializer, ABC):
|
@@ -500,25 +501,51 @@ class RDRWithCodeWriter(RippleDownRules, ABC):
|
|
500
501
|
conclusion_func_names = [f'conclusion_{rid}' for rid in rules_dict.keys()
|
501
502
|
if not isinstance(rules_dict[rid], MultiClassStopRule)]
|
502
503
|
all_func_names = condition_func_names + conclusion_func_names
|
504
|
+
rule_tree_file_path = f"{model_dir}/{self.generated_python_file_name}.py"
|
503
505
|
filepath = f"{model_dir}/{self.generated_python_defs_file_name}.py"
|
504
506
|
cases_path = f"{model_dir}/{self.generated_python_cases_file_name}.py"
|
505
507
|
cases_import_path = get_import_path_from_path(model_dir)
|
506
508
|
cases_import_path = f"{cases_import_path}.{self.generated_python_cases_file_name}" if cases_import_path \
|
507
509
|
else self.generated_python_cases_file_name
|
508
510
|
functions_source = extract_function_source(filepath, all_func_names, include_signature=False)
|
511
|
+
python_rule_tree_source = ""
|
512
|
+
with open(rule_tree_file_path, "r") as rule_tree_source:
|
513
|
+
python_rule_tree_source = rule_tree_source.read()
|
509
514
|
# get the scope from the imports in the file
|
510
515
|
scope = extract_imports(filepath, package_name=package_name)
|
516
|
+
rules_not_found = set()
|
511
517
|
for rule in [self.start_rule] + list(self.start_rule.descendants):
|
512
518
|
if rule.conditions is not None:
|
513
|
-
|
519
|
+
conditions_name = rule.generated_conditions_function_name
|
520
|
+
if conditions_name not in functions_source or conditions_name not in python_rule_tree_source:
|
521
|
+
rules_not_found.add(rule)
|
522
|
+
continue
|
523
|
+
rule.conditions.user_input = functions_source[conditions_name]
|
514
524
|
rule.conditions.scope = scope
|
515
525
|
if os.path.exists(cases_path):
|
516
526
|
module = importlib.import_module(cases_import_path, package=package_name)
|
517
527
|
importlib.reload(module)
|
518
528
|
rule.corner_case_metadata = module.__dict__.get(f"corner_case_{rule.uid}", None)
|
519
|
-
if
|
520
|
-
|
529
|
+
if not isinstance(rule, MultiClassStopRule):
|
530
|
+
conclusion_name = rule.generated_conclusion_function_name
|
531
|
+
if conclusion_name not in functions_source or conclusion_name not in python_rule_tree_source:
|
532
|
+
rules_not_found.add(rule)
|
533
|
+
rule.conclusion.user_input = functions_source[conclusion_name]
|
521
534
|
rule.conclusion.scope = scope
|
535
|
+
for rule in rules_not_found:
|
536
|
+
if isinstance(rule, MultiClassTopRule):
|
537
|
+
import pdb; pdb.set_trace()
|
538
|
+
rule.parent.set_immediate_alternative(rule.alternative)
|
539
|
+
if rule.refinement is not None:
|
540
|
+
ref_rules = [ref_rule for ref_rule in [rule.refinement] + list(rule.refinement.descendants)]
|
541
|
+
for ref_rule in ref_rules:
|
542
|
+
del ref_rule
|
543
|
+
else:
|
544
|
+
rule.parent.refinement = rule.alternative
|
545
|
+
if rule.alternative is not None:
|
546
|
+
rule.alternative = None
|
547
|
+
rule.parent = None
|
548
|
+
del rule
|
522
549
|
|
523
550
|
@abstractmethod
|
524
551
|
def write_rules_as_source_code_to_file(self, rule: Rule, file, parent_indent: str = "",
|
@@ -597,7 +624,7 @@ class RDRWithCodeWriter(RippleDownRules, ABC):
|
|
597
624
|
"""
|
598
625
|
pass
|
599
626
|
|
600
|
-
def _get_types_to_import(self) -> Tuple[Set[Type], Set[Type], Set[Type]]:
|
627
|
+
def _get_types_to_import(self) -> Tuple[Set[Union[Type, Callable]], Set[Type], Set[Type]]:
|
601
628
|
"""
|
602
629
|
:return: The types of the main, defs, and corner cases files of the RDR classifier that will be imported.
|
603
630
|
"""
|
@@ -930,6 +957,9 @@ class MultiClassRDR(RDRWithCodeWriter):
|
|
930
957
|
if rule.alternative:
|
931
958
|
self.write_rules_as_source_code_to_file(rule.alternative, filename, parent_indent, defs_file=defs_file,
|
932
959
|
cases_file=cases_file, package_name=package_name)
|
960
|
+
elif isinstance(rule, MultiClassTopRule):
|
961
|
+
with open(filename, "a") as file:
|
962
|
+
file.write(f"{parent_indent}return conclusions\n")
|
933
963
|
|
934
964
|
@property
|
935
965
|
def conclusion_type_hint(self) -> str:
|
@@ -939,8 +969,9 @@ class MultiClassRDR(RDRWithCodeWriter):
|
|
939
969
|
else:
|
940
970
|
return f"Set[Union[{', '.join(conclusion_types)}]]"
|
941
971
|
|
942
|
-
def _get_types_to_import(self) -> Tuple[Set[Type], Set[Type], Set[Type]]:
|
972
|
+
def _get_types_to_import(self) -> Tuple[Set[Union[Type, Callable]], Set[Type], Set[Type]]:
|
943
973
|
main_types, defs_types, cases_types = super()._get_types_to_import()
|
974
|
+
main_types.add(get_an_updated_case_copy)
|
944
975
|
main_types.update({Set, make_set})
|
945
976
|
defs_types.update({List, Set})
|
946
977
|
return main_types, defs_types, cases_types
|
@@ -972,28 +1003,43 @@ class MultiClassRDR(RDRWithCodeWriter):
|
|
972
1003
|
Stop a wrong conclusion by adding a stopping rule.
|
973
1004
|
"""
|
974
1005
|
rule_conclusion = evaluated_rule.conclusion(case_query.case)
|
975
|
-
|
976
|
-
|
977
|
-
|
1006
|
+
stop: bool = False
|
1007
|
+
add_filter_rule: bool = False
|
1008
|
+
if is_value_conflicting(rule_conclusion, case_query.target_value):
|
1009
|
+
if make_set(case_query.target_value).issubset(rule_conclusion):
|
1010
|
+
add_filter_rule = True
|
1011
|
+
else:
|
1012
|
+
stop = True
|
1013
|
+
elif make_set(case_query.core_attribute_type).issubset(make_set(evaluated_rule.conclusion.conclusion_type)):
|
1014
|
+
if make_set(case_query.target_value).issubset(rule_conclusion):
|
1015
|
+
add_filter_rule = True
|
1016
|
+
|
1017
|
+
if not stop:
|
978
1018
|
self.add_conclusion(rule_conclusion)
|
1019
|
+
if stop or add_filter_rule:
|
1020
|
+
refinement_type = MultiClassStopRule if stop else MultiClassFilterRule
|
1021
|
+
self.stop_or_filter_conclusion(case_query, expert, evaluated_rule, refinement_type=refinement_type)
|
979
1022
|
|
980
|
-
def
|
981
|
-
|
1023
|
+
def stop_or_filter_conclusion(self, case_query: CaseQuery,
|
1024
|
+
expert: Expert, evaluated_rule: MultiClassTopRule,
|
1025
|
+
refinement_type: Type[MultiClassRefinementRule] = MultiClassStopRule):
|
982
1026
|
"""
|
983
1027
|
Stop a conclusion by adding a stopping rule.
|
984
1028
|
|
985
1029
|
:param case_query: The case query to stop the conclusion for.
|
986
1030
|
:param expert: The expert to ask for differentiating features as new rule conditions.
|
987
1031
|
:param evaluated_rule: The evaluated rule to ask the expert about.
|
1032
|
+
:param refinement_type: The refinement type to use.
|
988
1033
|
"""
|
989
1034
|
conditions = expert.ask_for_conditions(case_query, evaluated_rule)
|
990
|
-
evaluated_rule.fit_rule(case_query)
|
991
|
-
if
|
992
|
-
self.
|
993
|
-
|
994
|
-
|
995
|
-
|
996
|
-
|
1035
|
+
evaluated_rule.fit_rule(case_query, refinement_type=refinement_type)
|
1036
|
+
if refinement_type is MultiClassStopRule:
|
1037
|
+
if self.mode == MCRDRMode.StopPlusRule:
|
1038
|
+
self.stop_rule_conditions = conditions
|
1039
|
+
if self.mode == MCRDRMode.StopPlusRuleCombined:
|
1040
|
+
new_top_rule_conditions = conditions.combine_with(evaluated_rule.conditions)
|
1041
|
+
case_query.conditions = new_top_rule_conditions
|
1042
|
+
self.add_top_rule(case_query)
|
997
1043
|
|
998
1044
|
def add_rule_for_case(self, case_query: CaseQuery, expert: Expert):
|
999
1045
|
"""
|