Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Python API

The installed distribution is xshi-math; these helpers are imported as xmath.incerto. Install the numerical and plotting extra with:

uv sync --locked --extra incerto

Run page examples in Python after installing from a repository checkout. Every fenced python block on the Incerto pages is executed by pytest; examples do not fetch data or save files. Each Output block is captured from its preceding example and checked against stdout, ignoring trailing whitespace only. Bundled dataset examples require an editable checkout (or a populated INCERTO_DATA_DIR). Longer examples expand under a Code dropdown.

Numeric output uses about four significant digits or three to four decimal places, with scientific notation for small probabilities. Counts remain integers; vectors print as short lists and dictionaries as key: value lines. Mathematical infinities and missing values print as inf and nan.

The base xmath helpers require only NumPy. The Incerto extra adds SciPy and Matplotlib; graph generation uses NetworkX and PyYAML from the development group. Dataset fetching uses standard-library urllib. The Python modules contain the full signatures and docstrings; there is no separate Sphinx build. Browse the module sources for implementations and use local help() for the installed version.

ModuleEntry points and purpose
xmath.incerto.gas_speedschi_speed, sample_chi_speed, fit_speed_models, speed_fit_table, speed_qq, squared_speed_ks, speed_fit_figure; Rayleigh chamber speeds and fitted comparisons
xmath.incerto.datasetsload_amazon_bookrank, load_nyc_dog_name_frequencies, load_sp500_prices; explicit local-cache and refresh helpers
xmath.incerto.distributionspareto_type1, double_pareto, hypsecant2, simple_normal_mixture, univariate_variance_gamma, generalized_pareto, generalized_extreme_value, frechet; SciPy-style distribution objects
xmath.incerto.estimatorshill_estimator (extreme-value index), hill_alpha_estimator (reciprocal exponent), hill_stability, pareto_mean_plugin, mean_excess, running_mean, max_to_sum_ratio, max_to_sum_path, gpd_threshold_fit
xmath.incerto.statsGaussian-calibrated dispersion_ratios, mean_absolute_deviation, median_absolute_deviation; normal and Student-t shoulder boundaries; empirical_survival_function (strict exceedance with ties) and lognorm_params_from_mean_and_variance
xmath.incerto.tail_diagnosticsregular_variation_ratio, iid_two_sum_tail, subexponential_sum_ratio; numerical calculations with support and integration checks
xmath.incerto.tail_classesbounded_spike_summary (population moments), log_survival_multiplier_ratio (log-domain tail ratios); used by the Prologue models
xmath.incerto.glossarypareto_tail_quantities (log survival, conditional means, tail contribution), pareto_normalized_maximum_cdf (exact iid maximum law); chapter 2 worked cases
xmath.incerto.lecture_riskrepeated_event_probability, survival_from_hazards, finite_payoff_mean, absorbing_resource_path, split_power_damage_logsf, block_failure_summary; chapter 3 worked models
xmath.incerto.finite_momentsnormal_mixture_log_density, normal_mixture_log_abs_survival, normal_mixture_absolute_moment, pareto_moment_estimator_summary, power_mean; finite-moment worked cases
xmath.incerto.multivariatestudent_entropy, student_mutual_information, bivariate_student, sample_correlation, symmetric_spectrum, regression_population_r2, normal_location_mixture_kurtosis; chapter 6 worked cases. Student helpers deliberately restrict degrees of freedom to [0.5, 1000].
xmath.incerto.figuresset_theme, style_axes, savefig, vertical_figure, distribution_card; shared figure style and deterministic export helpers
xmath.incerto.power_lawspareto_product_logsf, pareto_truncated_moment, student_double_pareto_scales, q_exponential_logsf, entropy_log_constraint_example; chapter 5 worked cases

Use pareto_type1 and hill_alpha_estimator.

import numpy as np
from xmath.incerto.distributions import pareto_type1
from xmath.incerto.estimators import hill_alpha_estimator

rng = np.random.default_rng(20261017)
x = pareto_type1.rvs(2.5, size=1000, random_state=rng)
alpha_hat = hill_alpha_estimator(x, k=100)
print(f"Estimated alpha: {alpha_hat:.3f}")

Output

Estimated alpha: 2.405

The example is a simulation, not a guarantee about estimation accuracy. The Hill note states the model and threshold assumptions. Use help() on an imported function for argument validation, return types, and numerical limits.

The empirical examples link to committed demo scripts and static figures. Dataset loading does not fetch by default. The S&P method explains the deliberately absent financial cache. The separate Normix API remains maintained upstream; this educational package does not vendor Normix.

Function reference

Signatures omit type annotations for readability; keyword-only markers and defaults match the installed helpers. See local help() for validation and return details. Distribution objects use SciPy’s frozen-law interface.

Datasets

Module: xmath.incerto.datasets.

DatasetNotAvailable

Raised when a dataset is missing or a fetch cannot provide usable data.

PriceSeries

Daily close-price series used by empirical examples.

PriceSeries.log_returns

PriceSeries.log_returns()

import numpy as np
from xmath.incerto.datasets import PriceSeries

prices = PriceSeries(
    name="synthetic", date=np.array(["2020-01-01", "2020-01-02", "2020-01-03"], dtype="datetime64[D]"),
    close=np.array([100., 90., 99.]), source="synthetic example",
)
dates, values = prices.log_returns()
print("Ending dates: [" + ", ".join(str(day) for day in dates) + "]")
print("Log returns: [" + ", ".join(f"{v:.4g}" for v in values) + "]")

Output

Ending dates: [2020-01-02, 2020-01-03]
Log returns: [-0.1054, 0.09531]

