J'ai posé une fois à Stack Overflow une question sur
la structure des données pour tricher aux dés . En particulier, je suis intéressé par la réponse à cette question: «Si nous avons un os à n facettes, dont la face i a une probabilité de tomber p
i . Quelle est la structure de données la plus efficace pour simuler les rouleaux d'un tel os? »
Cette structure de donnĂ©es peut ĂȘtre utilisĂ©e pour de nombreuses tĂąches. Par exemple, vous pouvez l'utiliser pour simuler des jets hexagonaux honnĂȘtes, en attribuant une probabilitĂ©
f r a c 1 6 de chaque cĂŽtĂ© de l'os, ou pour simuler une piĂšce de monnaie Ă©quitable par imitation d'un os bilatĂ©ral, dont la probabilitĂ© de tomber de chaque cĂŽtĂ© est Ă©gale Ă
f r a c 1 2 . Vous pouvez Ă©galement utiliser cette structure de donnĂ©es pour simuler directement la somme de deux os hexagonaux honnĂȘtes en crĂ©ant un os Ă 11 faces (avec les faces 2, 3, 4, ..., 12), dont chaque face a un poids de probabilitĂ© correspondant aux rouleaux de deux os honnĂȘtes. Cependant, vous pouvez Ă©galement utiliser cette structure de donnĂ©es pour simuler des tricheurs. Par exemple, si vous jouez au
craps avec un os, ce qui, comme vous le savez, n'est pas parfaitement honnĂȘte, vous pouvez utiliser cette structure de donnĂ©es pour simuler un grand nombre de rouleaux d'os et analyser la stratĂ©gie optimale. Vous pouvez Ă©galement essayer de simuler une
roue de roulette tout aussi imparfaite.
Si vous allez au-delà des jeux, vous pouvez appliquer cette structure de données dans la simulation de robots dont les capteurs ont des niveaux de défaillance connus. Par exemple, si un capteur de plage a une probabilité de 95% de renvoyer la valeur correcte, une probabilité de 4% d'une valeur trop petite et une probabilité de 1% d'une valeur trop élevée, vous pouvez utiliser cette structure de données pour simuler la lecture des lectures du capteur en générant un résultat aléatoire et simuler la lecture du capteur résultat.
La réponse que j'ai reçue sur Stack Overflow m'a impressionné pour deux raisons. Tout d'abord, dans la solution, il m'a été conseillé d'utiliser une technique puissante appelée la
méthode alias , qui, avec certaines hypothÚses raisonnables sur le modÚle de la machine, est capable, aprÚs une simple étape de préparation préliminaire, de simuler des roulements osseux dans le temps
O ( 1 ) . DeuxiĂšmement, j'ai Ă©tĂ© encore plus surpris que cet algorithme soit connu depuis des dĂ©cennies, mais je ne l'ai jamais rencontrĂ©! Ătant donnĂ© le temps de calcul consacrĂ© Ă la simulation, on pourrait s'attendre Ă ce que cette technique soit beaucoup plus connue. Quelques requĂȘtes sur Google m'ont donnĂ© beaucoup d'informations sur cette technique, mais je n'ai pas pu trouver un seul site oĂč une comprĂ©hension et une explication intuitives de cette technique se sont rĂ©unies.
Cet article est ma tentative de donner un bref aperçu des différentes approches pour simuler la triche osseuse, des techniques simples et trÚs peu pratiques à une méthode d'alias trÚs optimisée et efficace. J'espÚre que je serai en mesure de transmettre différentes façons de comprendre intuitivement la tùche et comment chacun d'entre eux met l'accent sur un nouvel aspect de la simulation d'un tricheur. Mon objectif pour chaque approche est d'étudier une idée motivante, un algorithme de base, une preuve de fidélité et une analyse de l'exécution (en termes de temps requis, de mémoire et d'aléatoire).
Entrée
Avant de passer aux détails spécifiques des différentes techniques, normalisons d'abord la terminologie et la notation.
Dans l'introduction de l'article, j'ai utilisé le terme «os tricheur» pour décrire un scénario généralisé dans lequel il existe un ensemble fini de résultats, chacun ayant une probabilité. Formellement, cela s'appelle une
distribution de probabilité discrÚte , et la tùche de simuler un os tricheur est appelée
échantillonnage à partir d'une distribution discrÚte .
Pour décrire notre distribution de probabilité discrÚte (os tricheur), nous supposerons que nous avons un ensemble de n probabilités
p 0 , p 1 , . . . , p n - 1 lié aux résultats

