2016-10-25 1 views
2

J'ai vraiment besoin d'aide car je suis bloqué au début du code.Générateur aléatoire exponentiellement distribué (fonction log) en python?

On m'a demandé de créer une fonction pour étudier la distribution exponentielle sur l'histogramme. La fonction est x = -log (1-y)/λ. λ est une constante et je me suis référé à cela comme lamdr dans le code et lui ai simplement donné 10. J'ai donné N (le nombre de nombres aléatoires) 10 et j'ai exécuté le code mais les résultats et les nombres aléatoires générés m'ont donné des résultats totalement différents; ci-dessous vous pouvez trouver le code, je ne sais pas ce qui s'est mal passé, j'espère que vous pourrez m'aider !! (J'utilise python 2)

import random 
import math 

N = raw_input('How many random numbers you request?: ') 
N = int(N) 
lamdr = raw_input('Enter a value:') 
lamdr = int(lamdr) 

def exprand(lamdr): 
    y = [] 
    for i in range(N): 
     y.append(random.uniform(0,1)) 
    return y 
y = exprand(lamdr) 
print 'Randomly generated numbers:', (y) 

x = [] 
for w in y: 
    x.append((math.log((1 - w)/lamdr)) * -1) 
print 'Results:', x 
+0

différent de quoi? vous voulez dire que vous l'exécutez deux fois et que vous obtenez des résultats différents à chaque fois? –

+0

J'ai deux listes pour les nombres aléatoires et les résultats, ce qui devrait dépendre de l'équation donnée, mais il ne correspond pas, donc par exemple j'ai des valeurs x pour les valeurs y générées aléatoirement – aleatha

+0

Vous attendez 'lambdr' la valeur de départ pour vos appels 'random.uniform()'? Vous auriez besoin de le graver avec 'random.seed (lambdr)' en premier si c'est le cas. Ensuite, vous obtiendrez la même séquence de nombres pour une valeur 'lambdr' donnée. – eddiem

Répondre

4

Après avoir visionné le code fourni, il semble que vous avez les pièces dont vous avez besoin, mais vous n'êtes pas les mettre ensemble.

Il vous a été demandé d'écrire la fonction exprand(lambdr) en utilisant la formule spécifiée. Python fournit déjà une fonction appelée random.expovariate(lambd) pour générer des exponentielles, mais que diable, nous pouvons toujours faire nôtres. Votre formule nécessite une valeur "aléatoire" pour y qui a une distribution uniforme entre zéro et un. The documentation for the random module nous dit que random.random() nous donnera une distribution uniforme (0,1). Donc, tout ce que nous devons faire est de remplacer y dans la formule avec cet appel de fonction, et nous sommes dans les affaires:

def exprand(lambdr): 
    return -math.log(1.0 - random.random())/lambdr 

Une note historique: Mathématiquement, si y a une distribution uniforme (0,1) , tout comme 1-y. Les implémentations de l'algorithme remontant aux années 1950 tireraient souvent parti de ce fait pour simplifier le calcul à -math.log(random.random())/lambdr. Mathématiquement, cela donne des résultats distributivement corrects puisque P {X = c} = 0 pour toute variable aléatoire continue X et constante c, mais il va exploser en Python pour l'occurrence 1 dans 2 où vous obtenez un zéro de random.random(). L'une des raisons historiques à cela était que lorsque les ordinateurs étaient plus lents que de nombreux ordres de grandeur, il était considéré que le fait d'abandonner l'opération arithmétique supplémentaire valait le moindre risque. Un autre était que les PRNG Multiplicatifs de Premier Module, qui étaient populaires à l'époque, ne donnent jamais de zéro. Ces jours-ci, il s'agit principalement d'un intérêt historique et d'un exemple intéressant où les mathématiques et l'informatique divergent parfois.

Retour au problème actuel. Maintenant vous devez juste appeler cette fonction N fois et stocker les résultats quelque part. Les candidats susceptibles de le faire sont des boucles ou des compréhensions de listes. Voici un exemple de ce dernier:

abuncha_exponentials = [exprand(0.2) for _ in range(5)] 

Cela va créer une liste de 5 exponentielles avec & lambda; = 0,2. Remplacez 0,2 et 5 par des valeurs appropriées fournies par l'utilisateur, et vous êtes en affaires. Imprimer la liste, faire un histogramme, l'utiliser comme entrée à autre chose ...

Remplacer exporand par expovariate dans la liste de compréhension devrait produire des résultats équivalents en utilisant le générateur exponentiel intégré de Python. C'est la beauté des fonctions comme une abstraction, une fois que quelqu'un les écrit, vous pouvez simplement les utiliser au contenu de votre coeur. Notez qu'en raison de l'utilisation de l'aléatoire, cela donnera des résultats différents chaque fois que vous l'exécutez, sauf si vous "graine" le générateur aléatoire à la même valeur à chaque fois.

2

WHAT @pjs a écrit est vrai à un point. Alors que la déclaration mathematically, if y has a uniform(0,1) distribution, so does 1-y semble être correcte, la proposition de remplacer le code par -math.log(random.random())/lambdr est tout simplement fausse. Pourquoi?Parce que le module Python random fournit U (0,1) dans la plage [0,1) (comme mentionné here), rendant ainsi ce remplacement non équivalent.

En terme plus profane, si votre U(0,1) est en fait générer des nombres dans l'intervalle [0,1), puis le code

import random 
def exprand(lambda): 
    return -math.log(1.0 - random.random())/lambda 

est correct, mais le code

import random 
def exprand(lambda): 
    return -math.log(random.random())/lambda 

est faux, il va parfois générer NaN/exception, comme log(0) sera appelé

+1

Un commentaire ou edit semble être une réponse plus appropriée qu'un vote négatif. – pjs

+0

@pjs Oui, mea culpa. Trop grand pour un commentaire, bien que ... –