Skip to content

Commit 93043fc

Browse files
committed
docs: render math via MathJax (arithmatex)
- mkdocs.yml: enable pymdownx.arithmatex (generic) + load MathJax 3 with a small config (docs/javascripts/mathjax.js, re-typesets on instant nav). - Convert the API-visible math to LaTeX $...$ / $$...$$ so it renders as math instead of literal `^{(k)}` etc.: the Copula class + generator, the four generator-precision override hooks (core.py), and the F^{-1} / composition notation in quickstart.md and api.md. Docstrings made raw (r""") so the TeX backslashes aren't mangled as escapes. mkdocs build --strict clean; 22 arithmatex spans render on the API page.
1 parent 618e966 commit 93043fc

5 files changed

Lines changed: 54 additions & 24 deletions

File tree

‎acopula/core.py‎

Lines changed: 24 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -42,18 +42,20 @@ def __exit__(self, *args):
4242

4343

4444
class Copula:
45-
"""Base class for Archimedean copulas in φ-notation.
45+
r"""Base class for Archimedean copulas in $\varphi$-notation.
4646
47-
Subclasses must implement generator(u) which returns φ(u), where
48-
u ∈ (0, 1], φ: (0,1] → [0, ∞), strictly decreasing, convex, φ(1)=0.
47+
Subclasses must implement `generator(u)`, which returns $\varphi(u)$,
48+
where $u \in (0, 1]$ and $\varphi:(0,1] \to [0,\infty)$ is strictly
49+
decreasing and convex with $\varphi(1)=0$.
4950
"""
5051

5152
def generator(self, u: jax.Array) -> jax.Array: # pragma: no cover - abstract
52-
"""Return the Archimedean generator φ(u).
53+
r"""Return the Archimedean generator $\varphi(u)$.
5354
54-
Subclasses **must** implement this. φ maps (0, 1] → [0, ∞), is
55-
strictly decreasing and convex, with φ(1) = 0. Everything else
56-
(density, inverse, sampling) is derived from it automatically.
55+
Subclasses **must** implement this. $\varphi$ maps $(0,1] \to
56+
[0,\infty)$, is strictly decreasing and convex, with $\varphi(1)=0$.
57+
Everything else (density, inverse, sampling) is derived from it
58+
automatically.
5759
"""
5860
raise NotImplementedError
5961

@@ -62,40 +64,41 @@ def generator_inv(self, t: jax.Array) -> jax.Array:
6264
return _invert_generator(self.generator, t)
6365

6466
def log_generator_kth_derivative(self, t: jax.Array, k: int) -> jax.Array:
65-
"""Return log |ψ^{(k)}(t)|, the log absolute k-th derivative.
67+
r"""Return $\log|\psi^{(k)}(t)|$, the log absolute $k$-th derivative.
6668
6769
Override this with a closed-form expression to bypass jet for
68-
specific families. For example, Clayton can use::
70+
specific families. For example, Clayton can use
6971
70-
lgamma(k + 1/theta) - lgamma(1/theta) - (k + 1/theta) * log1p(t)
72+
$$\log\Gamma(k + 1/\theta) - \log\Gamma(1/\theta)
73+
- (k + 1/\theta)\,\log(1+t).$$
7174
72-
The default returns None, which tells the framework to use
75+
The default returns ``None``, which tells the framework to use
7376
Taylor-mode AD via jet.
7477
"""
7578
return None # sentinel: use jet
7679

7780
def generator_taylor_coefficients(
7881
self, t: jax.Array, k_max: int
7982
) -> jax.Array:
80-
"""Return Taylor coefficients ``[ψ(t), ψ'(t)/1!, …, ψ^{(k_max)}(t)/k_max!]``.
83+
r"""Return Taylor coefficients $[\psi(t),\, \psi'(t)/1!,\, \ldots,\, \psi^{(k_{\max})}(t)/k_{\max}!]$.
8184
82-
Override this when the closed-form ψ has a numerically stable
85+
Override this when the closed-form $\psi$ has a numerically stable
8386
series representation that avoids the cancellations Taylor-mode
8487
AD on the closed form would produce at high derivative order.
85-
For example, AMH's ψ is the Laplace transform of Geometric(1−θ),
86-
so all Taylor coefficients are sums of same-sign terms (no
87-
cancellation):
88+
For example, AMH's $\psi$ is the Laplace transform of
89+
$\mathrm{Geometric}(1-\theta)$, so all Taylor coefficients are
90+
sums of same-sign terms (no cancellation):
8891
89-
ψ^{(k)}(t) = (-1)^k Σ_{x=1}^∞ x^k (1−θ) θ^{x−1} e^{−tx}
92+
$$\psi^{(k)}(t) = (-1)^k \sum_{x=1}^{\infty} x^k\,(1-\theta)\,\theta^{x-1}\,e^{-tx}.$$
9093
9194
The framework consults this hook everywhere it would otherwise
9295
call ``jet_array.jet`` on ``self.generator`` to get a Taylor
9396
expansion: the root density (``bell._root_assembly``) and the
9497
nesting composition (``compose.compute_composition_taylor``).
9598
Returning ``None`` (the default) tells those call sites to
9699
fall back to the jet path, which is correct but loses
97-
precision when ψ's derivatives have large alternating-sign
98-
cancellations (e.g. AMH past d≈30 in float64).
100+
precision when $\psi$'s derivatives have large alternating-sign
101+
cancellations (e.g. AMH past $d \approx 30$ in float64).
99102
100103
Args:
101104
t: scalar input point.
@@ -111,11 +114,11 @@ def generator_taylor_coefficients(
111114
def log_generator_taylor_coefficients(
112115
self, t: jax.Array, k_max: int
113116
) -> Optional[Tuple[jax.Array, jax.Array]]:
114-
"""Log-space variant of :meth:`generator_taylor_coefficients`.
117+
r"""Log-space variant of :meth:`generator_taylor_coefficients`.
115118
116119
Return ``(sign, log_abs)``, two arrays of shape ``(k_max + 1,)`` with
117120
118-
ψ^{(k)}(t) / k! == sign[k] * exp(log_abs[k]).
121+
$$\psi^{(k)}(t) / k! \;=\; \mathrm{sign}[k]\,\exp(\mathrm{log\_abs}[k]).$$
119122
120123
The Bell density consumes the Taylor coefficients as ``(sign, log|c|)``
121124
pairs internally, so a family whose normalized coefficients are

‎docs/api.md‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,8 @@ on its children to build the model tree.
3636
## Composition registry
3737

3838
For nested copulas that mix families, register a closed-form composition
39-
`ψ_outer⁻¹ ∘ ψ_inner`, or choose the fallback strategy used when none is
40-
registered.
39+
$\psi_{\text{outer}}^{-1} \circ \psi_{\text{inner}}$, or choose the fallback
40+
strategy used when none is registered.
4141

4242
::: acopula.register_composition
4343

‎docs/javascripts/mathjax.js‎

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// MathJax config for Material for MkDocs + pymdownx.arithmatex (generic mode).
2+
window.MathJax = {
3+
tex: {
4+
inlineMath: [["\\(", "\\)"]],
5+
displayMath: [["\\[", "\\]"]],
6+
processEscapes: true,
7+
processEnvironments: true,
8+
},
9+
options: {
10+
ignoreHtmlClass: ".*|",
11+
processHtmlClass: "arithmatex",
12+
},
13+
};
14+
15+
// Re-typeset on Material's instant-navigation page loads.
16+
document$.subscribe(() => {
17+
MathJax.startup.output.clearCache();
18+
MathJax.typesetClear();
19+
MathJax.texReset();
20+
MathJax.typesetPromise();
21+
});

‎docs/quickstart.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ print(grad) # ∂ll/∂params, exact
4949
For survival data, swap the leaf distribution and mark censored observations.
5050
Use `float64` distribution parameters since `acopula` enables
5151
`jax_enable_x64` at import. Pass `survival=True` so leaf inversion uses
52-
`F^{-1}(1 - u)`.
52+
$F^{-1}(1 - u)$.
5353

5454
```python
5555
def survival_model(params, obs):

‎mkdocs.yml‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,15 @@ markdown_extensions:
3434
- admonition
3535
- pymdownx.highlight
3636
- pymdownx.superfences
37+
- pymdownx.arithmatex: # $...$ / $$...$$ rendered by MathJax
38+
generic: true
3739
- toc:
3840
permalink: true
3941

42+
extra_javascript:
43+
- javascripts/mathjax.js
44+
- https://unpkg.com/mathjax@3/es5/tex-mml-chtml.js
45+
4046
plugins:
4147
- search
4248
- mkdocstrings:

0 commit comments

Comments
 (0)