Skip to content

Commit 47ce634

Browse files
Collected default values of parameters in their respective contexts
1 parent 50290c0 commit 47ce634

13 files changed

+205
-71
lines changed

app/context/physical_quantity.py

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
)
1111
from ..preview_implementations.physical_quantity_preview import preview_function
1212
from ..feedback.physical_quantity import feedback_string_generators as physical_quantity_feedback_string_generators
13+
from ..utility.expression_utilities import default_parameters as symbolic_default_parameters
1314
from ..utility.expression_utilities import (
1415
substitute_input_symbols,
1516
create_sympy_parsing_params,
@@ -537,12 +538,12 @@ def expression_preprocess(name, expr, parameters):
537538
search_string = r"[0-9\(\) ]\* "+unit_short_forms
538539
match_content = re.search(search_string, expr)
539540
while match_content is not None:
540-
expr = expr[0:match_content.span()[0]]+match_content.group().replace("*"," ")+expr[match_content.span()[1]:]
541+
expr = expr[0:match_content.span()[0]]+match_content.group().replace("*", " ")+expr[match_content.span()[1]:]
541542
match_content = re.search(search_string, expr)
542543

543544
prefixes = set(x[0] for x in set_of_SI_prefixes)
544545
fundamental_units = set(x[0] for x in set_of_SI_base_unit_dimensions)
545-
units_string = parameters.get("units_string", "SI common imperial")
546+
units_string = parameters["units_string"]
546547
valid_units = set()
547548
for key in units_sets_dictionary.keys():
548549
if key in units_string:
@@ -576,12 +577,28 @@ def parsing_parameters_generator(params, unsplittable_symbols=tuple(), symbol_as
576577
return parsing_parameters
577578

578579

580+
# CONSIDER: Move these to separate file so that they can be shared with
581+
# the preview function implementation (or move preview implementation here)
582+
default_parameters = deepcopy(symbolic_default_parameters)
583+
default_parameters.update(
584+
{
585+
"physical_quantity": True,
586+
"strictness": "natural",
587+
"units_string": "SI common imperial",
588+
}
589+
)
590+
591+
592+
default_criteria = ["response matches answer"]
593+
594+
579595
context = {
580596
"expression_preview": preview_function,
581597
"generate_criteria_parser": generate_criteria_parser,
582598
"expression_preprocess": expression_preprocess,
583599
"expression_parse": parse_quantity,
584-
"default_criteria": {"response matches answer"},
600+
"default_parameters": default_parameters,
601+
"default_criteria": default_criteria,
585602
"feedback_procedure_generator": feedback_procedure_generator,
586603
"feedback_string_generator": feedback_string_generator,
587604
"parsing_parameters_generator": parsing_parameters_generator,

app/context/symbolic.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from sympy import re as real_part
44

55
from ..utility.expression_utilities import (
6+
default_parameters,
67
parse_expression,
78
create_sympy_parsing_params,
89
preprocess_expression,
@@ -26,7 +27,7 @@ def expression_parse(name, expr, parameters, evaluation_result):
2627
return parse_expression(expr, parameters)
2728

2829

29-
default_criteria = {"response = answer"}
30+
default_criteria = ["response = answer"]
3031

3132

3233
def check_criterion(criterion, parameters_dict, generate_feedback=True):
@@ -783,6 +784,7 @@ def feedback_string_generator(tags, graph, parameters_dict):
783784
"generate_feedback": generate_criteria_parser,
784785
"expression_preprocess": expression_preprocess,
785786
"expression_parse": expression_parse,
787+
"default_parameters": default_parameters,
786788
"default_criteria": default_criteria,
787789
"feedback_procedure_generator": feedback_procedure_generator,
788790
"feedback_string_generator": feedback_string_generator,

app/docs/dev.md

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ The returned dictionary will be referred to as the `result` in this documentatio
2727
### Overview
2828
The overall flow of the evaluation procedure can be described as follows:
2929

30-
1. The function uses the paramters given in `params` to determine the context of the evaluation. What context means will be discussed in more detail in a later section.
30+
1. The function uses the parameters given in `params` to determine the context of the evaluation. What context means will be discussed in more detail in section TODO: Add section name here.
3131
2. After the context is determined the response, answer and criteria (either supplied via `params` or from the context) are analysed an necessary information is stored for future use in a dictionary with frozen valuues, i.e. a dictionary where new items can be added but existing items cannot be changed.
3232
3. The feedback generating procedure supplied by the context is used to generate feedback based on the contents of the frozen value dictionary.
3333
4. If all criteria are found to be satisfied the response is considered correct, i.e. the `is_correct` field in the result is set to true and the feedback string and list of tags generated by the feedback generation procedure are added to their respective fields.
@@ -36,21 +36,47 @@ The overall flow of the evaluation procedure can be described as follows:
3636

3737
### Context
3838

39-
The context is a data structure that contains at least the following seven pieves of information:
40-
- `default_criteria` A list of strings that describe the default criteria used if none are supplied by the input parameters.
39+
The context is a data structure that contains at least the following seven pieces of information:
40+
- `default_parameters` A dictionary where the keys are parameter names and the values are the default values that the evaluation function will use unless another value is provided together with the response. The only required field is the
4141
- `expression_parse` function that parses expressions (i.e. the `response` and `answer` inputs) into the form used by the feedback generation procedure.
4242
- `expression_preprocess` function that performs string manipulations that makes ensures that correctly written input expressions follows the conventions expected by `expression_parse`.
43-
- `expression_preview` is a function that generates a string that can be turned into a human-readable represenation of how the evaluation function interpreted the response.
43+
- `expression_preview` is a function that generates a string that can be turned into a human-readable representation of how the evaluation function interpreted the response.
4444
- `feedback_procedure_generator` function that generates a function for each criteria that can be used to evaluate if the criteria is satisfied or not. The output from this function should be a list of tags that the feedback string generator can use to produce human readable feedback.
4545
- `feedback_string_generator` function that takes tags and outputs human readable feedback strings.
4646
- `generate_criteria_parser` function that generates a parser that can be used to turn the criteria (given in string form) into a form that the feedback generation procedure can use to determine if they are correct or not.
4747

4848
The context can also contain other fields if necessary.
4949

50-
**Remark:** The current implementation uses a dictionary rather than a dedicated class for ease of iteration during the prototyping phase.
50+
**Remark:** The current implementation uses a dictionary rather than a dedicated class for ease of iteration during the initial development phase.
51+
52+
There are currently two different contexts:
53+
- `symbolic` Handles comparisons of various symbolic expressions. Defined in `context\symbolic.py`.
54+
- `physical_quantity` Handles comparisons of expressions involving units. Defined in `context\physical_quantity.py`.
55+
56+
**Remark:** Handwritten expressions are sent as latex, which requires extra preprocessing before the right context can be determined in some cases. It should be considered whether a new context, perhaps called `handwritten`, should be created for this purpose.
5157

5258
**TODO** Describe currently available contexts
59+
#### `symbolic` - Comparison of symbolic expressions
60+
61+
**Remark:** The `symbolic` context should probably be split into several smaller contexts, the following subdivision is suggested:
62+
- `numerical`: Comparison of expressions that can be evaluated to numerical values (e.g. expressions that are already numerical values or expressions only containing constants). Focuses on identifying if numerical values are greater than, less than, proportional to the expected answer or similar.
63+
- `symbolic`: Comparison of symbolic expressions that cannot be reduced to numerical values.
64+
- `equality`: Comparison of mathematical equalities (with the extra complexities that come with equivalence of equalities compared to equality of expressions).
65+
- `inequality`: Same as `equality` except for mathematical inequalities (which will require different choices when it comes to what can be considered equivalence). It might be appropriate to combine `equality` and `inequality` into one context (called `statements` or similar).
66+
- `collection`: Comparison of collections (e.g. sets, lists or intervals of the number line). Likely to consist mostly of code for handling comparison of individual elements using the other contexts, and configuring what counts as equivalence between different collections.
67+
68+
#### `physical_quantity` - Comparison of expressions that involve units
69+
70+
#### Code shared between different contexts
5371

5472
### Criteria
5573

56-
**TODO** Describe currently available contexts
74+
**TODO** Describe currently available criteria
75+
76+
#### Criteria command and grammar
77+
78+
#### Examples of commonly used criteria
79+
80+
### Feedback generation
81+
82+
### Returning final results

app/docs/user.md

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,10 @@ Note that this function is designed to handle comparisons of mathematical expres
88

99
### Optional parameters
1010

11-
There are twelve optional parameters that can be set: `complexNumbers`, `convention`, `criteria`, `elementary_functions`, `feedback_for_incorrect_response`, `multiple_answers_criteria`, `physical_quantity`, `plus_minus`/`minus_plus`, `specialFunctions`, `strict_syntax`, `strictness`, `symbol_assumptions`.
11+
There are 15 optional parameters that can be set: `atol`, `complexNumbers`, `convention`, `criteria`, `elementary_functions`, `feedback_for_incorrect_response`, `multiple_answers_criteria`, `physical_quantity`, `plus_minus`/`minus_plus`, `rtol`, `specialFunctions`, `strict_syntax`, `strictness`, `symbol_assumptions`.
12+
13+
## `atol`
14+
Sets the absolute tolerance, $e_a$, i.e. if the answer, $x$, and response, $\tilde{x}$, are numerical values then the response is considered equal to the answer if $|x-\tilde{x}| \leq e_aBy default `atol` is set to `0`, which means the comparison will be done with as high accuracy as possible. If either the answer or the response aren't numerical expressions this parameter is ignored.
1215

1316
## `complexNumbers`
1417

@@ -55,16 +58,19 @@ If unset, `physical_quantity` will default to `false`.
5558

5659
If `physical_quantity` is set to `true` the answer and response will interpreted as a physical quantity using units and conventions decided by the `strictness` and `units_string` parameters.
5760

58-
**Remark:** Setting `physical_quantity` to `true` will also mean that comparisons will be done numerically. If neither the `atol` nor `rtol` parameters are set, the evaluation function will choose a relative error based on the number of sigificant digits given in the answer.
61+
**Remark:** Setting `physical_quantity` to `true` will also mean that comparisons will be done numerically. If neither the `atol` nor `rtol` parameters are set, the evaluation function will choose a relative error based on the number of significant digits given in the answer.
5962

6063

6164
When `physical_quantity` the evaluation function will generate feedback based on the flowchart below.
6265

6366
**TODO:** Generate new flowchart for updated physical quantity feedback generation procedure.
6467

68+
## `rtol`
69+
Sets the relative tolerance, $e_r$, i.e. if the answer, $x$, and response, $\tilde{x}$, are numerical values then the response is considered equal to the answer if $\left|\frac{x-\tilde{x}}{x}\right| \leq e_r$. By default `rtol` is set to `0`, which means the comparison will be done with as high accuracy as possible. If either the answer or the response aren't numerical expressions this parameter is ignored.
70+
6571
## `strictness`
6672

67-
Constrols the conventions used when parsing physical quantities.
73+
Controls the conventions used when parsing physical quantities.
6874

6975
**Remark:** If `physical_quantity` is set to `false`, this parameter will be ignored.
7076

@@ -80,7 +86,9 @@ Controls what sets of units are used. There are three values `SI`, `common` and
8086

8187
If `SI` is chosen then only units from the tables `Base SI units` and `Derived SI units` (below) are allowed (in combinations with prefixes). If `common` is chosen then all the units allowed by `SI` as well as those listed in the tables for `Common non-SI units`. If `imperial` is chosen the base SI units and the units listed in the `Imperial units` table are allowed.
8288

83-
**Remark:** The different settings can also be combine, e.g. `SI common imperial` will allow all units.
89+
**Remark:** The different settings can also be combined, e.g. `SI common imperial` will allow all units.
90+
91+
The default setting is to allow all units, i.e. `units_string` is set to `SI common imperial`.
8492

8593
### Notation and definition of units
8694

@@ -317,7 +325,7 @@ In the example set there is a response area with `complexNumbers` set to `true`
317325

318326
Any response that is mathematically equivalent to $2+i$ will be accepted, e.g. `2+I`, `2+(-1)^(1/2)`, `conjugate(2-I)`, `2sqrt(2)e^(I*pi/4)+e^(I*3*pi/2)` or `re(2-I)-im(2-I)*I`.
319327

320-
**Note:** If the particular way that the answer is written matter, e.g. only answers on cartesian form should be accepted, then that requires further configuration, see the example *Syntactical comparison*.
328+
**Note:** If the particular way that the answer is written matter, e.g. only answers on Cartesian form should be accepted, then that requires further configuration, see the example *Syntactical comparison*.
321329

322330
### Using `constant` and `function` assumptions
323331

@@ -340,9 +348,9 @@ By default `compareExpressions` assumes that symbols are independent of each oth
340348
Taking the ratio of the given answer and the example response gives:
341349
$$ \frac{\frac{\partial^2 T}{\partial x^2}+\frac{\dot{q}}{k} - \frac{1}{\alpha}\frac{\partial T}{\partial t}}{\alpha k \frac{\partial^2 T}{\partial x^2}+ \alpha \dot{q} - k \frac{\partial T}{\partial t}} = \alpha k $$
342350

343-
By default $\alpha$ and $k$ are assumed to be variables so the ratio is not seen as a constant. This can be fixed by addding `('alpha','constant') ('k','constant')` to the `symbol_asssumptions` parameter.
351+
By default $\alpha$ and $k$ are assumed to be variables so the ratio is not seen as a constant. This can be fixed by adding `('alpha','constant') ('k','constant')` to the `symbol_asssumptions` parameter.
344352

345-
The make it simpler and more intuitive to write valid reponses we add the following input symbols:
353+
The make it simpler and more intuitive to write valid responses we add the following input symbols:
346354

347355
| Symbol | Code | Alternatives |
348356
| --------------------------------------- | ----------------------- | --------------------------- |
@@ -377,7 +385,7 @@ and
377385

378386
### Syntactical comparison
379387

380-
Typically `compareExpressions` only checks if the response is mathematically equivalent to the answer. If we want to require that the answer is written in a cetain way, e.g. Cartesian form vs. exponential form of a complex number or standard form vs factorized form of a polynomial, further comparsions need to be done. There are some built in standard forms that can be detected, as well as a method that tries to match the way that the response is written in a limited fashion. Either method can be activated either by setting the flag `syntactical_comparison` to `true`, or by using the criteria `response written as answer`.
388+
Typically `compareExpressions` only checks if the response is mathematically equivalent to the answer. If we want to require that the answer is written in a certain way, e.g. Cartesian form vs. exponential form of a complex number or standard form vs factorized form of a polynomial, further comparisons need to be done. There are some built in standard forms that can be detected, as well as a method that tries to match the way that the response is written in a limited fashion. Either method can be activated either by setting the flag `syntactical_comparison` to `true`, or by using the criteria `response written as answer`.
381389

382390
#### Standard forms for complex numbers
383391

app/evaluation.py

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -232,27 +232,19 @@ def evaluation_function(response, answer, params, include_test_data=False) -> di
232232
- if set to True, use basic dimensional analysis functionality.
233233
"""
234234

235-
# TODO: Top-down restructuring in progress, code below is not yet functional
236235
evaluation_result = EvaluationResult()
237236
evaluation_result.is_correct = False
238237

239238
symbolic_comparison_internal_messages = symbolic_feedback_string_generators["INTERNAL"]
240239

241-
parameters = {
242-
"comparison": "expression",
243-
"strict_syntax": True,
244-
}
245-
parameters.update(params)
240+
parameters = deepcopy(params)
246241

242+
# CONSIDER: Can this be moved into the preprocessing procedures in a consistent way?
243+
# Can it be turned into its own context? Or moved into the determine_context procedure?
244+
# What solution will be most consistently reusable?
247245
if parameters.get("is_latex", False):
248246
response = parse_latex(response, parameters.get("symbols", {}), False)
249247

250-
if params.get("strict_syntax", True):
251-
if "^" in response:
252-
evaluation_result.add_feedback(("NOTATION_WARNING_EXPONENT", symbolic_comparison_internal_messages("NOTATION_WARNING_EXPONENT")(dict())))
253-
if "!" in response:
254-
evaluation_result.add_feedback(("NOTATION_WARNING_FACTORIAL", symbolic_comparison_internal_messages("NOTATION_WARNING_FACTORIAL")(dict())))
255-
256248
reserved_expressions_strings = {
257249
"learner": {
258250
"response": response
@@ -263,6 +255,12 @@ def evaluation_function(response, answer, params, include_test_data=False) -> di
263255
}
264256
parameters.update({"reserved_expressions_strings": reserved_expressions_strings})
265257
context = determine_context(parameters)
258+
default_parameters = context["default_parameters"]
259+
for (key, value) in default_parameters.items():
260+
if key not in parameters.keys():
261+
parameters.update({key: value})
262+
if "criteria" not in parameters.keys():
263+
parameters.update({"criteria": ",".join(context["default_criteria"])})
266264
try:
267265
preview = context["expression_preview"](response, deepcopy(parameters))["preview"]
268266
except Exception:
@@ -278,6 +276,13 @@ def evaluation_function(response, answer, params, include_test_data=False) -> di
278276
}
279277
)
280278

279+
# FIXME: Move this into expression_utilities
280+
if params.get("strict_syntax", True):
281+
if "^" in response:
282+
evaluation_result.add_feedback(("NOTATION_WARNING_EXPONENT", symbolic_comparison_internal_messages("NOTATION_WARNING_EXPONENT")(dict())))
283+
if "!" in response:
284+
evaluation_result.add_feedback(("NOTATION_WARNING_FACTORIAL", symbolic_comparison_internal_messages("NOTATION_WARNING_FACTORIAL")(dict())))
285+
281286
reserved_expressions_success, reserved_expressions = parse_reserved_expressions(reserved_expressions_strings, parameters, evaluation_result)
282287
if reserved_expressions_success is False:
283288
return evaluation_result.serialise(include_test_data)

0 commit comments

Comments
 (0)