Stratos: Punto de Encuentro de Desarrolladores

¡Bienvenido a Stratos!

Acceder

Foros





Calcular array con tiempos aleatorios de llegada

Iniciado por Loover, 31 de Enero de 2008, 08:48:24 PM

« anterior - próximo »

Loover

Buenas, quiero calcular un array que contenta valores que representan la llegada de un cliente a un establecimiento, quiero que los clientes lleguen con una tasa de x clientes por hora.

Ejemplo. Array que muestra la llegada de 6 clientes con una tasa de 4 clientes por hora en los minutos que empiezan desde cero:

0, 19, 38, 61, 77, 99

¿Alguna idea para generar dicho array?
IndieLib Libreria 2.5d utilizando aceleración por hardware para la programación de juegos 2d.
Indie Rover The monkeys are reading!

Martinez

Si lo he entendido bien lo que necesitas es aplicar la teoria de colas (suena raro pero es asi), estoy refrescando la memoria que hace tiempo que me examine. En resumen seria una probabilidad que aumenta cada tiempo, es decir "probabilidad de que llegue un cliente en el minuto 0 es 0.2344" que llege en el minuto tal es....

Lo miro y te cuento.


Otra cosa mas simple es generar un numero aleatorio de 1 a 60 tantas veces como clientes por hora quieras. Por ejemplo array de 2 horas con 4 clientes hora:

1 - 35
2 - 42
3 - 12
4 - 27
5 - 05 + 60=65
.....

Loover

Había pensado en lo segundo, pero habría que ordenarlo. Aparte que así siempre se quedaría todo muy "homogeneo", nunca se daría el caso de que vengan más o menos de 4 clientes en una hora, que podría pasar aunque sea menos probable... además pensaba que habría una fórmula más "automática" :P
IndieLib Libreria 2.5d utilizando aceleración por hardware para la programación de juegos 2d.
Indie Rover The monkeys are reading!

Martinez

Esto es de lo mas simple y menos estadistico:



vector<int> llegadas;

int min_cph=2, max_cph=4;

int nHoras=4, nClientes;

for(int h=0; h<Horas; h++)
{
    nClientes=rand()%(max_cph-min_cph)+min_cph // Un numero entre 2 y 4
   for(int c=0; c<nClientes; c++)
   {
       llegadas.push_back(rand()%60 + h*60); // Numero de 0 a 59 mas la hora
   }
}

// y ahora a ordenar!!!

bool cambio=false;
do
{
  cambio=false;
   for(int i=0; i<llegadas.size()-1; i++)
   {
         if(llegadas[i]>llegadas[i+1])
         {
              int aux=llegadas[i];
              llegadas[i]=aux;
              llegadas[i+1]=aux;
              cambio=true;
         }
    }
}while(cambio);





Puede que haya errores xq no le he probado. El numero de clientes por hora es aleatorio con un minimo y un maximo.

davur

Como ha dicho Martinez, la teoría de colas proporciona el tratamiento formal de estos temas.

Para modelar tu problema pueden ser útiles los procesos markovianos, y en particular el proceso de Poisson.

ethernet

qué recuerdos de cuando estudiaba, aún recuerdo aquello de la distribución de poisson. Mi aportación en python

from random import random;
N_PER_HOUR = 4.0;
inv = N_PER_HOUR/60.0;
N_HOURS = 100;
min = [x for x in range(N_HOURS*60) if random() < inv];

media_cl = float(len(min))/N_HOURS;
print ("media clientes por hora: %f" % media_cl)
dist = [min[d+1] - min[d]  for d in range(0,len(min)-1)];
media = sum(dist)/(len(min)-1.0);
print ("media entre clientes %f" % (media));

== resultado
media clientes por hora: 4.090000
media entre clientes 14.661765

ethernet

Calculando la varianza en el primer caso me sale muy alta, en torno a la media (como es lógico para una función random uniforme). Para hacerlo un poco más decente se puede usar una campana de gauss para amoldar la varianza:

versión 2 del programa:


from random import random, gauss;
from math import sqrt;
N_PER_HOUR = 4.0;
inv = N_PER_HOUR/60.0;
N_HOURS = 100;

def printData(min):
   media_cl = float(len(min))/N_HOURS;
   print ("media clientes por hora: %f" % media_cl)
   dist = [min[d+1] - min[d]  for d in range(0,len(min)-1)];
   media = sum(dist)/(len(min)-1.0);
   print ("media entre clientes %f" % (media));
   print("varianza: %f" % sqrt((sum(map(lambda x: x*x,[d - media for d in dist]))/len(min))));


min = [x for x in range(N_HOURS*60) if random() < inv];
printData(min);
min = [];
minute = 0;
while(minute < N_HOURS*60):
   min.append(minute);
   minute += gauss(60.0/float(N_PER_HOUR),5.0);

printData(min);


== salida
C:\wrk>clientes.py
media clientes por hora: 3.920000
media entre clientes 15.281330
varianza: 14.627610
media clientes por hora: 4.020000
media entre clientes 14.930669
varianza: 4.845198

Loover

Gracias a todos, aunque sigo sin saber generar el array :D

Martínez, gracias por el código, sin embargo y por lo que comenté antes (no es real), no vale tal que así.