PriceSeries.negative_log_returns

PriceSeries.negative_log_returns()

import numpy as np
from xmath.incerto.datasets import PriceSeries

prices = PriceSeries(
    name="synthetic", date=np.array(["2020-01-01", "2020-01-02", "2020-01-03"], dtype="datetime64[D]"),
    close=np.array([100., 90., 99.]), source="synthetic example",
)
dates, values = prices.negative_log_returns()
print("Ending dates: [" + ", ".join(str(day) for day in dates) + "]")
print("Positive losses: [" + ", ".join(f"{v:.4g}" for v in values) + "]")

Output

Ending dates: [2020-01-02]
Positive losses: [0.1054]

BookRankData

Amazon book sales-rank observations.

DogNameFrequencyData

Normalized NYC dog-name frequencies from license-period records.

DogNameFrequencyData.frequency_for

DogNameFrequencyData.frequency_for(name)

import numpy as np
from xmath.incerto.datasets import DogNameFrequencyData

names = DogNameFrequencyData(np.array(["SAFARI"]), np.array([3]), "synthetic example")
for name in ("Safari", " safari ", "MISSING"):
    print(f"{name!r}: {names.frequency_for(name):d}")

Output

'Safari': 3
' safari ': 3
'MISSING': 0

data_root

data_root(data_dir=None)

from xmath.incerto.datasets import data_root

print(data_root(data_dir="/tmp/incerto-example-data").as_posix())

Output

/tmp/incerto-example-data

snapshot_path

snapshot_path(filename, data_dir=None)

from xmath.incerto.datasets import snapshot_path

print(snapshot_path("example.csv", data_dir="/tmp/incerto-example-data").as_posix())

Output

/tmp/incerto-example-data/snapshots/example.csv

cache_path

cache_path(filename, data_dir=None)

from xmath.incerto.datasets import cache_path

print(cache_path("example.csv", data_dir="/tmp/incerto-example-data").as_posix())

Output

/tmp/incerto-example-data/cache/example.csv

load_sp500_prices

load_sp500_prices(*, data_dir=None, fetch=False)

Load S&P 500 daily closes from the local cache, optionally fetching FRED.

load_amazon_bookrank

load_amazon_bookrank(*, data_dir=None)

Load the CC0 Amazon book sales-rank snapshot.

load_nyc_dog_name_frequencies

load_nyc_dog_name_frequencies(*, data_dir=None)

Load the NYC Open Data dog-name frequency snapshot.

write_sp500_fred_cache

write_sp500_fred_cache(destination, *, url=FRED_SP500_CSV_URL)

Fetch and clean the public FRED S&P 500 CSV into an untracked cache.

write_sp500_cache_from_csv

write_sp500_cache_from_csv(source, destination)

Clean a local S&P 500-like CSV into the standard untracked cache.

write_amazon_bookrank_snapshot

write_amazon_bookrank_snapshot(destination, *, url=KAGGLE_AMAZON_BOOKRANK_DOWNLOAD_URL)

Fetch and clean the CC0 Kaggle Amazon bookrank dataset.

write_nyc_dog_name_frequency_snapshot

write_nyc_dog_name_frequency_snapshot(destination, *, url=NYC_DOG_NAME_FREQUENCY_API_URL)

Fetch the server-aggregated NYC dog-name frequencies into a snapshot.

Distributions

Module: xmath.incerto.distributions.

Call an object below with its shape parameters to freeze a law; then use pdf(x), logpdf(x), cdf(x), sf(x), logsf(x), ppf(q), rvs(size=..., random_state=rng) or stats(moments="mv"). These methods belong to the linked distribution entry. scale is a positive scale multiplier, and loc shifts the support.

pareto_type1

pareto_type1(alpha, loc=0, scale=1)

Pareto Type I with positive exponent alpha; at loc=0, scale is the lower cutoff.

double_pareto

double_pareto(alpha, loc=0, scale=1)

Symmetric shifted double Pareto with positive exponent alpha; ordinary mean exists only above one.

hypsecant2

hypsecant2(loc=0, scale=1)

Density 0.5 / cosh(x)**2 at default location and scale (logistic scale one half).

simple_normal_mixture

simple_normal_mixture(a, loc=0, scale=1)

Equal centered normal mixture with component variances 1-a and 1+a, for 0 <= a < 1.

univariate_variance_gamma

univariate_variance_gamma(alpha, beta, lam, loc=0, scale=1)

Variance–gamma law requiring alpha > abs(beta) and lam > 0; this alpha is a decay parameter, not a Pareto exponent.

hypsecant2.chf

hypsecant2.chf(t, loc=0.0, scale=1.0)

from xmath.incerto.distributions import hypsecant2

values = hypsecant2.chf([0, 1, 2])
print("[" + ", ".join(f"{v:.4g}" for v in values) + "]")

Output

[1+0j, 0.6826+0j, 0.272+0j]

generalized_pareto

generalized_pareto(xi, beta=1.0)

Returns a frozen zero-location GPD with finite scalar shape ξ\xi and finite scale β>0\beta>0. Methods include pdf, cdf, sf, logsf, ppf, rvs and support. Support is [0,∞)[0,\infty) for ξ≥0\xi\ge0 and [0,−β/ξ][0,-\beta/\xi] for ξ<0\xi<0. CDF/survival extend continuously at support boundaries. Endpoint densities can be infinite when ξ<−1\xi<-1. Invalid parameters raise ValueError.

from xmath.incerto.distributions import generalized_pareto

law = generalized_pareto(-0.4)
print("Survival: [" + ", ".join(f"{v:.4g}" for v in law.sf([-1, 0, 1, 2.5, 3])) + "]")

