Skip to content

Commit 4169f8a

Browse files
Merge pull request #121 from lambda-feedback/tr135-update-algorithm
Tr135 update algorithm
2 parents fac8686 + 4222694 commit 4169f8a

File tree

2 files changed

+306
-248
lines changed

2 files changed

+306
-248
lines changed

app/evaluation.py

Lines changed: 35 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,6 @@
1111
from expression_utilities import preprocess_expression, parse_expression, create_sympy_parsing_params, substitute
1212
from preview import preview_function
1313

14-
15-
def feedback_not_dimensionless(groups):
16-
groups = list(groups)
17-
if len(groups) == 1:
18-
return f"The group {str(groups[0])} is not dimensionless."
19-
else:
20-
return "The groups "+", ".join([str(g) for g in groups[0:-1]])+"and"+str(groups[-1])+"are not dimensionless."
21-
2214
parsing_feedback_responses = {
2315
"PARSE_ERROR_WARNING": lambda x: f"`{x}` could not be parsed as a valid mathematical expression. Ensure that correct notation is used, that the expression is unambiguous and that all parentheses are closed.",
2416
"PER_FOR_DIVISION": "Note that 'per' was interpreted as '/'. This can cause ambiguities. It is recommended to use parentheses to make your entry unambiguous.",
@@ -27,12 +19,20 @@ def feedback_not_dimensionless(groups):
2719
"SUBSTITUTIONS_NOT_WRITTEN_CORRECTLY": "List of substitutions not written correctly.",
2820
}
2921

