Social Icons

twitterfacebookgoogle plusemail

martes, 21 de mayo de 2013

Simulación de red ad-hoc


En esta entrada se creó una simulación de una red ad-hoc que es el tema
de esta semana de redes de la telecomunicación.

En la simulación se tiene en cuenta que se encuentra en un campo en el
que se crea la red se encuentra por default en 800x800 en donde cada
nodo de la red en el que se ingresa tiene una cierta probabilidad de
que a paresca cada tiempo de espera; Se tomaron en cuenta tomar en
lugar de una distribución exponencial, una distribución bernoulli ya
que tiene resultados muy similares a la distribución geoemtrica que es
el mismo resultado obtenido por una distribución exponencial.

Cada nodo tiene una id única que se genera de manera incremental, inician
con una vida de 100 en el que cada retraso se les baja una cantidad de
5 y en caso de que transmitan un mensaje se baja la energía al nodo
tomando en cuenta el tamaño del mensaje y multiplicandoló por un
porcentaje del radio de transmisión.

Los nodos tienen un movimiento en el eje x y y en el cual se crea un
valor aleatorio según la velocidad configurada para que este se
diferencié con cada eje x y y para crear el efecto de movimiento.


Las transmisiones de un nodo a otro se crean cuando un enemigo se
encuentra presente dicho enemigo tiene casi las mismas propiedades que
el nodo con la excepción de que este tiene un radio más chico por
default y otro color que lo distingue de los demás nodos.

Los nodos que transmitan bajarán su batería y una vez que lleguen a 0 este
quedará en una lista negra de nodos por eliminar del campo, de la
misma manera ocurre con los enemigos pero en el caso de ellos estos
tienen una vida de 20 por default y una vez que lleguen a 0 este
quedará en una lista negra de enemigos por eliminar del campo.

Ahora veamos un video de como funciona la simulación con una
configuración que se encuentra por default.



Ahora veamos un video de como funciona la simulación con una probabilidad
de 20% de que a paresca un nodo por tiempo determinado y con una dimensión
de 1000x1000.