Output

Survival: [1, 1, 0.2789, 0, 0]

generalized_extreme_value

generalized_extreme_value(xi, mu=0.0, sigma=1.0)

Returns a frozen GEV with the page’s shape convention: positive ξ\xi is heavy-tailed, zero is Gumbel, negative has a finite right endpoint. The adapter uses scipy.stats.genextreme(c=-xi) and exposes the same methods as the GPD adapter. Require finite scalar parameters and σ>0\sigma>0. Outside support, density is zero and CDF/survival have their limiting values. For ξ<−1\xi<-1, the density diverges as the right endpoint is approached, although SciPy 1.18 returns zero at the endpoint itself. This single-point convention does not change probabilities. Invalid parameters raise ValueError.

from xmath.incerto.distributions import generalized_extreme_value

for xi in (-0.3, 0, 0.3):
    law = generalized_extreme_value(xi)
    print(f"xi={xi:.4g}: cdf(0)={law.cdf(0):.4g}, sf(4)={law.sf(4):.4g}")

Output

xi=-0.3: cdf(0)=0.3679, sf(4)=0
xi=0: cdf(0)=0.3679, sf(4)=0.01815
xi=0.3: cdf(0)=0.3679, sf(4)=0.06966

frechet

frechet(alpha, scale=1.0)

Returns a frozen zero-location Fréchet law with CDF exp⁡[−(y/scale)−α]\exp[-(y/\mathrm{scale})^{-\alpha}] for y>0y>0. Both parameters are finite positive scalars. Uses SciPy invweibull, including pdf, cdf, sf, logsf, ppf, rvs and support. At and below zero, density and CDF are zero, survival one. Use sf rather than subtracting cdf from one when the right tail is small. Invalid parameters raise ValueError. The adapter inherits SciPy’s numerical limits: for example, SciPy 1.18 returns nan for frechet(3).pdf(1e-100) because intermediate powers overflow, although the true density rounds to zero. The P1 figure grids avoid this range.

from xmath.incerto.distributions import frechet

law = frechet(1.5)
for y in (0, 1, 10):
    print(f"y={y:d}: pdf={law.pdf(y):.4g}, cdf={law.cdf(y):.4g}, sf={law.sf(y):.4g}")

Output

y=0: pdf=0, cdf=0, sf=1
y=1: pdf=0.5518, cdf=0.3679, sf=0.6321
y=10: pdf=0.004596, cdf=0.9689, sf=0.03113

Estimators

Module: xmath.incerto.estimators.

hill_estimator

hill_estimator(x, k)

from xmath.incerto.estimators import hill_estimator

print(f"xi: {hill_estimator([1, 2, 4, 8], k=2):.4g}")

Output

xi: 1.04

hill_alpha_estimator

hill_alpha_estimator(x, k)

from xmath.incerto.estimators import hill_alpha_estimator

for sample in ([1, 2, 4, 8], [1, 1, 1, 1]):
    print(sample, "alpha:", f"{hill_alpha_estimator(sample, k=2):.4g}")

Output

[1, 2, 4, 8] alpha: 0.9618
[1, 1, 1, 1] alpha: inf

pareto_mean_plugin

pareto_mean_plugin(x, *, x_m, axis=None)

from xmath.incerto.estimators import pareto_mean_plugin

for sample in ([1, 1], [1, 2], [4, 4]):
    print(f"{sample} {pareto_mean_plugin(sample, x_m=1):.4g}")

Output

[1, 1] 1
[1, 2] 1.53
[4, 4] inf

The cutoff is known; statistical calibration assumes an exact iid Pareto model.

hill_stability

hill_stability(x, k_values=None, *, num=100)

from xmath.incerto.estimators import hill_stability

for name, values in hill_stability([1, 2, 4, 8], [1, 2]).items():
    fmt = ".0f" if name == "k" else ".4g"
    print(f"{name}: [" + ", ".join(format(v, fmt) for v in values) + "]")

Output

k: [1, 2]
xi: [0.6931, 1.04]
alpha: [1.443, 0.9618]

running_mean

running_mean(x, axis=None)

from xmath.incerto.estimators import running_mean

values = running_mean([1, 2, 6])
print("Vector: [" + ", ".join(f"{v:.4g}" for v in values) + "]")
print("Rows:")
for row in running_mean([[1, 2, 6], [2, 4, 12]], axis=1):
    print("[" + ", ".join(f"{v:.4g}" for v in row) + "]")

Output

Vector: [1, 1.5, 3]
Rows:
[1, 1.5, 3]
[2, 3, 6]

max_to_sum_ratio

max_to_sum_ratio(x, axis=None)

from xmath.incerto.estimators import max_to_sum_ratio

print(f"{max_to_sum_ratio([1, 2, 7]):.4g}")

Output

0.7

max_to_sum_path

max_to_sum_path(x)

Returns the maximum divided by the sum for every prefix of a nonempty, finite, real, nonnegative one-dimensional list. Zero-total prefixes return nan. Log accumulation avoids overflow of the sum and avoids scaling early prefixes by a much larger future observation. Negative/nonfinite/complex values and wrong dimensions raise ValueError; ordinary rounding remains.

from xmath.incerto.estimators import max_to_sum_path

path = max_to_sum_path([0, 1, 1, 8])
print("Prefix ratios: [" + ", ".join(f"{v:.4g}" for v in path) + "]")

Output

Prefix ratios: [nan, 1, 0.5, 0.8]

gpd_threshold_fit

gpd_threshold_fit(x, threshold, *, min_exceedances=30)

