def __init__(self, arqEndereco, arqEstrategia): super(MonitorAspirador, self).__init__() self.enderecos = Enderecos(arqEndereco) self.endereco = self.enderecos.endereco("monitor") self.participantes = {} self._log = [] self.configuracao = json.load(open(arqEstrategia))
def __init__(self, configSim, configExe, configEnd, configComp): super(TestadorAspirador, self).__init__() self.configs = {} self.configs['sim'] = json.load(open(configSim)) self.configs['exe'] = json.load(open(configExe)) self.enderecos = Enderecos(configEnd) self.componentes = Componentes(configComp)
def __init__(self, agId, configEnd, configCom): super(AspiradorIII, self).__init__() self.mid = agId self.enderecos = Enderecos(configEnd) self.endereco = self.enderecos.endereco('agente') self.enderecoMonitor = self.enderecos.endereco('monitor') self.componentes = Componentes(configCom) self.socketReceive = None self.socketSend = None self.enviar = True #True se agente deve enviar mensagem, False caso esteja esperando resposta self.agindo = True #False para enviar ação de perceber self.ENERGIAMAX = 80.0 self.limiteRecarga = 0.25 self.RESERVATORIOMAX = 4 self.PLANO_EXPLORAR = 0 self.PLANO_RECARREGAR = 1 self.PLANO_DEPOSITAR = 2 self.PLANO_SUJEIRA = 3 self.tiposPlano = (self.PLANO_EXPLORAR, self.PLANO_RECARREGAR, self.PLANO_DEPOSITAR, self.PLANO_SUJEIRA) self.reiniciarMemoria()
def __init__(self, configEst, configEnd, configCom): super(Nsga2, self).__init__() self.crossoverProb = 0.0 self.mutacaoProb = 0.0 self.componentes = Componentes(configCom) self.configuracoes = json.load(open(configEst)) self.enderecos = Enderecos(configEnd) self.enderecos.participantes() #TODO: guardar o log self.npop = 0 self.maxite = 0
class MonitorAspirador(Monitor): def __init__(self, arqEndereco, arqEstrategia): super(MonitorAspirador, self).__init__() self.enderecos = Enderecos(arqEndereco) self.endereco = self.enderecos.endereco("monitor") self.participantes = {} self._log = [] self.configuracao = json.load(open(arqEstrategia)) @property def log(self): return self._log[:] def pronto(self): while True: msgTestador = self.socketReceive.recv().split() if msgTestador[0] == "###": for pid in self.participantes.keys(): self.socketsParticipantes[pid].send("###") break elif msgTestador[0] == "@@@": self.simulationLoop(msgTestador) else: print "Monitor: Mensagem '", msgTestador, "' desconhecida" def simulationLoop(self, msgTestador): resolucao, ncargas = None, None if len(msgTestador) > 1: resolucao = int(msgTestador[1]) ncargas = int(msgTestador[2]) nsujeiras = int(msgTestador[3]) self._log = [] for pid in self.participantes.keys(): self.socketsParticipantes[pid].send("@@@") while True: mmsg = self.socketReceive.recv() msg = mmsg.split() de, para, texto = int(msg[0]), int(msg[1]), msg[2:] # NOTE: o último elemento NÃO é uma string self._log.append((de, para, texto)) if para == -1: self.avaliar(1, resolucao, ncargas, nsujeiras) break self.socketsParticipantes[para].send(mmsg) def avaliar(self, agid, resolucao=None, ncargas=None, nsujeiras=None): nmovimentos = 0 nrecolhidos = 0 consumo = 0 consumoMax = 0 for de, para, texto in self._log: if para == agid: if texto[0] == "moveu": nmovimentos += 1 elif texto[0] == "limpou": nrecolhidos += 1 elif texto[0] == "recarregou": consumo -= 10 elif de == agid and texto[0] != "perceber": consumo += 1 if consumo > consumoMax: consumoMax = consumo fatorx = nrecolhidos / float(nsujeiras) tamanho = 0.0 if resolucao == None: tamanho = float(self.configuracao["resolucao"] ** 2) else: tamanho = float(resolucao ** 2) consumoMin = 0.0 if ncargas == None: consumoMin = (tamanho + nrecolhidos) / float(self.configuracao["carga"]) else: consumoMin = (tamanho + nrecolhidos) / float(ncargas) if nmovimentos < tamanho: obj1 = 50.0 * fatorx else: obj1 = 100.0 / 2 ** (log(nmovimentos / tamanho, 3.5)) if consumoMax < consumoMin: # caso em que o agente parou no caminho obj2 = 0.0 else: obj2 = fatorx * (100.0 / 2 ** (log(consumoMax / consumoMin, 4.5))) # print (obj1, obj2) self.socketTestador.send("%s %s" % (obj1, obj2)) def run(self): contexto = zmq.Context() self.socketReceive = contexto.socket(zmq.PULL) self.socketReceive.bind(self.endereco) self.socketTestador = contexto.socket(zmq.PUSH) self.socketTestador.connect(self.enderecos.endereco("testador")) self.socketsParticipantes = {} for chave in self.participantes.keys(): self.socketsParticipantes[chave] = contexto.socket(zmq.PUSH) self.socketsParticipantes[chave].connect(self.participantes[chave]) self.pronto() time.sleep(1) # este tempo é necessário para garantir o envio das mensagens para os participantes print "monitor finalizando..." def adicionarParticipante(self, pid, endereco): """ participante -> tupla contendo referência ao agente e o seu apelido. """ self.participantes[pid] = endereco def removerParticipante(self, pid): del self.participantes[pid]
class Nsga2(Process): def __init__(self, configEst, configEnd, configCom): super(Nsga2, self).__init__() self.crossoverProb = 0.0 self.mutacaoProb = 0.0 self.componentes = Componentes(configCom) self.configuracoes = json.load(open(configEst)) self.enderecos = Enderecos(configEnd) self.enderecos.participantes() #TODO: guardar o log self.npop = 0 self.maxite = 0 def run(self): raise NotImplementedError def fastNondominatedSort(self, populacao): """ returns a list of fronts. """ frontes = [] fronteAtual = [] for individuo in populacao: individuo.ndominam = 0 individuo.dominadas = [] for indiceI, individuo in enumerate(populacao): for indiceO, outroIndividuo in enumerate(populacao): if indiceI == indiceO: continue comp = individuo.comparar(outroIndividuo) if comp == COMP_DOMINA: individuo.dominadas.append(indiceO) elif comp == COMP_DOMINADA: individuo.ndominam += 1 if individuo.ndominam == 0: individuo.fitness = 1 fronteAtual.append(individuo) frontes.append(fronteAtual) i = 0 while len(frontes[i]) > 0: fronteAnterior = frontes[i] fronteNovo = [] for individuo in fronteAnterior: for indice in individuo.dominadas: q = populacao[indice] #tentativa de reduzir o acesso a índices de listas q.ndominam -= 1 if q.ndominam == 0: q.fitness = i + 2 fronteNovo.append(q) i += 1 frontes.append(fronteNovo) return frontes #NOTE: retorna um fronte vazio também? def configurar(self, **args): for k, valor in args.iteritems(): if k == 'npopulacao': self.npop = valor elif k == 'ngeracoes': self.maxite = valor elif k == 'crossover': self.crossoverProb = valor elif k == 'mutacao': self.mutacao = valor #TODO: modificar nomenclatura desse método. def crowdingDistanceAssignment(self, pontos): for i in pontos: i.distancia = 0.0 nobjetivos = len(pontos[0].objetivos) l = len(pontos) for m in range(nobjetivos): pontos = sorted(pontos, key=lambda ponto: ponto.objetivos[m]) pontos[0].distancia, pontos[-1].distancia = INFINITO, INFINITO i = 1 while (i < l-1): pontos[i].distancia += (pontos[i+1].objetivos[m] - pontos[i-1].objetivos[m]) i += 1 def gerarPopulacaoInicial(self): raise NotImplementedError def gerarPopulacao(self): raise NotImplementedError def gravarPopulacao(self, pid, populacao): log = open('populacao.txt','a') log.write(str(pid) + '\n') for individuo in populacao: for objetivo in individuo.objetivos: log.write(str(objetivo)+' ') log.write('\n') log.close() #TODO: mudar o nome para unir populações? def gerarConjunto(self, pop1, pop2): extra = filter(lambda p:p.cloned==False, pop2) for e in extra: for p in pop1: if e.cromossomo == p.cromossomo: break else: pop1.append(e) return pop1 def mainLoop(self): print "mainloop()" msg = self.socketReceive.recv() #aguarda mensagem de inicialização p = self.gerarPopulacaoInicial() self.gravarPopulacao(0, p) q = [] i = 0 while i < self.maxite: print >> sys.stderr, i, #log = open(self.mainlog,"a") #log.write("\nGeração %s\n" % (i+1)) #log.close() #print "Geração %s" % (i+1), #r = list(set(p + q)) r = self.gerarConjunto(p, q) frontes = self.fastNondominatedSort(r) p = [] for fronte in frontes: self.crowdingDistanceAssignment(fronte) p.extend(fronte) if len(p) >= self.npop: break p = sorted(p, key = lambda el: el.distancia, reverse = True) p = p[:self.npop] q = self.gerarPopulacao(p, self.npop) if i % 50 == 0: Nsga2Aspirador.draw(p, 'pop_%s.txt' % i) i += 1 self.gravarPopulacao(i, p) return p
class TestadorAspirador(Process): def __init__(self, configSim, configExe, configEnd, configComp): super(TestadorAspirador, self).__init__() self.configs = {} self.configs['sim'] = json.load(open(configSim)) self.configs['exe'] = json.load(open(configExe)) self.enderecos = Enderecos(configEnd) self.componentes = Componentes(configComp) def run (self): print '*'*20, 'Zephyrus', '*'*20 print 'conectando...' modo = self.configs['sim']['mode'] contexto = zmq.Context() self.socketReceive = contexto.socket(zmq.PULL) self.socketReceive.bind(self.enderecos.endereco('tester')) if modo == 'cent': #um testador self.inicializarParticipantesCentralizado() self.socketMonitor = contexto.socket(zmq.PUSH) self.socketMonitor.connect(self.enderecos.endereco('monitor')) self.socketConfiguracoes = contexto.socket(zmq.PUB) self.socketConfiguracoes.bind(self.enderecos.endereco('testador_par')) elif modo == 'dist': self.incializarParticipantesDistribuido() #... else: raise CoreException("Modo de funcionamento desconhecido: %s" % modo) self.socketEstrategia = contexto.socket(zmq.PUSH) self.socketEstrategia.connect(self.enderecos.endereco('estrategia')) self.loopPrincipal(modo) print 'finalizando os testes...' time.sleep(2) print >> sys.stderr, 'FIM' def inicializarParticipantesCentralizado(self): if not '<MANUAL>' in self.configs['exe']['monitor']: #monitor subp.Popen(self.configs['exe']['monitor'].split()) else: endereco = self.enderecos.endereco('monitor') #endereco = self.configs['end']['monitor'].split(',')[-1] print 'execute o monitor manualmente, esperado em: ', endereco raw_input('\npressione enter para continuar') pprint.pprint(self.configs) if not '<MANUAL>' in self.configs['exe']['environment']: #ambiente subp.Popen(self.configs['exe']['environment'].split()) else: endereco = self.enderecos.endereco('environment') #endereco = self.configs['end']['ambiente'].split(',')[-1] print 'execute o ambiente manualmente, esperado em: ', endereco raw_input('\npressione enter para continuar') for i, agente in enumerate(self.configs['exe']['agentes']): #agentes if not '<MANUAL>' in agente: subp.Popen(agente.split()) else: endereco = self.enderecos.endereco('agente') #endereco = self.configs['end']['agentes'][i].split(',')[-1] print 'execute o agente manualmente, esperado em: ', endereco raw_input('\npressione enter para continuar') if not '<MANUAL>' in self.configs['exe']['estrategia']: #estratégia subp.Popen(self.configs['exe']['estrategia'].split()) else: endereco = self.enderecos.endereco('estrategia') #endereco = self.configs['end']['estrategia'].split(',')[-1] print 'execute o estratégia manualmente, esperado em: ', endereco raw_input('\npressione enter para continuar') def incializarParticipantesDistribuido(self): pass #TODO! def loopPrincipal(self, modo): self.socketEstrategia.send("@@@") self.cenarioPadrao = map(int, self.configs['sim']['cenarioPadrao'].split()) resolucao = self.configs['sim']['resolucao'] ncargas = self.configs['sim']['carga'] sujeiras = self.configs['sim']['sujeira'] nomeAmbiente = self.enderecos.get('ambiente')[0] while True: msg = self.socketReceive.recv() if "###" in msg: self.socketConfiguracoes.send('%s ,' % nomeAmbiente) self.socketMonitor.send("###") break iagente = 1 linha = 0 coluna = 0 ambiente = map(self.componentes.juntar, map(int, msg.split()), self.cenarioPadrao) for i in xrange(len(ambiente)): agentes = filter(lambda k:self.componentes.checar(k, ambiente[i]), ['AG01', 'AG02', 'AG03', 'AG04']) if len(agentes) > 0: linha, coluna = i/resolucao, i%resolucao ambiente = ' '.join(map(str,ambiente)) resultados = [] for i in range(self.configs['sim']['repeat']): self.socketConfiguracoes.send('%s %s,%s,%s,%s,%s' % (nomeAmbiente, ambiente, resolucao,iagente,linha,coluna)) self.socketMonitor.send("@@@ %s %s %s" % (resolucao, ncargas, sujeiras)) #print ambiente resultados.append(map(float, self.socketReceive.recv().split())) obj1, obj2 = zip(*resultados) #unzip!!! medias = "%s %s" % (sum(obj1)/len(resultados), sum(obj2)/len(resultados)) #print 'medias', medias #medias = "%s %s" % (100 * random.random(), 100 * random.random()) self.socketEstrategia.send(medias) #print self.enderecos.get('ambiente')[0] # print 'recebi', msg # for resultado in resultados: # log.write(str(resultado)) # medias = sum(map(lambda k:k[0], resultados))/len(resultados), sum(map(lambda k:k[1], resultados))/len(resultados) # self.socketEstrategia.send("%s %s" % (medias[0], medias[1])) # return medias #TODO: expandir para uma versão com roteiro def iniciarSimulacao(self, modo): teste = self.socketReceive() tinicio = time() print 'Teste iniciado às: ', strftime("%H:%M:%S", localtime()) #self. self.configuracao = json.loads(open('configuracao.js').read()) self.cenarioPadrao = map(int, self._configuracao["cenarioPadrao"].split()) self.estrategia = self.estrategiaNsga2() populacao = self.estrategia.mainLoop() self.analise(populacao) tfim = time() print 'Teste finalizado às: ', strftime("%H:%M:%S", localtime()) print "tempo consumido: ", str(tfim - tinicio) + 's' def avaliarMultiplos(self, cenario): #print '@' ambiente = map(self.componentes.juntar, cenario, self.cenarioPadrao) #dimensao = self._configuracao["resolucao"] resultados = [] log = open(self._configuracao["mainlog"],'a') log.write('\n@\n') log.write(str(ambiente)) log.write('\n') #for v in ambiente: # print filter(lambda k:self.componentes.checar(k,v), self.componentes.items.keys()) ambiente = reduce(lambda a,b: a + ' '+ b, map(str, ambiente)) info = "%s %s %s," % (self._configuracao["resolucao"], self._configuracao["ncargas"], self._configuracao["nsujeiras"]) msg = info + ambiente for socket in self.socketAuxiliares: socket.send(msg) #socket.send(str(ambiente)) for i in xrange(self._configuracao["nauxiliares"]): msg = self.socketReceive.recv() resultados.append(map(float,msg.split())) #print 'recebi', msg for resultado in resultados: log.write(str(resultado)) log.write('\n') medias = sum(map(lambda k:k[0], resultados))/len(resultados), sum(map(lambda k:k[1], resultados))/len(resultados) log.write(str(medias)) log.close() return medias def analise(self, populacao): cenarios = [] for i in populacao: individuo = i.decodificar(self.componentes) cenarios.append(map(self.componentes.juntar, individuo, self.cenarioPadrao)) with open(self._configuracao['popfinal'], 'w') as a: for cenario in cenarios: for elemento in cenario: a.write(str(elemento) + ' ') a.write('\n')
class AspiradorIII(Process): def __init__(self, agId, configEnd, configCom): super(AspiradorIII, self).__init__() self.mid = agId self.enderecos = Enderecos(configEnd) self.endereco = self.enderecos.endereco('agente') self.enderecoMonitor = self.enderecos.endereco('monitor') self.componentes = Componentes(configCom) self.socketReceive = None self.socketSend = None self.enviar = True #True se agente deve enviar mensagem, False caso esteja esperando resposta self.agindo = True #False para enviar ação de perceber self.ENERGIAMAX = 80.0 self.limiteRecarga = 0.25 self.RESERVATORIOMAX = 4 self.PLANO_EXPLORAR = 0 self.PLANO_RECARREGAR = 1 self.PLANO_DEPOSITAR = 2 self.PLANO_SUJEIRA = 3 self.tiposPlano = (self.PLANO_EXPLORAR, self.PLANO_RECARREGAR, self.PLANO_DEPOSITAR, self.PLANO_SUJEIRA) self.reiniciarMemoria() def perceber(self, percebido): #define o momento em que o agente enxerga o ambiente captando informações sobre #existência de obstáculos e de sujeira. itens = ['PAREDEN', 'PAREDEL', 'PAREDES', 'PAREDEO', 'LIXO', 'LIXEIRA','RECARGA'] #posições: N, L, S ,O e 'sujo' (True indica presença de parede/sujeira). st = map(lambda item:self.componentes.checar(item, percebido),itens) return self.agir(st) def reiniciarMemoria(self): self.visitados = {} self.nvisitados = [] self.lixeiras = [] #posição de pontos de depósito de lixo self.recargas = [] #posição de pontos de recarga self.sujeiras = set() #posição de sujeiras encontradas self.x, self.y = 0, 0 self.percebido = None self.px, self.py = 0, 0 self.DELTA_POS = ((-1, 0), (0, 1), (1, 0), (0, -1)) #auxiliar em várias operações self.energia = self.ENERGIAMAX # self.limiteRecarga = 0.4 self.reservatorio = 0 self.plano = None #qual tipo de plano atualmente sendo executado self.movimentar = [] #sequência de movimentos a serem realizados self.nrecargas = 0 #usada durante a execução do plano de recarga self.recuperarMovimento = 0 #armazena um movimento tentado para recuperá-lo em caso de falha. def run(self): print 'Agente rodando!!!' contexto = zmq.Context() self.socketReceive = contexto.socket(zmq.PULL) self.socketReceive.bind(self.endereco) self.socketSend = contexto.socket(zmq.PUSH) self.socketSend.connect(self.enderecoMonitor) self.ready() def ready(self): print "Agent %s is ready." % (self.mid) while True: msg = self.socketReceive.recv() if msg == "@@@": self.reiniciarMemoria() self.enviar = True self.agindo = False while True: if self.enviar: if self.agindo == False: self.socketSend.send("%s %s perceber" % (self.mid, 0)) self.enviar = False else: acao = self.perceber(self.percebido) msg = "%s %s " % (self.mid, 0) #TODO: tratar o caso PARAR self.socketSend.send(msg + acao) self.enviar = False pass else: if self.agindo == False: msg = self.socketReceive.recv() self.enviar = True self.agindo = True self.percebido = int(msg.split()[2]) else: msg = self.socketReceive.recv() #apenas um feddback (ack) retorno = msg.split()[-1] if retorno == 'moveu': self.mover() elif retorno == 'limpou': self.limpar() elif retorno == 'recarregou': self.carregar() elif retorno == 'depositou': self.depositar() elif retorno == 'colidiu': self.colidir() elif retorno == 'parou': break elif retorno == 'nop': self.nop() else: pass self.enviar = True self.agindo = False elif msg == "###": print "Agente %s recebeu mensagem de finalização de atividades." % (self.mid) break else: print "Agente %s recebeu mensagem inválida." % (self.mid) def agir(self, st): self.memorizarAmbiente(st) if self.energia <= 0: return 'parar' if self.plano != None: if self.plano == self.PLANO_EXPLORAR: if len(self.movimentar) > 0: self.recuperarMovimento = self.movimentar.pop(0) self.px, self.py = self.DELTA_POS[self.recuperarMovimento] if len(self.movimentar) == 0: self.plano = None return "mover %s" % self.recuperarMovimento else: print 'erro na função agir' #TODO: transformar isso em execeção elif self.plano == self.PLANO_DEPOSITAR: if len(self.movimentar) > 0: self.recuperarMovimento = self.movimentar.pop(0) self.px, self.py = self.DELTA_POS[self.recuperarMovimento] self.energia -= 1 return "mover %s" % self.recuperarMovimento else: self.plano = None return "depositar" elif self.plano == self.PLANO_RECARREGAR: if len(self.movimentar) > 0: self.recuperarMovimento = self.movimentar.pop(0) self.px, self.py = self.DELTA_POS[self.recuperarMovimento] self.energia -= 1 return "mover %s" % self.recuperarMovimento else: self.nrecargas -= 1 if self.nrecargas == 0: self.plano = None return "recarregar" elif self.plano == self.PLANO_SUJEIRA: if len(self.movimentar) > 0: self.recuperarMovimento = self.movimentar.pop(0) self.px, self.py = self.DELTA_POS[self.recuperarMovimento] self.energia -= 1 return "mover %s" % self.recuperarMovimento else: self.plano = None return "limpar" else: print "plano desconhecido" #TODO: transformar em exceção elif (self.energia / self.ENERGIAMAX) < self.limiteRecarga: return self.tracarPlanoRecarga(st) elif self.reservatorio == self.RESERVATORIOMAX: return self.tracarPlanoDeposito(st) elif st[4] == True: self.energia -= 3 #consome energia independente de limpar ou não de verdade return 'limpar' else: return self.escolherDirecao(st[:4]) def memorizarAmbiente (self,st): if (self.x, self.y) in self.nvisitados: self.nvisitados.remove((self.x,self.y)) self.visitados[(self.x, self.y)] = st[0:4] visitados = self.visitados.keys() #NOTE: tentativa de melhorar o desempenho, gerando a lista apenas uma vez if st[0] == False: if ((self.x-1, self.y) not in visitados) and ((self.x-1, self.y) not in self.nvisitados): self.nvisitados.append((self.x-1, self.y)) if st[1] == False: if ((self.x, self.y+1) not in visitados) and ((self.x, self.y+1) not in self.nvisitados): self.nvisitados.append((self.x, self.y + 1)) if st[2] == False: if ((self.x+1, self.y) not in visitados) and ((self.x+1, self.y) not in self.nvisitados): self.nvisitados.append((self.x + 1, self.y)) if st[3] == False: if ((self.x, self.y-1) not in visitados) and ((self.x, self.y-1) not in self.nvisitados): self.nvisitados.append((self.x, self.y - 1)) if st[4] == True: self.sujeiras.add((self.x, self.y)) if (st[5] == True) and not ((self.x, self.y) in self.lixeiras): self.lixeiras.append((self.x, self.y)) if (st[6] == True) and not ((self.x, self.y) in self.recargas): self.recargas.append((self.x, self.y)) #TODO: a checagem de colisão no ambiente NÃO funciona para colisão com paredes def escolherDirecao(self, paredes): direcoes = [] for i, parede in enumerate(paredes): if not parede: direcoes.append(i) if len(direcoes) == 0: return 'parar' if len(self.nvisitados) == 0 and len(self.sujeiras) == 0: return 'parar' nvisitados = [] visitados = self.visitados.keys() for direcao in direcoes: if direcao == 0: if ((self.x-1, self.y) not in visitados): #TODO: buscas a visitados podem ser substituídas por buscas a nvisitados? nvisitados.append((0, (-1, 0))) elif direcao == 1: if ((self.x, self.y+1) not in visitados): nvisitados.append((1, (0, 1))) elif direcao == 2: if ((self.x+1, self.y) not in visitados): nvisitados.append((2, (1, 0))) else: if ((self.x, self.y-1) not in visitados): nvisitados.append((3, (0, -1))) if len(nvisitados) == 0: if len(self.nvisitados) == 0: return self.tracarPlanoSujeira() else: return self.tracarPlanoExploracao() choiced = choice(nvisitados) self.px, self.py = choiced[1] self.energia -= 1 self.recuperarMovimento = choiced[0] return 'mover %s' % self.recuperarMovimento def tracarPlanoRecarga(self,st): if len(self.recargas) == 0: return self.escolherDirecao(st[:4]) self.plano = self.PLANO_RECARREGAR self.nrecargas = int((self.ENERGIAMAX - self.energia)/10) if st[6] == True: #o agente já está em um ponto de recarga self.movimentar = [] self.nrecargas -= 1 return 'recarregar' minx, maxx, miny, maxy = self.calcularDimensoes() sizex = maxx - minx + 1 sizey = maxy - miny + 1 matriz = [[-1000 for i in range(sizey)] for i in range(sizex)] for x, y in self.visitados.keys(): matriz[x-minx][y-miny] = 1000 for x,y in self.recargas: matriz[x - minx][y - miny] = -1 caminho = self.caminhoMaisCurto(matriz, (self.x, self.y),minx, maxx,miny, maxy) self.movimentar = self.caminhoParaMovimentos(caminho) self.recuperarMovimento = self.movimentar.pop(0) self.energia -= 1 self.px, self.py = self.DELTA_POS[self.recuperarMovimento] return "mover %s" % self.recuperarMovimento def tracarPlanoDeposito(self,st): if len(self.lixeiras) == 0: return self.escolherDirecao(st[:4]) self.plano = self.PLANO_DEPOSITAR if st[5] == True: #o agente já está em um ponto de recarga self.movimentar = [] self.plano = None return 'depositar' minx, maxx, miny, maxy = self.calcularDimensoes() sizex = maxx - minx + 1 sizey = maxy - miny + 1 matriz = [[-1000 for i in range(sizey)] for i in range(sizex)] for x, y in self.visitados.keys(): matriz[x-minx][y-miny] = 1000 for x,y in self.lixeiras: matriz[x - minx][y - miny] = -1 caminho = self.caminhoMaisCurto(matriz, (self.x, self.y),minx, maxx,miny, maxy) self.movimentar = self.caminhoParaMovimentos(caminho) self.recuperarMovimento = self.movimentar.pop(0) self.energia -= 1 self.px, self.py = self.DELTA_POS[self.recuperarMovimento] return "mover %s" % self.recuperarMovimento def tracarPlanoSujeira(self): self.plano = self.PLANO_SUJEIRA minx, maxx, miny, maxy = self.calcularDimensoes() sizex = maxx - minx + 1 sizey = maxy - miny + 1 matriz = [[-1000 for i in range(sizey)] for i in range(sizex)] for x, y in self.visitados.keys(): matriz[x-minx][y-miny] = 1000 for x,y in self.sujeiras: matriz[x - minx][y - miny] = -1 caminho = self.caminhoMaisCurto(matriz, (self.x, self.y),minx, maxx,miny, maxy) self.movimentar = self.caminhoParaMovimentos(caminho) self.recuperarMovimento = self.movimentar.pop(0) self.energia -= 1 self.px, self.py = self.DELTA_POS[self.recuperarMovimento] return "mover %s" % self.recuperarMovimento def tracarPlanoExploracao(self): self.plano = self.PLANO_EXPLORAR minx, maxx, miny, maxy = self.calcularDimensoes() sizex = maxx - minx + 1 sizey = maxy - miny + 1 matriz = [[-1 for i in range(sizey)] for i in range(sizex)] for x, y in self.visitados.keys(): matriz[x-minx][y-miny] = 1000 caminho = self.caminhoMaisCurto(matriz, (self.x, self.y),minx, maxx,miny, maxy) self.movimentar = self.caminhoParaMovimentos(caminho) self.energia -= 1 self.recuperarMovimento = self.movimentar.pop(0) self.px, self.py = self.DELTA_POS[self.recuperarMovimento] return "mover %s" % self.recuperarMovimento def calcularDimensoes(self): visitados = self.visitados.keys() if len(self.nvisitados) != 0: maxx = max(max(visitados)[0], max(self.nvisitados)[0]) minx = min(min(visitados)[0], min(self.nvisitados)[0]) maxy = max(max(visitados, key=lambda k:k[1])[1],max(self.nvisitados, key=lambda k:k[1])[1]) miny = min(min(visitados, key=lambda k:k[1])[1],min(self.nvisitados, key=lambda k:k[1])[1]) else: maxx = max(visitados)[0] minx = min(visitados)[0] maxy = max(visitados, key=lambda k:k[1])[1] miny = min(visitados, key=lambda k:k[1])[1] return minx, maxx, miny, maxy def caminhoMaisCurto(self, matriz, atual, minx, maxx, miny, maxy): fila = deque() caminho = [] fila.append(atual) px, py = atual matriz[px-minx][py-miny] = 0 peso = 0 while len(fila) > 0: px, py = fila.popleft() if matriz[px - minx][py - miny] == -1: return (px,py) #TODO: se entrar aqui (é possível?) vai dar bug!!!!!! peso = matriz[px - minx][py - miny] direcoes = self.estadosParaDirecoes((px, py), self.visitados[(px, py)]) for direcao in direcoes: opx, opy = direcao if matriz[opx - minx][opy - miny] > peso + 1: #encontrou um caminho melhor (ou o primeiro caminho) até aquela posição. matriz[opx - minx][opy - miny] = peso + 1 fila.append(direcao) elif matriz[opx - minx][opy - miny] == -1: #encontrou uma posição que ainda não foi visitada. caminho.append((opx, opy)) while peso >= 0: #Sul if ((opx - minx + 1 <= maxx - minx) and (matriz[opx - minx + 1][opy - miny] == peso)): caminho.append((opx + 1, opy)) opx += 1 peso -= 1 continue #Oeste if ((opy - miny - 1 >= 0) and (matriz[opx - minx][opy - 1 - miny] == peso)): caminho.append((opx, opy - 1)) opy -= 1 peso -= 1 continue #Norte if (opx - minx - 1 >= 0) and (matriz[opx - minx - 1][opy - miny] == peso): caminho.append((opx - 1, opy)) peso -= 1 opx -= 1 continue if (opy - miny + 1 <= maxy - miny) and (matriz[opx - minx][opy + 1 - miny] == peso): caminho.append((opx, opy + 1)) peso -= 1 opy += 1 continue return caminho[::-1] print 'nao encontrou caminho!' print self.info() #Método auxiliar que realiza a conversão de estados(paredes) para direções def estadosParaDirecoes(self, pos, st): ret = [] x,y = pos if st[0] == False: ret.append((x-1,y)) if st[1] == False: ret.append((x,y+1)) if st[2] == False: ret.append((x+1,y)) if st[3] == False: ret.append((x,y-1)) return ret def caminhoParaMovimentos (self, caminho): movimentos = [] orix, oriy = caminho[0] for i in range(1,len(caminho)): desx, desy = caminho[i] if orix != desx: if orix > desx: movimentos.append(0) else: movimentos.append(2) else: if oriy > desy: movimentos.append(3) else: movimentos.append(1) orix, oriy = desx, desy return movimentos def limpar(self): #O agente executa a ação de limpar em sua posição atual. self.sujeiras.discard((self.x, self.y)) self.reservatorio += 1 def carregar(self): self.energia += 10 def depositar(self): self.energia -= 1 self.reservatorio = 0 def parar(self): #O agente permanece parado e apenas informa esse fato ao observador. self.info() while True: pass def mover(self): #movimento realizado com sucesso self.x += self.px self.y += self.py def colidir(self): print 'colidi' self.energia -= 1 if self.plano != None: self.movimentar.insert(0,self.recuperarMovimento) def nop(self): pass def info(self): print '*'*10 print 'posicao', (self.x, self.y) print self.energia, self.reservatorio, self.plano print 'visitados', self.visitados.keys() print 'nvisitados', self.nvisitados print 'lixeiras', self.lixeiras print 'recargas', self.recargas print 'sujeiras', self.sujeiras print '*'*10