The installed distribution is xshi-math; these helpers are imported as
xmath.incerto. Install the numerical and plotting extra with:
uv sync --locked --extra incertoRun 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.
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.405The 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': 0data_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-datasnapshot_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.csvcache_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.csvload_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 and
finite scale . Methods include pdf, cdf, sf, logsf,
ppf, rvs and support. Support is for and
for . CDF/survival extend continuously at
support boundaries. Endpoint densities can be infinite when .
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 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 . Outside support, density is zero and
CDF/survival have their limiting values. For , 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.06966frechet¶
frechet(alpha, scale=1.0)
Returns a frozen zero-location Fréchet law with CDF
for . 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.03113Estimators¶
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.04hill_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: infpareto_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] infThe 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.7max_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 (), 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: nanmean_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.8355median_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.483normal_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.7481empirical_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.5507Standard 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: 100The 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.5pareto_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 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-02Trials 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.62Probabilities 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.119The 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-17Blocks 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.25All 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.00375The 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 4Orders 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.505Entropy 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.01713Mutual 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: nancentered=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.25The 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.72Equal 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.771Matching 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.1159Independent quadrature uses and .
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 . dimension is a positive
integer; thermal_variance is the finite positive component variance .
The object exposes SciPy pdf, cdf, sf, ppf, moment, and rvs.
Support is ; 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.4535sample_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
and scale is for physical mean and shape .
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 and
.
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- 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 .
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 , 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 inchesdistribution_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: 3Base 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 0Exceedances are strict; the sample must be nonempty and finite.