Numerically fits a zero-location GPD to strict excesses above a finite threshold. Returns threshold, integer count, xi, beta, modified_scale (β^−ξ^u\widehat\beta-\widehat\xi u), success and status. Finite real one-dimensional data are required; invalid input raises. Insufficient or constant excesses, overflow when forming excesses, and failed numerical fits retain counts but report nan parameters and an explanatory status. The optimizer stops at 2,000 iterations or 4,000 evaluations. Checks cover numerical convergence, finite parameters/log density, positive scale and every excess’s support. Success is no guarantee of a global MLE, a valid tail model or an appropriate threshold. No confidence interval is returned.

from xmath.incerto.estimators import gpd_threshold_fit

fit = gpd_threshold_fit([1, 2, 2, 4], 2, min_exceedances=2)
print(f"Count: {fit['count']:d}; status: {fit['status']}")
print(f"xi: {fit['xi']:.4g}; beta: {fit['beta']:.4g}")

Output

Count: 1; status: insufficient count
xi: nan; beta: nan

mean_excess

mean_excess(x, thresholds, *, min_exceedances=1)

from xmath.incerto.estimators import mean_excess

for name, values in mean_excess([1, 2, 2, 4], [1, 2, 4]).items():
    fmt = ".0f" if name == "exceedances" else ".4g"
    print(f"{name}: [" + ", ".join(format(v, fmt) for v in values) + "]")

Output

threshold: [1, 2, 4]
mean_excess: [1.667, 2, nan]
exceedances: [3, 1, 0]

Stats

Module: xmath.incerto.stats.

mean_absolute_deviation

mean_absolute_deviation(x, axis=None)

from xmath.incerto.stats import mean_absolute_deviation

print(f"Gaussian-calibrated MeanAD: {mean_absolute_deviation([1, 2, 3]):.4g}")

Output

Gaussian-calibrated MeanAD: 0.8355

median_absolute_deviation

median_absolute_deviation(x, axis=None)

from xmath.incerto.stats import median_absolute_deviation

print(f"Gaussian-calibrated MedianAD: {median_absolute_deviation([1, 2, 3]):.4g}")

Output

Gaussian-calibrated MedianAD: 1.483

normal_peak_shoulder_tail

normal_peak_shoulder_tail(mu=0.0, sigma=1.0)

from xmath.incerto.stats import normal_peak_shoulder_tail

values = normal_peak_shoulder_tail()
print("Normal scale boundaries: [" + ", ".join(f"{v:.4g}" for v in values) + "]")

Output

Normal scale boundaries: [-2.136, -0.6622, 0.6622, 2.136]

normal_variance_peak_shoulder_tail

normal_variance_peak_shoulder_tail(mu=0.0, variance=1.0)

from xmath.incerto.stats import normal_variance_peak_shoulder_tail

values = normal_variance_peak_shoulder_tail()
print("Normal variance boundaries: [" + ", ".join(f"{v:.4g}" for v in values) + "]")

Output

Normal variance boundaries: [-2.334, -0.742, 0.742, 2.334]

t_peak_shoulder_tail

t_peak_shoulder_tail(df, mu=0.0, sigma=1.0)

from xmath.incerto.stats import t_peak_shoulder_tail

values = t_peak_shoulder_tail(3)
print("Student-3 scale boundaries: [" + ", ".join(f"{v:.4g}" for v in values) + "]")

Output

Student-3 scale boundaries: [-2.758, -0.6281, 0.6281, 2.758]

lognorm_params_from_mean_and_variance

lognorm_params_from_mean_and_variance(mean, variance)

from xmath.incerto.stats import lognorm_params_from_mean_and_variance

mu, sigma = lognorm_params_from_mean_and_variance(mean=2, variance=3)
print(f"Log-location: {mu:.4f}; log-scale: {sigma:.4f}")

Output

Log-location: 0.4133; log-scale: 0.7481

empirical_survival_function

empirical_survival_function(x)

from xmath.incerto.stats import empirical_survival_function

support, survival = empirical_survival_function([1, 2, 2, 4])
print("Support: [" + ", ".join(f"{v:.4g}" for v in support) + "]")
print("Strict survival: [" + ", ".join(f"{v:.4g}" for v in survival) + "]")

Output

Support: [1, 2, 4]
Strict survival: [0.75, 0.25, 0]

dispersion_ratios

dispersion_ratios(sample)

from xmath.incerto.stats import dispersion_ratios

for sample in ([2, 2, 2], [0, 0, 10], [1, 2, 3]):
    mean_ratio, median_ratio = dispersion_ratios(sample)
    print(f"{sample}: Std/MeanAD={mean_ratio:.4g}, Std/MedianAD={median_ratio:.4g}")

Output

[2, 2, 2]: Std/MeanAD=nan, Std/MedianAD=nan
[0, 0, 10]: Std/MeanAD=0.8463, Std/MedianAD=inf
[1, 2, 3]: Std/MeanAD=0.9772, Std/MedianAD=0.5507

Standard deviation uses ddof=0; both absolute deviations are Gaussian-calibrated.

Tail diagnostics

Module: xmath.incerto.tail_diagnostics.

regular_variation_ratio

regular_variation_ratio(survival, thresholds, *, multiplier=2.0)

from xmath.incerto.distributions import pareto_type1
from xmath.incerto.tail_diagnostics import regular_variation_ratio

result = regular_variation_ratio(pareto_type1(2).sf, [2, 4], multiplier=2)
for name, values in result.items():
    print(f"{name}: [" + ", ".join(f"{v:.4g}" for v in values) + "]")

Output

