Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions app/context/graph_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@
def outcome_tag(label: str, result: bool | None, inputs: Mapping[str, Any] | None = None) -> ReachedCriteria:
"""`{label+"_TRUE": inputs}` if `result` is True, `label+"_FALSE"` if it is False, otherwise `label+"_UNKNOWN"`."""
if result is True:
return {label+"_TRUE": inputs}
return {label + "_TRUE": inputs}
elif result is False:
return {label+"_FALSE": inputs}
return {label + "_FALSE": inputs}
else:
return {label+"_UNKNOWN": inputs}
return {label + "_UNKNOWN": inputs}


def outcome_graph(label: str, summary: str, details: str, evaluate: Evaluate) -> tuple[CriteriaGraph, OutputNode]:
Expand Down
5 changes: 2 additions & 3 deletions app/context/physical_quantity/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,12 @@
from types import MappingProxyType
from typing import Any

from lambdafeedback.criteria import CriteriaGraph
from lambdafeedback.criteria import CriteriaGraph, build_quantity_criteria_parser
from lambdafeedback.expression_parsing import ExpressionParams, SympyParsingConfig
from lambdafeedback.units import QuantityParams, preprocess_quantity

from app.context.base import Context
from app.context.defaults import base_default_parameters
from app.context.physical_quantity.criteria_parser import generate_criteria_parser
from app.context.physical_quantity.graphs.match import criterion_match_node
from app.context.physical_quantity.graphs.order import greater_than_node, greater_than_or_equal_node, less_than_node, less_than_or_equal_node
from app.context.physical_quantity.parsing import parse_quantity
Expand Down Expand Up @@ -83,7 +82,7 @@ def parsing_parameters_generator(

context = Context(
expression_preview=preview_function,
generate_criteria_parser=generate_criteria_parser,
generate_criteria_parser=build_quantity_criteria_parser,
expression_preprocess=expression_preprocess,
expression_parse=parse_quantity,
default_parameters=MappingProxyType(default_parameters),
Expand Down
6 changes: 3 additions & 3 deletions app/context/physical_quantity/comparison.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,17 +33,17 @@ def comparison_function(comparison_operator: str) -> Callable[[Basic, Basic, Sub

def comparison_function_inner(lhs: Basic, rhs: Basic, substitutions: Substitutions) -> bool:
expr0, expr1 = _substitute(lhs, rhs, substitutions)
return bool(comparison((expr0-expr1).cancel().simplify().simplify(), 0))
return bool(comparison((expr0 - expr1).cancel().simplify().simplify(), 0))
return comparison_function_inner


def is_proportional(lhs: Basic, rhs: Basic, substitutions: Substitutions) -> tuple[bool | None, float | None]:
expr0, expr1 = _substitute(lhs, rhs, substitutions)
if expr0.cancel().simplify().simplify() != 0:
ratio = (expr0/expr1).cancel().simplify()
ratio = (expr0 / expr1).cancel().simplify()
result = ratio.is_constant()
elif expr0.cancel().simplify().simplify() != 0:
ratio = (expr1/expr0).cancel().simplify()
ratio = (expr1 / expr0).cancel().simplify()
result = ratio.is_constant()
else:
result = False
Expand Down
52 changes: 0 additions & 52 deletions app/context/physical_quantity/criteria_parser.py

This file was deleted.

68 changes: 34 additions & 34 deletions app/context/physical_quantity/graphs/match.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,13 @@ def _missing_or_unexpected(parameters: EvaluationParameters, label: str, lhs_str
res_unit = parameters.reserved_expressions["response"].original_unit
ans_unit = parameters.reserved_expressions["answer"].original_unit
if res_value is None and ans_value is not None:
return {label+"_MISSING_VALUE": {"lhs": lhs_string, "rhs": rhs_string}}
return {label + "_MISSING_VALUE": {"lhs": lhs_string, "rhs": rhs_string}}
if res_value is not None and ans_value is None:
return {label+"_UNEXPECTED_VALUE": {"lhs": lhs_string, "rhs": rhs_string}}
return {label + "_UNEXPECTED_VALUE": {"lhs": lhs_string, "rhs": rhs_string}}
if res_unit is None and ans_unit is not None:
return {label+"_MISSING_UNIT": {"lhs": lhs_string, "rhs": rhs_string}}
return {label + "_MISSING_UNIT": {"lhs": lhs_string, "rhs": rhs_string}}
if res_unit is not None and ans_unit is None:
return {label+"_UNEXPECTED_UNIT": {"lhs": lhs_string, "rhs": rhs_string}}
return {label + "_UNEXPECTED_UNIT": {"lhs": lhs_string, "rhs": rhs_string}}
return None


Expand All @@ -58,10 +58,10 @@ def _within_tolerance(parameters: EvaluationParameters, lhs_string: str, rhs_str
res = parameters.reserved_expressions["response"].standard_value.simplify()
if (ans is not None and ans.is_constant()) and (res is not None and res.is_constant()):
if rtol > 0 and (ans != 0):
value_match = bool(abs(float((ans-res)/ans)) < rtol)
value_match = bool(abs(float((ans - res) / ans)) < rtol)
elif atol > 0 or (ans == 0):
answer_unit_factor = float(parameters.reserved_expressions["answer"].quantity.unit_factor)
value_match = bool(abs(float(ans-res)) < atol*answer_unit_factor)
value_match = bool(abs(float(ans - res)) < atol * answer_unit_factor)
return value_match


Expand Down Expand Up @@ -93,7 +93,7 @@ def _dimension_match(parameters: EvaluationParameters, label: str, lhs: Basic, r
def dimension_match(_response: Any) -> ReachedCriteria:
substitutions = [(key, expr.dimension) for (key, expr) in reserved_expressions]
dimension_match, _ = is_proportional(lhs, rhs, substitutions)
return outcome_tag(label+"_DIMENSION_MATCH", dimension_match is True, {"lhs": lhs_string, "rhs": rhs_string})
return outcome_tag(label + "_DIMENSION_MATCH", dimension_match is True, {"lhs": lhs_string, "rhs": rhs_string})
return dimension_match


Expand All @@ -105,23 +105,23 @@ def unit_comparison(_response: Any) -> ReachedCriteria:

if is_equal(lhs, rhs, substitutions) is True:
output_tags = {
label+"_UNIT_COMPARISON"+"_IDENTICAL": None
label + "_UNIT_COMPARISON" + "_IDENTICAL": None
}
else:
local_substitutions = [(key, expr.quantity.expanded_unit) for (key, expr) in reserved_expressions]
result, ratio = is_proportional(lhs, rhs, local_substitutions)
# `is_proportional` returns a ratio whenever the result is True
if result is True and ratio is not None and ratio >= 1000:
output_tags = {
label+"_UNIT_COMPARISON"+"_PREFIX_IS_LARGE": None
label + "_UNIT_COMPARISON" + "_PREFIX_IS_LARGE": None
}
elif result is True and ratio is not None and ratio <= 1/1000:
elif result is True and ratio is not None and ratio <= 1 / 1000:
output_tags = {
label+"_UNIT_COMPARISON"+"_PREFIX_IS_SMALL": None
label + "_UNIT_COMPARISON" + "_PREFIX_IS_SMALL": None
}
else:
output_tags = {
label+"_UNIT_COMPARISON"+"_SIMILAR": None
label + "_UNIT_COMPARISON" + "_SIMILAR": None
}

return output_tags
Expand All @@ -140,22 +140,22 @@ def _add_match_nodes(
)
graph.attach_new_criterion(
label,
label+"_TRUE",
label + "_TRUE",
summary=f"The quantities {inputs[0]} and {inputs[1]} match.",
details=f"The quantities {inputs[0]} and {inputs[1]} match.",
feedback_string_generator=physical_quantity_feedback_string_generators["MATCHES"]("QUANTITY_MATCH")
)
graph.attach_new_criterion(
label,
label+"_FALSE",
label + "_FALSE",
summary=f"The quantities {inputs[0]} and {inputs[1]} does not match.",
details=f"The quantities {inputs[0]} and {inputs[1]} does not match.",
feedback_string_generator=physical_quantity_feedback_string_generators["MATCHES"]("QUANTITY_MISMATCH")
)
attach_terminal_criterion(
graph,
label,
label+"_MISSING_VALUE",
label + "_MISSING_VALUE",
END,
summary="The response is missing a value.",
details="The response is missing a value.",
Expand All @@ -164,7 +164,7 @@ def _add_match_nodes(
attach_terminal_criterion(
graph,
label,
label+"_UNEXPECTED_VALUE",
label + "_UNEXPECTED_VALUE",
END,
summary="The response is expected only have unit(s), no value.",
details="The response is expected only have unit(s), no value.",
Expand All @@ -173,7 +173,7 @@ def _add_match_nodes(
attach_terminal_criterion(
graph,
label,
label+"_MISSING_UNIT",
label + "_MISSING_UNIT",
END,
summary="The response is missing unit(s).",
details="The response is missing unit(s).",
Expand All @@ -182,71 +182,71 @@ def _add_match_nodes(
attach_terminal_criterion(
graph,
label,
label+"_UNEXPECTED_UNIT",
label + "_UNEXPECTED_UNIT",
END,
summary="The response is expected to be a value without unit(s).",
details="The response is expected to be a value without unit(s).",
feedback_string_generator=physical_quantity_feedback_string_generators["MATCHES"]("UNEXPECTED_UNIT")
)
graph.attach_new_evaluation(
label+"_FALSE",
label+"_DIMENSION_MATCH",
label + "_FALSE",
label + "_DIMENSION_MATCH",
summary=f"Do the dimensions of {inputs[0]} and {inputs[1]} match?",
details=f"Do the dimensions of {inputs[0]} and {inputs[1]} match?",
evaluate=dimension_match
)
attach_terminal_criterion(
graph,
label+"_DIMENSION_MATCH",
label+"_DIMENSION_MATCH"+"_TRUE",
label + "_DIMENSION_MATCH",
label + "_DIMENSION_MATCH" + "_TRUE",
END,
summary=f"The quantities {inputs[0]} and {inputs[1]} have the same dimensions.",
details=f"The quantities {inputs[0]} and {inputs[1]} have the same dimensions.",
feedback_string_generator=physical_quantity_feedback_string_generators["MATCHES"]("DIMENSION_MATCH")
)
attach_terminal_criterion(
graph,
label+"_DIMENSION_MATCH",
label+"_DIMENSION_MATCH"+"_FALSE",
label + "_DIMENSION_MATCH",
label + "_DIMENSION_MATCH" + "_FALSE",
END,
summary=f"The quantities {inputs[0]} and {inputs[1]} have different dimensions.",
details=f"The quantities {inputs[0]} and {inputs[1]} have different dimensions.",
feedback_string_generator=physical_quantity_feedback_string_generators["MATCHES"]("DIMENSION_MISMATCH")
)
graph.attach_new_evaluation(
label+"_TRUE",
label+"_UNIT_COMPARISON",
label + "_TRUE",
label + "_UNIT_COMPARISON",
summary=f"Compares how similar the units of {inputs[0]} and {inputs[1]} are.",
details=f"Compares how similar the units of {inputs[0]} and {inputs[1]} are.",
evaluate=unit_comparison
)
graph.attach_new_criterion(
label+"_UNIT_COMPARISON",
label+"_UNIT_COMPARISON"+"_IDENTICAL",
label + "_UNIT_COMPARISON",
label + "_UNIT_COMPARISON" + "_IDENTICAL",
summary=f"The units of quantities {inputs[0]} and {inputs[1]} are identical.",
details=f"The units of quantities {inputs[0]} and {inputs[1]} are identical.",
feedback_string_generator=physical_quantity_feedback_string_generators["MATCHES"]("UNIT_COMPARISON_IDENTICAL")
)
graph.attach_new_criterion(
label+"_UNIT_COMPARISON",
label+"_UNIT_COMPARISON"+"_SIMILAR",
label + "_UNIT_COMPARISON",
label + "_UNIT_COMPARISON" + "_SIMILAR",
summary=f"The units of quantities {inputs[0]} and {inputs[1]} are similar.",
details=f"The units of quantities {inputs[0]} and {inputs[1]} are similar.",
feedback_string_generator=physical_quantity_feedback_string_generators["MATCHES"]("UNIT_COMPARISON_SIMILAR")
)
attach_terminal_criterion(
graph,
label+"_UNIT_COMPARISON",
label+"_UNIT_COMPARISON"+"_PREFIX_IS_LARGE",
label + "_UNIT_COMPARISON",
label + "_UNIT_COMPARISON" + "_PREFIX_IS_LARGE",
END,
summary=f"The units of {inputs[0]} are much greater than the units of {inputs[1]}.",
details=f"The units of {inputs[0]} are at least 1000 times greater than the units of {inputs[1]}.",
feedback_string_generator=physical_quantity_feedback_string_generators["MATCHES"]("PREFIX_IS_LARGE")
)
attach_terminal_criterion(
graph,
label+"_UNIT_COMPARISON",
label+"_UNIT_COMPARISON"+"_PREFIX_IS_SMALL",
label + "_UNIT_COMPARISON",
label + "_UNIT_COMPARISON" + "_PREFIX_IS_SMALL",
END,
summary=f"The units of {inputs[0]} are much smaller than the units of {inputs[1]}.",
details=f"The units of {inputs[0]} are at least 1000 times smaller than the units of {inputs[1]}.",
Expand Down
6 changes: 3 additions & 3 deletions app/context/physical_quantity/graphs/order.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ def comparison_base_graph(
inputs = criterion.children
_, _, lhs, rhs = parse_criterion_sides(criterion, parameters)

stardard_forms = [(key, expr.standard_value*expr.standard_unit) for (key, expr) in reserved_expressions]
stardard_forms = [(key, expr.standard_value * expr.standard_unit) for (key, expr) in reserved_expressions]
compare = comparison_function(comparison_operator)

def compare_evaluate(_response: Any) -> ReachedCriteria:
Expand All @@ -37,7 +37,7 @@ def compare_evaluate(_response: Any) -> ReachedCriteria:
attach_terminal_criterion(
graph,
label,
label+"_TRUE",
label + "_TRUE",
END,
summary=f"{inputs[0]} {comparison_operator} {inputs[1]} is true.",
details=f"{inputs[0]} {comparison_operator} {inputs[1]} is true.",
Expand All @@ -46,7 +46,7 @@ def compare_evaluate(_response: Any) -> ReachedCriteria:
attach_terminal_criterion(
graph,
label,
label+"_FALSE",
label + "_FALSE",
END,
summary=f"{inputs[0]} {comparison_operator} {inputs[1]} is false.",
details=f"{inputs[0]} {comparison_operator} {inputs[1]} is false.",
Expand Down
Loading