ripple-down-rules 0.5.53__py3-none-any.whl → 0.5.55__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/callable_expression.py +14 -8
- ripple_down_rules/experts.py +3 -1
- ripple_down_rules/utils.py +8 -1
- {ripple_down_rules-0.5.53.dist-info → ripple_down_rules-0.5.55.dist-info}/METADATA +1 -1
- {ripple_down_rules-0.5.53.dist-info → ripple_down_rules-0.5.55.dist-info}/RECORD +9 -9
- {ripple_down_rules-0.5.53.dist-info → ripple_down_rules-0.5.55.dist-info}/WHEEL +0 -0
- {ripple_down_rules-0.5.53.dist-info → ripple_down_rules-0.5.55.dist-info}/licenses/LICENSE +0 -0
- {ripple_down_rules-0.5.53.dist-info → ripple_down_rules-0.5.55.dist-info}/top_level.txt +0 -0
ripple_down_rules/__init__.py
CHANGED
@@ -93,7 +93,6 @@ class CallableExpression(SubclassJSONSerializer):
|
|
93
93
|
A callable that is constructed from a string statement written by an expert.
|
94
94
|
"""
|
95
95
|
encapsulating_function_name: str = "_get_value"
|
96
|
-
encapsulating_function: str = f"def {encapsulating_function_name}(case):"
|
97
96
|
|
98
97
|
def __init__(self, user_input: Optional[str] = None,
|
99
98
|
conclusion_type: Optional[Tuple[Type]] = None,
|
@@ -117,7 +116,7 @@ class CallableExpression(SubclassJSONSerializer):
|
|
117
116
|
if user_input is None:
|
118
117
|
user_input = build_user_input_from_conclusion(conclusion)
|
119
118
|
self.conclusion: Optional[Any] = conclusion
|
120
|
-
self._user_input: str = encapsulate_user_input(user_input, self.
|
119
|
+
self._user_input: str = encapsulate_user_input(user_input, self.get_encapsulating_function())
|
121
120
|
if conclusion_type is not None:
|
122
121
|
if is_iterable(conclusion_type):
|
123
122
|
conclusion_type = tuple(conclusion_type)
|
@@ -132,6 +131,13 @@ class CallableExpression(SubclassJSONSerializer):
|
|
132
131
|
self.visitor.visit(self.expression_tree)
|
133
132
|
self.mutually_exclusive: bool = mutually_exclusive
|
134
133
|
|
134
|
+
@classmethod
|
135
|
+
def get_encapsulating_function(cls, postfix: str = '') -> str:
|
136
|
+
"""
|
137
|
+
Get the encapsulating function that is used to wrap the user input.
|
138
|
+
"""
|
139
|
+
return f"def {cls.encapsulating_function_name}{postfix}(case):"
|
140
|
+
|
135
141
|
def __call__(self, case: Any, **kwargs) -> Any:
|
136
142
|
try:
|
137
143
|
if self.user_input is not None:
|
@@ -161,8 +167,8 @@ class CallableExpression(SubclassJSONSerializer):
|
|
161
167
|
"""
|
162
168
|
Combine this callable expression with another callable expression using the 'and' operator.
|
163
169
|
"""
|
164
|
-
cond1_user_input = self.user_input.replace(self.
|
165
|
-
cond2_user_input = other.user_input.replace(self.
|
170
|
+
cond1_user_input = self.user_input.replace(self.get_encapsulating_function(), "def _cond1(case):")
|
171
|
+
cond2_user_input = other.user_input.replace(self.get_encapsulating_function(), "def _cond2(case):")
|
166
172
|
new_user_input = (f"{cond1_user_input}\n"
|
167
173
|
f"{cond2_user_input}\n"
|
168
174
|
f"return _cond1(case) and _cond2(case)")
|
@@ -175,7 +181,7 @@ class CallableExpression(SubclassJSONSerializer):
|
|
175
181
|
new_function_body = extract_function_source(file_path, [function_name])[function_name]
|
176
182
|
if new_function_body is None:
|
177
183
|
return
|
178
|
-
self.user_input = self.
|
184
|
+
self.user_input = self.get_encapsulating_function() + '\n' + new_function_body
|
179
185
|
|
180
186
|
def write_to_python_file(self, file_path: str, append: bool = False):
|
181
187
|
"""
|
@@ -208,7 +214,7 @@ class CallableExpression(SubclassJSONSerializer):
|
|
208
214
|
Set the user input.
|
209
215
|
"""
|
210
216
|
if value is not None:
|
211
|
-
self._user_input = encapsulate_user_input(value, self.
|
217
|
+
self._user_input = encapsulate_user_input(value, self.get_encapsulating_function())
|
212
218
|
self.scope = get_used_scope(self.user_input, self.scope)
|
213
219
|
self.expression_tree = parse_string_to_expression(self.user_input)
|
214
220
|
self.code = compile_expression_to_code(self.expression_tree)
|
@@ -286,8 +292,8 @@ def parse_string_to_expression(expression_str: str) -> AST:
|
|
286
292
|
:param expression_str: The string which will be parsed.
|
287
293
|
:return: The parsed expression.
|
288
294
|
"""
|
289
|
-
if not expression_str.startswith(CallableExpression.
|
290
|
-
expression_str = encapsulate_user_input(expression_str, CallableExpression.
|
295
|
+
if not expression_str.startswith(CallableExpression.get_encapsulating_function()):
|
296
|
+
expression_str = encapsulate_user_input(expression_str, CallableExpression.get_encapsulating_function())
|
291
297
|
mode = 'exec' if expression_str.startswith('def') else 'eval'
|
292
298
|
tree = ast.parse(expression_str, mode=mode)
|
293
299
|
logging.debug(f"AST parsed successfully: {ast.dump(tree)}")
|
ripple_down_rules/experts.py
CHANGED
@@ -147,7 +147,7 @@ class Expert(ABC):
|
|
147
147
|
imports = ''
|
148
148
|
if func_source is not None:
|
149
149
|
uid = uuid.uuid4().hex
|
150
|
-
func_source = encapsulate_user_input(func_source, CallableExpression.
|
150
|
+
func_source = encapsulate_user_input(func_source, CallableExpression.get_encapsulating_function(f'_{uid}'))
|
151
151
|
else:
|
152
152
|
func_source = 'pass # No user input provided for this case.\n'
|
153
153
|
f.write(imports + func_source + '\n' + '\n\n\n\'===New Answer===\'\n\n\n')
|
@@ -241,6 +241,7 @@ class Human(Expert):
|
|
241
241
|
except IndexError:
|
242
242
|
self.use_loaded_answers = False
|
243
243
|
if user_input is not None:
|
244
|
+
case_query.scope.update(loaded_scope)
|
244
245
|
condition = CallableExpression(user_input, bool, scope=case_query.scope)
|
245
246
|
else:
|
246
247
|
user_input, condition = self.user_prompt.prompt_user_for_expression(case_query, PromptFor.Conditions)
|
@@ -266,6 +267,7 @@ class Human(Expert):
|
|
266
267
|
try:
|
267
268
|
loaded_scope, expert_input = self.all_expert_answers.pop(0)
|
268
269
|
if expert_input is not None:
|
270
|
+
case_query.scope.update(loaded_scope)
|
269
271
|
expression = CallableExpression(expert_input, case_query.attribute_type,
|
270
272
|
scope=case_query.scope,
|
271
273
|
mutually_exclusive=case_query.mutually_exclusive)
|
ripple_down_rules/utils.py
CHANGED
@@ -18,6 +18,8 @@ from textwrap import dedent
|
|
18
18
|
from types import NoneType
|
19
19
|
from typing import List
|
20
20
|
|
21
|
+
from casadi import conic_n_out
|
22
|
+
|
21
23
|
try:
|
22
24
|
import matplotlib
|
23
25
|
from matplotlib import pyplot as plt
|
@@ -499,7 +501,12 @@ def serialize_dataclass(obj: Any, seen=None) -> Any:
|
|
499
501
|
elif isinstance(obj, list):
|
500
502
|
return [serialize_dataclass(v, seen) for v in obj]
|
501
503
|
elif isinstance(obj, dict):
|
502
|
-
|
504
|
+
serialized_dict = {}
|
505
|
+
for k, v in obj.items():
|
506
|
+
if not isinstance(k, (str, int, bool, float, None)):
|
507
|
+
continue
|
508
|
+
serialized_dict[k] = serialize_dataclass(v, seen)
|
509
|
+
return serialized_dict
|
503
510
|
else:
|
504
511
|
try:
|
505
512
|
json.dumps(obj) # Check if the object is JSON serializable
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: ripple_down_rules
|
3
|
-
Version: 0.5.
|
3
|
+
Version: 0.5.55
|
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,13 +1,13 @@
|
|
1
|
-
ripple_down_rules/__init__.py,sha256=
|
2
|
-
ripple_down_rules/experts.py,sha256=
|
1
|
+
ripple_down_rules/__init__.py,sha256=GkbqAXIdwBcSMmD6Mp-8-dQ7eM_-v0SsaPm_pKzuwDs,100
|
2
|
+
ripple_down_rules/experts.py,sha256=8p5tFOWuQWgp9gt-6Yr6MFFphOTmpI9IJ3iepUyy3FY,12266
|
3
3
|
ripple_down_rules/helpers.py,sha256=TvTJU0BA3dPcAyzvZFvAu7jZqsp8Lu0HAAwvuizlGjg,2018
|
4
4
|
ripple_down_rules/rdr.py,sha256=FJYuRXgpUYSSK1pYrp2yeXb_ZZ2xjPED31tzxofokL4,48865
|
5
5
|
ripple_down_rules/rdr_decorators.py,sha256=pYCKLgMKgQ6x_252WQtF2t4ZNjWPBxnaWtJ6TpGdcc0,7820
|
6
6
|
ripple_down_rules/rules.py,sha256=TPNVMqW9T-_46BS4WemrspLg5uG8kP6tsPvWWBAzJxg,17515
|
7
7
|
ripple_down_rules/start-code-server.sh,sha256=otClk7VmDgBOX2TS_cjws6K0UwvgAUJhoA0ugkPCLqQ,949
|
8
|
-
ripple_down_rules/utils.py,sha256=
|
8
|
+
ripple_down_rules/utils.py,sha256=PMC0f1CNNINjZYXqzDuv3C1_nS3oTxj4zO8hhGpypJQ,51331
|
9
9
|
ripple_down_rules/datastructures/__init__.py,sha256=V2aNgf5C96Y5-IGghra3n9uiefpoIm_QdT7cc_C8cxQ,111
|
10
|
-
ripple_down_rules/datastructures/callable_expression.py,sha256=
|
10
|
+
ripple_down_rules/datastructures/callable_expression.py,sha256=w6Gpo1o-xnFvTaPrzJ2w7VgCjSr1xqp8LQG0jAl-mfc,12718
|
11
11
|
ripple_down_rules/datastructures/case.py,sha256=r8kjL9xP_wk84ThXusspgPMrAoed2bGQmKi54fzhmH8,15258
|
12
12
|
ripple_down_rules/datastructures/dataclasses.py,sha256=PuD-7zWqWT2p4FnGvnihHvZlZKg9A1ctnFgVYf2cs-8,8554
|
13
13
|
ripple_down_rules/datastructures/enums.py,sha256=ce7tqS0otfSTNAOwsnXlhsvIn4iW_Y_N3TNebF3YoZs,5700
|
@@ -17,8 +17,8 @@ ripple_down_rules/user_interface/ipython_custom_shell.py,sha256=24MIFwqnAhC6ofOb
|
|
17
17
|
ripple_down_rules/user_interface/object_diagram.py,sha256=tsB6iuLNEbHxp5lR2WjyejjWbnAX_nHF9xS8jNPOQVk,4548
|
18
18
|
ripple_down_rules/user_interface/prompt.py,sha256=AkkltdDIaioN43lkRKDPKSjJcmdSSGZDMYz7AL7X9lE,8082
|
19
19
|
ripple_down_rules/user_interface/template_file_creator.py,sha256=FGtLfYBfr4310c7Dfa9b2qiOWLNzHk1q3kdhD70Ilg4,13804
|
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.55.dist-info/licenses/LICENSE,sha256=ixuiBLtpoK3iv89l7ylKkg9rs2GzF9ukPH7ynZYzK5s,35148
|
21
|
+
ripple_down_rules-0.5.55.dist-info/METADATA,sha256=u3aR9vbi2_vnOUtcWnze18LhPouXxwUm_criDCAswOM,48189
|
22
|
+
ripple_down_rules-0.5.55.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
23
|
+
ripple_down_rules-0.5.55.dist-info/top_level.txt,sha256=VeoLhEhyK46M1OHwoPbCQLI1EifLjChqGzhQ6WEUqeM,18
|
24
|
+
ripple_down_rules-0.5.55.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|