threshold: [2, 4]
survival: [0.25, 0.0625]
multiplied_survival: [0.0625, 0.01562]
ratio: [0.25, 0.25]

iid_two_sum_tail

iid_two_sum_tail(rv, thresholds, *, rtol=1e-10, maxlevel=12)

from xmath.incerto.distributions import pareto_type1
from xmath.incerto.tail_diagnostics import iid_two_sum_tail

result = iid_two_sum_tail(pareto_type1(1.5), [3, 10, 100])
print("Fields:", ", ".join(result))
print("Two-sum ratio: [" + ", ".join(f"{v:.4g}" for v in result["ratio"]) + "]")
print("Quadrature success: [" + ", ".join(str(v) for v in result["success"]) + "]")

Output

Fields: x, threshold, log_tail, tail, log_ratio, ratio, success, log_abs_error, nfev
Two-sum ratio: [1.769, 1.391, 1.044]
Quadrature success: [True, True, True]

subexponential_sum_ratio

subexponential_sum_ratio(sampler, survival, thresholds, *, sample_size=100000, random_state=None)

from xmath.incerto.distributions import pareto_type1
from xmath.incerto.tail_diagnostics import subexponential_sum_ratio

law = pareto_type1(1.5)
result = subexponential_sum_ratio(
    law.rvs, law.sf, [3, 10], sample_size=10000, random_state=20261020,
)
for name, values in result.items():
    fmt = ".0f" if name == "sum_exceedances" else ".4g"
    print(f"{name}: [" + ", ".join(format(v, fmt) for v in values) + "]")

Output

threshold: [3, 10]
single_tail: [0.1925, 0.03162]
sum_tail: [0.6793, 0.0875]
ratio: [1.765, 1.383]
sum_exceedances: [6793, 875]

These seeded Monte Carlo values are finite-sample diagnostics.

Tail classes

Module: xmath.incerto.tail_classes.

bounded_spike_summary

bounded_spike_summary(epsilon)

from xmath.incerto.tail_classes import bounded_spike_summary

for name, value in bounded_spike_summary(0.01).items():
    print(f"{name}: {value:.4g}")

Output

support_radius: 10
mean: 0
variance: 1
kurtosis: 100

The symmetric three-point law has total nonzero probability epsilon.

log_survival_multiplier_ratio

log_survival_multiplier_ratio(log_survival, thresholds, *, multiplier=2.0)

from xmath.incerto.distributions import pareto_type1
from xmath.incerto.tail_classes import log_survival_multiplier_ratio

values = log_survival_multiplier_ratio(pareto_type1(2).logsf, [2, 10, 100])
print("[" + ", ".join(f"{v:.4g}" for v in values) + "]")

Output

[-1.386, -1.386, -1.386]

Glossary

Module: xmath.incerto.glossary.

pareto_tail_quantities

pareto_tail_quantities(alpha, x_m, threshold)

from xmath.incerto.glossary import pareto_tail_quantities

for alpha in (1, 1.5):
    result = pareto_tail_quantities(alpha, x_m=1, threshold=4)
    print(f"alpha={alpha:.4g}")
    for name, value in result.items():
        print(f"  {name}: {value:.4g}")

Output

alpha=1
  log_survival: -1.386
  mean_excess: inf
  conditional_mean: inf
  tail_first_moment: inf
alpha=1.5
  log_survival: -2.079
  mean_excess: 8
  conditional_mean: 12
  tail_first_moment: 1.5

pareto_normalized_maximum_cdf

pareto_normalized_maximum_cdf(y, *, alpha, n)

from xmath.incerto.glossary import pareto_normalized_maximum_cdf

for n in (1, 4, 16):
    values = pareto_normalized_maximum_cdf([0.5, 1, 2], alpha=1.5, n=n)
    print(f"n={n:d}: [" + ", ".join(f"{v:.4g}" for v in values) + "]")

Output

n=1: [0, 0, 0.6464]
n=4: [0.007359, 0.3164, 0.6906]
n=16: [0.04449, 0.3561, 0.6994]

The maximum is divided by xmn1/αx_m n^{1/\alpha} under an exact iid Pareto model.

Lecture risk

Module: xmath.incerto.lecture_risk.

repeated_event_probability

repeated_event_probability(probability, trials)

from xmath.incerto.lecture_risk import repeated_event_probability

for trials in (0, 1, 1000):
    print(f"{trials:d} {repeated_event_probability(1e-4, trials):.3e}")

Output

0 0.000e+00
1 1.000e-04
1000 9.517e-02

Trials are independent with the same event probability.

survival_from_hazards

survival_from_hazards(hazards)

from xmath.incerto.lecture_risk import survival_from_hazards

values = survival_from_hazards([0.02] * 3)
print("[" + ", ".join(f"{v:.4g}" for v in values) + "]")

Output

[1, 0.98, 0.9604, 0.9412]

The initial survival is included; inputs are conditional hazards.

finite_payoff_mean

finite_payoff_mean(probabilities, payoffs)

from xmath.incerto.lecture_risk import finite_payoff_mean

print(f"{finite_payoff_mean([0.98, 0.02], [1, -80]):.4g}")

Output

-0.62

Probabilities must sum to one; there is no implicit normalization.

absorbing_resource_path

absorbing_resource_path(initial, increments)

from xmath.incerto.lecture_risk import absorbing_resource_path

for increments in ([-4, 4], [4, -4]):
    path = absorbing_resource_path(3, increments)
    print(f"{increments}: [" + ", ".join(f"{v:.4g}" for v in path) + "]")

Output

[-4, 4]: [3, 0, 0]
[4, -4]: [3, 7, 3]

