Skip to main content

No project description provided

Project description

Latex-VM (Virtual Machine)

Coverage Bugs Quality Gate Status Code Smells

Latex-VM is a simple context environment for mathematical expressions in LaTeX. It supports variable and function declaration.

Type Aliases

Type Definition
Varname str
ExpressionStr str
EnvironmentVariables Dict[Varname, Any]

API

class ActionResult:
    def ok(self) -> bool

class GraphSession:
    @staticmethod
    def new(env: EnvironmentVariables = {}, rules: Dict[str, str] = {}) -> "GraphSession"
    def execute(self, input: str, simplify: bool = False) -> ActionResult[CalculatorAction, str]
    def get_env_functions(self) -> EnvironmentVariables
    def get_env_variables(self) -> EnvironmentVariables
    def get_env(self) -> EnvironmentVariables
    def force_resolve_function(self, input: str, use_sub_rule: bool = True) -> ActionResult[None, str]
    def add_sub_rule(self, pattern: str, replacement: str) -> None
    def remove_sub_rule(self, pattern: str) -> None
    def get_sub_rules(self) -> Dict[str, str]
    def clear_session(self) -> None

Example Usage

# Create a new graph session
session = GraphSession.new()

# Assignment expression
session.execute("y = 20")                                 # Action: CalculatorAction.VARIABLE_ASSIGNMENT, Ok(20)

# Function declaration expression
session.execute("double(x) = x * 2")                      # Action: CalculatorAction.FUNCTION_DEFINITION, Ok(double_func(x) = x * 2)
session.execute("pow(x) = x^2")                           # Action: CalculatorAction.FUNCTION_DEFINITION, Ok(pow_func(x) = x^2)

# Statement expression
session.execute("double(pow(2))")                         # Action: CalculatorAction.STATEMENT_EXECUTION, Ok(8)

# Function force-resolve (Does not converge to a value)
session.force_resolve_function("double(pow(x+2))")        # Ok((x + 2)**2*2)

Environment Variables and Value Retrieval

Note: All getters returns a copy in order to prevent mutation of internal variables.

session = GraphSession.new()
session.execute("y = 20")
session.execute("double(x) = x * 2")

# Get all environment variables
session.get_env()                       # {'y': '20', 'double_func': (['x'], 'x * 2')}

# Get only function varaibles
session.get_env_functions()             # {'double_func': (['x'], 'x * 2')}

# Get only variables
session.get_env_variables()             # {'y': '20'}

# Session can be cleared
session.clear_session()

Result and Error Handling

Methods which returns the ActionResult type conforms to the following handling.
Note: ActionResult.action holds the action value.

...

result = session.execute(...)

if result.ok():
  ...
  # use the result value
  # Note: The result.message contains the value
else:
  ...
  # handle errors...
  # Note: The result.message contains the error message

Session Loading

Sessions can easily be loaded by passing in pre-existing environment variables.

session_1 = GraphSession.new()
session_1.execute("double(x) = x * 2")

session_2 = GraphSession.new(session.get_env())
res = session_2.execute("double(5)")
print(res.message) # 10

Simplification

Expression simplification is optional. In cases where the input latex is very complex, it can greatly affect performance. For this reason, the simplify flag is defaulted to False. Addtionally, the simplify function is run with a timeout of 3 seconds, if failed, it will just yield the result without simplifying.

session = GraphSession.new()
# Action: CalculatorAction.FUNCTION_DEFINITION, Ok(f_func(x) = \frac{x}{3} + 3 + 20 + 20 + 20)
session.execute(r"f(x) = \frac{x}{3} + 3 + y + y + y")

# Action: CalculatorAction.FUNCTION_DEFINITION, Ok(f_func(x) = \frac{x}{3} + 63)
session.execute(r"f(x) = \frac{x}{3} + 3 + y + y + y", simplify=True)

Substitution Rules

The GraphSession.force_resolve_function method returns a Pythonic representation of the input. However, this representation may need to be modified in order to be usable. For this reason, there are substitution rules that can be applied to the output.

This behavior is enabled default, to resolve without using substitution rules, set use_sub_rule to False.

gs.execute(r"make_abs(x) = \left|x\right|")
gs.execute(r"pow(a, b) = a^{b}")

# Without any substituion rule
print(gs.force_resolve_function(r"pow(make_abs(x), make_abs(y))"))   # Ok(Abs(x)**Abs(y))

# We want abs(...) instead of Abs(...)
gs.add_sub_rule("Abs", "abs")
gs.force_resolve_function(r"pow(make_abs(x), make_abs(y))")   # Ok(abs(x)**abs(y))

# We need pow expressed using '^'
gs.add_sub_rule(r"\*\*", "^")
gs.force_resolve_function(r"pow(make_abs(x), make_abs(y))")   # Ok(abs(x)^abs(y))

# Resolve without using substitution rules
gs.force_resolve_function(r"pow(make_abs(x), make_abs(y))", use_sub_rule=False) # Ok(Abs(x)**Abs(y))

LaTeX override

You can override LaTeX functions by declaring a function with the same name. This allows you to customize the functionality of the function according to your needs.

# Works perfectly fine
print(gs.force_resolve_function(r"\sin\left(x\right)")) # Ok(sin(x))

# Override
gs.execute("double(x) = 2 x")
gs.execute("sin(a) = double(a)")

# Sin is now overridden
print(gs.force_resolve_function(r"\sin\left(x\right)")) # Ok(x*2)

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

latexvm-0.1.6.tar.gz (14.4 kB view hashes)

Uploaded Source

Built Distribution

latexvm-0.1.6-py3-none-any.whl (14.4 kB view hashes)

Uploaded Python 3

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page