From e37a2bfef4ba54095c3494c3e879317045437475 Mon Sep 17 00:00:00 2001 From: hjiawei Date: Thu, 24 Nov 2022 17:02:54 -0500 Subject: [PATCH 1/5] Added support for numpy NDarray method. Added corresponding tests --- examples/examples.ipynb | 53 +++++++++++++++++-- src/integration_tests/regression_test.py | 10 ++++ src/latexify/codegen/function_codegen.py | 13 +++++ src/latexify/codegen/function_codegen_test.py | 16 +++++- 4 files changed, 88 insertions(+), 4 deletions(-) diff --git a/examples/examples.ipynb b/examples/examples.ipynb index dd1aaf8..2650bd5 100644 --- a/examples/examples.ipynb +++ b/examples/examples.ipynb @@ -2,12 +2,13 @@ "cells": [ { "cell_type": "code", - "execution_count": 1, + "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "import math\n", - "import latexify" + "import latexify\n", + "import numpy as np" ] }, { @@ -165,11 +166,57 @@ "\n", "solve" ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "data": { + "text/latex": [ + "$$ \\displaystyle \\mathrm{numpy}(a) = \\begin{bmatrix} {1} & {2} & {3} & {4} \\\\ {5} & {6} & {7} & {8} \\\\ {9} & {10} & {11} & {12} \\end{bmatrix} $$" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "@latexify.function\n", + "def numpy(a):\n", + " return np.ndarray([1,2,3,4],[5,6,7,8],[9,10,11,12])\n", + "\n", + "numpy" + ] } ], "metadata": { + "kernelspec": { + "display_name": "Python 3.10.8 64-bit", + "language": "python", + "name": "python3" + }, "language_info": { - "name": "python" + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.8" + }, + "vscode": { + "interpreter": { + "hash": "8a94588eda9d64d9e9a351ab8144e55b1fabf5113b54e67dd26a8c27df0381b3" + } } }, "nbformat": 4, diff --git a/src/integration_tests/regression_test.py b/src/integration_tests/regression_test.py index fdbd080..9c9e62e 100644 --- a/src/integration_tests/regression_test.py +++ b/src/integration_tests/regression_test.py @@ -3,6 +3,7 @@ from __future__ import annotations import math +import numpy as np from collections.abc import Callable from typing import Any @@ -330,3 +331,12 @@ def solve(x): latex = r"\mathrm{solve}(x) = x" _check_function(solve, latex) + + +def test_generate_ndarray() -> None: + def solve(a): + """A 2x3 numpy matrix""" + return np.ndarray([1,2,3],[4,5,6]) + + latex = "\\mathrm{solve}(a) = \\begin{bmatrix} {1} & {2} & {3} \\\\ {4} & {5} & {6} \\end{bmatrix}" + _check_function(solve, latex) \ No newline at end of file diff --git a/src/latexify/codegen/function_codegen.py b/src/latexify/codegen/function_codegen.py index e660804..e60b24a 100644 --- a/src/latexify/codegen/function_codegen.py +++ b/src/latexify/codegen/function_codegen.py @@ -367,6 +367,19 @@ def visit_Call(self, node: ast.Call) -> str: + rf" \mathopen{{}}\left({{{elt}}}\mathclose{{}}\right)" ) + # Render NDarray method for numpy + if func_str == "ndarray": + # construct matrix + matrix_str = r"\begin{bmatrix} " + # iterate over rows + for row in node.args: + for col in row.elts: + matrix_str += self.visit(col) + r" & " + matrix_str = matrix_str[:-2] + r" \\ " + matrix_str = matrix_str[:-3] + r"\end{bmatrix}" + return matrix_str + + arg_strs = [self.visit(arg) for arg in node.args] return lstr + ", ".join(arg_strs) + rstr diff --git a/src/latexify/codegen/function_codegen_test.py b/src/latexify/codegen/function_codegen_test.py index 793ab62..5b6d0e3 100644 --- a/src/latexify/codegen/function_codegen_test.py +++ b/src/latexify/codegen/function_codegen_test.py @@ -4,7 +4,7 @@ import ast import textwrap - +import numpy as np import pytest from latexify import exceptions, test_utils @@ -31,6 +31,7 @@ def f(x): """ ) ).body[0] + breakpoint() assert isinstance(tree, ast.FunctionDef) latex_without_flag = "x" @@ -298,6 +299,7 @@ def test_visit_call_sum_prod_multiple_comprehension(code: str, latex: str) -> No ], ) def test_visit_call_sum_prod_with_if(src_suffix: str, dest_suffix: str) -> None: + breakpoint() for src_fn, dest_fn in [("sum", r"\sum"), ("math.prod", r"\prod")]: node = ast.parse(src_fn + src_suffix).body[0].value assert isinstance(node, ast.Call) @@ -744,3 +746,15 @@ def test_use_set_symbols_compare(code: str, latex: str) -> None: tree = ast.parse(code).body[0].value assert isinstance(tree, ast.Compare) assert function_codegen.FunctionCodegen(use_set_symbols=True).visit(tree) == latex + + +def test_special_arrays(): + tree = ast.parse(textwrap.dedent( + """ + def numpy(a): + return np.ndarray([1,2,3],[4,5,6]) + """ + )).body[0] + + assert isinstance(tree, ast.FunctionDef) + assert FunctionCodegen().visit(tree) == "\\mathrm{numpy}(a) = \\begin{bmatrix} {1} & {2} & {3} \\\\ {4} & {5} & {6} \\end{bmatrix}" From 9b0d0c4882344eccdf36c2c545dc3456f044c8db Mon Sep 17 00:00:00 2001 From: hjiawei Date: Thu, 24 Nov 2022 17:58:03 -0500 Subject: [PATCH 2/5] Removed breakpoints, fixed styles --- src/integration_tests/regression_test.py | 4 ++-- src/latexify/codegen/function_codegen.py | 1 - src/latexify/codegen/function_codegen_test.py | 15 +++++++++------ 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/integration_tests/regression_test.py b/src/integration_tests/regression_test.py index 9c9e62e..4a9e072 100644 --- a/src/integration_tests/regression_test.py +++ b/src/integration_tests/regression_test.py @@ -336,7 +336,7 @@ def solve(x): def test_generate_ndarray() -> None: def solve(a): """A 2x3 numpy matrix""" - return np.ndarray([1,2,3],[4,5,6]) + return np.ndarray([1, 2, 3], [4, 5, 6]) latex = "\\mathrm{solve}(a) = \\begin{bmatrix} {1} & {2} & {3} \\\\ {4} & {5} & {6} \\end{bmatrix}" - _check_function(solve, latex) \ No newline at end of file + _check_function(solve, latex) diff --git a/src/latexify/codegen/function_codegen.py b/src/latexify/codegen/function_codegen.py index e60b24a..f631562 100644 --- a/src/latexify/codegen/function_codegen.py +++ b/src/latexify/codegen/function_codegen.py @@ -378,7 +378,6 @@ def visit_Call(self, node: ast.Call) -> str: matrix_str = matrix_str[:-2] + r" \\ " matrix_str = matrix_str[:-3] + r"\end{bmatrix}" return matrix_str - arg_strs = [self.visit(arg) for arg in node.args] return lstr + ", ".join(arg_strs) + rstr diff --git a/src/latexify/codegen/function_codegen_test.py b/src/latexify/codegen/function_codegen_test.py index 5b6d0e3..8a15124 100644 --- a/src/latexify/codegen/function_codegen_test.py +++ b/src/latexify/codegen/function_codegen_test.py @@ -31,7 +31,6 @@ def f(x): """ ) ).body[0] - breakpoint() assert isinstance(tree, ast.FunctionDef) latex_without_flag = "x" @@ -299,7 +298,6 @@ def test_visit_call_sum_prod_multiple_comprehension(code: str, latex: str) -> No ], ) def test_visit_call_sum_prod_with_if(src_suffix: str, dest_suffix: str) -> None: - breakpoint() for src_fn, dest_fn in [("sum", r"\sum"), ("math.prod", r"\prod")]: node = ast.parse(src_fn + src_suffix).body[0].value assert isinstance(node, ast.Call) @@ -749,12 +747,17 @@ def test_use_set_symbols_compare(code: str, latex: str) -> None: def test_special_arrays(): - tree = ast.parse(textwrap.dedent( - """ + tree = ast.parse( + textwrap.dedent( + """ def numpy(a): return np.ndarray([1,2,3],[4,5,6]) """ - )).body[0] + ) + ).body[0] assert isinstance(tree, ast.FunctionDef) - assert FunctionCodegen().visit(tree) == "\\mathrm{numpy}(a) = \\begin{bmatrix} {1} & {2} & {3} \\\\ {4} & {5} & {6} \\end{bmatrix}" + assert ( + FunctionCodegen().visit(tree) + == "\\mathrm{numpy}(a) = \\begin{bmatrix} {1} & {2} & {3} \\\\ {4} & {5} & {6} \\end{bmatrix}" + ) From 274cf22772bd610316cf67caef18c55f9c69cd30 Mon Sep 17 00:00:00 2001 From: hjiawei Date: Thu, 24 Nov 2022 18:05:23 -0500 Subject: [PATCH 3/5] modified styles --- src/latexify/codegen/function_codegen_test.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/latexify/codegen/function_codegen_test.py b/src/latexify/codegen/function_codegen_test.py index 8a15124..160a896 100644 --- a/src/latexify/codegen/function_codegen_test.py +++ b/src/latexify/codegen/function_codegen_test.py @@ -746,7 +746,7 @@ def test_use_set_symbols_compare(code: str, latex: str) -> None: assert function_codegen.FunctionCodegen(use_set_symbols=True).visit(tree) == latex -def test_special_arrays(): +def test_generate_ndarrays(): tree = ast.parse( textwrap.dedent( """ @@ -756,8 +756,6 @@ def numpy(a): ) ).body[0] + latex = "\\mathrm{numpy}(a) = \\begin{bmatrix} {1} & {2} & {3} \\\\ {4} & {5} & {6} \\end{bmatrix}" assert isinstance(tree, ast.FunctionDef) - assert ( - FunctionCodegen().visit(tree) - == "\\mathrm{numpy}(a) = \\begin{bmatrix} {1} & {2} & {3} \\\\ {4} & {5} & {6} \\end{bmatrix}" - ) + assert FunctionCodegen().visit(tree) == latex From 2af25d4718b452a51935323de2c9d7037ebb3cba Mon Sep 17 00:00:00 2001 From: hjiawei Date: Fri, 25 Nov 2022 15:43:11 -0500 Subject: [PATCH 4/5] Fixed function name, added dependency in toml, removed unnecessary import --- examples/examples.ipynb | 52 +++++++++---------- pyproject.toml | 1 + src/latexify/codegen/function_codegen_test.py | 1 - 3 files changed, 27 insertions(+), 27 deletions(-) diff --git a/examples/examples.ipynb b/examples/examples.ipynb index 2650bd5..b1f588b 100644 --- a/examples/examples.ipynb +++ b/examples/examples.ipynb @@ -13,7 +13,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 4, "metadata": {}, "outputs": [ { @@ -21,19 +21,19 @@ "output_type": "stream", "text": [ "-1.0\n", - "\\mathrm{solve}(a, b, c) = \\frac{-b + \\sqrt{b^{{2}} - {4}ac}}{{2}a}\n" + "\\mathrm{solve}(a, b, c) = \\frac{-b + \\sqrt{b^{{2}} - {4} a c}}{{2} a}\n" ] }, { "data": { "text/latex": [ - "$$ \\displaystyle \\mathrm{solve}(a, b, c) = \\frac{-b + \\sqrt{b^{{2}} - {4}ac}}{{2}a} $$" + "$$ \\displaystyle \\mathrm{solve}(a, b, c) = \\frac{-b + \\sqrt{b^{{2}} - {4} a c}}{{2} a} $$" ], "text/plain": [ - "" + "" ] }, - "execution_count": 2, + "execution_count": 4, "metadata": {}, "output_type": "execute_result" } @@ -50,7 +50,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 5, "metadata": {}, "outputs": [ { @@ -59,10 +59,10 @@ "$$ \\displaystyle \\mathrm{sinc}(x) = \\left\\{ \\begin{array}{ll} {1}, & \\mathrm{if} \\ {x = {0}} \\\\ \\frac{\\sin{\\left({x}\\right)}}{x}, & \\mathrm{otherwise} \\end{array} \\right. $$" ], "text/plain": [ - "" + "" ] }, - "execution_count": 3, + "execution_count": 5, "metadata": {}, "output_type": "execute_result" } @@ -80,19 +80,19 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 6, "metadata": {}, "outputs": [ { "data": { "text/latex": [ - "$$ \\displaystyle \\mathrm{fib}(x) = \\left\\{ \\begin{array}{ll} {0}, & \\mathrm{if} \\ {x = {0}} \\\\ {1}, & \\mathrm{if} \\ {x = {1}} \\\\ \\mathrm{fib}\\left(x - {1}\\right) + \\mathrm{fib}\\left(x - {2}\\right), & \\mathrm{otherwise} \\end{array} \\right. $$" + "$$ \\displaystyle \\mathrm{fib}(x) = \\left\\{ \\begin{array}{ll} {0}, & \\mathrm{if} \\ {x = {0}} \\\\ {1}, & \\mathrm{if} \\ {x = {1}} \\\\ \\mathrm{fib}\\mathopen{}\\left(x - {1}\\mathclose{}\\right) + \\mathrm{fib}\\mathopen{}\\left(x - {2}\\mathclose{}\\right), & \\mathrm{otherwise} \\end{array} \\right. $$" ], "text/plain": [ - "" + "" ] }, - "execution_count": 4, + "execution_count": 6, "metadata": {}, "output_type": "execute_result" } @@ -113,19 +113,19 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 7, "metadata": {}, "outputs": [ { "data": { "text/latex": [ - "$$ \\displaystyle \\mathrm{greek}({\\alpha}, {\\beta}, {\\gamma}, {\\Omega}) = {\\alpha}{\\beta} + \\Gamma\\left({{\\gamma}}\\right) + {\\Omega} $$" + "$$ \\displaystyle \\mathrm{greek}({\\alpha}, {\\beta}, {\\gamma}, {\\Omega}) = {\\alpha} {\\beta} + \\Gamma\\left({{\\gamma}}\\right) + {\\Omega} $$" ], "text/plain": [ - "" + "" ] }, - "execution_count": 5, + "execution_count": 7, "metadata": {}, "output_type": "execute_result" } @@ -141,19 +141,19 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 8, "metadata": {}, "outputs": [ { "data": { "text/latex": [ - "$$ \\displaystyle \\frac{-b + \\sqrt{b^{{2}} - {4}ac}}{{2}a} $$" + "$$ \\displaystyle \\frac{-b + \\sqrt{b^{{2}} - {4} a c}}{{2} a} $$" ], "text/plain": [ - "" + "" ] }, - "execution_count": 6, + "execution_count": 8, "metadata": {}, "output_type": "execute_result" } @@ -169,29 +169,29 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 9, "metadata": {}, "outputs": [ { "data": { "text/latex": [ - "$$ \\displaystyle \\mathrm{numpy}(a) = \\begin{bmatrix} {1} & {2} & {3} & {4} \\\\ {5} & {6} & {7} & {8} \\\\ {9} & {10} & {11} & {12} \\end{bmatrix} $$" + "$$ \\displaystyle \\mathrm{myNdarray}(a) = \\begin{bmatrix} {1} & {2} & {3} & {4} \\\\ {5} & {6} & {7} & {8} \\\\ {9} & {10} & {11} & {12} \\end{bmatrix} $$" ], "text/plain": [ - "" + "" ] }, - "execution_count": 7, + "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "@latexify.function\n", - "def numpy(a):\n", + "def myNdarray(a):\n", " return np.ndarray([1,2,3,4],[5,6,7,8],[9,10,11,12])\n", "\n", - "numpy" + "myNdarray" ] } ], diff --git a/pyproject.toml b/pyproject.toml index 9324f7f..a006c77 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -50,6 +50,7 @@ dev = [ "pytest>=7.1", "twine>=4.0", "isort>=5.10", + "numpy>=1.23.4", ] [project.urls] diff --git a/src/latexify/codegen/function_codegen_test.py b/src/latexify/codegen/function_codegen_test.py index 160a896..e8f3be7 100644 --- a/src/latexify/codegen/function_codegen_test.py +++ b/src/latexify/codegen/function_codegen_test.py @@ -4,7 +4,6 @@ import ast import textwrap -import numpy as np import pytest from latexify import exceptions, test_utils From f79c1a87dd663525c356f6e1af16db9c72ab4249 Mon Sep 17 00:00:00 2001 From: hjiawei Date: Fri, 25 Nov 2022 15:44:55 -0500 Subject: [PATCH 5/5] removed unnecessary metadata --- examples/examples.ipynb | 5 ----- 1 file changed, 5 deletions(-) diff --git a/examples/examples.ipynb b/examples/examples.ipynb index b1f588b..eca5f68 100644 --- a/examples/examples.ipynb +++ b/examples/examples.ipynb @@ -196,11 +196,6 @@ } ], "metadata": { - "kernelspec": { - "display_name": "Python 3.10.8 64-bit", - "language": "python", - "name": "python3" - }, "language_info": { "codemirror_mode": { "name": "ipython",