The initial resource level is included and ruin is absorbing.

split_power_damage_logsf

split_power_damage_logsf(threshold, *, alpha, power, modules, exposure=1.0, x_m=1.0)

from xmath.incerto.lecture_risk import split_power_damage_logsf

for modules in (1, 16):
    value = split_power_damage_logsf(4, alpha=1.5, power=2, modules=modules)
    print(f"{modules:d} log survival: {value:.4g}")

Output

1 log survival: -1.04
16 log survival: -3.119

The model splits a Pareto power-damage exposure into equal modules.

block_failure_summary

block_failure_summary(probability, blocks, exposure=1.0)

from xmath.incerto.lecture_risk import block_failure_summary

for name, value in block_failure_summary(0.02, blocks=10).items():
    print(f"{name}: {value:.4g}")

Output

mean: 0.02
variance: 0.00196
any_failure: 0.1829
total_failure: 1.024e-17

Blocks fail independently and have equal all-or-nothing exposures.

Finite moments

Module: xmath.incerto.finite_moments.

normal_mixture_log_density

normal_mixture_log_density(x, variances, weights)

from xmath.incerto.finite_moments import normal_mixture_log_density

values = normal_mixture_log_density([0, 1, 4], [0.5, 50.5], [0.99, 0.01])
print("[" + ", ".join(f"{v:.4g}" for v in values) + "]")

Output

[-0.5814, -1.58, -7.643]

Components are centered Gaussian laws with the stated variances and weights.

normal_mixture_log_abs_survival

normal_mixture_log_abs_survival(u, variances, weights)

from xmath.incerto.finite_moments import normal_mixture_log_abs_survival

values = normal_mixture_log_abs_survival([0, 1, 4], [0.5, 50.5], [0.99, 0.01])
print("[" + ", ".join(f"{v:.4g}" for v in values) + "]")

Output

[0, -1.804, -5.161]

Thresholds are finite and nonnegative; exceedances are two-sided absolute values.

normal_mixture_absolute_moment

normal_mixture_absolute_moment(q, variances, weights)

from xmath.incerto.finite_moments import normal_mixture_absolute_moment

for order in (2, 4):
    print(f"{order} {normal_mixture_absolute_moment(order, [0.5, 50.5], [0.99, 0.01]):.4g}")

Output

2 1
4 77.25

All positive-order absolute moments exist for a finite Gaussian mixture.

pareto_moment_estimator_summary

pareto_moment_estimator_summary(alpha, q, n, x_m=1.0)

from xmath.incerto.finite_moments import pareto_moment_estimator_summary

for alpha in (1.5, 3, 6):
    print(f"alpha={alpha:.4g}")
    for name, value in pareto_moment_estimator_summary(alpha, q=2, n=200).items():
        print(f"  {name}: {value:.4g}")

Output

alpha=1.5
  moment: inf
  estimator_variance: nan
alpha=3
  moment: 3
  estimator_variance: inf
alpha=6
  moment: 1.5
  estimator_variance: 0.00375

The empirical moment averages n iid exact Pareto observations.

power_mean

power_mean(sample, order)

from xmath.incerto.finite_moments import power_mean

for order in (1, 2, 4, float("inf")):
    print(f"{order} {power_mean([0, 0, 0, -4], order):.4g}")

Output

1 1
2 2
4 2.828
inf 4

Orders are at least one; powers use absolute values and normalization by sample size.

Multivariate

Module: xmath.incerto.multivariate.

student_entropy

student_entropy(nu, dimension, logdet=0.0)

from xmath.incerto.multivariate import student_entropy

for dimension in (1, 2):
    print(f"{dimension} {student_entropy(3, dimension, logdet=0):.4g}")

Output

1 1.773
2 3.505

Entropy is in nats; logdet is the log determinant of scatter.

student_mutual_information

student_mutual_information(nu, rho=0.0)

from xmath.incerto.multivariate import student_mutual_information

for nu in (1, 5):
    print(f"{nu} {student_mutual_information(nu, rho=0):.4g}")

Output

1 0.2242
5 0.01713

Mutual information is in nats for unit diagonal scatter.

bivariate_student

bivariate_student(rng, nu, rho, size)

import numpy as np
from xmath.incerto.multivariate import bivariate_student

rng = np.random.default_rng(20261020)
for row in bivariate_student(rng, nu=3, rho=0.6, size=3):
    print("[" + ", ".join(f"{v:.4g}" for v in row) + "]")

Output

[-1.722, -1.126]
[-1.263, -0.0244]
[7.266, 2.572]

Each pair shares one gamma precision, with unit diagonal scatter and off-diagonal rho.

sample_correlation

sample_correlation(x, y, *, centered=True)

from xmath.incerto.multivariate import sample_correlation

for centered in (True, False):
    print(f"{centered} {sample_correlation([1, 2, 3], [3, 2, 1], centered=centered):.4g}")
print(f"Constant centered column: {sample_correlation([1, 1, 1], [1, 2, 3]):.4g}")

Output

True -1
False 0.7143
Constant centered column: nan

centered=True uses Pearson correlation; False uses the uncentered cosine along the last axis.

symmetric_spectrum

symmetric_spectrum(matrix)

from xmath.incerto.multivariate import symmetric_spectrum

values = symmetric_spectrum([[0, 2], [2, 0]])
print("[" + ", ".join(f"{v:.4g}" for v in values) + "]")

Output

[-2, 2]

The real square input must be finite, nonempty, and exactly symmetric.

regression_population_r2

regression_population_r2(slope, error_variance)

from xmath.incerto.multivariate import regression_population_r2

