Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generates algorithmic environment from algpseudocode #152

Merged
merged 14 commits into from
Dec 10, 2022
Merged
Show file tree
Hide file tree
Changes from 7 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
79 changes: 79 additions & 0 deletions src/integration_tests/algorithmic_style_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
"""End-to-end test cases of algorithmic style."""

from __future__ import annotations

from typing import Any, Callable

from latexify import frontend
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this file should be a unit test frontend_{algorithmic?}_test.py because frontend is not intended to be used directly.
Or it'd be okay to use just exported functions and Style.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can move it, but function_expansion_test and regression_test basically use frontend directly, as they use frontend.function.

Similarly, this file uses function.get_latex. Both of these functions are exported in __init__.py, so it feels somewhat like an integration test, because we're testing end-to-end behavior from function to generated $LaTeX$ output

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So it turns that the issue comes from the old implementation of these tests, will consider it later.



def check_algorithm(
fn: Callable[..., Any],
latex: str,
**kwargs,
) -> None:
"""Helper to check if the obtained function has the expected LaTeX form.
Args:
ZibingZhang marked this conversation as resolved.
Show resolved Hide resolved
fn: Function to check.
latex: LaTeX form of `fn`.
**kwargs: Arguments passed to `frontend.get_latex`.
"""
# Checks the syntax:
# def fn(...):
# ...
# latexified = get_latex(fn, style=ALGORITHM, **kwargs)
latexified = frontend.get_latex(fn, style=frontend.Style.ALGORITHMIC, **kwargs)
assert latexified == latex


# TODO(ZibingZhang) changing fact -> factorial breaks because factorial is replaced by
ZibingZhang marked this conversation as resolved.
Show resolved Hide resolved
# !, substitutions should not occur for the name of the procedure
def test_factorial() -> None:
def fact(n):
if n == 0:
return 1
else:
return n * fact(n - 1)

latex = (
r"\begin{algorithmic} "
ZibingZhang marked this conversation as resolved.
Show resolved Hide resolved
r"\Procedure{fact}{$n$} "
r"\If{$n = 0$} "
r"\State \Return $1$ "
r"\Else "
r"\State \Return $n \mathrm{fact} \mathopen{}\left( n - 1 \mathclose{}\right)$ "
r"\EndIf "
r"\EndProcedure "
r"\end{algorithmic}"
)
check_algorithm(fact, latex)


def test_collatz() -> None:
def collatz(n):
iterations = 0
while n > 1:
if n % 2 == 0:
n = n / 2
ZibingZhang marked this conversation as resolved.
Show resolved Hide resolved
else:
n = 3 * n + 1
iterations = iterations + 1
return iterations

latex = (
r"\begin{algorithmic} "
r"\Procedure{collatz}{$n$} "
r"\State $\mathrm{iterations} \gets 0$ "
r"\While{$n > 1$} "
r"\If{$n \mathbin{\%} 2 = 0$} "
r"\State $n \gets \frac{n}{2}$ "
r"\Else \State $n \gets 3 n + 1$ "
r"\EndIf "
r"\State $\mathrm{iterations} \gets \mathrm{iterations} + 1$ "
r"\EndWhile "
r"\State \Return $\mathrm{iterations}$ "
r"\EndProcedure "
r"\end{algorithmic}"
)

check_algorithm(collatz, latex)
38 changes: 22 additions & 16 deletions src/integration_tests/function_expansion_test.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
"""End-to-end test cases of function expansion."""

from __future__ import annotations

import math

from integration_tests import utils
from integration_tests import integration_utils


def test_atan2() -> None:
Expand All @@ -11,7 +15,7 @@ def solve(x, y):
r"\mathrm{solve}(x, y) ="
r" \arctan \mathopen{}\left( \frac{y}{x} \mathclose{}\right)"
)
utils.check_function(solve, latex, expand_functions={"atan2"})
integration_utils.check_function(solve, latex, expand_functions={"atan2"})


def test_atan2_nested() -> None:
Expand All @@ -22,55 +26,57 @@ def solve(x, y):
r"\mathrm{solve}(x, y) ="
r" \arctan \mathopen{}\left( \frac{e^{y}}{e^{x}} \mathclose{}\right)"
)
utils.check_function(solve, latex, expand_functions={"atan2", "exp"})
integration_utils.check_function(solve, latex, expand_functions={"atan2", "exp"})


def test_exp() -> None:
def solve(x):
return math.exp(x)