22+
23+
def feedback_not_dimensionless(groups):
24+
groups = list(groups)
25+
if len(groups) == 1:
26+
return f"The group {str(groups[0])} is not dimensionless."
27+
else:
28+
return "The groups "+", ".join([str(g) for g in groups[0:-1]])+" and "+str(groups[-1])+" are not dimensionless."
29+
3030
buckingham_pi_feedback_responses = {
3131
"VALID_CANDIDATE_SET": "",
3232
"NOT_DIMENSIONLESS": feedback_not_dimensionless,
3333
"MORE_GROUPS_THAN_REFERENCE_SET": "Response has more groups than necessary.",
34-
"CANDIDATE_GROUPS_NOT_INDEPENDENT": lambda r, n: f"Groups in response are not independent. It has {r} independent groups and contains {n} groups.",
35-
"TOO_FEW_INDEPENDENT_GROUPS": lambda name, r, n: f"{name} contains too few independent groups. It has {r} independent products and needs at least {n} independent groups.",
34+
"CANDIDATE_GROUPS_NOT_INDEPENDENT": lambda r, n: f"Groups in response are not independent. It has {r} independent group(s) and contains {n} groups.",
35+
"TOO_FEW_INDEPENDENT_GROUPS": lambda name, r, n: f"{name} contains too few independent groups. It has {r} independent group(s) and needs at least {n} independent groups.",
3636
"UNKNOWN_SYMBOL": lambda symbols: "Unknown symbol(s): "+", ".join([str(s) for s in symbols])+".",
3737
"SUM_WITH_INDEPENDENT_TERMS": lambda s: f"Sum in {s} group contains more independent terms that there are groups in total. Group expressions should ideally be written as a comma-separated list where each item is an entry of the form `q_1**c_1*q_2**c_2*...*q_n**c_n`."
3838
}
@@ -136,6 +136,24 @@ def evaluation_function(response, answer, params) -> dict:
136136
Function that provides some basic dimensional analysis functionality.
137137
"""
138138

139+
def wrap_feedback_function(output):
140+
def wrapped_function(*args):
141+
return output
142+
return wrapped_function
143+
144+
custom_feedback = params.get("custom_feedback", None)
145+
if custom_feedback is not None:
146+
feedback_responses_list = [parsing_feedback_responses, buckingham_pi_feedback_responses]
147+
for feedback_responses in feedback_responses_list:
148+
for key in custom_feedback.keys():
149+
if key in feedback_responses.keys():
150+
if isinstance(feedback_responses[key], str):
151+
feedback_responses[key] = custom_feedback[key]
152+
elif callable(feedback_responses[key]):
153+
feedback_responses[key] = wrap_feedback_function(custom_feedback[key])
154+
else:
155+
raise Exception("Cannot handle given costum feedback for "+key)
156+
139157
if params.get("is_latex", False):
140158
response = preview_function(response, params)["preview"]["sympy"]
141159

@@ -191,7 +209,7 @@ def evaluation_function(response, answer, params) -> dict:
191209
try:
192210
expr = parse_expression(res, parsing_params).simplify()
193211
expr = expr.expand(power_base=True, force=True)
194-
except Exception as e:
212+
except Exception:
195213
separator = "" if len(remark) == 0 else "\n"
196214
return {"is_correct": False, "feedback": parsing_feedback_responses["PARSE_ERROR_WARNING"](response)+separator+remark}
197215
if isinstance(expr, Add):
@@ -238,7 +256,7 @@ def evaluation_function(response, answer, params) -> dict:
238256
quantity_strings = eval(quantities_strings[index+1:index_match])
239257
quantity = tuple(map(lambda x: parse_expression(x, parsing_params), quantity_strings))
240258
quantities.append(quantity)
241-
except Exception as e:
259+
except Exception:
242260
raise Exception(parsing_feedback_responses["QUANTITIES_NOT_WRITTEN_CORRECTLY"])
243261
index = quantities_strings.find('(', index_match+1)
244262
response_symbols = list(map(lambda x: x[0], quantities))
@@ -278,14 +296,14 @@ def evaluation_function(response, answer, params) -> dict:
278296
for quantity in quantities:
279297
dimension = dimension.subs(quantity[0], quantity[1])
280298
answer_dimensions.append(posify(dimension)[0].simplify())
281-
299+
282300
# Check that answers are dimensionless
283-
for k,dimension in enumerate(answer_dimensions):
301+
for k, dimension in enumerate(answer_dimensions):
284302
if not dimension.is_constant():
285303
raise Exception(buckingham_pi_feedback_responses["NOT_DIMENSIONLESS"]("$"+latex(answer_groups[k])+"$"))
286304

287305
# Check that there is a sufficient number of independent groups in the answer
288-
answer_matrix = get_exponent_matrix(answer_groups,answer_symbols)
306+
answer_matrix = get_exponent_matrix(answer_groups, answer_symbols)
289307
if answer_matrix.rank() < number_of_groups:
290308
raise Exception(buckingham_pi_feedback_responses["TOO_FEW_INDEPENDENT_GROUPS"]("Answer", answer_matrix.rank(), number_of_groups))
291309

@@ -320,7 +338,7 @@ def evaluation_function(response, answer, params) -> dict:
320338

321339
# Check the special case where one groups expression contains several power products
322340
separator = "" if len(remark) == 0 else "\n"
323-
answer_matrix = get_exponent_matrix(answer_groups,answer_symbols)
341+
answer_matrix = get_exponent_matrix(answer_groups, answer_symbols)
324342
if answer_matrix.rank() > answer_number_of_groups:
325343
raise Exception(buckingham_pi_feedback_responses["SUM_WITH_INDEPENDENT_TERMS"]("answer"))
326344
response_matrix = get_exponent_matrix(response_groups, answer_symbols)
@@ -330,7 +348,7 @@ def evaluation_function(response, answer, params) -> dict:
330348
return {"is_correct": valid, "feedback": feedback.get("feedback", "")+separator+remark, **interp}
331349

332350
list_of_substitutions_strings = parameters.get("substitutions", [])
333-
if isinstance(list_of_substitutions_strings,str):
351+
if isinstance(list_of_substitutions_strings, str):
334352
list_of_substitutions_strings = [list_of_substitutions_strings]
335353

336354
if "quantities" in parameters.keys():
@@ -468,19 +486,6 @@ def find_matching_parenthesis(string, index):
468486
return -1
469487

470488

471-
def get_exponent_matrix(expressions, symbols):
472-
exponents_list = []
473-
for expression in expressions:
474-
exponents = []
475-
for symbol in symbols:
476-
exponent = expression.as_coeff_exponent(symbol)[1]
477-
if exponent == 0:
478-
exponent = -expression.subs(symbol, 1/symbol).as_coeff_exponent(symbol)[1]
479-
exponents.append(exponent)
480-
exponents_list.append(exponents)
481-
return Matrix(exponents_list)
482-
483-
484489
def expression_to_latex(expression, parameters, parsing_params, remark):
485490
unsplittable_symbols = parsing_params.get("unsplittable_symbols", ())
486491
symbol_dict = parsing_params.get("symbol_dict", {})

0 commit comments

Comments
 (0)