# Simulation par la méthode de Monte-Carlo

# Incertitude de type A : traitement statistique 
# Incertitude de type B : propagation. Relever les diverses causes d’erreurs liées au matériel utilisé et au protocole utilisé.
# Le a/racine(3) correspond à +/- a si on a une répartition uniforme

#http://jlamerenx.fr/wp-content/uploads/2020/11/Estimation_dune_incertitude_type_par_la_méthode_de_Monte_Carlo.html

#Principe de la méthode Monte-Carlo
#Le résultat d'une mesure correspond à l'ensemble des valeurs raisonnablement attribuables à la grandeur mesurée.
#L'écart-type de cet ensemble de valeurs est appelée à l'incertitude-type.
#Evaluation de type A : Lorsque la mesure est répétée plusieurs fois, l'expérimentateur obtient plusieurs valeurs de la grandeur mesurée. L'incertitude-type est l'écart-type de cet ensemble de valeurs.
#Evaluation de type B : Lorsque l'expérience n'est pas répétée plusieurs fois, il faut mettre en oeuvre une autre méthode pour évaluer l'incertitude-type. Dans ce contexte, la méthode de Monte-Carlo consiste à simuler numériquement la répétition de l'expérience. L'écart-type de l'ensemble des valeurs obtenues lors des ces répétitions in silico fournit l'incertitude-type recherchée.
#La méthode de Monte-Carlo est très utile à mettre en oeuvre dans le cas d'une propagation d'incertitudes, c'est-à-dire lorsque l'on souhaite déterminer l'incertitude-type sur une grandeur calculée à partir de grandeurs expérimentales, mesurées ou fournies.

# Exemple sur un titrage
# on mesure la concentration Ca de l'acide, on connaît:
# le volume Vsol de la prise d'essai
# le volume Veq à l'équivalence
# la concentration Cb de la solution titrante

import numpy as np

N = 100000 # nombre de tirages simulés (comme si nous avions effectué N mesures)
Ca = [] # Liste des valeurs calculées de la concentration Ca
for k in range(N) : # procédure de tirage
	Vsol = np.random.uniform(9.9,10.1) # toutes les valeurs sont équiprobables
	Veq = np.random.triangular(9.6 , 9.7 , 9.8) # la valeur centrale est plus probable que les valeurs latérales
	Cb = np.random.uniform(.099 , .101) # équiprobables
	Ca.append(Cb * Veq / Vsol) # on calcule la valeur de Ca pour chaque tirage

Ca_moy = sum(Ca)/N # calcul de la valeur moyenne des mesures 
uCa = np.std(Ca,ddof=1) # calcul de l'écart-type 

print(f'Concentration Ca : {Ca_moy} mol/L') 
print(f'Incertitude-type u(Ca) : {uCa} mol/L')
#print('Ca : {} +/- {} mol/L'.format(round(Ca_moy,5), round(uCa,5)))