latex = r"\mathrm{solve}(x) = e^{x}"
utils.check_function(solve, latex, expand_functions={"exp"})
integration_utils.check_function(solve, latex, expand_functions={"exp"})


def test_exp_nested() -> None:
def solve(x):
return math.exp(math.exp(x))

latex = r"\mathrm{solve}(x) = e^{e^{x}}"
utils.check_function(solve, latex, expand_functions={"exp"})
integration_utils.check_function(solve, latex, expand_functions={"exp"})


def test_exp2() -> None:
def solve(x):
return math.exp2(x)

latex = r"\mathrm{solve}(x) = 2^{x}"
utils.check_function(solve, latex, expand_functions={"exp2"})
integration_utils.check_function(solve, latex, expand_functions={"exp2"})


def test_exp2_nested() -> None:
def solve(x):
return math.exp2(math.exp2(x))

latex = r"\mathrm{solve}(x) = 2^{2^{x}}"
utils.check_function(solve, latex, expand_functions={"exp2"})
integration_utils.check_function(solve, latex, expand_functions={"exp2"})


def test_expm1() -> None:
def solve(x):
return math.expm1(x)

latex = r"\mathrm{solve}(x) = \exp x - 1"
utils.check_function(solve, latex, expand_functions={"expm1"})
integration_utils.check_function(solve, latex, expand_functions={"expm1"})


def test_expm1_nested() -> None:
def solve(x, y, z):
return math.expm1(math.pow(y, z))

latex = r"\mathrm{solve}(x, y, z) = e^{y^{z}} - 1"
utils.check_function(solve, latex, expand_functions={"expm1", "exp", "pow"})
integration_utils.check_function(
solve, latex, expand_functions={"expm1", "exp", "pow"}
)


def test_hypot_without_attribute() -> None:
Expand All @@ -80,15 +86,15 @@ def solve(x, y, z):
return hypot(x, y, z)

latex = r"\mathrm{solve}(x, y, z) = \sqrt{ x^{2} + y^{2} + z^{2} }"
utils.check_function(solve, latex, expand_functions={"hypot"})
integration_utils.check_function(solve, latex, expand_functions={"hypot"})


def test_hypot() -> None:
def solve(x, y, z):
return math.hypot(x, y, z)

latex = r"\mathrm{solve}(x, y, z) = \sqrt{ x^{2} + y^{2} + z^{2} }"
utils.check_function(solve, latex, expand_functions={"hypot"})
integration_utils.check_function(solve, latex, expand_functions={"hypot"})


def test_hypot_nested() -> None:
Expand All @@ -99,23 +105,23 @@ def solve(a, b, x, y):
r"\mathrm{solve}(a, b, x, y) ="
r" \sqrt{ \sqrt{ a^{2} + b^{2} }^{2} + x^{2} + y^{2} }"
)
utils.check_function(solve, latex, expand_functions={"hypot"})
integration_utils.check_function(solve, latex, expand_functions={"hypot"})


def test_log1p() -> None:
def solve(x):
return math.log1p(x)

latex = r"\mathrm{solve}(x) = \log \mathopen{}\left( 1 + x \mathclose{}\right)"
utils.check_function(solve, latex, expand_functions={"log1p"})
integration_utils.check_function(solve, latex, expand_functions={"log1p"})


def test_log1p_nested() -> None:
def solve(x):
return math.log1p(math.exp(x))

latex = r"\mathrm{solve}(x) = \log \mathopen{}\left( 1 + e^{x} \mathclose{}\right)"
utils.check_function(solve, latex, expand_functions={"log1p", "exp"})
integration_utils.check_function(solve, latex, expand_functions={"log1p", "exp"})


def test_pow_nested() -> None:
Expand All @@ -126,12 +132,12 @@ def solve(w, x, y, z):
r"\mathrm{solve}(w, x, y, z) = "
r"\mathopen{}\left( w^{x} \mathclose{}\right)^{y^{z}}"
)
utils.check_function(solve, latex, expand_functions={"pow"})
integration_utils.check_function(solve, latex, expand_functions={"pow"})


def test_pow() -> None:
def solve(x, y):
return math.pow(x, y)

latex = r"\mathrm{solve}(x, y) = x^{y}"
utils.check_function(solve, latex, expand_functions={"pow"})
integration_utils.check_function(solve, latex, expand_functions={"pow"})
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
"""Utilities for integration tests."""
odashi marked this conversation as resolved.
Show resolved Hide resolved

from __future__ import annotations

from typing import Any, Callable

from latexify import frontend
Expand Down
Loading