Este es el código. 
from random import randint, random
from threading import Thread
from time import sleep
from sys import argv
from math import cos, sin
import pygame
#Metodo que retorna un color en RGB dado un numero
def asignColor(grupo):
return ((grupo * 5 + 7) % 256, (grupo * 13 + 41) % 256, (grupo * 29 + 13) % 256)
#clase del enemigo
class Enemigo:
#En el constructor tomamos como parametro
# coordenadas (x, y), el color, el radio, una id que se genera de manera incremental y una vida
def __init__(self, (x,y), color, radio, id, vida):
self.x = x
self.y = y
self.color = color
self.radio = radio
self.id = id
self.vida = vida
self.visible = True #Nos sirve para determinar si el nodo esta por ser removido
return
#Nos sirve para desplegar el enemigo en el canvas
def display(self):
#tomamos la velocidad configurada
global velocidad
#Cambio en el eje x y y tomando como referencia la velocidad
dx = randint(-velocidad, velocidad+1)
dy = randint(-velocidad, velocidad+1)
#Se aplica la diferencia en las coordenadas para hacer que el enemigo se mueva
self.x +=dx
self.y +=dy
#Dibuja el enemigo
pygame.draw.circle(WIN, self.color, (self.x, self.y), self.radio, 1)
#Dibuja un estatus del enemigo
WIN.blit( pygame.font.SysFont("Arial",10 ).render("ENEMIGO %s VIDA %s"%(self.id, self.vida),True,(0, 0, 0), (255, 255, 255) ), (self.x, self.y))
#Barra de vida
pygame.draw.rect( WIN, (0, 0, 0), ( (self.x, self.y+10), (self.radio *2, self.radio * 0.5) ) )
pygame.draw.rect( WIN, obtenerColorVida(self.vida), ( (self.x, self.y+10), ( ( (self.radio * 2 ) * ( ( self.vida ) * 1.0 / 100) ) , ( self.radio * 0.5 ) ) ) )
return
#clase del nodo
class Nodo:
#En el constructor tomamos como parametro
# coordenadas (x, y), el color, el radio, una id que se genera de manera incremental y una vida
def __init__(self, (x,y), color, radio, id, vida):
self.x = x
self.y = y
self.color = color
self.radio = radio
self.id = id
self.vida = vida
self.mensaje = ''
self.visible = True #Nos sirve para determinar si el nodo esta por ser removido
return
#Metodo que dado una lista de nodos verifica que se encuentren
#dentro del rango de transmision en caso de ser asi les pasa el mensaje
#y se le resta el costo de energia segun su tamanio y radio
def transmite(self, nodos):
for nodo in nodos:
if radioDeTransmision(self.radio, self.x, self.y, (nodo.x, nodo.y) ):
nodo.mensaje = self.mensaje
self.vida -= obtenerCostoEnergia(self.radio, self.mensaje)
return nodos
#Nos sirve para desplegar el nodo en el canvas
def display(self):
#Tomamos la velocidad configurada
global velocidad
#El cambio en el eje x y y por medio de un randint
dx = randint(-velocidad, velocidad+1)
dy = randint(-velocidad, velocidad+1)
#Se obtiene la diferencia para poder hacer que hagan un movimiento
self.x +=dx
self.y +=dy
#Se dibuja el nodo (circulo) dado su radio y color
pygame.draw.circle(WIN, self.color, (self.x, self.y), self.radio, 1)
#Se pinta el estatus del nodo
WIN.blit( pygame.font.SysFont("Arial",10 ).render("ID %s VIDA %s MSG %s "%(self.id, self.vida, self.mensaje),True,(0, 0, 0), (255, 255, 255) ), (self.x, self.y))
#Barra de vida del nodo
pygame.draw.rect( WIN, (0, 0, 0), ( (self.x, self.y+10), (self.radio*0.5, self.radio * 0.1) ) )
pygame.draw.rect( WIN, obtenerColorVida(self.vida), ( (self.x, self.y+10), ( ( (self.radio * 0.5 ) * ( ( self.vida ) * 1.0 / 100) ) , ( self.radio * 0.1 ) ) ) )
return
#Dada una coordenada se verifica que esten dentro de un radio
#en caso de que lo cumple regresa un True en otro caso sera un False
def radioDeTransmision(radio, xc, yc, coordenada):
x, y = coordenada
if ( ( ( x - xc ) ** 2 ) + ( ( y - yc ) ** 2 ) ) < ( radio ** 2 ):
return True
return False
#Segun la cantidad de vida dado nos regresara
#un color determinado en RGB
def obtenerColorVida(vida):
if vida >= 66:
color = ( 0, 255, 0 )
elif vida < 66 and vida > 33:
color = ( 255, 245, 0 )
else:
color = ( 255, 0, 0 )
return color
#Tomando el radio y el largo del mensaje se obtendra
#el costo de transmision
def obtenerCostoEnergia(radio, mensaje):
return ( len(mensaje) * ( radio / 100 ) )
#clase de Simulacion que hereda de la clase Thread
class Simulacion(Thread):
def __init__(self):
Thread.__init__(self)
self.nodos = list()
self.enemigos = list()
self.contador_enemigos = 0
self.contador_nodos = 0
return
def run(self):
#Toma el canvas (WIN), tiempo de retraso, el color de FONDO y la propabilodad de que a paresca un nodo
global WIN, tiempo, FONDO, p, pe
run = True
#Se crea un nodo
self.creaNodo()
#Se despliega el nodo
self.nodos[0].display()
#Se actualiza el canvas
pygame.display.update()
#Se coloca un tiempo de retraso configurado
sleep(tiempo)
#Se crea una lista para enemigos por eliminar del canvas
enemigosEliminar = list()
#Se crea una lista para nodos por eliminar del canvas
nodosEliminar = list()
#Mientras run siga siendo True corre
while run:
#Itera cada evento seleccionado
for event in pygame.event.get():
#En caso de usar QUIT cambiamos run a False
if event.type == pygame.QUIT:
run = False
#Limpieza del canvas
WIN.fill(FONDO)
#Se iteran los enemigos
for e in xrange(len(self.enemigos)):
#En caso de que el enemigo no sea visible
#brinca el enemigo
if not self.enemigos[e].visible:
continue
#Se iteran los nodos
for n in xrange(len(self.nodos)):
#En caso de que los nodos no sea visible
#brinca el nodo
if not self.nodos[n].visible:
continue
#En caso de que el enemigo se encuentre en el radio del nodo se coloca
# como mensaje al nodo en el que se encuentra el enemigo
if radioDeTransmision(self.nodos[n].radio, \
self.nodos[n].x, \
self.nodos[n].y, \
(self.enemigos[e].x, self.enemigos[e].y)):
self.nodos[n].mensaje = 'Enemigo en zona de %s '%(self.nodos[n].id)
#Mientras el random nos de un numero menor a la probabilidad de nodo
#este generara un nuevo nodo
if random() < p:
self.creaNodo()
#Mientras el random nos de un numero menor a la probabilidad de enemigo
#este generara un nuevo enemigo
if random() < pe:
self.creaEnemigo()
#Por cada enemigo se le quita cierta vida
#en caso que tenga vida menor a 0 se le coloca
# en su propiedad de que ya no sera visible
#despues se pintan los enemigos visibles
for e in xrange(len(self.enemigos)):
if self.enemigos[e].vida > 5:
self.enemigos[e].vida -= 5
else:
enemigosEliminar.append(self.enemigos[e])
self.enemigos[e].visible = False
if not self.enemigos[e].visible:
continue
self.enemigos[e].display()
#Se iteran todos los nodos se le quita cierta vida
#en caso que tenga vida menor a 0 se le coloca
#en su propiedad de que ya no sera visible
#despues se pintan los nodos visibles
for n in xrange(len(self.nodos)):
print self.nodos[n].id, self.nodos[n].vida
if self.nodos[n].vida > 0:
self.nodos[n].vida -= 5
if self.nodos[n].mensaje != '':
self.nodos[n].transmite(self.nodos)
else:
nodosEliminar.append(self.nodos[n])
self.nodos[n].visible = False
if not self.nodos[n].visible:
continue
self.nodos[n].display()
#Se actualiza el canvas
pygame.display.update()
#Se crea un retraso
sleep(tiempo)
#Se remueven los enemigos en la lista de enemigosEliminar
for e in enemigosEliminar:
try:
self.enemigos.remove(e)
except:
pass
#Se remueven los nodos en la lista de nodosEliminar
for n in nodosEliminar:
try:
self.nodos.remove(n)
except:
pass
return
#Pinta los nodos que se han comunicado
def pintaRedComunicacion(self, comunicacion):
global WIN
if len(comunicacion) >= 3:
print comunicacion
for i in xrange(len(comunicacion)):
if len(comunicacion) != i+1:
x1, y1 = comunicacion[i]
x2, y2 = comunicacion[i+1]
pygame.draw.line(WIN , (255, 0, 0), (x1, y1), (x2, y2), 1 )
return
#Se crea un nodo enemigo
def creaEnemigo(self):
#Se toma la configuracion de su radio (re), vida (vidaEnemigo), porcentaje (margen)
global re, vidaEnemigo, porcentaje
#Contador de los enemigos creados
self.contador_enemigos += 1
#Se le da una posicion al enemigo de manera aleatoria con un color rojo en RGB, una id con numero de enemigos y una vida propia
enemigo = Enemigo( ( randint( DIM * 0.10 , DIM * porcentaje ), randint( DIM * 0.10, DIM * porcentaje ) ), (255, 0, 0), re, self.contador_enemigos, vidaEnemigo)
#Se agrega a la lista de enemigos los enemigos
self.enemigos.append( enemigo )
return
def creaNodo(self):
#Se toma la configuracion de su radio (re), vida (vidaEnemigo), porcentaje (margen)
global r, vidaNodo, porcentaje
#Contador de los nodos creados
self.contador_nodos+=1
#Se le da una posicion al nodo de manera aleatoria con un color en RGB obtenido a partir del contador de nodos , una id osea el numero de nodos y una vida propia
nodo = Nodo( ( randint( DIM * 0.10 , DIM * porcentaje ), randint( DIM * 0.10, DIM * porcentaje ) ), asignColor( self.contador_nodos ), r, self.contador_nodos , vidaNodo)
#Se agrega el nodo a la lista de nodos
self.nodos.append( nodo )
return
#Dimensiones del canvas
DIM = 500
#porcentaje del canvas
porcentaje = 0.6
#color de fondo(blanco)
FONDO = ( 255, 255, 255)
#inicia pygame
pygame.init()
#se crea el canvas
WIN = pygame.display.set_mode((DIM, DIM))
#Se coloca un titulo al canvas
pygame.display.set_caption('Simulacion Adhoc')
#Se rellena de un color al canvas
WIN.fill(FONDO)
#Parametro de tiempo
try:
tiempo = float(argv[1])
except:
tiempo = 3
#Parametro de probabilidad de nodo
try:
p = float(argv[2])
except:
p = 0.1
#Parametro de radio del nodo
try:
r = float(argv[3])
except:
r = 200
#Parametro de probabilidad de enemigo
try:
pe = float(argv[4])
except:
pe = 0.08
#Parametro de radio de enemigo
try:
re = float(argv[5])
except:
re = 10
#Parametro de vida del nodo
try:
vidaNodo = int(argv[6])
except:
vidaNodo = 100
#Parametro de vida del enemigo
try:
vidaEnemigo = int(argv[7])
except:
vidaEnemigo = 20
#Parametro de velocidad
try:
velocidad = int(argv[8])
except:
velocidad = 10
def main():
#Crea una simulacion
s = Simulacion()
#corre simulacion
s.run()
main()

1 comentarios:

  1. El movimiento es algo pausado y la propagación de mensajes deja algo por desear. 8 pts.

    ResponderEliminar