print(f"{regression_population_r2(slope=1, error_variance=3):.4g}")

Output

0.25

The error is independent and the predictor has variance one.

normal_location_mixture_kurtosis

normal_location_mixture_kurtosis(separation, sigma=1.0)

from xmath.incerto.multivariate import normal_location_mixture_kurtosis

for separation in (0, 2):
    print(f"{separation:d} {normal_location_mixture_kurtosis(separation, sigma=1):.4g}")

Output

0 3
2 1.72

Equal Gaussian components are centered at plus and minus separation, with common standard deviation sigma.

Power laws

Module: xmath.incerto.power_laws.

pareto_product_logsf

pareto_product_logsf(log_threshold, a, b)

import numpy as np
from xmath.incerto.power_laws import pareto_product_logsf

for a, b in ((1, 2), (1, 1)):
    values = pareto_product_logsf(np.log([1, 10, 100]), a, b)
    print(f"a={a:d}, b={b:d}: [" + ", ".join(f"{v:.4g}" for v in values) + "]")

Output

a=1, b=2: [-0, -1.661, -3.917]
a=1, b=1: [-0, -1.108, -2.881]

The factors are independent unit-minimum Paretos; thresholds enter on the log scale.

pareto_truncated_moment

pareto_truncated_moment(cutoff, alpha, order, *, x_m=1.0)

from xmath.incerto.power_laws import pareto_truncated_moment

for order in (1, 1.5, 2):
    values = pareto_truncated_moment([10, 100], alpha=1.5, order=order)
    print(f"order={order:.4g}: [" + ", ".join(f"{v:.4g}" for v in values) + "]")

Output

order=1: [2.051, 2.7]
order=1.5: [3.454, 6.908]
order=2: [6.487, 27]

Truncation uses the indicator below cutoff, without conditional renormalization.

student_double_pareto_scales

student_double_pareto_scales(alpha)

from xmath.incerto.power_laws import student_double_pareto_scales

for name, value in student_double_pareto_scales(3).items():
    print(f"{name}: {value:.4g}")

Output

student_tail_constant: 1.103
tail_scale: 0.7683
variance_scale: 0.5774
tail_matched_variance: 1.771

Matching uses a unit shifted double Pareto and requires alpha > 2.

q_exponential_logsf

q_exponential_logsf(x, q, beta=1.0)

from xmath.incerto.power_laws import q_exponential_logsf

for q in (0.75, 1, 1.25):
    values = q_exponential_logsf([0, 1, 2], q, beta=2)
    print(f"q={q:.4g}: [" + ", ".join(f"{v:.4g}" for v in values) + "]")

Output

q=0.75: [-0, -3.466, -inf]
q=1: [-0, -2, -4]
q=1.25: [-0, -1.216, -2.079]

The normalized law requires x >= 0 and 0 < q < 2; -inf means zero survival.

entropy_log_constraint_example

entropy_log_constraint_example()

from xmath.incerto.power_laws import entropy_log_constraint_example

for name, value in entropy_log_constraint_example().items():
    print(f"{name}: {value:.4g}")

Output

pareto_mass: 1
pareto_log_moment: 0.5
pareto_entropy: 0.8069
log_gamma_mass: 1
log_gamma_log_moment: 0.5
log_gamma_entropy: 0.6909
kl: 0.1159

Independent quadrature uses xm=1x_m=1 and Elog⁡X=1/2\mathbb E\log X=1/2.

Gas speeds

Module: xmath.incerto.gas_speeds. These helpers simulate equilibrium observations, not collision trajectories. The Rayleigh note derives the chamber, effusion, and finite-system laws and gives the seeded seven-family comparison.

chi_speed

chi_speed(dimension=2, thermal_variance=1.0)

Return the frozen chi law with scale kT/m\sqrt{kT/m}. dimension is a positive integer; thermal_variance is the finite positive component variance kT/mkT/m. The object exposes SciPy pdf, cdf, sf, ppf, moment, and rvs. Support is [0,∞)[0,\infty); dimensions 1, 2, and 3 are half-normal, Rayleigh, and Maxwell. Density and CDF are zero below zero.

from xmath.incerto.gas_speeds import chi_speed

for d in (2, 3):
    law = chi_speed(d)
    print(f"d={d}: mean={law.mean():.4f}, variance={law.var():.4f}")

Output

d=2: mean=1.2533, variance=0.4292
d=3: mean=1.5958, variance=0.4535

sample_chi_speed

sample_chi_speed(size, *, dimension=2, thermal_variance=1.0, random_state=None)

Draw independent normal components in an array of shape (dimension, size) and reduce their lengths with hypot. Return a one-dimensional speed array. Counts must be positive integers. random_state accepts an integer seed, a NumPy Generator, or None. All first components precede all second components in the random stream; changing size changes that pairing. Zero or nonfinite numerical draws raise rather than being replaced.

SpeedFit

An immutable record returned by fit_speed_models. Fields are name, law (frozen SciPy distribution), parameters (number estimated), log_likelihood, aic, ks_statistic, ks_pvalue, and boundary. The last field is empty for an interior fit, or names the GIG boundary law. Reported p-values are uncorrected for fitting. Parameters of law follow SciPy’s conventions; in particular inverse Gaussian shape is μ/κ\mu/\kappa and scale is κ\kappa for physical mean μ\mu and shape κ\kappa.

fit_speed_models

fit_speed_models(sample)

