ripple-down-rules 0.5.89__py3-none-any.whl → 0.5.91__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ripple_down_rules/__init__.py +1 -1
- ripple_down_rules/datastructures/case.py +7 -6
- ripple_down_rules/experts.py +8 -6
- ripple_down_rules/user_interface/prompt.py +23 -20
- {ripple_down_rules-0.5.89.dist-info → ripple_down_rules-0.5.91.dist-info}/METADATA +1 -1
- {ripple_down_rules-0.5.89.dist-info → ripple_down_rules-0.5.91.dist-info}/RECORD +9 -9
- {ripple_down_rules-0.5.89.dist-info → ripple_down_rules-0.5.91.dist-info}/WHEEL +0 -0
- {ripple_down_rules-0.5.89.dist-info → ripple_down_rules-0.5.91.dist-info}/licenses/LICENSE +0 -0
- {ripple_down_rules-0.5.89.dist-info → ripple_down_rules-0.5.91.dist-info}/top_level.txt +0 -0
ripple_down_rules/__init__.py
CHANGED
@@ -329,9 +329,9 @@ def create_case_attribute_from_iterable_attribute(attr_value: Any, name: str, ob
|
|
329
329
|
|
330
330
|
def show_current_and_corner_cases(case: Any, targets: Optional[Dict[str, Any]] = None,
|
331
331
|
current_conclusions: Optional[Dict[str, Any]] = None,
|
332
|
-
last_evaluated_rule: Optional[Rule] = None) ->
|
332
|
+
last_evaluated_rule: Optional[Rule] = None) -> str:
|
333
333
|
"""
|
334
|
-
|
334
|
+
Get the the data to show of the new case and if last evaluated rule exists also show that of the corner case.
|
335
335
|
|
336
336
|
:param case: The new case.
|
337
337
|
:param targets: The target attribute of the case.
|
@@ -341,9 +341,10 @@ def show_current_and_corner_cases(case: Any, targets: Optional[Dict[str, Any]] =
|
|
341
341
|
corner_case = None
|
342
342
|
targets = {f"target_{name}": value for name, value in targets.items()} if targets else {}
|
343
343
|
current_conclusions = {name: value for name, value in current_conclusions.items()} if current_conclusions else {}
|
344
|
+
information = ""
|
344
345
|
if last_evaluated_rule:
|
345
346
|
action = "Refinement" if last_evaluated_rule.fired else "Alternative"
|
346
|
-
|
347
|
+
information += f"{action} needed for rule: {last_evaluated_rule}\n"
|
347
348
|
corner_case = last_evaluated_rule.corner_case
|
348
349
|
|
349
350
|
corner_row_dict = None
|
@@ -367,6 +368,6 @@ def show_current_and_corner_cases(case: Any, targets: Optional[Dict[str, Any]] =
|
|
367
368
|
corner_conclusion = last_evaluated_rule.conclusion(case)
|
368
369
|
corner_row_dict.update({corner_conclusion.__class__.__name__: corner_conclusion})
|
369
370
|
all_table_rows.append(corner_row_dict)
|
370
|
-
|
371
|
-
|
372
|
-
|
371
|
+
information += "\n" + "=" * 50 + "\n"
|
372
|
+
information += "\n" + table_rows_as_str(all_table_rows) + "\n"
|
373
|
+
return information
|
ripple_down_rules/experts.py
CHANGED
@@ -225,12 +225,13 @@ class Human(Expert):
|
|
225
225
|
def ask_for_conditions(self, case_query: CaseQuery,
|
226
226
|
last_evaluated_rule: Optional[Rule] = None) \
|
227
227
|
-> CallableExpression:
|
228
|
+
data_to_show = None
|
228
229
|
if (not self.use_loaded_answers or len(self.all_expert_answers) == 0) and self.user_prompt.viewer is None:
|
229
|
-
show_current_and_corner_cases(case_query.case, {case_query.attribute_name: case_query.target_value},
|
230
|
+
data_to_show = show_current_and_corner_cases(case_query.case, {case_query.attribute_name: case_query.target_value},
|
230
231
|
last_evaluated_rule=last_evaluated_rule)
|
231
|
-
return self._get_conditions(case_query)
|
232
|
+
return self._get_conditions(case_query, data_to_show)
|
232
233
|
|
233
|
-
def _get_conditions(self, case_query: CaseQuery) \
|
234
|
+
def _get_conditions(self, case_query: CaseQuery, data_to_show: Optional[str] = None) \
|
234
235
|
-> CallableExpression:
|
235
236
|
"""
|
236
237
|
Ask the expert to provide the differentiating features between two cases or unique features for a case
|
@@ -251,7 +252,7 @@ class Human(Expert):
|
|
251
252
|
case_query.scope.update(loaded_scope)
|
252
253
|
condition = CallableExpression(user_input, bool, scope=case_query.scope)
|
253
254
|
else:
|
254
|
-
user_input, condition = self.user_prompt.prompt_user_for_expression(case_query, PromptFor.Conditions)
|
255
|
+
user_input, condition = self.user_prompt.prompt_user_for_expression(case_query, PromptFor.Conditions, prompt_str=data_to_show)
|
255
256
|
if user_input == 'exit':
|
256
257
|
exit()
|
257
258
|
if not self.use_loaded_answers:
|
@@ -283,9 +284,10 @@ class Human(Expert):
|
|
283
284
|
except IndexError:
|
284
285
|
self.use_loaded_answers = False
|
285
286
|
if not self.use_loaded_answers:
|
287
|
+
data_to_show = None
|
286
288
|
if self.user_prompt.viewer is None:
|
287
|
-
show_current_and_corner_cases(case_query.case)
|
288
|
-
expert_input, expression = self.user_prompt.prompt_user_for_expression(case_query, PromptFor.Conclusion)
|
289
|
+
data_to_show = show_current_and_corner_cases(case_query.case)
|
290
|
+
expert_input, expression = self.user_prompt.prompt_user_for_expression(case_query, PromptFor.Conclusion, prompt_str=data_to_show)
|
289
291
|
if expert_input is None:
|
290
292
|
self.all_expert_answers.append(({}, None))
|
291
293
|
elif expert_input != 'exit':
|
@@ -20,14 +20,14 @@ from ..datastructures.dataclasses import CaseQuery
|
|
20
20
|
from ..datastructures.enums import PromptFor
|
21
21
|
from .ipython_custom_shell import IPythonShell
|
22
22
|
from ..utils import make_list
|
23
|
-
from threading import
|
23
|
+
from threading import RLock
|
24
24
|
|
25
25
|
|
26
26
|
class UserPrompt:
|
27
27
|
"""
|
28
28
|
A class to handle user prompts for the RDR.
|
29
29
|
"""
|
30
|
-
shell_lock:
|
30
|
+
shell_lock: RLock = RLock() # To ensure that only one thread can access the shell at a time
|
31
31
|
|
32
32
|
def __init__(self, viewer: Optional[RDRCaseViewer] = None):
|
33
33
|
"""
|
@@ -52,8 +52,8 @@ class UserPrompt:
|
|
52
52
|
prev_user_input: Optional[str] = None
|
53
53
|
callable_expression: Optional[CallableExpression] = None
|
54
54
|
while True:
|
55
|
-
|
56
|
-
|
55
|
+
with self.shell_lock:
|
56
|
+
user_input, expression_tree = self.prompt_user_about_case(case_query, prompt_for, prompt_str, code_to_modify=prev_user_input)
|
57
57
|
if user_input is None:
|
58
58
|
if prompt_for == PromptFor.Conclusion:
|
59
59
|
self.print_func(f"{Fore.YELLOW}No conclusion provided. Exiting.{Style.RESET_ALL}")
|
@@ -95,23 +95,26 @@ class UserPrompt:
|
|
95
95
|
:param code_to_modify: The code to modify. If given will be used as a start for user to modify.
|
96
96
|
:return: The user input, and the executable expression that was parsed from the user input.
|
97
97
|
"""
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
98
|
+
self.print_func("Entered shell")
|
99
|
+
prompt_str = f"{Fore.WHITE}{prompt_str}" if prompt_str is not None else ''
|
100
|
+
if prompt_for == PromptFor.Conclusion:
|
101
|
+
prompt_str += f"\n{Fore.MAGENTA}Give possible value(s) for:"
|
102
|
+
else:
|
103
|
+
prompt_str += f"\n{Fore.MAGENTA}Give conditions on when can the rule be evaluated for:"
|
103
104
|
case_query.scope.update({'case': case_query.case})
|
104
105
|
shell = None
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
106
|
+
if self.viewer is None:
|
107
|
+
prompt_str = self.construct_prompt_str_for_shell(case_query, prompt_for, prompt_str)
|
108
|
+
shell = IPythonShell(header=prompt_str, prompt_for=prompt_for, case_query=case_query,
|
109
|
+
code_to_modify=code_to_modify)
|
110
|
+
else:
|
111
|
+
|
112
|
+
self.viewer.update_for_case_query(case_query, prompt_str,
|
113
|
+
prompt_for=prompt_for, code_to_modify=code_to_modify)
|
114
|
+
user_input, expression_tree = self.prompt_user_input_and_parse_to_expression(shell=shell)
|
115
|
+
self.print_func("Exited shell")
|
116
|
+
return user_input, expression_tree
|
111
117
|
|
112
|
-
self.viewer.update_for_case_query(case_query, prompt_str,
|
113
|
-
prompt_for=prompt_for, code_to_modify=code_to_modify)
|
114
|
-
return self.prompt_user_input_and_parse_to_expression(shell=shell)
|
115
118
|
|
116
119
|
|
117
120
|
def construct_prompt_str_for_shell(self, case_query: CaseQuery, prompt_for: PromptFor,
|
@@ -129,9 +132,9 @@ class UserPrompt:
|
|
129
132
|
prompt_str += (f"\ne.g. `{Fore.GREEN}return {Fore.BLUE}len{Fore.RESET}(case.attribute) > {Fore.BLUE}0` "
|
130
133
|
f"{Fore.MAGENTA}\nOR `{Fore.GREEN}return {Fore.YELLOW}True`{Fore.MAGENTA} (If you want the"
|
131
134
|
f" rule to be always evaluated) \n"
|
132
|
-
f"You can also do {Fore.YELLOW}%edit{Fore.MAGENTA} for more complex conditions
|
135
|
+
f"You can also do {Fore.YELLOW}%edit{Fore.MAGENTA} for more complex conditions.\n")
|
133
136
|
|
134
|
-
prompt_str = f"{Fore.MAGENTA}{prompt_str}{Fore.YELLOW}\n(Write %help for guide){Fore.RESET}"
|
137
|
+
prompt_str = f"{Fore.MAGENTA}{prompt_str}{Fore.YELLOW}\n(Write %help for guide){Fore.RESET}\n"
|
135
138
|
return prompt_str
|
136
139
|
|
137
140
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: ripple_down_rules
|
3
|
-
Version: 0.5.
|
3
|
+
Version: 0.5.91
|
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,5 +1,5 @@
|
|
1
|
-
ripple_down_rules/__init__.py,sha256=
|
2
|
-
ripple_down_rules/experts.py,sha256=
|
1
|
+
ripple_down_rules/__init__.py,sha256=uyb8hWuyA5vHaaPt2RGAvSO9sYTIhVRfdLUv8-D-KIE,100
|
2
|
+
ripple_down_rules/experts.py,sha256=4-dMIVeMzFXCLYl_XBG_P7_Xs4sZih9-vZxCIPri6dA,12958
|
3
3
|
ripple_down_rules/helpers.py,sha256=v4oE7C5PfQUVJfSUs1FfLHEwrJXEHJLn4vJhJMvyCR8,4453
|
4
4
|
ripple_down_rules/rdr.py,sha256=C6bvlq6MsKa2Mym1wW6JUMj705aCaoihTP279TM6eT0,55218
|
5
5
|
ripple_down_rules/rdr_decorators.py,sha256=pj7SwswB9UVdv4-c8pzcOsGTG0Elt7JEG6k65fsnOdk,9202
|
@@ -8,17 +8,17 @@ ripple_down_rules/start-code-server.sh,sha256=otClk7VmDgBOX2TS_cjws6K0UwvgAUJhoA
|
|
8
8
|
ripple_down_rules/utils.py,sha256=KvD-uqPfHw5THsIrR0D52oKqKggvKk5sfachARDg7PM,61978
|
9
9
|
ripple_down_rules/datastructures/__init__.py,sha256=V2aNgf5C96Y5-IGghra3n9uiefpoIm_QdT7cc_C8cxQ,111
|
10
10
|
ripple_down_rules/datastructures/callable_expression.py,sha256=f3wUPTrLa1INO-1qfgVz87ryrCABronfyq0_JKWoZCs,12800
|
11
|
-
ripple_down_rules/datastructures/case.py,sha256=
|
11
|
+
ripple_down_rules/datastructures/case.py,sha256=PJ7_-AdxYic6BO5z816piFODj6nU5J6Jt1YzTFH-dds,15510
|
12
12
|
ripple_down_rules/datastructures/dataclasses.py,sha256=qoTFHV8Hi-X8VtfC9VdvH4tif73YjF3dUe8dyHXTYts,10993
|
13
13
|
ripple_down_rules/datastructures/enums.py,sha256=ce7tqS0otfSTNAOwsnXlhsvIn4iW_Y_N3TNebF3YoZs,5700
|
14
14
|
ripple_down_rules/user_interface/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
15
15
|
ripple_down_rules/user_interface/gui.py,sha256=_lgZAUXxxaBUFQJAHjA5TBPp6XEvJ62t-kSN8sPsocE,27379
|
16
16
|
ripple_down_rules/user_interface/ipython_custom_shell.py,sha256=6v99tlNcfRyZpnPxq3FfqgFgxbJ5zkA2jVAXamTH1C0,6575
|
17
17
|
ripple_down_rules/user_interface/object_diagram.py,sha256=FEa2HaYR9QmTE6NsOwBvZ0jqmu3DKyg6mig2VE5ZP4Y,4956
|
18
|
-
ripple_down_rules/user_interface/prompt.py,sha256=
|
18
|
+
ripple_down_rules/user_interface/prompt.py,sha256=JceEUGYsd0lIvd-v2y3D3swoo96_C0lxfp3CxM7Vfts,8900
|
19
19
|
ripple_down_rules/user_interface/template_file_creator.py,sha256=ELHYhZEjHsMdG5ebbOghfZtPBpPtuJDWQRAkLpfcSFM,13553
|
20
|
-
ripple_down_rules-0.5.
|
21
|
-
ripple_down_rules-0.5.
|
22
|
-
ripple_down_rules-0.5.
|
23
|
-
ripple_down_rules-0.5.
|
24
|
-
ripple_down_rules-0.5.
|
20
|
+
ripple_down_rules-0.5.91.dist-info/licenses/LICENSE,sha256=ixuiBLtpoK3iv89l7ylKkg9rs2GzF9ukPH7ynZYzK5s,35148
|
21
|
+
ripple_down_rules-0.5.91.dist-info/METADATA,sha256=MUz6L1fPCoVAOBvI6hXOqBceYxcnQRbRdGVtT7U1ER0,48214
|
22
|
+
ripple_down_rules-0.5.91.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
23
|
+
ripple_down_rules-0.5.91.dist-info/top_level.txt,sha256=VeoLhEhyK46M1OHwoPbCQLI1EifLjChqGzhQ6WEUqeM,18
|
24
|
+
ripple_down_rules-0.5.91.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|