. Bien que les rĂ©sultats puissent ĂȘtre quelconques (aigle / queues, nombres sur les os, couleurs, etc.), pour simplifier, je considĂ©rerai le rĂ©sultat comme une sorte de nombre rĂ©el positif correspondant Ă un indice donnĂ©.
Travailler avec des nombres réels sur un ordinateur est la «zone grise» de l'informatique. Il existe de nombreux algorithmes rapides, dont la vitesse est fournie uniquement par la capacité de
calculer la fonction de plancher d'un nombre réel arbitraire en un temps constant, et des inexactitudes numériques dans la représentation des nombres à virgule flottante peuvent détruire complÚtement certains algorithmes. Par conséquent, avant de commencer toute discussion sur les algorithmes qui fonctionnent avec des probabilités, c'est-à -dire entrer dans le monde sombre des nombres réels, je dois clarifier ce qu'un ordinateur peut et ne peut pas faire.
Ci-aprĂšs, je suppose que toutes les opĂ©rations suivantes peuvent ĂȘtre effectuĂ©es en temps constant:
- Addition. soustraction, multiplication, division et comparaison de nombres réels arbitraires . Nous devrons le faire pour manipuler les probabilités. Cela peut sembler une hypothÚse audacieuse, mais si nous supposons que la précision d'un nombre réel est limitée par un polynÎme de la taille du mot machine (par exemple, un double 64 bits sur une machine 32 bits), mais je ne pense pas que ce soit trop déraisonnable.
- Génération d'un nombre réel uniforme dans l'intervalle [0, 1). Pour simuler le caractÚre aléatoire, nous avons besoin d'une source de valeurs aléatoires. Je suppose que nous pouvons générer un nombre réel de précision arbitraire en temps constant. Cela dépasse de loin les capacités d'un véritable ordinateur, mais il me semble que pour les besoins de cette discussion, cela est acceptable. Si nous acceptons de sacrifier une fraction de la précision en disant qu'un double arbitraire IEEE-754 est dans l'intervalle [0, 1], alors nous perdrons en fait la précision, mais le résultat sera probablement suffisamment précis pour la plupart des applications.
- Calcul du plancher entier (arrondi vers le bas) d'un nombre réel. Ceci est acceptable si nous supposons que nous travaillons avec le double IEEE-754, mais en général, une telle exigence pour un ordinateur n'est pas faisable.
Il vaut la peine de se poser la question - est-il raisonnable de supposer que nous pouvons mener Ă bien toutes ces opĂ©rations? Dans la pratique, nous utilisons rarement les probabilitĂ©s indiquĂ©es Ă un tel niveau de prĂ©cision auquel l'erreur d'arrondi inhĂ©rente au double IEEE-754 peut causer de graves problĂšmes, nous pouvons donc remplir toutes les exigences ci-dessus simplement en travaillant exclusivement avec le double IEEE. Cependant, si nous nous trouvons dans un environnement oĂč les probabilitĂ©s sont indiquĂ©es
exactement comme des nombres rationnels de haute prĂ©cision, alors de telles restrictions peuvent ĂȘtre dĂ©raisonnables.
Simulation osseuse honnĂȘte
Avant de passer au cas plus gĂ©nĂ©ral de lancer un os de triche arbitraire, commençons par un algorithme plus simple qui servira de bloc de construction pour les algorithmes suivants: simuler un os honnĂȘte Ă face n. Par exemple, des dĂ©s hexagonaux honnĂȘtes peuvent ĂȘtre utilisĂ©s pour jouer au Monopoly ou Risk, ou lancer une piĂšce honnĂȘte (dĂ©s Ă double face), etc.
Pour ce cas particulier, il existe un algorithme simple, élégant et efficace pour simuler le résultat. L'algorithme est basé sur l'idée suivante: supposons que nous pouvons générer des nombres réels vraiment aléatoires et uniformément répartis dans l'intervalle
[ 0 , 1 ) . Cet intervalle peut ĂȘtre illustrĂ© comme suit:
Maintenant, si nous voulons quitter
n os à facettes, alors une façon est de diviser l'intervalle
[ 0 , 1 ) sur
n zones de taille égale, chacune ayant une longueur
f r a c 1 n . Cela ressemble Ă ceci:
Ensuite, nous générons un nombre réel choisi au hasard dans l'intervalle
[ 0 , 1 ) cela tombe sûrement dans l'un de ces petits domaines. à partir de cela, nous pouvons calculer le résultat du roulement de l'os en regardant la zone dans laquelle le nombre est tombé. Par exemple, si notre valeur sélectionnée au hasard tombe à cet endroit:
on peut alors dire que 2 sont tombés sur l'os (si l'on suppose que les bords de l'os sont indexés à partir de zéro).
Il est graphiquement facile de voir quelle rĂ©gion a une valeur alĂ©atoire, mais comment codons-nous cela dans un algorithme? Et ici, nous profitons du fait que c'est un os honnĂȘte. Ătant donnĂ© que tous les intervalles sont de taille Ă©gale, Ă savoir
f r a c 1 n , alors nous pouvons voir quelle est la plus grande valeur
je est telle que
f r a c i n pas plus qu'une valeur gĂ©nĂ©rĂ©e alĂ©atoirement (appelons cette valeur x). Vous remarquerez peut-ĂȘtre que si nous voulons trouver la valeur maximale, telle que
f r a c i n l e x , cela revient Ă trouver la valeur maximale
n tel que
i l e x n . Mais cela signifie par définition que
i= lfloorxn rfloor , le plus grand entier positif n'est pas supĂ©rieur Ă xn. Par consĂ©quent, cela nous conduit Ă cet algorithme de simulation osseuse Ă facettes n honnĂȘte (trĂšs simple):
Algorithme: simulation osseuse honnĂȘte
- Générer une valeur aléatoire uniformément distribuée x dans la gamme [0,1) .
- Retour lfloorxn rfloor .
Compte tenu de nos hypothĂšses ci-dessus sur les calculs, cet algorithme fonctionne dans le temps O(1) .
Deux conclusions peuvent ĂȘtre tirĂ©es de cette section. Tout d'abord, nous pouvons diviser l'intervalle
[0,1) en partie de sorte qu'un nombre rĂ©el alĂ©atoire uniformĂ©ment rĂ©parti dans cet intervalle se rĂ©duit naturellement Ă l'une des nombreuses options discrĂštes Ă notre disposition. Dans la suite de cet article, nous exploiterons activement cette technique. DeuxiĂšmement, il peut ĂȘtre difficile de dĂ©terminer Ă quel intervalle spĂ©cifique appartient une valeur alĂ©atoire, mais si nous savons quelque chose sur les parties (dans ce cas, elles sont toutes de la mĂȘme taille), alors nous pouvons mathĂ©matiquement simplement dĂ©terminer quelle partie se rĂ©fĂšre Ă un particulier point.
Simulation d'os de triche avec os honnĂȘte
Avec un algorithme de simulation osseuse honnĂȘte, pouvons-nous l'adapter pour simuler un os tricheur? Fait intĂ©ressant, la rĂ©ponse est oui, mais une solution nĂ©cessitera plus d'espace.
De la section précédente, il est intuitivement clair que pour simuler un lancer d'os de triche, il suffit de diviser l'intervalle
[0,1) en morceaux, puis dĂ©terminez quelle partie nous frappons. Cependant, dans le cas gĂ©nĂ©ral, cela peut ĂȘtre beaucoup plus compliquĂ© qu'il n'y paraĂźt. Disons que nous avons un tĂ©traĂšdre avec des probabilitĂ©s de face
frac12 ,
frac13 ,
frac112 et
frac112 (nous pouvons nous assurer que c'est la distribution de probabilité correcte, car
frac12+ frac13+ frac112+ frac112= frac612+ frac412+ frac112+ frac112= frac1212 ) Si nous divisons l'intervalle
[0,1) en quatre parties de ces tailles, nous obtenons alors les éléments suivants:
Malheureusement, Ă ce stade, nous sommes bloquĂ©s. MĂȘme si nous connaissions un nombre alĂ©atoire dans l'intervalle
[0,1) , il n'y a pas d'astuces mathĂ©matiques simples pour dĂ©terminer automatiquement dans quelle partie ce nombre est tombĂ©. Je ne veux pas dire que cela est impossible - comme vous le verrez, nous pouvons utiliser de nombreux excellents trucs - mais aucun d'eux n'a la simplicitĂ© mathĂ©matique de l'algorithme honnĂȘte de projection d'os.
Cependant, nous pouvons Ă©galement adapter la technique utilisĂ©e pour un os honnĂȘte. Prenons l'exemple de l'os discutĂ© ci-dessus. La probabilitĂ© de fronts descendants est
frac12 ,
frac13 ,
frac112 et
frac112 . Si nous réécrivons ceci pour que tous les membres aient un diviseur commun, nous obtenons les valeurs
frac612 ,
frac412 ,
frac112 et
frac112 . Par consĂ©quent, nous pouvons percevoir cette tĂąche comme suit: au lieu de jeter un os tĂ©traĂ©drique avec des probabilitĂ©s pondĂ©rĂ©es, pourquoi ne pas jeter un os honnĂȘte Ă 12 cĂŽtĂ©s, sur les bords duquel il y a des valeurs en double? Puisque nous savons simuler un os honnĂȘte, cela sera analogue Ă la sĂ©paration par intervalles
[0,1) en morceaux de cette façon:
Ensuite, nous les affectons à différents résultats comme suit:
Maintenant, il sera trĂšs simple de simuler un lancer d'os - nous jetons simplement ce nouvel os honnĂȘte, puis nous regardons quel visage est tombĂ© et lisons sa valeur. Cette premiĂšre Ă©tape peut ĂȘtre effectuĂ©e par l'algorithme prĂ©sentĂ© ci-dessus, qui nous donnera un nombre entier de nombres dans l'intervalle