Return an AIC-sorted tuple of SpeedFit records for Gaussian, Rayleigh, Weibull, Gamma, inverse Gamma, inverse Gaussian, and GIG. Input must be a one-dimensional vector of at least three finite positive observations and must not be constant. Locations of positive families are fixed at zero. Gaussian has two estimated parameters, Rayleigh one, GIG three, and the others two. Inverse Gamma is fitted through the Gamma MLE of reciprocals; the transformation’s Jacobian is independent of its parameters.

The GIG fit includes normalizable Gamma and inverse Gamma boundaries. An inward score test certifies a boundary maximum using concavity in natural parameters, as proved in the note. Otherwise SciPy’s interior optimizer must converge within 4,000 iterations and 8,000 evaluations, and its likelihood must match or beat both boundaries to within 10-7. This numerical branch does not certify a global optimum. The frozen interior law uses SciPy’s geninvgauss(p, b, scale=scale): the note’s canonical parameters are a=b/scalea=b/\mathrm{scale} and bcanonical=b scaleb_{\rm canonical}=b\,\mathrm{scale}.

Nonfinite diagnostics and optimizer failures raise. Large interior GIG samples may be slow because their CDF uses quadrature. GIG’s AIC retains the nominal three-parameter penalty on a boundary; its usual regular-model interpretation is not asserted there. KS uses the ordinary exact finite-nn distribution for a specified continuous CDF, without adjusting for the estimated parameters. Very small p-values may underflow to zero.

speed_fit_table

speed_fit_table(fits)

Return a text table sorted by AIC: model, parameter count, AIC (one decimal), KS distance (four decimals), and raw p-value (three significant digits). This function formats the supplied records; it performs no fitting or test.

speed_qq

speed_qq(sample, law, probabilities=None)

Return (theoretical, empirical) quantile arrays. Input observations are finite, positive, and one-dimensional. The law must expose ppf. The default uses 199 equally spaced probabilities from 0.005 to 0.995; an explicit nonempty vector must increase strictly inside (0,1)(0,1). Empirical quantiles use NumPy’s linear interpolation. Nonfinite theoretical quantiles raise. No observations are removed and no confidence band is added.

squared_speed_ks

squared_speed_ks(sample, thermal_variance=1.0)

Return a dictionary with float statistic and pvalue for a two-sided KS comparison of squared speeds against Exp⁡(2kT/m)\operatorname{Exp}(2kT/m), where the argument is the mean. The helper estimates no parameters. Usual calibration requires iid observations and thermal_variance specified independently of them. The input must be a finite positive vector and the variance finite and positive. Arithmetic overflow raises.

speed_fit_figure

speed_fit_figure(sample, fits, *, kind="density", thermal_variance=1.0)

Return a Matplotlib figure, applying the shared DejaVu Serif theme at scale 1.1 and five-inch single-column layout. Supply the sample used to produce the seven fits. kind="density" draws two panels with 80-bin histograms and 401-point fitted curves on linear and log axes. kind="qq" draws five panels, grouping families by quantile range and ending with squared speeds against the fixed exponential law. It uses speed_qq’s default grid and does not clip the displayed quantiles. thermal_variance supplies the exponential null and the density viewport scale, not a new fit. The caller closes or saves the figure; the helper writes no files.

Figures

Module: xmath.incerto.figures.

set_theme

set_theme(*, scale=1.0)

Apply the Incerto Matplotlib theme.

style_axes

style_axes(axes, *, grid_axis='y', legend=True)

Apply final Incerto styling to one or more axes.

savefig

savefig(fig, path, **kwargs)

Save a figure with Incerto defaults.

vertical_figure

vertical_figure(panels, *, panel_height=3.8)

Returns a figure and a flat array of vertically stacked axes, five inches wide. panels is a positive integer; panel_height is positive and finite. Call set_theme with scale=1.1 for the P1 mobile layout. This adds no drawing or export side effect.

import matplotlib.pyplot as plt
from xmath.incerto.figures import set_theme, vertical_figure

set_theme(scale=1.1)
fig, axes = vertical_figure(3)
print(f"Panels: {len(axes):d}; width: {fig.get_figwidth():.4g} inches")
plt.close(fig)

Output

Panels: 3; width: 5 inches

distribution_card

distribution_card(models, x, tail_x, *, title, support_note, coordinate="x", tail_label="Survival")

Returns a three-panel density/CDF/log-log survival figure. models contains (frozen_law, label) pairs exposing pdf, cdf, sf and support; x and tail_x are increasing finite vectors, with positive tail_x. Finite support endpoints get dotted markers in the corresponding curve color. Exact zero survival is masked on log axes; the visible probability range starts at 10-8. Nonfinite evaluations raise, including a grid point on a singular density endpoint. The caller supplies support text and explicit parameters; the helper performs no moment matching.

Use savefig for deterministic SVG export. This example constructs the card without writing files:

Code
import matplotlib.pyplot as plt
import numpy as np
from xmath.incerto.distributions import generalized_pareto
from xmath.incerto.figures import distribution_card, set_theme

set_theme(scale=1.1)
fig = distribution_card(
    [(generalized_pareto(-0.4), "xi = -0.4")],
    np.linspace(-0.2, 4, 101), np.geomspace(0.05, 10, 101),
    title="GPD", support_note="Support: 0 ≤ y ≤ 2.5", coordinate="Excess y",
)
print(f"Card panels: {len(fig.axes):d}")
plt.close(fig)

Output

Card panels: 3

Base package

exceedance_fraction

xmath.exceedance_fraction(samples, threshold)

from xmath import exceedance_fraction

for threshold in (0, 2, 4):
    print(f"{threshold:d} {exceedance_fraction([1, 2, 2, 4], threshold):.4g}")

Output

0 1
2 0.25
4 0

Exceedances are strict; the sample must be nonempty and finite.