Advanced Usage of latexSymb: Building Complex Mathematical Documents

Introduction

This vignette demonstrates advanced techniques for using latexSymb to create complex mathematical documents. We’ll explore how to organize your code effectively, create reusable functions, and build sophisticated mathematical expressions.

Code Organization: The Two-File Pattern

When working with complex mathematical documents, it’s beneficial to separate your symbol definitions and helper functions from your main document content. This pattern offers several advantages:

  1. Cleaner Documents: Your .Rmd file remains focused on content rather than setup
  2. Reusability: Symbol definitions can be shared across multiple documents
  3. Maintainability: Changes to symbols or functions are centralized
  4. Readability: Mathematical logic is easier to follow without setup code

Example: Setting Up a Symbol Library

Create a separate .R file for your symbols, for instance:

# my_symbols.R
library(latexSymb)
data(common)
attach(common)
#> The following objects are masked from common (pos = 3):
#> 
#>     Comps, Ints, Nats, Rats, Reals, al, be, bgs, ch, comma, de, des,
#>     endl, ep, eq, et, f, g, ga, geq, gt, h, i, indic, infty, io, j, k,
#>     ka, l, la, ldots, leq, lt, m, mapsto, minus, mu, n, neq, nu, om,
#>     om, ph, pi, plus, ps, quad, rh, ruler, si, ta, th, thus, times, to,
#>     up, x, xi, y, z, ze
#> The following object is masked from package:base:
#> 
#>     pi

# Define document-specific symbols
pt <- lsymb("x")
pt_prime <- lsymb("x'")
metric_space <- lsymb("\\mathcal{X}")
measure <- lsymb("\\mu")

# Create specialized functions
dist <- function(x, y) lsymb("d") * pths(x * comma * y)

Then, use a separate .Rmd to write the body of your document. In that file, set:

knitr::opts_chunk$set(results = "asis", echo = FALSE)
source("my_symbols.R")

to make sure that the LaTeX code gets correctly rendered.

Creating Powerful Helper Functions

You can use latexSymb to handle complicated mathematical expressions. The following patterns can be helpful.

Pattern 1: Building Complex Expressions

Create functions that compose to build sophisticated expressions:

# Expectation operator
exp_val <- function(x) lsymb("\\mathbb{E}") * sqbr(x)

sq <- function(x) pths(x)^2

# Absolute value
abs <- function(x) lsymb("\\abs{", x, "}")

# Indicator function
indic <- function(condition) {
  lsymb("\\mathbbm{1}") |> under(br(condition))
}

# Composed example
X <- lsymb("X")
Y <- lsymb("Y")

Then you can create expressions like exp_val(sq(abs(X - Y))) |> il() to obtain \(\mathbb{E} \left[ \left( \abs{ X - Y } \right) ^{ 2 } \right]\) and exp_val(X * indic(Y > 0)) |> il() for \(\mathbb{E} \left[ X \mathbbm{1} _{ \lbrace NA \rbrace } \right]\).

Pattern 2: Multi-line Equation Builders

This pattern uses lists and the lenv() function. Each element of the list corresponds to a row of your displayed expression:

# Build a proof step by step
proof_steps <- list(
  ruler * dist(x, y) * leq * dist(x, z) + dist(z, y) * endl,
  ruler * thus * dist(x, y) - dist(x, z) * leq * dist(z, y)
) |>
  lenv("align*", rows = _)

\[\begin{align*}& d \left( x , y \right) \leq d \left( x , z \right) + d \left( z , y \right) \\& \Rightarrow d \left( x , y \right) - d \left( x , z \right) \leq d \left( z , y \right)\end{align*}\]

Complex Example: Statistical Proof

Here’s how these techniques combine in practice:

# Setup
sample_size <- lsymb("n")
observation <- lsymb("X") |> under(i)
sample_mean <- lsymb("\\bar{X}")
conv_distr <- lsymb("\\overset{d}{\\rightarrow}")
sqrt <- function(x) lsymb("\\sqrt{", x, "}")

# Build a Central Limit Theorem statement
clt_statement <- list(
  ruler * sqrt(sample_size) * (pths(sample_mean - mu) / si) *
    conv_distr * lsymb("N(0,1)") * endl,
  ruler * lsymb("\\text{where }") *
    sample_mean * eq * (1 / sample_size) * Sum(observation, from = i * eq * 1, to = sample_size)
) |>
  lenv("align*", rows = _)

\[\begin{align*}& \sqrt{ n } \frac{ \left( \bar{X} - \mu \right) }{ \sigma } \overset{d}{\rightarrow} N(0,1) \\& \text{where } \bar{X} = \frac{ 1 }{ n } \sum _{ i = 1 } ^{ n } X _{ i }\end{align*}\]

Conclusion

By organizing your code into separate files, creating reusable functions, and following consistent patterns, you can efficiently create complex mathematical documents with latexSymb. The key is to:

  1. Separate concerns: Keep symbol definitions in .R files
  2. Build abstractions: Create functions for repeated patterns
  3. Compose functions: Build complex expressions from simple parts