From 1215e90b7d7d6ea63cfad9f0ac6a962944c48144 Mon Sep 17 00:00:00 2001 From: Marcus Messer Date: Thu, 18 Dec 2025 12:45:49 +0000 Subject: [PATCH 1/3] Added alias passing --- app/evaluation_tests.py | 2 +- app/preview_tests.py | 34 ++++++++++++++++++++++++++++---- app/utility/preview_utilities.py | 12 +++++++++-- 3 files changed, 41 insertions(+), 7 deletions(-) diff --git a/app/evaluation_tests.py b/app/evaluation_tests.py index d8473c7..43dfba8 100755 --- a/app/evaluation_tests.py +++ b/app/evaluation_tests.py @@ -173,7 +173,7 @@ def test_multi_character_implicit_multi_variable(self): ("e**ea", False, True), ("e**Ea", False, True), ("e^{ea}", True, True), - # ("e^{Ea}", True, True), # TODO: Support aliases for latex input + ("e^{Ea}", True, True), ] ) def test_e_latex(self, response, is_latex, is_correct): diff --git a/app/preview_tests.py b/app/preview_tests.py index c9291d9..0850c76 100644 --- a/app/preview_tests.py +++ b/app/preview_tests.py @@ -121,11 +121,11 @@ def test_eulers_number_notation(self, response, is_latex, elementary_functions, ("e**ea", False, "e^{ea}", "E**ea", {"ea": {"aliases": ["ea", "Ea"], "latex": "ea"}}), ("e**Ea", False, "e^{ea}", "E**ea", {"ea": {"aliases": ["ea", "Ea"], "latex": "ea"}}), ("e^{ea}", True, "e^{ea}", "exp(ea)", {"ea": {"aliases": ["ea", "Ea"], "latex": "ea"}}), - # ("e^{Ea}", True, "e^{Ea}", "e**ea", {"ea": {"aliases": ["ea", "Ea"], "latex": "ea"}}), # TODO: Clarify if we want to be able to use aliases for LaTeX? + ("e^{Ea}", True, "e^{Ea}", "e**ea", {"ea": {"aliases": ["ea", "Ea"], "latex": "ea"}}), ("e**aea", False, "e^{aea}", "E**aea", {"aea": {"aliases": ["aea", "aEa"], "latex": "aea"}}), ("e**aEa", False, "e^{aea}", "E**aea", {"aea": {"aliases": ["aea", "aEa"], "latex": "aea"}}), ("e^{aea}", True, "e^{aea}", "exp(aea)", {"aea": {"aliases": ["aea", "aEa"], "latex": "aea"}}), - # ("e^{aEa}", True, "e^{aEa}", "e**aea", {"aea": {"aliases": ["aea", "aEa"], "latex": "aea"}}), # TODO: Clarify if we want to be able to use aliases for LaTeX? + ("e^{aEa}", True, "e^{aEa}", "e**aea", {"aea": {"aliases": ["aea", "aEa"], "latex": "aea"}}), ] ) def test_e_latex(self, response, is_latex, response_latex, response_sympy, symbols): @@ -140,9 +140,35 @@ def test_e_latex(self, response, is_latex, response_latex, response_sympy, symbo assert "preview" in result.keys() preview = result["preview"] - assert preview["latex"] == response_latex - assert preview["sympy"] == response_sympy + assert preview["latex"] == response_latex, "latex_error" + assert preview["sympy"] == response_sympy, "sympy_error" + + @pytest.mark.parametrize( + "response, is_latex, response_latex, response_sympy, symbols", [ + ("ab", False, "ab", "ab", {"ab": {"aliases": ["Ab", "AB", "aB"], "latex": "ab"}}), + ("Ab", False, "ab", "ab", {"ab": {"aliases": ["Ab", "AB", "aB"], "latex": "ab"}}), + ("aB", False, "ab", "ab", {"ab": {"aliases": ["Ab", "AB", "aB"], "latex": "ab"}}), + ("AB", False, "ab", "ab", {"ab": {"aliases": ["Ab", "AB", "aB"], "latex": "ab"}}), + ("ab", True, "ab", "ab", {"ab": {"aliases": ["Ab", "AB", "aB"], "latex": "ab"}}), + ("Ab", True, "Ab", "ab", {"ab": {"aliases": ["Ab", "AB", "aB"], "latex": "ab"}}), + ("aB", True, "aB", "ab", {"ab": {"aliases": ["Ab", "AB", "aB"], "latex": "ab"}}), + ("AB", True, "AB", "ab", {"ab": {"aliases": ["Ab", "AB", "aB"], "latex": "ab"}}), + ] + ) + def test_alias(self, response, is_latex, response_latex, response_sympy, symbols): + params = { + "is_latex": is_latex, + "strict_syntax": False, + "elementary_functions": True, + "symbols": symbols, + } + + result = preview_function(response, params) + assert "preview" in result.keys() + preview = result["preview"] + assert preview["latex"] == response_latex, "latex error" + assert preview["sympy"] == response_sympy, "sympy error" @pytest.mark.parametrize( "response, is_latex, response_latex, response_sympy", diff --git a/app/utility/preview_utilities.py b/app/utility/preview_utilities.py index 8b8984b..41538c5 100644 --- a/app/utility/preview_utilities.py +++ b/app/utility/preview_utilities.py @@ -1,8 +1,10 @@ import re from typing import TypedDict + +from sympy.parsing.sympy_parser import standard_transformations, implicit_multiplication_application from typing_extensions import NotRequired -from sympy import Symbol +from sympy import Symbol, parse_expr, srepr from latex2sympy2 import latex2sympy from copy import deepcopy @@ -177,6 +179,12 @@ def parse_latex(response: str, symbols: SymbolDict, simplify: bool, parameters=N substitutions[latex_symbol_str_postprocess] = Symbol(sympy_symbol_str) + aliases = symbols[sympy_symbol_str]['aliases'] + transformations = (standard_transformations + (implicit_multiplication_application,)) + for alias in aliases: + substitutions[parse_expr(alias, transformations=transformations)] = Symbol(sympy_symbol_str) + + parsed_responses = set() for expression in response_set: try: @@ -195,7 +203,7 @@ def parse_latex(response: str, symbols: SymbolDict, simplify: bool, parameters=N if simplify is True: expression_postprocess = expression_postprocess.simplify() - parsed_responses.add(str(expression_postprocess.xreplace(substitutions))) + parsed_responses.add(str(expression_postprocess.subs(substitutions))) if len(parsed_responses) < 2: return parsed_responses.pop() From de5f1293477a5e932d761145a3fc23eb6bd28cce Mon Sep 17 00:00:00 2001 From: Marcus Messer Date: Thu, 18 Dec 2025 12:58:59 +0000 Subject: [PATCH 2/3] Enforcing E to be treated as a symbol when parsing aliases --- app/utility/preview_utilities.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/utility/preview_utilities.py b/app/utility/preview_utilities.py index 41538c5..99f0219 100644 --- a/app/utility/preview_utilities.py +++ b/app/utility/preview_utilities.py @@ -182,7 +182,7 @@ def parse_latex(response: str, symbols: SymbolDict, simplify: bool, parameters=N aliases = symbols[sympy_symbol_str]['aliases'] transformations = (standard_transformations + (implicit_multiplication_application,)) for alias in aliases: - substitutions[parse_expr(alias, transformations=transformations)] = Symbol(sympy_symbol_str) + substitutions[parse_expr(alias, transformations=transformations, local_dict={'E': Symbol("E")})] = Symbol(sympy_symbol_str) parsed_responses = set() From 3fe99718beac81f006f3fe839bbd72213e2906b8 Mon Sep 17 00:00:00 2001 From: Marcus Messer Date: Thu, 18 Dec 2025 13:55:00 +0000 Subject: [PATCH 3/3] Fixed issue with parsing E --- app/utility/preview_utilities.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/app/utility/preview_utilities.py b/app/utility/preview_utilities.py index 99f0219..6a8d3e6 100644 --- a/app/utility/preview_utilities.py +++ b/app/utility/preview_utilities.py @@ -182,7 +182,19 @@ def parse_latex(response: str, symbols: SymbolDict, simplify: bool, parameters=N aliases = symbols[sympy_symbol_str]['aliases'] transformations = (standard_transformations + (implicit_multiplication_application,)) for alias in aliases: - substitutions[parse_expr(alias, transformations=transformations, local_dict={'E': Symbol("E")})] = Symbol(sympy_symbol_str) + if not alias.strip(): + continue + try: + parsed_alias = parse_expr( + alias, + transformations=transformations, + global_dict={}, + local_dict={'Symbol': Symbol,'E': Symbol("E")} + ) + substitutions[parsed_alias] = Symbol(sympy_symbol_str) + except Exception as e: + print(e) + substitutions[Symbol(alias)] = Symbol(sympy_symbol_str) parsed_responses = set()