Estoy buscando implementar un sistema basado en el azar que esté sesgado por un evento anterior.
Antecedentes: Hace algunos años, recuerdo una actualización para World of Warcraft que anunciaba que implementaron una nueva calculadora de probabilidad que contrarrestaría las cadenas de eventos puntiagudos. (por ejemplo, realizar golpes críticos o esquivar varias veces seguidas). La idea era que en el caso de que esquivaras un golpe, la posibilidad de que esquivaras el siguiente golpe disminuiría, pero funcionaría en ambos sentidos. No esquivar un golpe aumentaría igualmente la posibilidad de esquivar el siguiente golpe. El truco principal aquí, fue que durante varias pruebas, la posibilidad de esquivar aún correspondería al porcentaje dado al jugador en su hoja de estadísticas.
Este tipo de sistema me intrigó mucho en ese momento, y ahora estoy en la situación de necesitar tal solución.
Aquí están mis problemas:
- Supongo que podría encontrar recursos en línea para implementar dicho sistema, pero es posible que me falten las palabras de moda relevantes para encontrarlo.
- También necesito este enfoque para ajustar un sistema que no sea binomial (es decir, dos resultados), sino que contenga 4 eventos mutuamente excluyentes.
Mi enfoque actual es similar al de un sistema de boletos de rifa. Cuando ocurre un evento, cambio los pesos a favor de todos los demás eventos. Esto podría funcionar si los cuatro eventos fueran igualmente probables, pero en mi caso, las necesidades deben ser mucho más frecuentes. Pero a medida que el evento frecuente ocurre con más frecuencia, cambia los pesos del otro mucho más de lo previsto y parece que no puedo encontrar los números para los cambios de peso que se necesitan para mantener el recuento promedio de boletos alrededor de los valores iniciales del evento. dado.
Unos pocos indicadores de dirección o un ejemplo claro serían muy apreciados.
Respuestas:
Básicamente, lo que está pidiendo es un generador de eventos "semi-aleatorio" que genere eventos con las siguientes propiedades:
La tasa promedio a la que ocurre cada evento se especifica de antemano.
Es menos probable que ocurra el mismo evento dos veces seguidas de lo que sería al azar.
Los eventos no son completamente predecibles.
Una forma de hacerlo es implementar primero un generador de eventos no aleatorio que satisfaga los objetivos 1 y 2, y luego agregar algo de aleatoriedad para satisfacer el objetivo 3.
Para el generador de eventos no aleatorio, podemos usar un algoritmo de interpolación simple . Específicamente, sea p 1 , p 2 , ..., p n las probabilidades relativas de los eventos 1 a n , y sea s = p 1 + p 2 + ... + p n la suma de los pesos. Luego podemos generar una secuencia no aleatoria de eventos con la máxima equidistribución utilizando el siguiente algoritmo:
Inicialmente, sea e 1 = e 2 = ... = e n = 0.
Para generar un evento, incremente cada e i por p i , y genere el evento k para el cual e k es más grande (rompiendo los lazos de la forma que desee).
Disminuya e k por s , y repita desde el paso 2.
Por ejemplo, dados tres eventos A, B y C, con p A = 5, p B = 4 y p C = 1, este algoritmo genera algo así como la siguiente secuencia de salidas:
Observe cómo esta secuencia de 30 eventos contiene exactamente 15 As, 12 Bs y 3 Cs. No es bastante óptima distribuye - hay algunas ocurrencias de dos como en una fila, que podría haber sido evitado - pero se acerca.
Ahora, para agregar aleatoriedad a esta secuencia, tiene varias opciones (no necesariamente mutuamente excluyentes):
Puede seguir los consejos de Philipp y mantener un "mazo" de N próximos eventos, para un número N de tamaño apropiado . Cada vez que necesita generar un evento, elige un evento aleatorio del mazo y luego lo reemplaza con el siguiente evento de salida por el algoritmo de difuminado anterior.
Aplicando esto al ejemplo anterior, con N = 3, produce, por ejemplo:
mientras que N = 10 produce el aspecto más aleatorio:
Tenga en cuenta cómo los eventos comunes A y B terminan con muchas más carreras debido a la combinación, mientras que los eventos C raros todavía están bastante bien espaciados.
Puede inyectar algo de aleatoriedad directamente en el algoritmo de interpolación. Por ejemplo, en lugar de incrementar e i por p i en el paso 2, podría incrementarlo por p i × random (0, 2), donde random ( a , b ) es un número aleatorio distribuido uniformemente entre a y b ; esto produciría resultados como los siguientes:
o podría incrementar e i por p i + random (- c , c ), lo que produciría (para c = 0.1 × s ):
o, para c = 0.5 × s :
Observe cómo el esquema aditivo tiene un efecto de aleatorización mucho más fuerte para los eventos raros C que para los eventos comunes A y B, en comparación con el multiplicativo; esto puede o no ser deseable. Por supuesto, también podría usar alguna combinación de estos esquemas, o cualquier otro ajuste a los incrementos, siempre que conserve la propiedad de que el incremento promedio de e i es igual a p i .
Alternativamente, podría perturbar la salida del algoritmo de interpolación reemplazando a veces el evento k elegido por uno aleatorio (elegido de acuerdo con los pesos brutos p i ). Siempre y cuando también use la misma k en el paso 3 que la salida en el paso 2, el proceso de interpolación aún tenderá a igualar las fluctuaciones aleatorias.
Por ejemplo, aquí hay algunos resultados de ejemplo, con un 10% de posibilidades de que cada evento sea elegido al azar:
y aquí hay un ejemplo con un 50% de posibilidades de que cada salida sea aleatoria:
También podría considerar alimentar una mezcla de eventos puramente aleatorios y difusos en una plataforma / grupo de mezcla, como se describió anteriormente, o tal vez aleatorizar el algoritmo de interpolación eligiendo k aleatoriamente, según lo ponderado por los e i s (tratando los pesos negativos como cero).
PD. Aquí hay algunas secuencias de eventos completamente al azar, con las mismas tasas promedio, para comparar:
Tangente: Dado que en los comentarios se ha debatido si es necesario, para las soluciones basadas en plataformas, permitir que la plataforma se vacíe antes de que se vuelva a llenar, decidí hacer una comparación gráfica de varias estrategias de relleno de plataformas:
Trama de varias estrategias para generar lanzamientos de monedas semialeatorios (con una proporción de 50:50 de cara a cruz en promedio). El eje horizontal es el número de vueltas, el eje vertical es la distancia acumulativa de la relación esperada, medida como (caras - colas) / 2 = caras - vueltas / 2.
Las líneas rojas y verdes en la gráfica muestran dos algoritmos no basados en mazos para comparación:
Las otras tres líneas (azul, morado y cian) muestran los resultados de tres estrategias basadas en mazos, cada una implementada usando un mazo de 40 cartas, que inicialmente se llena con 20 cartas "caras" y 20 cartas "colas":
Por supuesto, la trama anterior es solo una realización única de un proceso aleatorio, pero es razonablemente representativa. En particular, puede ver que todos los procesos basados en mazos tienen un sesgo limitado y se mantienen bastante cerca de la línea roja (determinista), mientras que la línea verde puramente aleatoria finalmente se desvía.
(De hecho, la desviación de las líneas azul, púrpura y cian lejos de cero está estrictamente limitada por el tamaño de la plataforma: la línea azul nunca puede alejarse más de 10 pasos de cero, la línea púrpura solo puede alejarse 15 pasos de cero , y la línea cian puede desplazarse como máximo 20 pasos desde cero. Por supuesto, en la práctica, cualquiera de las líneas que realmente alcancen su límite es extremadamente improbable, ya que existe una fuerte tendencia a que vuelvan más cerca de cero si se alejan demasiado. apagado.)
De un vistazo, no hay una diferencia obvia entre las diferentes estrategias basadas en mazos (aunque, en promedio, la línea azul se mantiene algo más cerca de la línea roja, y la línea cian se mantiene un poco más lejos), pero una inspección más cercana de la línea azul revela un patrón determinista distinto: cada 40 dibujos (marcados por las líneas verticales grises punteadas), la línea azul se encuentra exactamente con la línea roja en cero. Las líneas moradas y cian no están tan estrictamente restringidas y pueden mantenerse alejadas de cero en cualquier punto.
Para todas las estrategias basadas en mazos, la característica importante que mantiene limitada su variación es el hecho de que, mientras las cartas se sacan del mazo al azar, el mazo se rellena de manera determinista. Si las cartas utilizadas para rellenar el mazo fueran elegidas al azar, todas las estrategias basadas en el mazo serían indistinguibles de la elección aleatoria pura (línea verde).
fuente
No tires dados, reparte cartas.
Tome todos los resultados posibles de su RNG, colóquelos en una lista, revuélvalos aleatoriamente y devuelva los resultados en el orden aleatorio. Cuando esté al final de la lista, repita.
Los resultados aún se distribuirán de manera uniforme, pero los resultados individuales no se repetirán a menos que el último de la lista también sea el primero del siguiente.
Cuando esto sea demasiado predecible para su gusto, puede usar una lista que sea
n
el número de resultados posibles y poner cada resultado posible en ellosn
antes de barajar. O podría reorganizar la lista antes de que se repita por completo.fuente
Puedes probar un gráfico aleatorio de Markov . Considere cada evento que puede ocurrir como un nodo en un gráfico. Desde cada evento, haga un enlace entre sí que posiblemente pueda venir después. Cada uno de estos enlaces está ponderado por algo llamado probabilidad de transición . Luego, realiza una caminata aleatoria del gráfico de acuerdo con el modelo de transición.
Por ejemplo, puede tener un gráfico que represente el resultado de un ataque (golpe crítico, esquivar, etc.). Inicialice el nodo inicial a uno elegido al azar, dadas las estadísticas del jugador (simplemente "tire los dados"). Luego, en el próximo ataque, decida qué sucede después dado el modelo de transición.
Se debe tener cuidado para decidir cómo ponderar las transiciones. Por un lado, todas las transiciones que salen de un nodo deben sumar una probabilidad de 1. Una cosa simple que podría hacer es hacer una transición de cada nodo a cualquier otro nodo, con pesos equivalentes a la probabilidad de que ocurran esos eventos. a priori , dado que el evento actual no puede volver a ocurrir.
Por ejemplo, si tiene tres eventos:
Puede configurar el modelo de transición de modo que un golpe crítico no vuelva a ocurrir simplemente redistribuyendo su masa de probabilidad a los otros eventos de manera uniforme:
EDITAR: como dicen los comentarios a continuación, este modelo no es lo suficientemente complicado como para obtener el comportamiento deseado. En su lugar, es posible que deba agregar varios estados adicionales.
fuente
Aquí hay una implementación que creé en C # que:
He agregado algunos comentarios para que pueda ver lo que estoy haciendo.
Espero que esto ayude, sugiera mejoras a este código en los comentarios, ¡gracias!
fuente
Permítanme generalizar un poco la respuesta de mklingen . Básicamente, desea implementar la Falacia del jugador , aunque le proporcionaré un método más general aquí:
Digamos que hay
n
posibles eventos con probabilidadesp_1, p_2, ..., p_n
. Cuandoi
sucedió el evento , su probabilidad se reescalará con un factor0≤a_i≤1/p_i
(este último es importante, de lo contrario terminará con una probabilidad mayor que uno y los otros eventos deben tener probabilidades negativas , que básicamente significan eventos " anti ". O algo así) normalmentea_i<1
. Podría, por ejemploa_i=p_i
, elegir , lo que significa que la probabilidad de que un evento ocurra por segunda vez es la probabilidad original de que el evento ocurra exactamente dos veces seguidas, por ejemplo, un segundo lanzamiento de moneda tendría una probabilidad de 1/4 en lugar de 1/2. Por otro lado, también puede tener algunosa_i>1
, lo que significaría desencadenar un "golpe de suerte / desgracia".Todos los demás eventos serán igualmente probables entre sí, es decir, todos deben ser reescalados por el mismo factor de
b_i
manera que la suma de todas las probabilidades sea igual a uno, es decirHasta ahora, muy simple. Pero ahora agreguemos otro requisito: considerando todas las secuencias posibles de dos eventos, las probabilidades de evento único extraídas de allí serán las probabilidades originales.
Dejar
denota la probabilidad de que
j
ocurra un evento después del eventoi
y tenga en cuenta que ap_ij≠p_ji
menos queb_i=b_j (2)
(lo que(1)
implicaa_j = 1 - a_i*p_i + (1-a_i)*p_i/p_j
). Esto es también lo que requiere el teorema de Bayes y esto también implicatal como lo desee Solo tenga en cuenta que esto significa que uno
a_i
soluciona todos los demás.Ahora veamos qué sucede cuando aplicamos este procedimiento varias veces, es decir, para secuencias de tres y más eventos. Básicamente, hay dos opciones para elegir las probabilidades amañadas del tercer evento:
a) Olvídate del primer evento y la plataforma como si solo ocurriera el segundo, es decir
Tenga en cuenta que esto generalmente viola Bayes, ya que, por ejemplo,
p_jik≠p_ikj
en la mayoría de los casos.b) Use las probabilidades
p_ij
(para fijasi
) como nuevas probabilidadespi_j
de las que obtiene las nuevas probabilidadespi_jk
para que el eventok
suceda a continuación. Depende de usted modificarloai_j
o no, pero tenga en cuenta que los nuevosbi_j
son definitivamente diferentes debido a los modificadospi_j
. Por otra parte, la elección deai_j
probablemente esté restringida al requerir que todas las permutacionesijk
ocurran con la misma probabilidad. Veamos...y permutaciones cíclicas de los mismos, que deben ser iguales para los casos respectivos.
Me temo que mi continuación de esto tendrá que esperar un tiempo ...
fuente
Creo que la mejor opción es utilizar la selección de elementos ponderados al azar. Hay una aplicación para C # aquí , pero que se puede encontrar con facilidad o hecho para otros idiomas.
La idea sería reducir el peso de una opción cada vez que se selecciona, y aumentarla cada vez que no se elige.
Por ejemplo, si disminuye el peso de la opción seleccionada
NumOptions-1
y aumenta el peso de todas las demás opciones en 1 (teniendo cuidado de eliminar elementos con peso <0 y leerlos cuando se elevan por encima de 0) , cada opción se seleccionará aproximadamente la misma cantidad de veces durante un largo período, pero las opciones elegidas recientemente serán mucho menos propensas a ser elegidas.El problema con el uso de un orden aleatorio, como lo sugieren muchas otras respuestas, es que después de cada opción, pero se ha elegido una, puede predecir con 100% de certeza qué opción se elegirá a continuación. Eso no es muy al azar.
fuente
Mi respuesta es incorrecta, mi prueba fue defectuosa.
Dejo esta respuesta aquí para la discusión y los comentarios que señalan las fallas en este diseño, pero la prueba real fue incorrecta.
fuente
Podrías hacer lo que es esencialmente un filtro. Mantenga un registro de los n eventos pasados. La probabilidad es algún filtro aplicado a esos eventos. El 0 ° filtro es la probabilidad base, si es 0, entonces lo esquivó, si 1 falló. Digamos que la base era del 25%, y el filtro disminuye a la mitad en cada iteración. Su filtro sería entonces:
Siéntase libre de continuar si lo desea. La probabilidad general de este esquema es ligeramente mayor que la probabilidad base de .25. De hecho, la probabilidad, dado el mismo esquema, es (estoy llamando a x la probabilidad real, p es la entrada de probabilidad):
Resolviendo para x, se encuentra la respuesta es
p(1+1/2+1/4+1/8)/(1+p(1/2+1/4+1/8)
, o para nuestro caso dado,x=0.38461538461
. Pero lo que realmente quieres es encontrar p, dada x. Eso resulta ser un problema más difícil. Si asumió un filtro infinito, el problema se convierte enx+x*p=2*p
, op=x/(2-x)
. Entonces, al aumentar su filtro, podría resolver un número p que, en promedio, le dará los mismos resultados, pero a un ritmo que depende de cuánto éxito haya sucedido recientemente.Básicamente, utiliza los valores anteriores para determinar cuál es el umbral de aceptación en esta ronda y toma un valor aleatorio. Luego produzca el siguiente valor aleatorio dado el filtro.
fuente
Al igual que usted se propuso, uno de los enfoques para esto es implementar un azar ponderado. La idea es hacer un generador de números aleatorios (o resultados) donde se puedan modificar los pesos y los resultados.
Aquí hay una implementación de esto en Java.
EDITAR En el caso en que desee ajustar los pesos automáticamente, por ejemplo, aumente la posibilidad de A cuando el resultado fue B. Puede
nextOutcome()
método, por lo que modifica el peso de acuerdo con el resultadosetWeight()
para modificar el peso de acuerdo con el resultado.fuente