# -*- coding: utf-8 -*- import builtins import math import random as rnd import statistics import numpy as np from util import translate from . import basic, trig from .docs import * __desc__ = translate("Docs", "Statistics") doc_c("catalan", "G", "Catalan's constant") c_catalan = 0.91596559417721901505460351493238411077414937428167 doc_c("glaisher", "A", "Glaisher-Kinkelin constant") c_glaisher = 1.28242712910062263687534256886979172776768892732500 def listfunc(func): def wrapper(*args): if builtins.len(args) == 1: if isinstance(args[0], list): try: return func(args[0]) except: pass try: return func(list(iter(args[0]))) except: pass return func(list(args)) setattr(wrapper, "listfunc", True) return wrapper doc("choice", [ ("args", "List(Any)") ], translate("Docs", "Returns a random element from {{args}}."), ["choix"]) @listfunc def choice(args): return rnd.choice(args) choix = choice doc("arithm_mean", [ ("args", "List(Number)") ], translate("Docs", "Returns the arithmetic mean of {{args}}."), ["moyenne", "average"]) @listfunc def arithm_mean(args): return statistics.mean(args) average = arithm_mean moyenne = arithm_mean doc("harmonic_mean", [ ("args", "List(Number)") ], translate("Docs", "Returns the harmonic mean of {{args}}."), ["moyenne_harmo"]) @listfunc def harmonic_mean(args): if "harmonic_mean" not in dir(statistics): return builtins.len(args) / sum([1 / x for x in args]) return statistics.harmonic_mean(args) moyenne_harmo = harmonic_mean doc("sum", [ ("args", "List(Number)") ], translate("Docs", "Returns the sum of all the terms of {{args}}.")) @listfunc def sum(args): return builtins.sum(args) doc("binomial", [ ("n", "Number"), ("k", "Number") ], translate("Docs", "Returns the binomial coefficient for a subset of size {{k}} and a set of size {{n}}.")) def binomial(n, k): """Calculates the binomial coefficient.""" return math.gamma(n + 1) / (math.gamma(k + 1) * math.gamma(n - k + 1)) doc("max", [ ("args", "List(Number)") ], translate("Docs", "Returns the maximum value of {{args}}.")) @listfunc def max(args): return builtins.max(args) doc("min", [ ("args", "List(Number)") ], translate("Docs", "Returns the minimum value of {{args}}.")) @listfunc def min(args): return builtins.min(args) doc("max_index", [ ("args", "List(Number)") ], translate("Docs", "Returns the index of maximum value of {{args}}.")) @listfunc def max_index(args): return args.index(builtins.max(args)) doc("min_index", [ ("args", "List(Number)") ], translate("Docs", "Returns the index of minimum value of {{args}}.")) @listfunc def min_index(args): return args.index(builtins.min(args)) doc("gamma", [ ("x", "Number") ], translate("Docs", "Returns the Gamma function at {{x}}.")) def gamma(x): return math.gamma(x) doc("log_gamma", [ ("x", "Number") ], translate("Docs", "Returns the natural logarithm of the absolute value of the Gamma function at {{x}}.")) def log_gamma(x): return math.lgamma(x) doc("fact", [ ("x", "Integer") ], translate("Docs", "Returns the factorial of {{x}}.")) def fact(x): return math.factorial(x) doc("erf", [ ("x", "Number") ], translate("Docs", "Returns the error function at {{x}}.")) def erf(x): return math.erf(x) doc("erfc", [ ("x", "Number") ], translate("Docs", "Returns the complementary error function at {{x}}.")) def erfc(x): return math.erfc(x) doc("erfinv", [ ("y", "Number") ], translate("Docs", "Returns the inverse of the error function at {{y}}.")) def erfinv(y): # courtesy of # https://github.com/antelopeusersgroup/antelope_contrib/blob/master/lib/location/libgenloc/erfinv.c#L15 a = [0.886226899, -1.645349621, 0.914624893, -0.140543331] b = [-2.118377725, 1.442710462, -0.329097515, 0.012229801] c = [-1.970840454, -1.624906493, 3.429567803, 1.641345311] d = [3.543889200, 1.637067800] if y > 1: return None if y == 1: return math.copysign(1, y) * float("inf") if y <= 0.7: z = y * y num = (((a[3] * z + a[2]) * z + a[1]) * z + a[0]) dem = ((((b[3] * z + b[2]) * z + b[1]) * z + b[0]) * z + 1.0) x = y * num / dem else: z = math.sqrt(-math.log((1.0 - abs(y)) / 2.0)) num = ((c[3] * z + c[2]) * z + c[1]) * z + c[0] dem = (d[1] * z + d[0]) * z + 1.0 x = (math.copysign(1.0, y)) * num / dem for _ in [1, 2]: x = x - (erf(x) - y) / ((2 / math.sqrt(trig.c_pi)) * math.exp(-x * x)) return x doc("erfcinv", [ ("y", "Number") ], translate("Docs", "Returns the inverse of the complementary error function at {{y}}.")) def erfcinv(y): return erfinv(1 - y) doc("map", [ ("func", "Function(1 arg)"), ("lst", "List") ], translate("Docs", "Applies {{func}} to each element of {{lst}} and returns the resulting list."), ["appl"]) def map(func, lst): return [func(x) for x in lst] appl = map doc("filter", [ ("func", "Function(1 arg)"), ("lst", "List") ], translate("Docs", "Returns a list containing all elements of {{lst}} for which {{func}} returns a truthy value."), ["filtre"]) def filter(func, lst): return [x for x in lst if func(x)] filtre = filter doc("slice", [ ("lst", "List"), ("start", "Integer", "0 <= start <= end <= len(lst)"), ("end", "Integer", "start <= end <= len(lst)", None) ], translate("Docs", "Returns a slice of the specified list, from index {{start}} (inclusive) to either index " "{{end}} (exclusive) or the end of the list."), ["tranche"]) def slice(lst, start, end=None): start = int(start) if end is not None: end = int(end) return lst[start:end] return lst[start:] tranche = slice doc("stand_dev", [ ("lst", "List(Number)"), ], translate("Docs", "Returns the population standard deviation of {{lst}}."), ["ecart_type"]) @listfunc def stand_dev(lst): return statistics.pstdev(lst) ecart_type = stand_dev doc("variance", [ ("lst", "List(Number)"), ], translate("Docs", "Returns the population variance of {{lst}}.")) @listfunc def variance(lst): return statistics.pvariance(lst) doc("stand_dev_sample", [ ("lst", "List(Number)"), ], translate("Docs", "Returns the sample standard deviation of {{lst}}."), ["ecart_type_echant"]) @listfunc def stand_dev_sample(lst): return statistics.stdev(lst) ecart_type_echant = stand_dev_sample doc("variance_sample", [ ("lst", "List(Number)"), ], translate("Docs", "Returns the sample variance of {{lst}}."), ["variance_echant"]) @listfunc def variance_sample(lst): return statistics.variance(lst) variance_echant = variance_sample doc("random", [], translate("Docs", "Returns a random number between 0 (inclusive) and 1 (exclusive)."), ["alea"]) def random(): return rnd.random() alea = random doc("randint", [ ("a", "Integer"), ("b", "Integer") ], translate("Docs", "Returns a random integer between {{a}} and {{b}} (inclusive)."), ["alea_ent"]) def randint(a, b): if b < a: a, b = b, a return math.floor((b - a + 1) * random() + a) alea_ent = randint doc("fib", [ ("n", "Integer") ], translate("Docs", "Returns the {{n}}-th Fibonacci number.")) def fib(n): a, b = 1, 1 for i in range(int(n) - 1): a, b = b, a + b return a doc("euler", [ ("n", "Integer") ], translate("Docs", "Returns the {{n}}-th Euler number.")) def euler(n): # odd indices are zero if int(n) % 2 != 0: return 0 n = int(n / 2) return basic.pow(-1, n) \ * complex(0, 1) \ * sum(sum(binomial(k, j) * ((basic.pow(-1, j) * basic.pow(k - 2 * j, 2 * n + 1)) / ( basic.pow(2, k) * basic.pow(complex(0, 1), k) * k)) for j in range(0, k + 1) ) for k in range(1, 2 * n + 2) ) doc("beta", [ ("a", "Number"), ("b", "Number") ], translate("Docs", "Returns the Beta function at {{a}} and {{b}}.")) def beta(a, b): return (gamma(a) * gamma(b)) / gamma(a + b) doc("median", [ ("lst", "List(Number)"), ], translate("Docs", "Returns the median of {{lst}}.")) @listfunc def median(lst): return statistics.median(lst) doc("mode", [ ("lst", "List(Number)"), ], translate("Docs", "Returns the mode of {{lst}}.")) @listfunc def mode(lst): return statistics.mode(lst) doc("d_binomial", [ ("n", "Integer"), ("p", "Real", "0 <= p <= 1"), ("k", "Integer") ], translate("Docs", "Returns the probability for {{k}} with the binomial distribution of parameters {{n}} and {{p}}.")) @listfunc def d_binomial(n, p, k): return binomial(n, k) * basic.pow(p, k) * basic.pow(1 - p, n - k) doc("len", [ ("T", "List") ], translate("Docs", "Returns the number of elements in {{T}}."), ["taille"]) @listfunc def len(T): return builtins.len(T) taille = len doc("swap", [ ("T", "List"), ("a", "Integer"), ("b", "Integer") ], translate("Docs", "Swaps the elements of {{t}} at indices {{a}} and {{b}}.")) def swap(T, a, b): T[a], T[b] = T[b], T[a] return T doc("range", [ ("start", "Number"), ("end", "Number"), ("step", "Number", None, 1) ], translate("Docs", "Generates a list containing all number from {{start}} (inclusive) to {{end}} (exclusive) with a step of {{step}}.")) def range(start, end=None, step=None): if end is None: end = start start = 0 if step is None: if end < start: step = -1 else: step = 1 return [x.item() for x in np.arange(start, end, step)] doc("irange", [ ("start", "Number"), ("end", "Number"), ("step", "Number", None, 1) ], translate("Docs", "Generates a list containing all number from {{start}} (inclusive) to {{end}} (inclusive) with a step of {{step}}.")) def irange(start, end=None, step=None): if end is None: end = start start = 0 if step is None: if end < start: step = -1 else: step = 1 return [x.item() for x in np.arange(start, end + step, step)] doc("d_normal_pdf", [ ("mu", "Real"), ("sigma", "Real"), ("x", "Real") ], translate("Docs", "Returns the probability for {{x}} with the normal distribution of parameters µ={{mu}} and σ={{sigma}}.")) def d_normal_pdf(mu, sigma, x): return 1 / (sigma * math.sqrt(2 * trig.c_pi)) * math.exp( - (math.pow(x - mu, 2) / (2 * math.pow(sigma, 2)))) doc("d_normal_std_pdf", [ ("x", "Real") ], translate("Docs", "Returns the probability for {{x}} with the standard normal distribution (µ=0 and σ=1).")) def d_normal_std_pdf(x): return 1 / math.sqrt(2 * trig.c_pi) * math.exp(-pow(x, 2) / 2) doc("d_normal_cdf", [ ("mu", "Real"), ("sigma", "Real"), ("x", "Real") ], translate("Docs", "Returns the cumulative probability for {{x}} with the normal distribution of parameters µ={{mu}} and σ={{sigma}}.")) def d_normal_cdf(mu, sigma, x): return d_normal_std_cdf((x - mu) / sigma) doc("d_normal_std_cdf", [ ("x", "Real") ], translate("Docs", "Returns the cumulative probability for {{x}} with the standard normal distribution (µ=0 and σ=1).")) def d_normal_std_cdf(x): return 1 - 0.5 * erfc(x / math.sqrt(2)) doc("d_normal_cdf_inv", [ ("mu", "Real"), ("sigma", "Real"), ("p", "Real") ], translate("Docs", "Returns the number with cumulative probability {{p}} with the normal distribution of parameters µ={{mu}} and σ={{sigma}}.")) def d_normal_cdf_inv(mu, sigma, p): return d_normal_std_cdf_inv(p) * sigma + mu doc("d_normal_std_cdf_inv", [ ("p", "Real") ], translate("Docs", "Returns the number with cumulative probability {{p}} with the standard normal distribution (µ=0 and σ=1).")) def d_normal_std_cdf_inv(p): return erfcinv((1 - p) * 2) * math.sqrt(2)