. Afin de lier cet entier Ă l'une des faces de l'os du tricheur d'origine, nous allons stocker un tableau auxiliaire de douze Ă©lĂ©ments reliant chacun de ces nombres au rĂ©sultat d'origine. Cela peut ĂȘtre reprĂ©sentĂ© graphiquement comme suit:
Pour formaliser cela sous la forme d'un algorithme, nous dĂ©crivons Ă la fois l'Ă©tape d'initialisation (obtention de la table) et l'Ă©tape de gĂ©nĂ©ration (simulation d'un lancer osseux alĂ©atoire). Ces deux Ă©tapes sont importantes Ă considĂ©rer dans cet algorithme et les suivants, car le temps de prĂ©paration doit ĂȘtre excellent.
Au stade de l'initialisation, nous commençons par chercher le
multiple le
moins commun de toutes les probabilitĂ©s donnĂ©es pour les bords de l'os (dans notre exemple, la LCL est 12). NOC est utile ici car il correspond au plus petit diviseur commun que nous pouvons utiliser pour toutes les fractions, et donc le nombre de faces du nouvel os honnĂȘte que nous roulerons. AprĂšs avoir reçu ce CNO (nous le dĂ©signons par L), nous devons dĂ©terminer combien de faces du nouvel os seront rĂ©parties sur chacune des faces de l'os tricheur d'origine. Dans notre exemple, le visage avec probabilitĂ©
frac12 obtient six cÎtés du nouvel os depuis
frac12 fois12=6 . De mĂȘme, la partie avec probabilitĂ©
frac13 obtient 4 visages depuis
frac13 fois12=4 . Dans une forme plus généralisée, si L est une LCL de probabilités, et
pi est la probabilité d'un visage
i les os, puis nous mettons en évidence les visages
i os de Sharpie d'origine
L cdotpi facettes de l'os honnĂȘte.
Voici le pseudocode de l'algorithme ci-dessus:
Algorithme: simuler l'os de triche avec de l'os honnĂȘte
- Initialisation :
- Trouver le CNO des dĂ©nominateurs de probabilitĂ© p0,p1,...,pnâ1 ; le dĂ©noter L
- SĂ©lectionnez un tableau A la taille L pour comparer les rĂ©sultats de rouleaux d'os honnĂȘtes avec les rouleaux de l'os d'origine.
- Pour chaque visage i de l'os initial, nous effectuons les opérations suivantes dans n'importe quel ordre:
- Nous attribuons comme suit L cdotpi des éléments A valeur i .
- Génération :
- Nous gĂ©nĂ©rons un lancer d'os honnĂȘte pour L -os osseux; appeler le visage S .
- Retour A[S] .
Cet algorithme peut ĂȘtre simple, mais quelle est son efficacitĂ©? La gĂ©nĂ©ration de rouleaux osseux est assez rapide - chaque rouleau osseux nĂ©cessite
O(1) runtime pour générer un jet de dés aléatoire en utilisant l'algorithme précédent, et plus encore
O(1) heures de travail pour rechercher la table. Cela nous donne le temps de travail total.
O(1) .
Cependant, l'Ă©tape d'initialisation peut ĂȘtre extrĂȘmement coĂ»teuse. Pour que cet algorithme fonctionne, nous devons allouer de l'espace Ă un tableau de la taille du NLC des dĂ©nominateurs de toutes les fractions d'entrĂ©e. Dans notre exemple (
frac12 ,
frac13 ,
frac112 ,
frac112 ), il est de 12, pour d'autres valeurs d'entrĂ©e, les valeurs peuvent ĂȘtre pathologiquement mauvaises. Par exemple, regardons les fractions
frac9999991000000 et
frac11000000 . Le CNO des dénominateurs est égal à un million, donc il devrait y avoir un million d'éléments dans notre tableau!
Malheureusement, les choses pourraient ĂȘtre encore pires. Dans l'exemple prĂ©cĂ©dent, on peut au moins «s'attendre» Ă ce que l'algorithme occupe beaucoup de mĂ©moire, car les deux dĂ©nominateurs des fractions sont Ă©gaux Ă un million. Cependant, nous pouvons avoir de nombreuses probabilitĂ©s pour lesquelles la CNP est nettement supĂ©rieure Ă chaque dĂ©nominateur individuel. Par exemple, regardons les probabilitĂ©s
frac115 ,
frac110 ,
frac56 . Ici, le NOC des dénominateurs est de 30, ce qui est plus que n'importe lequel des dénominateurs. Le design fonctionne ici parce que

,

et

; en d'autres termes, chaque dĂ©nominateur est un produit de deux nombres premiers sĂ©lectionnĂ©s dans un pool de trois valeurs. Par consĂ©quent, leur NOC est le produit de tous ces nombres premiers, car chaque dĂ©nominateur doit ĂȘtre un diviseur du NOC. Si nous gĂ©nĂ©ralisons cette construction et considĂ©rons tout ensemble de
k nombres premiers et prendre une fraction pour chacun des produits par paires de ces nombres premiers, alors le NOC sera beaucoup plus que chaque dénominateur individuel. En fait, l'une des meilleures limites supérieures que nous pouvons obtenir pour le CNO sera
O( prodni=0di) oĂč
di Est le dénominateur
i cette probabilité. Cela ne permet pas d'utiliser un tel algorithme en conditions réelles, lorsque les probabilités sont inconnues à l'avance, car la mémoire nécessaire pour stocker la table de taille
O( prodni=0di) , Il peut facilement s'avérer supérieur au volume pouvant tenir dans la RAM.
En d'autres termes, dans de nombreux cas, cet algorithme se comporte bien. Si toutes les probabilitĂ©s sont les mĂȘmes, alors toutes les probabilitĂ©s obtenues Ă l'entrĂ©e sont Ă©gales
frac1n pour certains
n . Ensuite, les dénominateurs des CNO sont égaux
n , c'est-Ă -dire qu'en consĂ©quence, l'os honnĂȘte jetĂ© aura
n faces, et chaque facette de l'os d'origine correspondra Ă une facette de l'os honnĂȘte. Par consĂ©quent, le temps d'initialisation est
O(n) . Cela peut ĂȘtre reprĂ©sentĂ© graphiquement comme suit:
Cela nous donne les informations suivantes sur l'algorithme:
Algorithme | Temps d'initialisation | Temps de génération | Mémoire occupée |
---|
| Le meilleur | Le pire | Le meilleur | Le pire | Le meilleur | Le pire |
---|
HonnĂȘtetĂ© os sharler bone | Theta(n) | O( prodni=0di) | ThĂȘta(1) | Theta(n) | O( prodni=0di) |
Autre dĂ©tail important sur cet algorithme: il suppose que nous recevrons des probabilitĂ©s pratiques sous forme de fractions avec de bons dĂ©nominateurs. Si les probabilitĂ©s sont spĂ©cifiĂ©es comme IEEE-754 double, cette approche risque d'ĂȘtre dĂ©sastreuse en raison de petites erreurs d'arrondi; Imaginez que nous ayons les probabilitĂ©s 0,25 et 0,250000000001! Par consĂ©quent, cette approche est probablement prĂ©fĂ©rable de ne pas utiliser, sauf dans des cas particuliers oĂč les probabilitĂ©s se comportent bien et sont spĂ©cifiĂ©es dans un format correspondant aux opĂ©rations avec des nombres rationnels.
Simulation de piÚces asymétriques
Notre explication d'une simple primitive alĂ©atoire (os honnĂȘte) a conduit Ă un algorithme de simulation d'os de triche simple mais potentiellement terriblement inefficace. L'Ă©tude d'autres primitives alĂ©atoires simples Ă©clairera peut-ĂȘtre d'autres approches pour rĂ©soudre ce problĂšme.
Une tùche simple mais étonnamment utile consiste à simuler une piÚce asymétrique à l'aide d'un générateur de nombres aléatoires. Si nous avons une piÚce avec la probabilité d'un aigle
ptĂȘtes , alors comment simuler le lancer d'une telle piĂšce asymĂ©trique?
Plus tÎt, nous avons développé une approche intuitive: le partitionnement par intervalles
[0,1) sur une séquence de telles régions que lors du choix d'une valeur aléatoire dans l'intervalle, elle apparaßt dans certaines régions avec une probabilité égale à la taille de la région. Pour simuler une piÚce asymétrique en utilisant une valeur aléatoire uniformément distribuée dans l'intervalle
[0,1) il faut rompre l'intervalle
[0,1) comme suit:
Et puis générer une valeur aléatoire uniformément distribuée dans l'intervalle
[0,1) pour voir dans quelle zone il se trouve. Heureusement, nous n'avons qu'un seul point de partage, il est donc trÚs facile de déterminer dans quelle zone il se trouve; si la valeur est inférieure
ptĂȘtes , puis l'aigle est tombĂ© sur la piĂšce, sinon - queues. Pseudocode:
Algorithme: simuler une piÚce asymétrique
- Générer une valeur aléatoire uniformément distribuée dans l'intervalle [0,1) .
- Si x < p t ĂȘ t e s , retournez "l'aigle".
- Si x g e p t ĂȘ t e s , renvoyez la queue.
Puisque nous pouvons générer une valeur aléatoire uniformément distribuée dans l'intervalle
[ 0 , 1 ) Ă temps
O ( 1 ) , et nous pouvons également comparer des nombres réels pour
O ( 1 ) , alors cet algorithme s'exécute dans le temps
O ( 1 ) .
Simuler des os honnĂȘtes Ă l'aide de piĂšces asymĂ©triques
De la discussion prĂ©cĂ©dente, nous savons que nous pouvons simuler un os de triche en utilisant de l'os honnĂȘte, si nous supposons que nous sommes prĂȘts Ă dĂ©penser plus d'espace mĂ©moire. Ătant donnĂ© que nous pouvons percevoir une piĂšce asymĂ©trique comme un os bilatĂ©ral tricheur, cela signifie que nous pouvons simuler une piĂšce asymĂ©trique Ă l'aide d'un os honnĂȘte. Il est intĂ©ressant de voir que l'inverse peut Ă©galement ĂȘtre fait - pour simuler un os honnĂȘte Ă l'aide d'une piĂšce asymĂ©trique.
Le design est simple, Ă©lĂ©gant et peut ĂȘtre facilement gĂ©nĂ©ralisĂ© pour simuler un os tricheur en utilisant une variĂ©tĂ© de piĂšces asymĂ©triques.Conception pour simuler une piĂšce asymĂ©trique divise l'intervalle[ 0 , 1 ) en deux zones - la zone «aigles» et la zone «queues» en fonction de la probabilitĂ© que les aigles tombent sur les os. Nous avons dĂ©jĂ vu une astuce similaire utilisĂ©e pour simuler honnĂȘten- os Ă facettes: intervalle[ 0 , 1 ) Ă©tait divisĂ© enn zones Ă©gales. Par exemple, lors du lancement d'un os tĂ©traĂ©drique, nous avons obtenu la sĂ©paration suivante:Supposons maintenant que nous soyons intĂ©ressĂ©s Ă simuler un rouleau de cet os honnĂȘte en utilisant un ensemble de piĂšces asymĂ©triques. Une solution est la suivante: imaginez que nous contournons ces zones de gauche Ă droite, en nous demandant Ă chaque fois si nous voulons nous arrĂȘter dans la zone actuelle, ou si nous allons continuer. Par exemple, disons que nous voulons sĂ©lectionner au hasard l'une de ces zones. En partant de la zone la plus Ă gauche, nous lancerons une piĂšce asymĂ©trique, qui nous dira si nous devons nous arrĂȘter dans cette zone ou continuer Ă avancer. Puisque nous devons choisir parmi toutes ces zones uniformĂ©ment avec probabilitĂ©14 , alors nous pouvons le faire en lançant une piĂšce asymĂ©trique, les aigles sur lesquels tomber avec probabilitĂ©14 .
Si un aigle tombe, nous nous arrĂȘtons dans la zone actuelle. Sinon, nous passons Ă la zone suivante.Si les piĂšces tombent, nous nous retrouvons dans la deuxiĂšme zone et nous demandons Ă nouveau si nous devons sĂ©lectionner Ă nouveau cette zone ou continuer Ă bouger. Vous pourriez penser que pour cela, nous devons lancer une autre piĂšce avec la probabilitĂ© d'un aigle14 , mais en rĂ©alitĂ© ce n'est pas vrai! Pour voir la faille de ce raisonnement, nous devons arriver Ă une situation extrĂȘme - si dans chaque zone nous lançons une piĂšce sur laquelle l'aigle tombe avec probabilitĂ©14 , c'est-Ă -dire qu'il y a une petite chance que dans chaque zone la piĂšce tombe en queue, c'est-Ă -dire que nous devrons abandonner toutes les zones. Lorsque nous traversons des rĂ©gions, nous devons en quelque sorte continuer d'augmenter la probabilitĂ© qu'un aigle tombe sur une piĂšce. Dans une situation extrĂȘme, si nous nous trouvons dans la derniĂšre zone, la piĂšce doit avoir un aigle avec probabilitĂ©1 , parce que si nous rejetions tous les domaines prĂ©cĂ©dents, la bonne dĂ©cision serait d'arrĂȘter dans le dernier domaine.Pour dĂ©terminer la probabilitĂ© avec laquelle notre piĂšce asymĂ©trique devrait lancer un aigle aprĂšs avoir sautĂ© la premiĂšre zone, nous devons noter qu'aprĂšs avoir sautĂ© la premiĂšre zone, il n'en reste que trois. Alors que nous roulons un os honnĂȘte, nous avons besoin que chacune de ces trois zones soit sĂ©lectionnĂ©e avec probabilitĂ©13 .
Par conséquent, intuitivement, il semble que nous devrions avoir un deuxiÚme os sur lequel l'aigle tombe avec probabilité 13 .
En utilisant un raisonnement similaire, on peut comprendre que lorsqu'une queue apparaĂźt dans la deuxiĂšme rĂ©gion du rĂ©seau dans la troisiĂšme rĂ©gion, la piĂšce doit ĂȘtre lĂąchĂ©e par l'aigle avec probabilitĂ© 12 , et dans la derniĂšre zone - avec probabilitĂ©1 .
Cette comprĂ©hension intuitive nous conduit Ă l'algorithme suivant. Notez que nous n'avons pas discutĂ© de l'exactitude ou de l'erreur de cet algorithme; nous le ferons bientĂŽt.Algorithme: simuler des os honnĂȘtes Ă l'aide de piĂšces asymĂ©triques
- Pour i = 0 Ă n - 1 :
- Lancez une piÚce asymétrique avec la probabilité d'un aigle 1n - i .
- Si l'aigle tombe, revenez je .
Cet algorithme est simple et, dans le pire des cas, s'exécute dans le temps. O ( n ) .
Mais comment vérifier si c'est correct? Pour le savoir, nous avons besoin du théorÚme suivant:ThéorÚme: l' algorithme ci - dessus renvoie le cÎtéi avec probabilité1n pour tout sélectionnéje .
Preuve: considérer toute constanten ℠0 . En utilisant une forte induction, nous prouvons que chacun des n faces a une probabilité de choix1n .
Pour notre exemple, nous montrons que le visage 0 dĂ©s a une probabilitĂ© de choix1n . Mais cela dĂ©coule directement de l'algorithme lui-mĂȘme - nous choisissons la face 0 si sur une piĂšce asymĂ©trique avec la probabilitĂ© d'un aigle 1n , 1n .
0,1,2,...,kâ1 , 1n k . k , k , 1nâk . k 1n , , k est donnĂ© commekn . Cela signifie que la probabilitĂ© que l'algorithme ne sĂ©lectionne pas l'un des premiers k faces est Ă©gal Ă 1 - kn =nn -kn =n-kn . Autrement dit, la probabilitĂ© de choisir un visage k est donnĂ© commen - kn 1n - k =1n , qui doit ĂȘtre montrĂ©. Ainsi, chaque face de l'os est sĂ©lectionnĂ©e de maniĂšre uniforme et alĂ©atoire.
Bien sĂ»r, l'algorithme est assez inefficace - en utilisant la premiĂšre technique, nous pouvons simuler un lancer de dĂ©s honnĂȘtes dans le temps O ( 1 ) !
Mais cet algorithme peut ĂȘtre utilisĂ© comme tremplin vers un algorithme suffisamment efficace pour simuler un os tricheur Ă l'aide de piĂšces asymĂ©triques.Simulation de l'os de Shuler Ă l'aide de piĂšces asymĂ©triques
L'algorithme présenté ci-dessus est intéressant en ce qu'il nous donne un cadre simple pour simuler un os à l'aide d'un ensemble de piÚces. Nous commençons par lancer une piÚce pour déterminer s'il faut sélectionner la premiÚre facette de l'os ou passer au reste. Dans ce processus, nous devons gérer soigneusement l'échelle des probabilités restantes.Voyons comment vous pouvez utiliser cette technique pour simuler un lancer d'os infidÚle. Nous utilisons notre exemple avec probabilités12 ,
13 ,
112 ,
112 .
Lui, si vous ne vous en souvenez pas, divise l'intervalle [ 0 , 1 ) comme suit:Voyons maintenant comment simuler un tel os de triche à l'aide de piÚces asymétriques. On peut commencer par lancer une piÚce avec la probabilité d'un aigle12 pour déterminer si nous devons retourner face 0. Si un aigle tombe sur cette piÚce, alors trÚs bien! Nous avons terminé. Sinon, nous devons lancer une autre piÚce pour décider de sélectionner la prochaine facette. Comme précédemment, malgré le fait que la prochaine facette a une probabilité de choix13 , nous ne voulons pas lancer une piÚce sur laquelle l'aigle tombe avec probabilité13 , car la moitié de la «masse» des probabilités a été rejetée lorsque nous n'avons pas sélectionné de ligne avec12 .
En fait, puisque la moitié de la masse des probabilités a disparu, alors si nous normalisons les probabilités restantes, nous obtiendrons des probabilités mises à jour: 23 ,
16 ,
16 .
Par consĂ©quent, la deuxiĂšme piĂšce doit ĂȘtre lancĂ©e avec probabilitĂ© 23 .
Si cette piÚce est également à queue, nous devons choisir entre deux faces 112 .
Puisqu'à ce stade nous allons nous débarrasser de 56 masses de probabilités, alors nous pouvons normaliser à nouveau les probabilités des parties112 pour que chacun ait sa chance12 gouttes d'aigle, c'est-à -dire que la troisiÚme piÚce aura une probabilité12 .
La derniÚre piÚce, si jamais elle lui vient, devrait jeter l'aigle avec probabilité 1 puisqu'il s'agit du domaine le plus récent.Pour résumer, les probabilités des piÚces seront les suivantes:- Premier lancer: 12
- DeuxiĂšme rouleau: 23
- TroisiĂšme rouleau: 12
- QuatriĂšme rouleau: 1
Il peut ĂȘtre intuitif d'oĂč viennent ces nombres, mais pour transformer la sĂ©lection en algorithme, nous devons crĂ©er une construction formelle du choix des probabilitĂ©s. L'idĂ©e sera la suivante - Ă chaque Ă©tape, nous nous souvenons du reste de la masse des probabilitĂ©s. Au dĂ©but, avant que la premiĂšre piĂšce ne soit lancĂ©e, elle est Ă©gale Ă 1 .
AprÚs avoir lancé la premiÚre piÚce 1 - p 0 .
AprÚs avoir lancé une deuxiÚme piÚce 1 - p 0 - p 1 .
Plus gĂ©nĂ©ralement aprĂšs le lancer k le reste de la masse de probabilitĂ© est1 - â k - 1 i = 0 p i .
Chaque fois que nous lançons une piĂšce pour dĂ©terminer s'il faut ou non sĂ©lectionner une zone k , par consĂ©quent, nous jetons une piĂšce, la probabilitĂ© qu'un aigle tombe sur laquelle est Ă©gale Ă la fraction de la probabilitĂ© restante occupĂ©e par la probabilitĂ©p k , qui est dĂ©fini commep k1 - â k - 1 i = 0 p i .
Cela nous donne l'algorithme suivant pour tricher la simulation osseuse avec un ensemble de piÚces asymétriques (nous prouverons son exactitude et sa durée d'exécution juste ci-dessous):Algorithme: os Schuler de piÚces asymétriques
- Initialisation :
- Nous gardons des probabilités p i pour une utilisation future.
- Génération :
ensemblem a s s = 1
Pouri = 0 Ă n - 1 :
- Lancez une piÚce asymétrique avec la probabilité d'un aigle p im a s s .
- Si l'aigle tombe, revenez je .
- Sinon, nous définissons m a s s = m a s s - p i
D'un point de vue intuitif, c'est logique, mais est-ce mathématiquement vrai? Heureusement, la réponse est oui grùce à une généralisation de la preuve ci-dessus:ThéorÚme: l'algorithme montré ci-dessus renvoie un visagei avec probabilitép i pour tout sélectionnéje .
Preuve: considérer toute constanten ℠0 . , n pi .
, 0 p0 . 0 , , p0mass . mass 1 , p01=p0 , 0 p0 , .
, 0,1,...,kâ1 p0,p1,...,pkâ1 k . k , k , pkmass . k , , k âkâ1i=0pi . , k 1ââkâ1i=0pi . , k , pkmass k , m a s s = 1 - â k - 1 i = 0 p i . Cela signifie que la probabilitĂ© globale de choisir un visage k est donnĂ© comme( 1 - â k - 1 i = 0 p i ) p k1 - â k - 1 i = 0 p i =pk, selon les besoins.
Ăvaluons maintenant la complexitĂ© temporelle de cet algorithme. Nous savons que le temps d'initialisation peut ĂȘtreÎ ( 1 ) si nous conservons une copie de surface du tableau de probabilitĂ© d'entrĂ©e, mais il peut y avoirÎ ( n ) afin que nous puissions enregistrer notre propre version du tableau (au cas oĂč la fonction appelante voudrait la changer plus tard). La gĂ©nĂ©ration mĂȘme d'un rĂ©sultat de projection osseuse peut nĂ©cessiter dans le pire des casÎ ( n ) lancers, et un seul lancer au mieux.Cependant, aprĂšs rĂ©flexion, il devient clair que le nombre de lancers de piĂšces nĂ©cessaires est fortement influencĂ© par la distribution entrante. Dans le meilleur des cas, nous aurons une distribution de probabilitĂ© dans laquelle toute la masse des probabilitĂ©s est concentrĂ©e sur le premier bord de l'os, et toutes les autres probabilitĂ©s sont nulles. Dans ce cas, un tirage au sort nous suffit. Dans le pire des cas, la masse entiĂšre des probabilitĂ©s est concentrĂ©e dans la toute derniĂšre facette de l'os, et sur toutes les autres faces, elle est Ă©gale Ă zĂ©ro. Dans ce cas, nous devons jetern .
.
X , .
P[X=1] , ,
P[X=2] â , , ..
X ,
E[X] . ,
E[X]=nâi=1iâ
P[X=i]
P[X=i] ? - .
0 , .
1 , â ,
0 , ,
1 . ,
i ,
i+1 :
i , ,
iâ1 , , ,
i . ,
i pi , ,
E[X]=nâi=1iâ
P[X=i]=nâi=1iâ
piâ1=nâi=1((iâ1)piâ1+piâ1)=nâi=1((iâ1)piâ1)+nâi=1piâ1
Notez que dans la derniÚre simplification, le premier terme est équivalent
sumnâ1i=0i cdotpi ce qui est Ă©quivalent
mathbbE[p] , le rĂ©sultat attendu d'un lancer de dĂ©s! De plus, le deuxiĂšme terme est Ă©gal Ă
1 car c'est la somme de toutes les probabilités. Cela signifie que
mathbbE[X]= mathbbE[p]+1 . Autrement dit, le nombre attendu de lancers de piÚces est égal à un plus l'attente mathématique d'un lancer de dé!
Algorithme | Temps d'initialisation | Temps de génération | Mémoire occupée |
---|
| Le meilleur | Le pire | Le meilleur | Le pire | Le meilleur | Le pire |
---|
HonnĂȘtetĂ© os sharler bone | Theta(n) | O( prodni=0di) | ThĂȘta(1) | Theta(n) | O( prodni=0di) |
Os Schuler de piĂšces asymĂ©triques | Theta(n) | ThĂȘta(1) | Theta(n) | Theta(n) |
Généraliser les piÚces asymétriques: simuler un os tricheur
Dans l'exemple ci-dessus, nous avons pu simuler efficacement une piĂšce asymĂ©trique, car nous n'avions Ă prendre en compte qu'un seul point de partage. Comment gĂ©nĂ©raliser efficacement cette idĂ©e Ă un os de triche dans lequel le nombre de visages peut ĂȘtre arbitraire?
Comme vous pouvez le voir, une piÚce asymétrique est un os de triche, avec seulement deux faces. Par conséquent, nous pouvons percevoir une piÚce asymétrique simplement comme un cas particulier d'un problÚme plus général que nous voulons résoudre. Lors de la résolution du problÚme des piÚces asymétriques, nous divisons l'intervalle
[0,1) en deux zones - une pour l'aigle, la seconde pour la queue - puis pour trouver la zone, nous utilisons le fait qu'il n'y a qu'un seul point de partage. Si nous avons un os à n faces, alors il y aura plus de zones, et donc plusieurs points de division. Supposons, par exemple, que nous ayons un os à sept cÎtés avec des probabilités
frac14 ,
frac15 ,
frac18 ,
frac18 ,
frac110 ,
frac110 ,
frac110 . Si nous voulons diviser l'intervalle
[0,1) en sept parties, nous procédons comme suit:
Remarquez oĂč se trouvent ces zones. Le premier domaine commence par
0 et se termine
frac14 . Le deuxiĂšme domaine commence par
frac14 et se termine par
frac14+ frac15= frac920 . Plus généralement, si les probabilités sont égales
p0,p1,...,pnâ1 , alors les zones seront des intervalles
[0,p0) ,
[p0,p0+p1) ,
[p0+p1,p0+p1+p2) etc. C'est le domaine
i limité par intervalle
[ sumiâ1j=0pj, sumij=0pj)
Notez que la différence entre ces deux valeurs est
pi c'est-à -dire que la superficie totale de la région est
pi au besoin.
Maintenant, nous savons oĂč se trouvent les zones. Si nous voulons choisir une valeur alĂ©atoire uniformĂ©ment distribuĂ©e
x dans la gamme
[0,1) , alors comment déterminer dans quel intervalle tombe-t-il? Si nous utilisons l'algorithme de piÚce asymétrique comme point de départ, l'idée sera la suivante: en partant du point final de la premiÚre région, remontez constamment dans toutes les zones jusqu'à ce que nous trouvions un point final dont la valeur est supérieure à la valeur
x . Si nous faisons cela, nous trouverons la premiÚre région contenant le point
x , et donc notre valeur. Par exemple, si nous avons choisi une valeur aléatoire
x= frac2740 , puis effectuez la recherche suivante:
D'oĂč nous pouvons conclure que la facette 3 est tombĂ©e sur des dĂ©s avec indexation Ă partir de zĂ©ro.
Un tel algorithme de balayage linéaire nous donnera un algorithme de temps
O(n) pour trouver le bord Ă©jectĂ© de l'os. Cependant, nous pouvons amĂ©liorer considĂ©rablement son temps d'exĂ©cution en utilisant l'observation suivante: une sĂ©rie de points d'extrĂ©mitĂ© de rĂ©gions forme une sĂ©quence croissante (puisque nous ajoutons toujours de plus en plus de probabilitĂ©s, dont aucune ne peut ĂȘtre infĂ©rieure Ă zĂ©ro). Par consĂ©quent, nous voulons rĂ©pondre Ă la question suivante: ayant une sĂ©quence croissante de valeurs et un certain point de contrĂŽle, nous devons trouver la premiĂšre valeur de l'intervalle strictement supĂ©rieure au point de contrĂŽle. C'est le moment idĂ©al pour utiliser
la recherche binaire ! Par exemple, voici une recherche binaire sur le tableau ci-dessus pour trouver la zone Ă laquelle il appartient
x= frac3940 :
Cela nous donne un algorithme au fil du temps.
Theta( logn) pour lier une valeur aléatoire uniformément distribuée dans l'intervalle
[0,1) au bord d'un os abandonné. De plus, le temps de prétraitement est suffisant pour construire la table des points de terminaison
Theta(n) ; nous calculons simplement des sommes partielles de probabilités à mesure que nous progressons.
Cet algorithme est parfois appelé algorithme de
sélection de la
roulette car il sĂ©lectionne une zone alĂ©atoire en utilisant une technique similaire Ă une roulette - lancer une balle dans un intervalle et observer oĂč elle s'arrĂȘte. En pseudo-code, l'algorithme ressemble Ă ceci:
Algorithme: sélection de la roulette
- Initialisation :
- Sélectionnez un tableau A la taille n
- Nous mettons A[0]=p0 .
- Pour chaque probabilitĂ© i de 1 avant nâ1 :
- Nous mettons A[i]=A[iâ1]+pi
- Génération :
- Générer une valeur aléatoire uniformément distribuée x dans la gamme [0,1)
- En utilisant une recherche binaire, nous trouvons l'index i le plus petit élément A ce qui est moins x .
- Retour i .
La comparaison entre cet algorithme et celui donné précédemment semble assez impressionnante:
Algorithme | Temps d'initialisation | Temps de génération | Mémoire occupée |
---|
| Le meilleur | Le pire | Le meilleur | Le pire | Le meilleur | Le pire |
---|
HonnĂȘtetĂ© os sharler bone | Theta(n) | O( prodni=0di) | ThĂȘta(1) | Theta(n) | O( prodni=0di) |
Os Schuler de piĂšces asymĂ©triques | Theta(n) | ThĂȘta(1) | Theta(n) | Theta(n) |
Sélection de roue de roulette | Theta(n) | Theta( logn) | Theta(n) |
De toute évidence, nous avons maintenant un algorithme bien meilleur que celui d'origine. La discrétion de la probabilité ne semblait que prometteuse au début, mais cette nouvelle approche, basée sur la valeur continue et la recherche binaire, semble bien meilleure. Cependant, il est toujours possible d'améliorer ces indicateurs grùce à l'utilisation intelligente d'un ensemble de techniques hybrides, dont nous parlerons ci-dessous.
Un détail intéressant de cet algorithme est que, bien que l'utilisation de la recherche binaire garantisse le pire des cas pour générer des nombres aléatoires
O( logn) , il ne permet pas non plus une recherche plus rapide; c'est-à -dire que le temps de génération sera également égal
Omega( logn) . Peut-il ĂȘtre amĂ©liorĂ©? Il s'avĂšre que vous le pouvez.
Supposons que nous passions d'une recherche binaire sur une liste de probabilités cumulatives à l'utilisation d'un
arbre de recherche binaire . Par exemple, ayant l'ensemble de probabilités donné ci-dessus, nous pouvons construire l'arbre de recherche binaire suivant pour leur distribution cumulative:
Maintenant, si nous voulons simuler un roulement d'os, nous pouvons générer un nombre uniformément distribué dans l'intervalle
[0,1) puis regardez à quel intervalle il se trouve dans cet arbre de recherche binaire (BST). Puisqu'il s'agit d'un arbre de recherche binaire équilibré, le meilleur temps de recherche est
O(1) et le pire
O( logn) .
Cependant, en supposant que nous en savons plus sur la distribution de probabilité, nous pouvons faire beaucoup mieux. Par exemple, supposons que nos probabilités soient égales
frac99100 ,
frac1600 ,
frac1600 ,
frac1600 ,
frac1600 ,
frac1600 ,
frac1600 . Autrement dit, la distribution de probabilitĂ© est extrĂȘmement asymĂ©trique et presque toute la masse des probabilitĂ©s est concentrĂ©e sur une seule face. Nous pouvons construire une BST Ă©quilibrĂ©e pour ces probabilitĂ©s:
Bien que cet arbre de recherche binaire soit parfaitement équilibré, il n'est pas trÚs adapté à nos tùches. Comme nous savons que dans 99 cas sur 100, la valeur aléatoire sera dans la plage
[0, frac99100) , alors il est inutile de stocker le nĆud pour cet intervalle oĂč il se trouve maintenant. En fait, cela signifie que presque tout le temps, nous ferons deux comparaisons inutiles avec les zones bleues et jaunes. Ătant donnĂ© qu'avec une probabilitĂ© trĂšs Ă©levĂ©e, nous devrions ĂȘtre les premiers Ă vĂ©rifier le plus grand intervalle, il serait logique de dĂ©sĂ©quilibrer l'arbre afin de rendre le cas moyen bien meilleur en raison des autres. Ceci est montrĂ© ici:
Maintenant, nous allons probablement terminer la recherche en trouvant immĂ©diatement la zone souhaitĂ©e aprĂšs la premiĂšre tentative. Dans le cas trĂšs improbable oĂč la zone souhaitĂ©e se trouve dans le reste
( frac99100,1] on descend calmement jusqu'au bout de l'arbre qui est en fait bien équilibré.
Dans une forme généralisée, nous voulons résoudre le problÚme suivant:
Ătant donnĂ© un ensemble donnĂ© de probabilitĂ©s, trouvez un arbre de recherche binaire pour ces probabilitĂ©s qui minimise le temps de recherche attendu.
Heureusement, ce problÚme est trÚs bien étudié et est appelé le
problĂšme d'arbre de recherche binaire optimal . Il existe de nombreux algorithmes pour rĂ©soudre ce problĂšme; on sait que la solution exacte peut ĂȘtre trouvĂ©e Ă temps
O(n2) en utilisant
la programmation dynamique , et qu'il existe de bons algorithmes de temps linéaire qui peuvent trouver des solutions approximatives. De plus, pour obtenir un facteur constant de la solution optimale, vous pouvez utiliser la structure de données de l'
arbre d'affichage (arbre en expansion) (arbre de recherche binaire à équilibrage automatique).
Il est intĂ©ressant de noter que le meilleur cas pour le comportement de ces arbres de recherche binaires optimisĂ©s se produit lorsque les distributions de probabilitĂ© sont extrĂȘmement asymĂ©triques, car nous pouvons simplement dĂ©placer les nĆuds contenant la grande majoritĂ© de la masse de probabilitĂ© vers la racine de l'arbre, et le pire est lorsque la distribution est Ă©quilibrĂ©e, car alors l'arbre doit ĂȘtre large et peu profond. C'est l'opposĂ© du comportement de l'algorithme prĂ©cĂ©dent, dans lequel un honnĂȘte algorithme a Ă©tĂ© utilisĂ© pour simuler un tricheur!
Dans le meilleur des cas, nous avons un tricheur dans lequel une face tombe toujours (c'est-Ă -dire qu'elle a une probabilitĂ© de 1 et toutes les autres faces ont une probabilitĂ© de 0). C'est une exagĂ©ration extrĂȘme de notre exemple prĂ©cĂ©dent, mais dans ce cas, la recherche se terminera toujours aprĂšs la premiĂšre tentative. Dans le pire des cas, toutes les probabilitĂ©s sont Ă©gales et nous obtenons une recherche BST standard. Nous arrivons Ă ce qui suit:
Algorithme | Temps d'initialisation | Temps de génération | Mémoire occupée |
---|
| Le meilleur | Le pire | Le meilleur | Le pire | Le meilleur | Le pire |
---|
HonnĂȘtetĂ© os sharler bone | Theta(n) | O( prodni=0di) | ThĂȘta(1) | Theta(n) | O( prodni=0di) |
Os Schuler de piĂšces asymĂ©triques | Theta(n) | ThĂȘta(1) | Theta(n) | Theta(n) |
Sélection de roue de roulette | Theta(n) | Theta( logn) | Theta(n) |
SĂ©lection optimale des roues de roulette | O(n2) | ThĂȘta(1) | O( logn) | Theta(n) |
Lancer de fléchettes
Jusqu'Ă prĂ©sent, nous avons envisagĂ© deux primitives qui nous ont aidĂ©s Ă construire des algorithmes pour simuler un os tricheur: l'os honnĂȘte et la piĂšce asymĂ©trique. En utilisant uniquement de l'os honnĂȘte, nous arrivons Ă un algorithme (hĂ©las, peu pratique) pour tricher l'os, et Ă partir de piĂšces asymĂ©triques, nous avons pu inventer un algorithme rapide pour tricher l'os. Ces deux approches peuvent-elles ĂȘtre combinĂ©es pour crĂ©er un algorithme basĂ© sur des os honnĂȘtes et des piĂšces asymĂ©triques? Il s'avĂšre que oui, et en fait, l'algorithme rĂ©sultant est meilleur que ces deux approches.
Jusqu'à ce moment, nous avons visualisé l'intervalle
[0,1) et les probabilités des faces osseuses comme intervalle unidimensionnel. Ces deux algorithmes sélectionnent un point dans l'intervalle
[0,1) et posez-le sur un segment de ligne droite, dont la longueur correspond à une sorte de probabilité. Plus les segments que nous créons sont longs, plus la probabilité de choisir ce segment est grande. Mais que faire si vous essayez de penser non pas en une, mais en deux dimensions? Et si nous prenons la probabilité
pi pas la longueur d'un segment de ligne droite, mais l'aire d'un rectangle?
Commençons par revenir à notre exemple précédent avec probabilités
frac12 ,
frac13 ,
frac112 ,
frac112 . Nous représentons ces probabilités sous forme de rectangles de largeur
w (avec quelques arbitraires
w>0 ) et hauteur
pi (ainsi, l'aire du rectangle sera Ă©gale Ă
w cdotpi ):
Notez que l'aire totale de ces rectangles est
w depuis la zone
sumnâ1i=0wpi=w sumnâ1i=0pi=w
Supposons maintenant que nous dessinons un rectangle englobant autour de ces rectangles dont la largeur est
4w (car il y a quatre quadrangles), et la hauteur est
frac12 (puisque le rectangle le plus haut a une hauteur
frac12 ):
Nous pouvons imaginer que ce rectangle est divisĂ© en cinq zones - quatre zones correspondent Ă des probabilitĂ©s diffĂ©rentes et une zone indique un espace inutilisĂ©. En prenant cette pause, nous pouvons considĂ©rer l'algorithme de simulation de lancer de dĂ©s alĂ©atoire comme un jeu de flĂ©chettes. Supposons que nous lançons une flĂ©chette (parfaitement uniformĂ©ment rĂ©partie) sur cette cible. Si elle tombe dans l'espace inutilisĂ©, nous sortons la flĂ©chette et la jetons Ă nouveau, en rĂ©pĂ©tant le processus jusqu'Ă ce que nous entrions dans l'un des rectangles. Ătant donnĂ© que plus la probabilitĂ© est grande, plus le rectangle est grand, plus la probabilitĂ© de lancer le bord de l'os est grande, plus la probabilitĂ© de tomber dans son rectangle est Ă©levĂ©e. En fait, si nous fixons la condition que nous sommes dĂ©jĂ tombĂ©s dans
une sorte de rectangle, nous obtenons ce qui suit:
mathbbP[ mboxafrappélerectanglepourlecÎtéi| mboxfrapperunrectangle]= frac mboxairederectanglepouri mboxairetotalederectangle= fracwpiw=pi
En d'autres termes, lorsque nous tombons finalement dans une sorte de rectangle avec notre fléchette uniformément répartie, nous sélectionnons le rectangle de face
i os tricheur avec probabilité
pi , c'est-à -dire avec la probabilité dont nous avons besoin! Autrement dit, si nous pouvons trouver un moyen efficace de simuler le lancement de fléchettes aléatoires sur ce rectangle, alors nous aurons un moyen efficace de simuler le lancement d'un dé aléatoire.
Une façon de simuler des lancers de fléchettes sur ce rectangle consiste à sélectionner deux valeurs uniformément réparties dans l'intervalle
[0,1) les mettre Ă l'Ă©chelle Ă la largeur et Ă la hauteur appropriĂ©es, puis vĂ©rifier la zone sous la flĂ©chette. Cependant, cela pose le mĂȘme problĂšme que nous avions lorsque nous avons essayĂ© de dĂ©terminer la rĂ©gion unidimensionnelle dans laquelle se trouve la valeur alĂ©atoire. Cependant, il existe une sĂ©rie d'observations vraiment merveilleuses, grĂące Ă laquelle dĂ©terminer le lieu de l'impact peut ĂȘtre une tĂąche simple, sinon triviale.
PremiĂšre observation: nous avons montrĂ© que la largeur de ces rectangles peut ĂȘtre choisie arbitrairement, car tous ont une largeur Ă©gale. Les hauteurs, bien sĂ»r, dĂ©pendent des probabilitĂ©s des faces des os. Cependant, si nous mettons Ă l'Ă©chelle uniformĂ©ment toutes les hauteurs par un certain nombre rĂ©el positif
h , alors les zones relatives de tous les rectangles seront les mĂȘmes. En fait, pour tout nombre rĂ©el positif
h surface totale de tous les rectangles aprÚs avoir mis leur hauteur à l'échelle
h calculé comme
sumnâ1i=0whpi=wh sumnâ1i=0pi=wh
Nous allons maintenant considĂ©rer la probabilitĂ© de choisir un rectangle individuel, en nous limitant Ă la condition que nous frappions dĂ©finitivement une sorte de rectangle. En utilisant les mĂȘmes calculs, nous obtenons ce qui suit:
mathbbP[ mboxafrappélerectanglepourlecÎtéi| mboxfrapperunrectangle]= frac mboxairederectanglepouri mboxairetotalederectangle= fracwhpiwh=pi
Autrement dit, la probabilité de choisir un seul rectangle ne change pas si nous les mettons à l'échelle de façon linéaire et uniforme.
Puisque nous pouvons choisir n'importe quel facteur d'Ă©chelle appropriĂ©, pourquoi ne pas mettre Ă l'Ă©chelle ces rectangles de sorte que la hauteur du cadre de sĂ©lection soit toujours 1? Ătant donnĂ© que la hauteur du cadre de sĂ©lection est dĂ©terminĂ©e par la valeur maximale
pi probabilités d'entrée, alors nous pouvons commencer par mettre à l'échelle chacun des rectangles par un facteur
frac1pmax oĂč
pmax Est la probabilitĂ© maximale de toutes les probabilitĂ©s d'entrĂ©e. GrĂące Ă cela, nous obtenons la hauteur du rectangle 1. De mĂȘme, comme nous pouvons choisir n'importe quelle largeur arbitraire pour les rectangles, prenons la largeur 1. Cela signifie que pour
n les probabilités de la largeur totale du cadre de délimitation sont
n , et la hauteur totale est 1. Ceci est illustré dans la figure:
Nous sommes maintenant prĂȘts Ă rĂ©flĂ©chir Ă la façon de lancer une flĂ©chette alĂ©atoire dans un rectangle et de dĂ©terminer dans quoi elle est tombĂ©e. La chose la plus importante est que nous pouvons diviser le rectangle afin qu'il ne soit pas composĂ© de plusieurs petits rectangles et d'un espace vide d'une forme Ă©trange. Au lieu de cela, la zone est dĂ©coupĂ©e en un ensemble de
2n rectangles, deux sur chacun
n probabilités d'entrée. Ceci est montré ici:
Remarquez comment ce rectangle se forme. Pour chaque face de l'os du tricheur, nous avons une colonne d'une largeur de 1 et d'une hauteur de 1, divisée en deux espaces - un demi-espace "oui" correspondant à un rectangle de cette taille et un demi-espace "non" correspondant à la partie restante de la colonne.
Voyons maintenant comment lancer une fléchette. Une fléchette parfaitement uniforme jetée dans ce rectangle aura des composants
x et
y . Ici le composant
x qui devrait ĂȘtre dans l'intervalle
[0,1) , correspond à la colonne que la fléchette frappe. Composant
y qui devrait ĂȘtre dans l'intervalle
[0,1) , correspond à la hauteur de notre colonne. Sélection des composants
x affecte la face de l'os tricheur que nous considérons et le choix du composant
y correspond à savoir si nous avons choisi cette facette ou non. Mais attendez - nous connaissons déjà ces deux idées! Sélection de coordonnées
x correspondant Ă la colonne, semblable Ă jeter un os honnĂȘte pour dĂ©cider du choix de la colonne. SĂ©lection de coordonnĂ©es
y correspond au lancer d'une piÚce asymétrique pour déterminer s'il faut sélectionner un visage ou lancer à nouveau! Cette observation est si importante que nous la rendons absolument compréhensible:
Le choix d'un point alĂ©atoire dans cet intervalle revient Ă lancer un os honnĂȘte et Ă lancer une piĂšce asymĂ©trique.
En fait, ce rĂ©sultat peut ĂȘtre perçu comme une opportunitĂ© beaucoup plus puissante. Pour simuler un os tricheur, nous construisons un ensemble de piĂšces asymĂ©triques, une pour chaque face de l'os, puis roulons un os honnĂȘte pour dĂ©terminer quelle piĂšce lancer. Sur la base du roulement de l'os, si un aigle tombe sur la piĂšce correspondante, nous sĂ©lectionnons la face correspondante, et si les queues tombent, jetons Ă nouveau l'os et rĂ©pĂ©tons le processus.
. -, â «»
pipmax , «»
pmaxâpipmax . , 1. -,
1 , . , : - , , ( , ). . , , . .
: /
- :
- pi ; pmax .
- Coins n , «» .
- i de 0 avant nâ1 :
- Coins[i]=pipmax
- :
- :
- n- i [0,n) .
- , Coins[i] .
- , i .
.
O(n) ,
O(n) Coins ,
O(n) . ,
O(1) . ? , , - . , . , (
1n ), . , , , , - , . ,
i pipmax , -
nâ1âi=0(1npipmax)=1nnâ1âi=0pipmax=1nâ
pmaxnâ1âi=0pi=1nâ
pmax
- , , , , ,
nâ
pmax . ?
pmax .
pmax 1 ( ).
n ,
n . , , , , . ,
pmax 1n , , . Si
pmax=1n , 1. . Si
pmax=1n , (
1n ), 1, , 1. , , .
,
pmax , , , . , ,
n , , 1. , , «»
1pmax , 1,
1pmax . , «»
1nâ
pmax . , , «»,
pmax . , , .
:
Algorithme | | | |
---|
| | | | | | |
---|
| Î(n) | O(âni=0di) | Î(1) | Î(n) | O(âni=0di) |
| Î(n) | Î(1) | Î(n) | Î(n) |
| Î(n) | Î(logn) | Î(n) |
| O(n2) | Î(1) | O(logn) | Î(n) |
/ | Î(n) | Î(1) | Î(n) () | Î(n) |
, . . ?
Alias-
, . , . , , «» , . , , , . - , , - , .
, , ,
. .
12 ,
13 ,
112 ,
112 . ,
14 . ,
14 ,
12 ? , .
1 , :
,
14 1. , , :
1Ă4 . , :
, ,
12 et
13 . ? ,
12 112 ? , - , :
, , . ,
12 et
13 , .
12 , . , :
, , :
. -, . , ; . , , . -, , , - , , . , . â ,
. , â , , . , . , , , - ( ).
alias- . -, , . , , . , , , .
, , ? , , . , , , , , . , . , - , , , ( ) , - .
(alias) , «» - . - «alias» «alias-».
, , . - ( !), () , , alias- :
Prob alias Alias .
n . , alias , ( ). , . - -
i .
Prob[i] . , ,
i , ,
Alias[i] . alias :
Alias
,
Alias et
Prob . , , :
, , . ,
12 ,
13 ,
112 ,
112 . (
k=n=4 ),
1=44 . , alias, , . , 4, :
, , (
13 ,
13 ) 1. , - . ( ) :
- . , , , 1 (
2 et
43 ). ;
43 .
43 , ;
23 de
43 , :
, . ,
3 , , , . , . , ,
1 , (,
23 ) :
, - , 1, . (
2 ),
13 de
2 :
, . , - , 1 (
13 ), :
-
1 , . â
53 :
, 1. , :
! .
, :
- - , 1, , Prob .
- - , 1, , Alias , .
, ? «», ? , . : , 1 (
1n ,
n ). , , , , 1 ( ) 1 ( ). , . , ? , . , , . , .
:
: k h0 , h1 , ..., hkâ1 , , âkâ1i=0hi=k , k , 1, , , i - i - .
: . , k=1 , 1. 0 - . , 1, , 0 - 0 - .
, - , , ..., , , . , , , , - (, ), , . , , avec ; , . , , . , - , , . , ( ), , . , , ( ) . , et .
. dans - ( , et ). . , , , . , , . , , dans , . , , , , . .
, , alias, , . alias.
Alias
, alias-. 1 1, :
: Alias-
- :
- sur .
- et , .
- For :
- , .
- ( ),
- .
- .
- .
- .
- , 1.
- .
- :
- - ; .
- , .
- , .
- .
, ,
. . -,
,
.
,
, .
. , :
alias- , . - (,
), .
. ,
. .
et
, .
,
. :
: Alias-
- :
- et , .
- .
- dans .
- For :
- ; .
- ; .
- .
- .
- .
- Ă .
- , 1.
- .
- :
- - ; .
- , .
- , .
- .
.
et
-
, BST
.
,
.
:
Algorithme | | | |
---|
| | | | | | |
---|
| | | | | |
| | | | |
| | | |
| | | | |
/ | | | () | |
Alias- | | | |
Alias- | | | |
, . , , , alias-.
«A Linear Algorithm For Generating Random Numbers With a Given Distribution» , alias-.
: 1, 1. . «» , «» «». :
, , , . , :
: () Alias-
: . .
- :
- et , .
- , et .
- .
- :
- Si , Ă .
- ( ) Ă .
- :
- ; .
- ; .
- .
- .
- .
- Si , dans .
- ($p_g \ge 1$) dans .
- :
- ; .
- .
- :
- - ; .
- , .
- , .
- .
(, ) : -
, . .
(
, , ).
1,
,
1, . 1, , , 1.
. , , , . .
, .
,
,
,
,
,
,
. , ,
,
,
,
,
,
,
. :
, :
( ) .
,
:
.
,
:
:
, , , . , :
, :
, , :
,
, .
alias .
, . , , IEEE-754 double, . , , :
- , , . , , , , , ( , ).
- , , . , , , .
,
. , ,
,
.
, . , , ,
. -, ,
, ,
. , . :
: Alias-
- :
- et , .
- , et .
- .
- :
- Si , dans .
- ( ) dans .
- et : ( )
- ; .
- ; .
- .
- .
- . ( . )
- Si , dans .
- ( ) dans .
- :
- ; .
- .
- : - .
- ; .
- .
- :
- - ; .
- , .
- , .
- .
, â .
, .
, , .
, () , .
,
et
.
, ( ) :
Algorithme | | | |
---|
| | | | | | |
---|
| | | | | |
| | | | |
| | | |
| | | | |
/ | | | () | |
Alias- | | | |
Alias- | | | |
Alias- | | | |
Ouah! ! , . , (alias- ) , - .
alias- , , - ,
alias- Java ,
.
, !