Gracias también a tí, ethernet, aunque no es lo que pedía, sino el código que genere el array en sí, no las medias, varianzas, etc. Por lo que tampoco me vale, aparte que no tengo ni idea de Phyton :D. Pero desempolvaré el libro de estadística a ver si Poisson me resuelve el tema.

Gracias a ti también davur, miraré como he dicho Poisson.

Por aquí van los tiros: http://www.um.es/or/ampliacion/node8.html, mañana me lo miro con calma.
IndieLib Libreria 2.5d utilizando aceleración por hardware para la programación de juegos 2d.
Indie Rover The monkeys are reading!

Pogacha

Generalmente existen otro tipo de restricciones para la generacion de niveles, y antes de que pierdas tiempo buscando la solución analitica la cual tendras que modificar por cada cambio que hagas te conviene la solución bruta.

Esto siempre que quieras crear los niveles por anticipación y guardarlos en un archivo, cosa altamente recomendada si queires asegurar un balance adecuado en el juego.



const int cantidad_de_clientes;
const float tiempo_total = 60.0f * 4.0f;
const int restriccion_de_clientes_por_hora = 4;
const int restriccion_de_clientes_por_media_hora = 2;
const float restriccion_de_separacion_de_clientes = 45.0f;

float tiempos[ cantidad_de_clientes ];

bool Comprobar_Restricciones()
{
 for(int i=0; i<cantidad_de_clientes - restriccion_de_clientes_por_hora-1; i++)
   if(tiempos[i]+60.0f>tiempos[i+restriccion_de_clientes_por_hora+1]) return false;
  ...

  ...
  return true;
}

void calcular()
{
 bool todo_ok = false;

 while(!todo_ok)
 {
        for(int i=0; i<cantidad_de_clientes; ++i)  
                  tiempos[i] = frand(tiempo_total);
        ordenar(tiempos, cantidad_de_clientes);
        todo_ok = comprobar_restricciones();
  }

 Guardar_En_Archivo();
}


De esta manera puedes ir probando los niveles y cuando ves un patron que no te gusta lo agregas a las restricciones, por ejemplo 3 personajes iguales, todos agrupados a la ves y demas.

Saludos

Loover

Hey, gracias por esa otra idea adicional!

En realidad esto no es para el juego (en el juego las peticiones de los clientes van en una línea de tiempos, no por azar), es para una práctica de la universidad, por lo que tiene que ser matemáticamente precisa. Pero vamos creo que he encontrado el método adecuado aquí: http://books.google.com/books?id=3oHztjMSuL8C&pg=PA658&lpg=PA658&dq=utilizaci%C3%B3n+promedio+del+local&source=web&ots=nKyC877OBM&sig=v49m_oyl62t-UkKMnVDDq2KimQw#PPA648,M1

Que describe la siguiente fórmula:
T = -(1/tasa) * ln (1 - R)

Siendo R un número aleatorio entre (0 y 1)

¡Perfect!
IndieLib Libreria 2.5d utilizando aceleración por hardware para la programación de juegos 2d.
Indie Rover The monkeys are reading!

Zaelsius

Cita de: "Loover"es para una práctica de la universidad

¿Y lo dices ahora, eh,  pillín? :D

Si no llegas a ser tú y además lo hubieses dicho en tu mensaje inicial, te hubiesen llovido piedras xDDD

Loover

:P

... también es muy útil para juegos... ¿no? :P
IndieLib Libreria 2.5d utilizando aceleración por hardware para la programación de juegos 2d.
Indie Rover The monkeys are reading!

Pogacha

A mi no me dejabas otra idea que pensar ... es como que yo estuviera haciendo un juego de aviones y vengo a un foro de desarrollo de juegos donde tengo 3 threads abiertos sobre este juego y pregunto
Yo: tengo que simular un misil, como hago?
Respuesta: Y depende del contexto que no lo estas dando, pero suponiendo que por casualidad sea para tu juego, has esto ...
Yo: No en realidad es para fisica I que tengo que rendir la semana que viene.

Yo caí como tonto ... no se que otra interpretación podria haberle dado.
Jajajaj

Martinez

Juas juas yo pensaba que era para el juego!!! XDXD

Pero no me dijiste que lo segundo!! (creo que no llegue a entenderte). Bueno no iba mal encaminado con lo de las teorias de colas, ya que se usan distribuciones exponenciales, entre otras la de Poisson. Me alegro que lo hayas solucionado.

Nos vemos.

ethernet

loover: he puesto la media y varianza para comprobar que el resultado es bueno, los valores de los minutos están en la variable min, que es un array que contiene los minutos en los que llegan los cientes.

En resumen mi código era así:


min = [];
minute = 0;
while(minute < N_HOURS*60):
   min.append(minute);
   minute += gauss(60.0/float(N_PER_HOUR),5.0);


donde min es lo que te he dicho. Está claro que no vale para tu propósito, ya nos contarás como lo resuelves.






Stratos es un servicio gratuito, cuyos costes se cubren en parte con la publicidad.
Por favor, desactiva el bloqueador de anuncios en esta web para ayudar a que siga adelante.
Muchísimas gracias.