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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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() |
El movimiento es algo pausado y la propagación de mensajes deja algo por desear. 8 pts.
ResponderEliminar