From 59b68d585b31600cd775767aaa07372ea1780cf4 Mon Sep 17 00:00:00 2001 From: Alex Hagen Date: Sun, 31 Jan 2021 10:41:31 -0800 Subject: [PATCH 1/6] non-working sympy simplification --- pytexit/core/core.py | 28 ++++++++++++++++------------ setup.py | 1 + 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/pytexit/core/core.py b/pytexit/core/core.py index 63ad269..3fbda5b 100644 --- a/pytexit/core/core.py +++ b/pytexit/core/core.py @@ -11,6 +11,11 @@ from warnings import warn from six.moves import range from six.moves import map +from sympy.core.sympify import sympify +from sympy.parsing.sympy_parser import parse_expr, standard_transformations, implicit_multiplication_application, convert_xor +from sympy.printing.latex import latex +from sympy.simplify.simplify import simplify +from sympy import cancel unicode_tbl = { 'α': 'alpha', @@ -372,18 +377,17 @@ def visit_BinOp(self, n): # Special binary operators if isinstance(n.op, ast.Div): if self.simplify_fractions: - left_is_int = self.looks_like_int(left) - right_is_int = self.looks_like_int(right) - if left_is_int or right_is_int: - if left_is_int and right_is_int: - return self.division('%d' % int(float(left)), - '%d' % int(float(right))) - elif left_is_int: - return self.division('%d' % int(float(left)), - self.visit(n.right)) - else: - return self.division(self.visit(n.left), - '%d' % int(float(right))) + expression = left + ' / ' + right + transformations = (standard_transformations + (implicit_multiplication_application,) + (convert_xor,)) + left = left.replace('E', 'Y').strip() + right = right.replace('E', 'Y').strip() + parsed_left = parse_expr(left, + transformations=transformations) + parsed_right = parse_expr(right, + transformations=transformations) + expression = cancel(parsed_left / parsed_right) + print(latex(expression)) + return latex(expression) return self.division(self.visit(n.left), self.visit(n.right)) elif isinstance(n.op, ast.FloorDiv): return r'\left\lfloor\frac{%s}{%s}\right\rfloor' % \ diff --git a/setup.py b/setup.py index d275b0e..a6b2d36 100644 --- a/setup.py +++ b/setup.py @@ -40,6 +40,7 @@ "Operating System :: OS Independent"], install_requires=[ 'six', # python 2-3 compatibility], + 'sympy' ], scripts=[ 'scripts/py2tex'], From f38ab670134664e77f25e2c9ea151f3ed7576bae Mon Sep 17 00:00:00 2001 From: Alex Hagen Date: Mon, 1 Feb 2021 07:13:05 -0800 Subject: [PATCH 2/6] need a last_in_fraction command` --- pytexit/core/core.py | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/pytexit/core/core.py b/pytexit/core/core.py index 3fbda5b..c3852d1 100644 --- a/pytexit/core/core.py +++ b/pytexit/core/core.py @@ -12,7 +12,7 @@ from six.moves import range from six.moves import map from sympy.core.sympify import sympify -from sympy.parsing.sympy_parser import parse_expr, standard_transformations, implicit_multiplication_application, convert_xor +from sympy.parsing.sympy_parser import parse_expr, standard_transformations, implicit_multiplication_application, convert_xor, split_symbols_custom, _token_splittable from sympy.printing.latex import latex from sympy.simplify.simplify import simplify from sympy import cancel @@ -377,17 +377,24 @@ def visit_BinOp(self, n): # Special binary operators if isinstance(n.op, ast.Div): if self.simplify_fractions: - expression = left + ' / ' + right - transformations = (standard_transformations + (implicit_multiplication_application,) + (convert_xor,)) + transformations = (standard_transformations + + (implicit_multiplication_application,) + (convert_xor,)) left = left.replace('E', 'Y').strip() right = right.replace('E', 'Y').strip() parsed_left = parse_expr(left, transformations=transformations) parsed_right = parse_expr(right, transformations=transformations) + print(parsed_left) + print(parsed_right) expression = cancel(parsed_left / parsed_right) - print(latex(expression)) - return latex(expression) + if False: #TODO [ahagen]: insert a `needs_latex` command here + expression = latex(expression) + else: + expression = str(expression) + expression = expression.replace('Y', 'E') + print(expression) + return expression return self.division(self.visit(n.left), self.visit(n.right)) elif isinstance(n.op, ast.FloorDiv): return r'\left\lfloor\frac{%s}{%s}\right\rfloor' % \ From 22b3fb29968da82206f0162e827c851893f24a3b Mon Sep 17 00:00:00 2001 From: Alex Hagen Date: Tue, 2 Feb 2021 07:46:05 -0800 Subject: [PATCH 3/6] working for initial example --- pytexit/core/core.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/pytexit/core/core.py b/pytexit/core/core.py index c3852d1..5beb6db 100644 --- a/pytexit/core/core.py +++ b/pytexit/core/core.py @@ -379,21 +379,19 @@ def visit_BinOp(self, n): if self.simplify_fractions: transformations = (standard_transformations + (implicit_multiplication_application,) + (convert_xor,)) + # TODO[ahagen]: Find a way to replace with something that wont ever occur left = left.replace('E', 'Y').strip() right = right.replace('E', 'Y').strip() parsed_left = parse_expr(left, transformations=transformations) parsed_right = parse_expr(right, transformations=transformations) - print(parsed_left) - print(parsed_right) expression = cancel(parsed_left / parsed_right) - if False: #TODO [ahagen]: insert a `needs_latex` command here + if isinstance(n.right, ast.Name): expression = latex(expression) else: expression = str(expression) expression = expression.replace('Y', 'E') - print(expression) return expression return self.division(self.visit(n.left), self.visit(n.right)) elif isinstance(n.op, ast.FloorDiv): From c103bc91f5ea5be3fe6ea51a5d08a8b61e0aa604 Mon Sep 17 00:00:00 2001 From: Alex Hagen Date: Wed, 3 Feb 2021 08:07:03 -0800 Subject: [PATCH 4/6] fixed unused letter and added to test --- pytexit/core/core.py | 20 ++++++++++++++++---- pytexit/test/test_functions.py | 2 ++ 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/pytexit/core/core.py b/pytexit/core/core.py index 5beb6db..af5007f 100644 --- a/pytexit/core/core.py +++ b/pytexit/core/core.py @@ -17,6 +17,8 @@ from sympy.simplify.simplify import simplify from sympy import cancel +alphabet = 'TUVWXYZ' + unicode_tbl = { 'α': 'alpha', 'β': 'beta', @@ -379,19 +381,29 @@ def visit_BinOp(self, n): if self.simplify_fractions: transformations = (standard_transformations + (implicit_multiplication_application,) + (convert_xor,)) - # TODO[ahagen]: Find a way to replace with something that wont ever occur - left = left.replace('E', 'Y').strip() - right = right.replace('E', 'Y').strip() + # replace E with an unused letter - sympy thinks E=exp(1) + unused_letter = 'A' + for letter in alphabet: + if letter not in left and letter not in right: + unused_letter = letter + break + left = left.replace('E', unused_letter).strip() + right = right.replace('E', unused_letter).strip() + # parse the expression into a sympy expression and simplify parsed_left = parse_expr(left, transformations=transformations) parsed_right = parse_expr(right, transformations=transformations) expression = cancel(parsed_left / parsed_right) if isinstance(n.right, ast.Name): + # if the right is not a division op, then we need to convert + # to latex expression = latex(expression) else: + # otherwise we need to use sympy-ish expressions expression = str(expression) - expression = expression.replace('Y', 'E') + # turn everything back to E + expression = expression.replace(unused_letter, 'E') return expression return self.division(self.visit(n.left), self.visit(n.right)) elif isinstance(n.op, ast.FloorDiv): diff --git a/pytexit/test/test_functions.py b/pytexit/test/test_functions.py index 9a64e66..8072a9a 100644 --- a/pytexit/test/test_functions.py +++ b/pytexit/test/test_functions.py @@ -26,6 +26,7 @@ def test_py2tex(verbose=True, **kwargs): r'1<2 Date: Mon, 8 Feb 2021 06:49:58 -0800 Subject: [PATCH 5/6] fixed the range comprehension --- pytexit/core/core.py | 10 ++++++++++ pytexit/test/test_functions.py | 6 +++--- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/pytexit/core/core.py b/pytexit/core/core.py index af5007f..7dcc683 100644 --- a/pytexit/core/core.py +++ b/pytexit/core/core.py @@ -135,6 +135,16 @@ def visit_ListComp(self, n, kwout=False): else: kw['min'] = 0 kw['max'] = self.visit(comp.iter.args[0]) + # Remove 1 for range max + try: + kw['max'] = int(kw['max'])-1 + except ValueError: + if kw['max'].endswith(r'+1'): + # write 'sum([... range(N+1)])' as (sum^N) + kw['max'] = kw['max'][:-2] + else: + # write 'sum([... range(N)])' as (sum^N-1) + kw['max'] = r'{0}-1'.format(kw['max']) kw['content'] = self.visit(n.elt) args = r'%s, %s=%s..%s' % ( diff --git a/pytexit/test/test_functions.py b/pytexit/test/test_functions.py index 8072a9a..9d46ff7 100644 --- a/pytexit/test/test_functions.py +++ b/pytexit/test/test_functions.py @@ -24,9 +24,9 @@ def test_py2tex(verbose=True, **kwargs): r'quad(f,0,np.inf)', r'2*4', r'1<2 Date: Mon, 8 Feb 2021 12:15:06 -0800 Subject: [PATCH 6/6] importing within division to keep python2 compatibility --- pytexit/core/core.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/pytexit/core/core.py b/pytexit/core/core.py index 7dcc683..6b7607f 100644 --- a/pytexit/core/core.py +++ b/pytexit/core/core.py @@ -11,11 +11,7 @@ from warnings import warn from six.moves import range from six.moves import map -from sympy.core.sympify import sympify -from sympy.parsing.sympy_parser import parse_expr, standard_transformations, implicit_multiplication_application, convert_xor, split_symbols_custom, _token_splittable -from sympy.printing.latex import latex -from sympy.simplify.simplify import simplify -from sympy import cancel + alphabet = 'TUVWXYZ' @@ -389,6 +385,11 @@ def visit_BinOp(self, n): # Special binary operators if isinstance(n.op, ast.Div): if self.simplify_fractions: + from sympy.core.sympify import sympify + from sympy.parsing.sympy_parser import parse_expr, standard_transformations, implicit_multiplication_application, convert_xor, split_symbols_custom, _token_splittable + from sympy.printing.latex import latex + from sympy.simplify.simplify import simplify + from sympy import cancel transformations = (standard_transformations + (implicit_multiplication_application,) + (convert_xor,)) # replace E with an unused letter - sympy thinks E=exp(1)