Source code for Mes_fctions_probabilistes_new

from __future__ import division
import sys
import src.scripts.Mes_fctions.Mes_fctions_deterministes
from src.scripts.Mes_fctions.Mes_fctions_deterministes import * 
     
from sympy import Rational
import random
from math import *
from src.scripts.pxs_runtime import myst


[docs] def randnbres(n, p): """ Retourne une liste de n rationnels, tirés aléatoirement entre 0 et p, mais dont la somme vaut 1 Paramètres: - n (int): Nombre de valeurs rationnelles à générer - p (int): Borne supérieure pour les valeurs aléatoires (exclusif) Retourne: - list: Liste de n rationnels dont la somme est égale à 1 """ # Générer n nombres entiers aléatoires entre 0 et p-1 l = [random.randint(0, p-1) for _ in range(n)] # Calculer la somme totale A = sum(l) # Si la somme est 0, on génère au moins un nombre non nul if A == 0: index = random.randint(0, n-1) l[index] = random.randint(1, p-1) A = l[index] # Convertir chaque nombre en rationnel pour que la somme soit 1 m = [Rational(val, A) for val in l] return m
[docs] def randnbresstrictpositifs(n, k, p): """ Retourne une liste de n entiers, tirés aléatoirement entre k et p Paramètres: - n (int): Nombre d'entiers à générer - k (int): Borne inférieure (incluse) - p (int): Borne supérieure (exclue) Retourne: - list: Liste de n entiers aléatoires dans l'intervalle [k, p-1] """ # Générer directement n nombres aléatoires entre k et p-1 return [random.randint(k, p-1) for _ in range(n)]
[docs] def Multiple_of_p_in_L(p, L): """ Créer, à partir de la liste L, une liste ne contenant que les élements de L qui sont divisibles par p Paramètres: - p (int): Le diviseur - L (list): Liste d'entiers à filtrer Retourne: - list: Liste des éléments de L divisibles par p """ return [x for x in L if x % p == 0]
[docs] def rand_p_proba_a_partir_list(p, L): """ Retourne une liste composée de p éléments de la liste initiale L, pris au hasard (uniformément) Paramètres: - p (int): Nombre d'éléments à sélectionner - L (list): Liste source Retourne: - list: Une liste de p éléments tirés au hasard de L """ # Vérifier que p n'est pas supérieur à la longueur de L if p > len(L): p = len(L) # Utiliser random.sample pour sélectionner p éléments aléatoires sans remise return random.sample(L, p)
[docs] def Test_proba_pris_in_list(L, ind, p, nber_max, Lpartielle): """ Teste si le nombre L[ind] peut être choisi comme valeur d'une probabilité. Cette fonction vérifie si L[ind] peut être accepté comme poids d'une probabilité en tenant compte de: - La somme totale des poids, qui ne doit pas dépasser nber_max (pour pouvoir renormaliser) - Il faut avoir p probabilités au total - On a déjà sélectionné len(Lpartielle) poids Paramètres: - L (list): Liste des valeurs possibles pour les poids - ind (int): Indice du poids à tester dans L - p (int): Nombre total de probabilités à générer - nber_max (int/float): Valeur maximale pour la somme des poids - Lpartielle (list): Liste des poids déjà sélectionnés Retourne: - int: 1 si L[ind] peut être accepté, 0 sinon """ # Somme des poids déjà sélectionnés sum_partielle = sum(Lpartielle) # Nombre de poids restant à choisir après celui-ci remaining = p - len(Lpartielle) - 1 # Vérifier si la contrainte peut être satisfaite avec ce poids # 1. La somme actuelle + le nouveau poids + les poids minimaux restants ≤ nber_max if sum_partielle + L[ind] + remaining * L[0] > nber_max: return 0 return 1
[docs] def Poids_d_une_proba_in_list(Linit, p, nber_max): """ Renvoie une liste de p poids, pris dans la liste Linit dont la somme vaut nber_max, pour autant que ce soit possible Paramètres: - Linit (list): Liste des valeurs possibles pour les poids - p (int): Nombre de poids à sélectionner - nber_max (int/float): Valeur cible pour la somme des poids Retourne: - list: Liste de p poids dont la somme est nber_max, ou None si impossible """ # Vérifier si la somme est possible min_possible = p * min(Linit) # Somme minimale possible max_possible = p * max(Linit) # Somme maximale possible if nber_max < min_possible or nber_max > max_possible: return None # Impossible d'atteindre la somme cible # Trier la liste pour faciliter la recherche Linit_sorted = sorted(Linit) def backtrack(index, current_sum, current_list): # Si nous avons sélectionné p éléments et la somme est correcte if len(current_list) == p and current_sum == nber_max: return current_list.copy() # Important de retourner une copie # Si nous avons dépassé la somme cible ou trop d'éléments if current_sum > nber_max or len(current_list) >= p: return None # Si nous ne pouvons pas atteindre la somme cible avec les éléments restants min_remaining = (p - len(current_list)) * Linit_sorted[0] max_remaining = (p - len(current_list)) * Linit_sorted[-1] if current_sum + min_remaining > nber_max or current_sum + max_remaining < nber_max: return None # Essayer chaque élément for i in range(len(Linit)): # Parcourir toute la liste car nous avons besoin de l'index dans Linit, pas Linit_sorted # Éviter de réutiliser les éléments déjà utilisés if Linit[i] not in current_list or current_list.count(Linit[i]) < Linit.count(Linit[i]): # Ajouter l'élément à notre sélection actuelle current_list.append(Linit[i]) # Récursivement essayer avec cet élément result = backtrack(i, current_sum + Linit[i], current_list) # Si nous avons trouvé une solution, la retourner if result: return result # Sinon, retirer l'élément et essayer le suivant current_list.pop() return None # Commencer le backtracking return backtrack(0, 0, [])
from math import sqrt, exp, pi
[docs] def nor(x): """ Calcule la densité de la loi normale standard N(0,1) au point x. Paramètre: - x (float): Point où évaluer la densité Retourne: - float: Valeur de la densité de probabilité en x """ return (1 / sqrt(2 * pi)) * exp(-0.5 * x**2)
from sympy import Symbol, Piecewise, Abs
[docs] def fctionofafiniteRV(f, X): """ Crée une nouvelle variable aléatoire finie Y = f(X) à partir d'une variable aléatoire finie X existante et d'une fonction f. Parameters: ----------- f : callable La fonction à appliquer à la variable aléatoire X X : RandomSymbol Une variable aléatoire finie (de type FiniteRV) Returns: -------- RandomSymbol La nouvelle variable aléatoire Y = f(X) Si la somme des probabilités n'est pas égale à 1, retourne un message d'erreur Example: -------- >>> from sympy.stats import FiniteRV, density >>> from sympy import Rational >>> X = FiniteRV('X', {0: Rational(1, 3), 1: Rational(2, 3)}) >>> Y = fctionofafiniteRV(lambda x: x**2, X) >>> density(Y).dict {0: Rational(1, 3), 1: Rational(2, 3)} """ # Récupération des noms pour créer un nom descriptif stX = str(X) stf = str(f) # Récupération du dictionnaire de densité de X pmf_X = density(X).dict # Création du nouveau dictionnaire pour f(X) dico = {} # Application de la fonction f à chaque valeur possible de X for key, value in pmf_X.items(): new_key = f(key) # Agrégation des probabilités pour les valeurs identiques dico[new_key] = dico.get(new_key, 0) + value # Vérification que la somme des probabilités vaut 1 # Note: cette vérification est probablement superflue car on ne fait que # redistribuer les probabilités existantes, donc la somme reste 1 total_prob = sum(dico.values()) # Si la somme est 1 (ou très proche), on crée la nouvelle VA if abs(total_prob - 1) < 1e-10: # Tolérance pour les erreurs d'arrondi name = f"{stf}_of_{stX}" return FiniteRV(name, dico) else: return f"Error: The sum of probabilities ({total_prob}) does not equal 1"
[docs] def ExpandFiniteRV(f, X, name_of_f_of_X_for_LaTeX, ponctu=''): """ Génère une représentation LaTeX de la distribution de probabilité de f(X). Parameters: ----------- f : callable La fonction à appliquer à la variable aléatoire X X : RandomSymbol Une variable aléatoire finie name_of_f_of_X_for_LaTeX : str Nom à utiliser pour f(X) dans la sortie LaTeX ponctu : str, optional Type de ponctuation à utiliser ('point', 'virg', ou '') Returns: -------- str La représentation LaTeX de la distribution de probabilité de f(X) """ # Définir la ponctuation terminaison = '.' if ponctu == 'point' else (',' if ponctu == 'virg' else '') # Symbole de probabilité et nom de la variable U = 'mathbf{P}' # Utiliser \mathbf{P} au lieu de \bP T = name_of_f_of_X_for_LaTeX # Calculer f(X) en tant que variable aléatoire alpha = fctionofafiniteRV(f, X) # Extraire les valeurs et probabilités density_dict = density(alpha).dict values = list(density_dict.keys()) probabilities = list(density_dict.values()) # Construire la sortie LaTeX latex_output = myst(r"""\begin{align*}""", globals(), locals()) # Traiter toutes les paires (valeur, probabilité) n = len(density_dict) for i in range(n): s = str(values[i]) r = str(probabilities[i]) # Définir la ponctuation appropriée if i == n - 1: # Dernier élément punct = terminaison else: punct = ',' # Ajouter la ligne à la sortie avec des parenthèses cohérentes latex_output += myst(r"""&\\py{U}(\py{T}=\py{s})=\py{r}\py{punct}&""", globals(), locals()) # Ajouter un saut de ligne tous les 4 éléments (sauf pour le dernier) if (i + 1) % 4 == 0 and i < n - 1: latex_output += "\n" latex_output += myst(r"""\end{align*}""", globals(), locals()) return latex_output
# A commenter!!!!!!
[docs] def ExpandExpFiniteRV(f, X, name_of_the_original_rv, latex_name_of_f_of_alpha, name_funct_and_name_rv, ponctu=''): """ Génère une représentation LaTeX du calcul de l'espérance E[f(X)], où X est une variable aléatoire finie. Parameters: ----------- f : callable La fonction à appliquer à la variable aléatoire X X : RandomSymbol Une variable aléatoire finie name_of_the_original_rv : str Nom de la variable aléatoire X pour l'affichage LaTeX latex_name_of_f_of_alpha : str Représentation LaTeX de f(alpha) name_funct_and_name_rv : str Représentation LaTeX de f(X) pour l'en-tête E[f(X)] ponctu : str, optional Type de ponctuation à utiliser ('point', 'virg', ou '') Returns: -------- str La représentation LaTeX du calcul de E[f(X)] """ # Définir la ponctuation terminaison = '.' if ponctu == 'point' else (',' if ponctu == 'virg' else '') # Calculer f(X) en tant que variable aléatoire alpha = fctionofafiniteRV(f, X) # Extraire les valeurs et probabilités density_dict = density(alpha).dict values = list(density_dict.keys()) probabilities = list(density_dict.values()) # Calculer l'espérance E[f(X)] expected_value = sum(v * p for v, p in zip(values, probabilities)) result = str(expected_value) # Construire l'en-tête LaTeX latex_output = "\\begin{align*}\n" latex_output += "\\mathbf{E}[" + name_funct_and_name_rv + "]&=\\sum_{\\alpha\\in " + \ name_of_the_original_rv + "(\\Omega)}" + \ latex_name_of_f_of_alpha + "\\cdot\\mathbf{P}(" + \ name_of_the_original_rv + "=\\alpha)\\\\\n" # Construire les lignes de calcul n = len(density_dict) items_per_line = 5 # Nombre d'éléments par ligne current_line = "&=" for i in range(n): value = values[i] prob = probabilities[i] # Formater le terme if i > 0 and i % items_per_line == 0: current_line += "\\\\\n&\\hspace{2ex}+ " elif i > 0: current_line += " + " # Dernier terme de la somme if i == n - 1: current_line += f"{value}\\cdot {prob}\\\\" else: current_line += f"{value}\\cdot {prob}" # Ajouter le résultat final latex_output += current_line + "\n" latex_output += f"&={result}{terminaison}\n" latex_output += "\\end{align*}\n" return latex_output
# A vérifier !!!!!!
[docs] def ComputeExpFiniteRV(f, X): """ Calcule l'espérance mathématique E[f(X)] pour une variable aléatoire finie X. Cette fonction est un cas particulier de ComputeExp_p_FiniteRV avec p=1. Parameters: ----------- f : callable La fonction à appliquer à la variable aléatoire X X : RandomSymbol Une variable aléatoire finie Returns: -------- sympy.Expr L'espérance E[f(X)] Example: -------- >>> from sympy import Rational >>> from sympy.stats import FiniteRV >>> X = FiniteRV('X', {1: Rational(1, 4), 2: Rational(1, 2), 3: Rational(1, 4)}) >>> ComputeExpFiniteRV_optimized(lambda x: x**2, X) # E[X^2] Rational(5, 2) """ # Calculer la variable aléatoire f(X) transformed_X = fctionofafiniteRV(f, X) # Calculer E[f(X)] directement return sum(value * prob for value, prob in density(transformed_X).dict.items())
# A vérifier !!!!!!
[docs] def VarFiniteRV(f, X): """ Calcule la variance Var(f(X)) d'une variable aléatoire finie X transformée par une fonction f. Utilise la formule: Var(f(X)) = E[f(X)²] - E[f(X)]² Parameters: ----------- f : callable La fonction à appliquer à la variable aléatoire X X : RandomSymbol Une variable aléatoire finie Returns: -------- sympy.Expr La variance de f(X) Example: -------- >>> from sympy import Rational >>> from sympy.stats import FiniteRV >>> X = FiniteRV('X', {1: Rational(1, 2), 2: Rational(1, 2)}) >>> VarFiniteRV_optimized(lambda x: x**2, X) Rational(9, 4) """ # Calculer f(X) en tant que variable aléatoire transformed_X = fctionofafiniteRV(f, X) # Récupérer la distribution de probabilité pmf = density(transformed_X).dict # Calculer E[f(X)] et E[f(X)²] en une seule passe expected_value = 0 expected_square = 0 for value, probability in pmf.items(): expected_value += value * probability expected_square += value**2 * probability # Calculer la variance: Var(f(X)) = E[f(X)²] - E[f(X)]² variance = expected_square - expected_value**2 return variance
# A vérifier !!!!!!
[docs] def ComputeExp_p_FiniteRV(f, X, p): """ Calcule l'espérance mathématique E[f(X)^p] pour une variable aléatoire finie X, une fonction f et un exposant p. Parameters: ----------- f : callable La fonction à appliquer à la variable aléatoire X X : RandomSymbol Une variable aléatoire finie p : int or float L'exposant à appliquer au résultat de f(X) Returns: -------- sympy.Expr L'espérance E[f(X)^p] Example: -------- >>> from sympy import Rational >>> from sympy.stats import FiniteRV >>> X = FiniteRV('X', {1: Rational(1, 3), 2: Rational(2, 3)}) >>> ComputeExp_p_FiniteRV_optimized(lambda x: x, X, 2) # E[X^2] Rational(5, 3) """ # Définir la fonction composée g(x) = f(x)^p def g(x): return f(x)**p # Alternative si la fonction compo existe: # g = compo(f, p) # Calculer la variable aléatoire g(X) transformed_X = fctionofafiniteRV(g, X) # Calculer directement E[g(X)] en une seule passe expected_value = sum(value * prob for value, prob in density(transformed_X).dict.items()) return expected_value
[docs] def randnbresstrictpositifsreel(n, k, p, s): """ Génère une liste de n nombres réels positifs aléatoires. Parameters: ----------- n : int Nombre de valeurs à générer k : int Borne inférieure pour la partie entière des nombres p : int Borne supérieure pour la partie entière des nombres (non incluse) s : int Nombre de chiffres significatifs après la virgule (Note: la fonction actuelle utilise toujours 1 décimale indépendamment de s) Returns: -------- list Liste de n nombres réels aléatoires entre k et p avec des décimales Example: -------- >>> from sympy.stats import DiscreteUniform, sample_iter >>> randnbresstrictpositifsreel_optimized(5, 1, 10, 1) [1.7, 3.4, 7.9, 2.3, 8.6] # Résultat exemple avec des valeurs aléatoires """ from sympy.stats import DiscreteUniform, sample_iter import random # Génération plus efficace utilisant directement les fonctions appropriées if s <= 0: # Si aucun chiffre après la virgule n'est demandé, retourner des entiers integers = list(sample_iter(DiscreteUniform('W', list(range(k, p))), numsamples=n)) return integers # Créer une liste pour stocker les résultats result = [] # Générer une liste de n entiers aléatoires entre k et p-1 integers = list(sample_iter(DiscreteUniform('W', list(range(k, p))), numsamples=n)) # Générer une liste de n nombres décimaux entre 0 et 0.9 (un chiffre significatif) decimals = [round(random.random(), s) for _ in range(n)] # Combiner les deux pour créer les nombres réels for i in range(n): result.append(round(integers[i] + decimals[i], s)) return result