API reference¶
The curated public API is re-exported at the top level (e.g. qjax.q_log); the
canonical definitions live in the submodules documented below. Every entry on
this page is rendered from the source docstrings by
mkdocstrings, so it cannot disagree with the
installed version.
How to read these pages
Signatures show the annotations from the source. Arguments, returns, and
raises come from the Google-style docstring sections — the same text help()
prints in a REPL. Click Source on any entry to see the implementation.
Core — deformed functions¶
functions
¶
q-deformed elementary functions and the Tsallis q-algebra.
This module implements the two foundational maps of non-extensive statistics,
the q-logarithm and q-exponential, together with the q-deformed
arithmetic they induce. Each function is a pure, differentiable JAX expression
that recovers its Boltzmann–Gibbs counterpart as q -> 1.
Definitions¶
The q-logarithm and its inverse, the q-exponential, are
where \([\cdot]_+ = \max(\cdot, 0)\). Both reduce to \(\ln\) and \(\exp\) as \(q \to 1\).
Numerical form¶
Evaluating \((x^{1-q} - 1)/(1-q)\) directly loses catastrophically to
cancellation as \(q \to 1\) — in float32 the relative error peaks near
4e-3 around q = 1.00001. Both functions are therefore written through
jax.numpy.expm1 / jax.numpy.log1p, which are exact in that
regime:
The shared factor is the entire function \((e^t - 1)/t \to 1\) as
\(t \to 0\), so no q = 1 special case is needed at all: the classical
limit falls out of the same expression. Near \(t = 0\) a short Taylor series
replaces the ratio, which keeps not only the value but also the derivative with
respect to q correct — a hard where(q == 1, ...) branch would return a
q-independent expression and hence a spurious zero q-gradient.
q_log
¶
q_log(x: Array, q: Scalar) -> Array
q-logarithm \(\ln_q(x) = (x^{1-q} - 1)/(1-q)\).
Recovers the natural logarithm as q -> 1, continuously and with the
correct derivative in q (see the module docstring).
At x = 0 the limit is -1/(1-q) for q < 1 and -inf for
q >= 1. Negative x is outside the domain and yields NaN.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
x
|
Array
|
Non-negative input, any shape. |
required |
q
|
Scalar
|
Entropic index (scalar). |
required |
Returns:
| Type | Description |
|---|---|
Array
|
Element-wise |
Source code in qjax/core/functions.py
q_exp
¶
q_exp(x: Array, q: Scalar) -> Array
q-exponential \(\exp_q(x) = [1 + (1-q)x]_+^{1/(1-q)}\).
Inverse of q_log and the limit of math.exp as q -> 1.
Past the Tsallis cut-off — that is, wherever 1 + (1-q)x <= 0 — the
exponent 1/(1-q) decides the value: the result is 0 for q < 1
(positive exponent) and +inf for q > 1 (negative exponent), matching
the genuine divergence of the q-exponential there.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
x
|
Array
|
Input, any shape. |
required |
q
|
Scalar
|
Entropic index (scalar). |
required |
Returns:
| Type | Description |
|---|---|
Array
|
Element-wise |
Source code in qjax/core/functions.py
q_add
¶
q_add(a: Array, b: Array, q: Scalar) -> Array
q-addition \(a \oplus_q b = a + b + (1-q)\,a\,b\).
The deformed sum satisfies q_log(x*y) = q_add(q_log(x), q_log(y)) and
reduces to ordinary addition as q -> 1.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
a
|
Array
|
First operand. |
required |
b
|
Array
|
Second operand. |
required |
q
|
Scalar
|
Entropic index (scalar). |
required |
Returns:
| Type | Description |
|---|---|
Array
|
Element-wise |
Source code in qjax/core/functions.py
q_diff
¶
q_diff(a: Array, b: Array, q: Scalar) -> Array
q-subtraction \(a \ominus_q b = (a - b)/(1 + (1-q)b)\).
Inverse of q_add in its first argument: q_add(q_diff(a, b), b) == a.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
a
|
Array
|
First operand. |
required |
b
|
Array
|
Second operand. |
required |
q
|
Scalar
|
Entropic index (scalar). |
required |
Returns:
| Type | Description |
|---|---|
Array
|
Element-wise |
Source code in qjax/core/functions.py
q_prod
¶
q_prod(a: Array, b: Array, q: Scalar) -> Array
q-product \(a \otimes_q b = [a^{1-q} + b^{1-q} - 1]_+^{1/(1-q)}\).
Dual to q_add: it satisfies q_exp(x+y) = q_prod(q_exp(x), q_exp(y))
and reduces to ordinary multiplication as q -> 1. Defined for a, b >= 0.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
a
|
Array
|
First operand (non-negative). |
required |
b
|
Array
|
Second operand (non-negative). |
required |
q
|
Scalar
|
Entropic index (scalar). |
required |
Returns:
| Type | Description |
|---|---|
Array
|
Element-wise |
Source code in qjax/core/functions.py
q_div
¶
q_div(a: Array, b: Array, q: Scalar) -> Array
q-division \(a \oslash_q b = [a^{1-q} - b^{1-q} + 1]_+^{1/(1-q)}\).
Inverse of q_prod in its first argument and the limit of ordinary
division as q -> 1. Defined for a, b >= 0.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
a
|
Array
|
Numerator (non-negative). |
required |
b
|
Array
|
Denominator (non-negative). |
required |
q
|
Scalar
|
Entropic index (scalar). |
required |
Returns:
| Type | Description |
|---|---|
Array
|
Element-wise |
Source code in qjax/core/functions.py
Core — entropy and divergences¶
entropy
¶
Tsallis entropy, cross-entropy, and relative entropy (q-divergence).
These information measures generalize Shannon's entropy and the
Kullback–Leibler divergence through the entropic index q, recovering them in
the limit q -> 1. They are the natural objective functions for
non-extensive learning.
tsallis_entropy
¶
Tsallis entropy \(S_q(p) = (1 - \sum_i p_i^q)/(q - 1)\).
Recovers the Shannon entropy \(-\sum_i p_i \log p_i\) as q -> 1.
The entropy is concave in p and non-negative for probability vectors.
Computed in the equivalent form \(\sum_i p_i \ln_q(1/p_i)\), which
agrees with the definition above whenever p sums to one and, unlike it,
stays finite and correctly differentiable in q at q = 1. The two
forms differ on an unnormalized p, for which the definition above is
genuinely singular at q = 1.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
p
|
Array
|
Probability mass values along |
required |
q
|
Scalar
|
Entropic index (scalar). |
required |
axis
|
int
|
Axis over which the distribution is defined. |
-1
|
Returns:
| Type | Description |
|---|---|
Array
|
Tsallis entropy reduced over |
Source code in qjax/core/entropy.py
tsallis_cross_entropy
¶
Tsallis cross-entropy \(H_q(y, p) = -\sum_i y_i \ln_q p_i\).
A drop-in q-deformed classification loss. With one-hot y it reduces
to -q_log(p_correct, q), and to the standard cross-entropy as q -> 1.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
p
|
Array
|
Predicted probabilities along |
required |
y
|
Array
|
Target distribution along |
required |
q
|
Scalar
|
Entropic index (scalar). |
required |
axis
|
int
|
Axis over which the distributions are defined. |
-1
|
Returns:
| Type | Description |
|---|---|
Array
|
Tsallis cross-entropy reduced over |
Source code in qjax/core/entropy.py
tsallis_divergence
¶
Tsallis relative entropy \(D_q(p\,\|\,r)\).
Defined as \(D_q(p\|r) = \big(\sum_i p_i^q r_i^{1-q} - 1\big)/(q - 1)\),
equivalently \(-\sum_i p_i \ln_q(r_i / p_i)\). Recovers the
Kullback–Leibler divergence as q -> 1 and is non-negative.
The second form is the one evaluated: it agrees with the first whenever
p sums to one and, unlike it, stays correctly differentiable in q at
q = 1.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
p
|
Array
|
First distribution along |
required |
r
|
Array
|
Second (reference) distribution along |
required |
q
|
Scalar
|
Entropic index (scalar). |
required |
axis
|
int
|
Axis over which the distributions are defined. |
-1
|
Returns:
| Type | Description |
|---|---|
Array
|
Tsallis divergence reduced over |
Source code in qjax/core/entropy.py
Core — the q-Gaussian distribution¶
distributions
¶
The q-Gaussian distribution.
The q-Gaussian maximizes Tsallis entropy under a fixed second moment, just
as the Gaussian maximizes Shannon entropy. Its density is
with normalization constant \(C_q\). It interpolates between heavy-tailed
distributions (1 < q < 3; Student-t like) and compactly supported ones
(q < 1), recovering the Gaussian as q -> 1.
normalization
¶
normalization(q: Scalar) -> Array
Normalization constant \(C_q\) of the unit-\beta q-Gaussian.
Defined piecewise (see Tsallis, 2009) so that \(\int p(x)\,dx = 1\):
q < 1: \(C_q = \frac{2\sqrt{\pi}\,\Gamma(1/(1-q))} {(3-q)\sqrt{1-q}\,\Gamma(\tfrac{3-q}{2(1-q)})}\)q = 1: \(C_q = \sqrt{\pi}\)1<q<3: \(C_q = \frac{\sqrt{\pi}\,\Gamma(\tfrac{3-q}{2(q-1)})} {\sqrt{q-1}\,\Gamma(1/(q-1))}\)
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
q
|
Scalar
|
Entropic index (scalar), required to satisfy |
required |
Returns:
| Type | Description |
|---|---|
Array
|
The scalar normalization constant |
Source code in qjax/core/distributions.py
q_gaussian_pdf
¶
q_gaussian_pdf(
x: Array, q: Scalar = 1.0, beta: Scalar = 1.0
) -> Array
Density of the q-Gaussian, \(\sqrt{\beta}/C_q\,\exp_q(-\beta x^2)\).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
x
|
Array
|
Evaluation points, any shape. |
required |
q
|
Scalar
|
Entropic index (scalar), |
1.0
|
beta
|
Scalar
|
Inverse-width parameter |
1.0
|
Returns:
| Type | Description |
|---|---|
Array
|
Density values, same shape as |
Source code in qjax/core/distributions.py
q_gaussian_logpdf
¶
q_gaussian_logpdf(
x: Array, q: Scalar = 1.0, beta: Scalar = 1.0
) -> Array
Log-density of the q-Gaussian.
Computed as \(\tfrac12\log\beta - \log C_q + \log\!\exp_q(-\beta x^2)\).
Returns -inf outside the (compact) support when q < 1, where the
density vanishes.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
x
|
Array
|
Evaluation points, any shape. |
required |
q
|
Scalar
|
Entropic index (scalar), |
1.0
|
beta
|
Scalar
|
Inverse-width parameter |
1.0
|
Returns:
| Type | Description |
|---|---|
Array
|
Log-density values, same shape as |
Source code in qjax/core/distributions.py
sample
¶
Draw q-Gaussian samples for 1 <= q < 3.
For 1 < q < 3 the q-Gaussian is a rescaled Student-t: with
\(\nu = (3-q)/(q-1)\) degrees of freedom,
where \(T_\nu = Z/\sqrt{W/\nu}\) with \(Z \sim \mathcal N(0,1)\) and
\(W \sim \chi^2_\nu\). This yields exactly the family variance
\(1/((5-3q)\beta)\) for q < 5/3. At q = 1 the Gaussian
\(Z/\sqrt{2\beta}\) is returned.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
key
|
Array
|
A |
required |
q
|
Scalar
|
Entropic index (scalar), |
1.0
|
beta
|
Scalar
|
Inverse-width parameter |
1.0
|
shape
|
tuple[int, ...]
|
Output shape. |
()
|
Returns:
| Type | Description |
|---|---|
Array
|
Samples of the requested |
Source code in qjax/core/distributions.py
Core — activations (entmax)¶
activations
¶
Tsallis entmax: the q-deformed softmax / sparsemax family.
entmax is the probability mapping obtained by regularizing the
maximum-score problem with Tsallis entropy:
with Tsallis entropy \(S_q^{T}(p) = \tfrac{1}{q(q-1)}(1 - \sum_i p_i^q)\). Its solution has the closed form (Peters, Niculae & Martins, 2019)
where the threshold \(\tau\) enforces \(\sum_i p_i = 1\). For q = 1
it is the ordinary softmax; q = 2 is sparsemax. Larger q gives
sparser distributions, q < 1 gives distributions denser (higher entropy)
than softmax, and q -> 0^+ approaches the uniform distribution.
Differentiation¶
The threshold is located by bisection, but the mapping is not differentiated
through that loop — doing so yields a wrong (and non-symmetric) Jacobian. The
solve is wrapped in jax.lax.stop_gradient and the derivative is supplied
by a jax.custom_jvp rule built from the implicit function theorem.
Writing \(s_i = p_i^{2-q}\) and \(h_i = -p_i \log p_i\) (both zero off the support), and letting \(T(v) = v - s\,\sum_j v_j / \sum_j s_j\), both tangents share a single form:
so the Jacobian with respect to z is
\(J = \mathrm{diag}(s) - s s^\top / \sum_i s_i\) — symmetric, positive
semi-definite, and annihilating the all-ones vector (entmax is invariant to
a constant shift of z). Because custom_jvp is used rather than
custom_vjp, forward mode, reverse mode, and higher-order derivatives are all
exact.
tsallis_entmax
¶
Tsallis entmax over a simplex axis.
Solves for the threshold tau such that sum([(q-1)z - tau]_+^{1/(q-1)})
equals one. q = 1 short-circuits to a numerically stable softmax.
Gradients are exact: the threshold search is not differentiated through, and
a jax.custom_jvp rule supplies the implicit-function derivative with
respect to both z and q. The Jacobian in z is
diag(s) - s s^T / sum(s) with s = p ** (2 - q).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
z
|
Array
|
Scores / logits; the distribution is formed along |
required |
q
|
Scalar
|
Entropic index (scalar), |
2.0
|
axis
|
int
|
Axis over which to normalize. |
-1
|
num_iters
|
int
|
Number of bisection steps for the threshold search. A Newton polish step follows, so the result is accurate even for small values. |
50
|
Returns:
| Type | Description |
|---|---|
Array
|
Probabilities with the same shape as |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
Source code in qjax/core/activations.py
Neural-network building blocks¶
Framework-agnostic pieces for Tsallis models: everything here operates on plain arrays and pytrees, so it composes with Flax, Equinox, Haiku, or hand-rolled JAX without adding a dependency on any of them.
reparam
¶
Keeping a learnable entropic index inside its valid range.
Treating q as a free parameter and optimizing it directly does not work: the
Tsallis primitives are undefined at q <= 0, the q-Gaussian requires
q < 3, and gradient descent will happily step outside either bound. The
standard remedy — used verbatim in six of this repository's examples before it
lived here — is to optimize an unconstrained real q_raw and squash it:
bounded_q
¶
bounded_q(
q_raw: Scalar, lo: Scalar = 1.0, hi: Scalar = 3.0
) -> Array
Map an unconstrained parameter to an entropic index in (lo, hi).
The map is smooth and strictly monotone, so gradients flow to q_raw
everywhere and the optimizer can never leave the interval. q_raw = 0
corresponds to the midpoint.
The interval is open in exact arithmetic but closed in floating point: the
sigmoid saturates to exactly 0 or 1 once |q_raw| exceeds roughly
37 (float64) or 17 (float32), so q can reach lo or hi
exactly. Choose lo strictly inside the valid domain — q > 0 for the
Tsallis primitives, q < 3 for the q-Gaussian — rather than relying
on strict inequality here.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
q_raw
|
Scalar
|
Unconstrained real parameter, any shape. |
required |
lo
|
Scalar
|
Lower bound of the open interval (exclusive). |
1.0
|
hi
|
Scalar
|
Upper bound of the open interval (exclusive). |
3.0
|
Returns:
| Type | Description |
|---|---|
Array
|
The entropic index, same shape as |
Example
import jax.numpy as jnp from qjax.nn import bounded_q float(bounded_q(jnp.asarray(0.0), 1.0, 3.0)) 2.0
Source code in qjax/nn/reparam.py
inverse_bounded_q
¶
inverse_bounded_q(
q: Scalar, lo: Scalar = 1.0, hi: Scalar = 3.0
) -> Array
Invert bounded_q to initialize q_raw at a chosen q.
Useful for starting training from a meaningful index — q = 1 for a
softmax-like attention map, say — rather than from the interval midpoint.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
q
|
Scalar
|
Target entropic index, strictly inside |
required |
lo
|
Scalar
|
Lower bound used by |
1.0
|
hi
|
Scalar
|
Upper bound used by |
3.0
|
Returns:
| Type | Description |
|---|---|
Array
|
The |
Source code in qjax/nn/reparam.py
attention
¶
Attention whose normalizer is tsallis_entmax.
Replacing the softmax in an attention block with entmax makes the sparsity
of the attention map a property of the entropic index rather than a fixed choice:
q = 1 reproduces ordinary softmax attention, q = 2 gives sparsemax
(most positions receive exactly zero weight), and q < 1 spreads the weight
more evenly than softmax. Because q is differentiable, it can be learned
jointly with the rest of the network — see bounded_q.
entmax_attention
¶
entmax_attention(
queries: Array,
keys: Array,
values: Array,
q: Scalar = 2.0,
mask: Array | None = None,
scale: Scalar | None = None,
num_iters: int = 50,
) -> tuple[Array, Array]
Scaled dot-product attention normalized by tsallis_entmax.
Computes entmax_q(Q K^T / sqrt(d)) V over the last (key) axis. Leading
axes broadcast, so the same call serves single-head, multi-head, and batched
inputs.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
queries
|
Array
|
Query vectors, shape |
required |
keys
|
Array
|
Key vectors, shape |
required |
values
|
Array
|
Value vectors, shape |
required |
q
|
Scalar
|
Entropic index (scalar), |
2.0
|
mask
|
Array | None
|
Optional boolean array broadcastable to the score shape
|
None
|
scale
|
Scalar | None
|
Divisor applied to the scores. Defaults to |
None
|
num_iters
|
int
|
Bisection steps for the |
50
|
Returns:
| Type | Description |
|---|---|
Array
|
A |
Array
|
|
tuple[Array, Array]
|
|
Example
import jax.numpy as jnp from qjax.nn import entmax_attention q_vec = jnp.ones((2, 4)) k = jnp.ones((2, 5, 4)) v = jnp.ones((2, 5, 3)) context, attn = entmax_attention(q_vec, k, v, q=2.0) context.shape, attn.shape ((2, 3), (2, 5))
Source code in qjax/nn/attention.py
losses
¶
Loss functions built on the Tsallis information measures.
The Tsallis cross-entropy \(H_q(y, p) = -\sum_i y_i \ln_q p_i\) is a drop-in
replacement for the usual cross-entropy that recovers it at q = 1.
Its practical appeal is robustness to label noise, and that lives at q < 1.
There the q-logarithm is bounded below,
so a confidently wrong prediction — the signature of a mislabelled example --
contributes at most \(1/(1-q)\) instead of diverging, and its gradient is
capped with it. At q = 1 the penalty is unbounded, and for q > 1 it grows
faster than the logarithm (like \(p^{1-q}\)), which sharpens the model on
clean data at the cost of amplifying bad labels.
tsallis_cross_entropy_loss
¶
tsallis_cross_entropy_loss(
logits_or_probs: Array,
targets: Array,
q: Scalar = 1.0,
from_logits: bool = True,
normalizer_q: Scalar | None = None,
axis: int = -1,
reduction: str = "mean",
) -> Array
q-deformed cross-entropy loss.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
logits_or_probs
|
Array
|
Unnormalized scores if |
required |
targets
|
Array
|
Target distribution along |
required |
q
|
Scalar
|
Entropic index of the loss. |
1.0
|
from_logits
|
bool
|
Whether to normalize the input first. |
True
|
normalizer_q
|
Scalar | None
|
Entropic index of the |
None
|
axis
|
int
|
Axis holding the class distribution. |
-1
|
reduction
|
str
|
|
'mean'
|
Returns:
| Type | Description |
|---|---|
Array
|
The reduced loss, or the per-example losses when |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
Note
A sparse normalizer (normalizer_q > 1) can assign exactly zero
probability to the true class, for which the loss is a genuine +inf.
That is mathematically correct but hostile to optimization; either pair a
deformed loss with normalizer_q=1.0 or keep q close to 1
early in training.
Source code in qjax/nn/losses.py
Shared — types, validation, and series¶
types
¶
Type aliases shared across qjax.
These aliases keep signatures readable without imposing a hard dependency on a
specific array backend. At runtime every value is a jax.Array, but the
aliases also accept Python scalars and NumPy arrays, which JAX promotes
automatically.
Array and Scalar were previously the same alias, so the distinction
between "an array of any shape" and "a single real number" was documentation
only and a type checker could not act on it. Scalar is now the narrower of
the two: it excludes the nested sequences that Array accepts, which is the
real constraint on an entropic index.
validation
¶
Validation and broadcasting helpers for the entropic index q.
Tsallis primitives are parameterized by a single real number q (the entropic
index). These helpers normalize q to a JAX scalar and provide a numerically
robust mask for the q -> 1 limit, where most closed-form expressions become
indeterminate (0 / 0).
as_scalar_q
¶
as_scalar_q(q: Scalar) -> Array
Coerce an entropic index to a floating-point JAX scalar.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
q
|
Scalar
|
The entropic index, as a Python number or array-like. |
required |
Returns:
| Type | Description |
|---|---|
Array
|
A 0-d |
Source code in qjax/shared/validation.py
near_one
¶
Boolean mask for indices that should use the q -> 1 (classical) limit.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
q
|
Scalar
|
The entropic index. |
required |
eps
|
float
|
Half-width of the neighborhood around |
Q_EPS
|
Returns:
| Type | Description |
|---|---|
Array
|
A boolean array, broadcastable against |
Array
|
|
Source code in qjax/shared/validation.py
positive_q_or_nan
¶
positive_q_or_nan(q: Scalar) -> Array
Reject a non-positive entropic index.
The Tsallis entropy normalizer \(1/(q(q-1))\) is singular at q = 0,
so the entmax family is undefined for q <= 0. A Python-level
raise is impossible under jax.jit, so the check is split: a
statically known q fails loudly at trace time, while a traced q
(e.g. a learnable parameter that wandered out of range) is mapped to NaN
so the failure is visible downstream instead of silently plausible.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
q
|
Scalar
|
The entropic index. |
required |
Returns:
| Type | Description |
|---|---|
Array
|
|
Array
|
is non-positive. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
Source code in qjax/shared/validation.py
series
¶
Entire-function ratios used to take the q -> 1 limit stably.
Every Tsallis closed form is a 0/0 indeterminate at q = 1, and the
textbook way to evaluate it — select a separate Boltzmann-Gibbs expression when
|q - 1| is small — has two defects:
- Between the switch-over point and the region where the deformed form is
accurate there is a band in which neither is: subtracting
1fromx^{1-q} ~ 1loses most of the mantissa. In float32 the relative error of(x^{1-q} - 1)/(1-q)peaks near4e-3aroundq = 1.00001. - The classical branch does not depend on
q, so its derivative with respect toqis identically zero. A learnable entropic index that wanders into the switch-over window sees a hard zero gradient.
Both vanish if the indeterminate quotient is written through the entire
functions below, which are analytic at the origin and equal 1 there. The
classical limit then falls out of the same expression, with no branch on q
and no loss of accuracy.
Near the origin each ratio is evaluated by its Taylor series rather than by the direct form, which keeps the value and the derivative correct.
Plots¶
Plotting requires the optional plots extra: pip install "qjax[plots]".
style
¶
Publication-grade plotting style for qjax, themed on the brand ramp.
use_qjax_style configures Matplotlib for research-grade, vector output:
serif text with Computer-Modern math, embedded fonts, thin in-pointing ticks,
and a color cycle drawn from the qjax ramp. qcolors samples a discrete
sequence from that ramp so a family of curves indexed by q shares a coherent
identity, and save_figure writes a tight, font-embedded PDF.
The ramp¶
QJAX_RAMP is the ten-step green-blue scale the logo and documentation are
built from, ordered light to dark. It is registered with Matplotlib as
"qjax" (plus "qjax_r"), so CMAP works anywhere a colormap name does.
It is a sequential scale: it encodes magnitude, which is exactly what a family
of curves indexed by q needs. Two consequences worth knowing:
qcolorswindows the ramp to[0.40, 1.0]by default. The three lightest steps sit between 1.3:1 and 1.7:1 against white — invisible as thin lines. The window starts where the ramp first clears the 2:1 floor for a sequential light end.- The ramp cannot supply a categorical palette. Exhaustive search over all 1820 four-colour subsets (including interpolated mid-steps) found none that passes the categorical checks: every subset with usable separation (normal-vision OKLab ΔE >= 15) buys it from the extremes that fall outside the lightness band and below 3:1 contrast. Where a figure distinguishes methods rather than magnitudes, carry identity with linestyle and markers and let colour be the secondary cue.
qcolors
¶
Sample n evenly spaced colors from the qjax ramp.
Intended for curves indexed by an ordered parameter — a family of q
values, a noise sweep — where the reader should see the ordering in the
color. For unordered categories (competing methods, class labels) the ramp
cannot give reliable separation; see the module docstring.
The default [lo, hi] window starts partway down the ramp so the lightest
curve still reads against a white page.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
n
|
int
|
Number of colors to return. |
required |
lo
|
float
|
Lower bound of the colormap window, in |
QCOLORS_LO
|
hi
|
float
|
Upper bound of the colormap window, in |
QCOLORS_HI
|
Returns:
| Type | Description |
|---|---|
list
|
A list of |
Source code in qjax/plots/style.py
qlinestyles
¶
Return n distinguishable Matplotlib linestyles.
The brand ramp is sequential, so colour alone cannot separate more than about
three unordered categories: sampling it for four competing methods puts two
dark blues side by side that measure well under the readability floor (OKLab
ΔE ~6 against a floor of 15). Pairing qcolors with these dash patterns
supplies the second, non-colour channel, which also keeps figures readable in
grayscale print and for colour-vision deficiencies.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
n
|
int
|
Number of linestyles to return. |
required |
Returns:
| Type | Description |
|---|---|
list[LineStyle]
|
A list of |
list[LineStyle]
|
number of defined patterns. |
Source code in qjax/plots/style.py
use_qjax_style
¶
Apply the qjax publication style (serif math, vector PDF, brand-ramp cycle).
Source code in qjax/plots/style.py
save_figure
¶
Save fig as a tight, font-embedded vector PDF.
The extension is forced to .pdf and the parent directory is created if
needed, so callers can pass a bare stem like figures/q_gaussian.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
fig
|
Figure
|
The figure to write. |
required |
path
|
str | Path
|
Destination path; any extension is replaced with |
required |
transparent
|
bool
|
If |
False
|
Returns:
| Type | Description |
|---|---|
Path
|
The resolved output path. |
Source code in qjax/plots/style.py
functions
¶
Plots of the q-deformed elementary functions across a range of q.
plot_q_log
¶
plot_q_log(
q_values: Sequence[float] = (0.5, 0.8, 1.0, 1.5, 2.0),
x_range: tuple[float, float] = (0.05, 4.0),
num: int = 400,
ax: Axes | None = None,
) -> Axes
Plot the q-logarithm for several entropic indices.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
q_values
|
Sequence[float]
|
Entropic indices to draw, one curve each. |
(0.5, 0.8, 1.0, 1.5, 2.0)
|
x_range
|
tuple[float, float]
|
|
(0.05, 4.0)
|
num
|
int
|
Number of sample points. |
400
|
ax
|
Axes | None
|
Existing axis to draw on; a new one is created if |
None
|
Returns:
| Type | Description |
|---|---|
Axes
|
The axis containing the plot. |
Source code in qjax/plots/functions.py
plot_q_exp
¶
plot_q_exp(
q_values: Sequence[float] = (0.5, 0.8, 1.0, 1.5, 2.0),
x_range: tuple[float, float] = (-3.0, 2.0),
num: int = 400,
ax: Axes | None = None,
) -> Axes
Plot the q-exponential for several entropic indices.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
q_values
|
Sequence[float]
|
Entropic indices to draw, one curve each. |
(0.5, 0.8, 1.0, 1.5, 2.0)
|
x_range
|
tuple[float, float]
|
|
(-3.0, 2.0)
|
num
|
int
|
Number of sample points. |
400
|
ax
|
Axes | None
|
Existing axis to draw on; a new one is created if |
None
|
Returns:
| Type | Description |
|---|---|
Axes
|
The axis containing the plot. |
Source code in qjax/plots/functions.py
distributions
¶
Plots of the q-Gaussian density across a range of q.
plot_q_gaussian
¶
plot_q_gaussian(
q_values: Sequence[float] = (0.5, 1.0, 1.5, 2.0, 2.5),
beta: float = 1.0,
x_range: tuple[float, float] = (-5.0, 5.0),
num: int = 500,
ax: Axes | None = None,
) -> Axes
Plot the q-Gaussian density for several entropic indices.
Lower q gives compact support; q -> 1 is the Gaussian; higher q
(up to 3) gives progressively heavier tails.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
q_values
|
Sequence[float]
|
Entropic indices to draw, one curve each ( |
(0.5, 1.0, 1.5, 2.0, 2.5)
|
beta
|
float
|
Shared inverse-width parameter. |
1.0
|
x_range
|
tuple[float, float]
|
|
(-5.0, 5.0)
|
num
|
int
|
Number of sample points. |
500
|
ax
|
Axes | None
|
Existing axis to draw on; a new one is created if |
None
|
Returns:
| Type | Description |
|---|---|
Axes
|
The axis containing the plot. |