def update(self, milliseconds): if self.cooldown > 0: self.cooldown -= milliseconds else: self.work_requested -= milliseconds if self.work_requested <= 0: self.end = True msg_mgr.add_msg("[INFO] JOB {0} ENDED".format(self.id))
def switch_with(self, cell): temp = self.element self.element = cell.element self.element.cell = self cell.element = temp cell.element.cell = cell self.element.already_moved = MOVE_COOLDOWN cell.element.already_moved = MOVE_COOLDOWN msg_mgr.add_msg("[INFO] Switched elements between {0} and {1}".format(self, cell)) info_mgr.add_switch(self, cell)
def add_neighbor(self, cell): # print "ADD NEIGH > ", str(self.position), str(cell.position) if cell.position == (self.position[0] -1, self.position[1]): self.neighbor[L] = cell cell.neighbor[R] = self elif cell.position == (self.position[0], self.position[1] -1): self.neighbor[U] = cell cell.neighbor[D] = self elif cell.position == (self.position[0] +1, self.position[1]): self.neighbor[R] = cell cell.neighbor[L] = self elif cell.position == (self.position[0], self.position[1] +1): self.neighbor[D] = cell cell.neighbor[U] = self else: msg_mgr.add_msg("[ERROR] : ca.py > add_neighbor. SELF = {0} : OTHER = {1}".format(self, cell))
def add_element(self, element): from_e_p = False # print self.limit, MAX_CELLS if 2*(self.limit+1) > math.sqrt(MAX_CELLS): msg_mgr.add_msg("[INFO] > Too many cells, pass") return False if self.empty_position: p = self.empty_position.pop(0) position = "{0}-{1}".format(p[0], p[1]) pos_vector = (p[0], p[1]) from_e_p = True else: position = "{0}-{1}".format(self.next_new[0], self.next_new[1]) pos_vector = (self.next_new[0], self.next_new[1]) if not position in self.elements: element.position = (pos_vector[0], pos_vector[1]) self.elements[position] = element self.elements[position].set_net(self) for p in ((pos_vector[0], pos_vector[1]-1), (pos_vector[0], pos_vector[1]+1), (pos_vector[0]-1, pos_vector[1]), (pos_vector[0]+1, pos_vector[1])): neig_pos = "{0}-{1}".format(p[0], p[1]) if neig_pos in self.elements: self.elements[neig_pos].add_neighbor(element) if not from_e_p: if self.add_direction == U: self.next_new = (self.next_new[0], self.next_new[1] -1) if self.next_new[1] < -self.limit: self.add_direction = R elif self.add_direction == R: self.next_new = (self.next_new[0] +1, self.next_new[1]) if self.next_new[0] > self.limit: self.add_direction = D elif self.add_direction == D: self.next_new = (self.next_new[0], self.next_new[1] +1) if self.next_new[1] > self.limit: self.add_direction = L else: self.next_new = (self.next_new[0] -1, self.next_new[1]) if self.next_new[0] < -self.limit: self.add_direction = U return pos_vector else: self.limit += 1 self.next_new = (self.next_new[0]-1, self.next_new[1] -1) return self.add_element(element)
def main(): end = False visualize_graphs = False automata = ca.ca_net() pygame.init() plt.ion() clock = pygame.time.Clock() screen = pygame.display.set_mode(WINDOW_SIZE) cmd_str = "" cmd_vect = [] cmd_file = open("cmd.txt") for line in cmd_file.readlines(): time, cmd = line.split(" ") cmd_vect.append([time, cmd]) cmd_file.close() plt.figure(figsize=(4, 8)) # ax1 = wl_fig.add_subplot(411) # ax2 = wl_fig.add_subplot(412) # ax3 = wl_fig.add_subplot(413) # ax4 = wl_fig.add_subplot(414) start_time = pygame.time.get_ticks() last_update_time = pygame.time.get_ticks() # jobid = 0 # new_jobs = 0 # moved_jobs = 0 # ended_jobs = 0 # tot_ended_jobs = 0 # move_of_ended_jobs = 0 # # cell_wl_history = {} # wl_history = [] # moved_jobs_history = [] # wl_variance_history = [] # new_jobs_history = [] # medium_distance_history = [] # average_moved_times = [] activate_line = [real_net.WL_ACTIVATE_THRESHOLD*100 for _ in range(MAX_WL_HISTORY)] deactivate_line = [real_net.WL_DEACTIVATE_THRESHOLD*100 for _ in range(MAX_WL_HISTORY)] for _ in range(0): net_node = real_net.node((0,0)) cell = ca.ca_cell(element = net_node) automata.add_element(cell) for cell in automata.elements.values(): info_mgr.add_cell(position_name(cell.element), history_len=0) # cell_wl_history[position_name(cell.element)] = [] # for cell in automata.elements: # for _ in range(random.randint(10,60)): # j = real_net.job(jobid, start_time, random.randint(5, 2200)) # automata.elements[cell].element.add_job(j) # jobid += 1 # new_jobs += 1 i = -1 font = pygame.font.Font("font.otf", 12) small_font = pygame.font.Font("font.otf", 8) while not end: clock.tick(MAX_FRAMERATE) i += 1 current_time = pygame.time.get_ticks() * TIME_SPEED if len(cmd_vect) >= 1 and int(cmd_vect[0][0]) < current_time: _, cmd_str = cmd_vect.pop(0) msg_mgr.add_msg("[INFO] Cmd from file : {0}".format(cmd_str[:-1])) pygame.event.post(pygame.event.Event(USEREVENT, {'data' : cmd})) for e in pygame.event.get(): if e.type == QUIT: end = True elif e.type == KEYDOWN and e.key == K_n: # print len(automata.elements), automata.full() if not automata.full(): position = random2dpos() inserted = False while not inserted and not automata.full(): if not (position in automata.elements_position()): net_node = real_net.node(position) cell = ca.ca_cell(element = net_node) if automata.add_element(cell): info_mgr.add_cell(position_name(net_node), history_len=info_mgr.cell_length()) # cell_wl_history[position_name(net_node)] = [0 for _ in range(len(cell_wl_history[random.choice(cell_wl_history.keys())]))] inserted = True msg_mgr.add_msg("[INFO] Added new node : real_pos {0} - automata_pos {1}".format( str(net_node.position), str(cell.position))) else: position = random2dpos() else: msg_mgr.add_msg("[INFO] > Automata full") # print len(automata.elements), automata.full() elif e.type == KEYDOWN and e.key == K_c: cell = random.choice(automata.elements.keys()) for _ in range(random.randint(10,60)): j = real_net.job(info_mgr.get_next_jobid(), start_time, random.randint(5, 2000)) automata.elements[cell].element.add_job(j) # jobid += 1 # new_jobs += 1 elif e.type == KEYDOWN and e.key == pygame.locals.K_ESCAPE: current_element = None for el in automata.elements.values(): if el.position == (0,0): current_element = el.element cmd_str = "a,{0}-{1},50,500,1".format(*current_element.position) msg_mgr.add_msg("[INFO] Shortcut from keyboard : {0}".format(cmd_str)) _, params = analyze_cmd(cmd_str) cell_pos = params[0] num_jobs = int(params[1]) work_requested = int(params[2]) min_workload=int(params[3]) posts = [position_name2(automata.elements[x].element.position) for x in automata.elements] if cell_pos in posts: current_node = None for x in automata.elements: if position_name2(automata.elements[x].element.position) == cell_pos: current_node = automata.elements[x].element for _ in range(num_jobs): j = real_net.job(info_mgr.get_next_jobid(), start_time, work_requested, min_workload) current_node.add_job(j) msg_mgr.add_msg("[INFO] Added {0} new jobs to {1}".format(str(num_jobs), cell_pos)) else: msg_mgr.add_msg("[ERROR] Something went wrong while adding jobs to {0} node".format(cell_pos)) elif e.type == USEREVENT or (e.type == KEYDOWN and e.key == pygame.locals.K_RETURN): cmd_type, params = analyze_cmd(cmd_str) if cmd_type: if cmd_type == ADD_JOB and len(params) == 4: try: cell_pos = params[0] num_jobs = int(params[1]) work_requested = int(params[2]) min_workload=int(params[3]) posts = [position_name2(automata.elements[x].element.position) for x in automata.elements] if cell_pos in posts: current_node = None for x in automata.elements: if position_name2(automata.elements[x].element.position) == cell_pos: current_node = automata.elements[x].element for _ in range(num_jobs): j = real_net.job(info_mgr.get_next_jobid(), start_time, work_requested, min_workload) current_node.add_job(j) # jobid +=1 # new_jobs +=1 msg_mgr.add_msg("[INFO] Added {0} new jobs to {1}".format(str(num_jobs), cell_pos)) else: msg_mgr.add_msg("[ERROR] Something went wrong while adding jobs to {0} node".format(cell_pos)) except Exception as e: msg_mgr.add_msg("[INFO] Bad command : {0}".format(e)) elif cmd_type == ADD_NODE and len(params) == 2: if not automata.full(): position = (int(params[0]), int(params[1])) inserted = False while not inserted and not automata.full(): if not (position in automata.elements_position()): net_node = real_net.node(position) cell = ca.ca_cell(element = net_node) if automata.add_element(cell): info_mgr.add_cell(position_name(net_node), history_len=info_mgr.cell_length(), default_value=0) # cell_wl_history[position_name(net_node)] = [0 for _ in range(len(cell_wl_history[random.choice(cell_wl_history.keys())]))] inserted = True msg_mgr.add_msg("[INFO] Added new node : real_pos {0} - automata_pos {1}".format( str(net_node.position), str(cell.position))) else: msg_mgr.add_msg("[ERROR] Can't add node in {0}".format(str(position))) elif cmd_type == DELETE_NODE: pos = (int(params[0]), int(params[1])) pos2 = automata.get_cell_pos(pos) automata.remove(pos2) msg_mgr.add_msg("[INFO] Removed node : real_pos {0} - automata_pos {1}".format(str(pos), str(pos2))) elif cmd_type == QUIT_SIM: end = True cmd_str = "" elif e.type == KEYDOWN and e.key == pygame.locals.K_F3: visualize_graphs = not visualize_graphs elif e.type == KEYDOWN and e.key == pygame.locals.K_F5: end = True elif e.type == KEYDOWN: cmd_str += str(e.unicode) automata.update(current_time - start_time) # moved_jobs += new_moved_jobs # ended_jobs += new_ended_jobs # move_of_ended_jobs += new_move_of_ended_jobs # moved_jobs += automata.update(current_time - start_time) screen.fill((250, 250, 250)) grph_act_chr = "" if not visualize_graphs: grph_act_chr = "not " image = font.render("Iter : {0:5} | Time : {1:10} | Framerate {2:5} | Plotting {3}active".format(i, current_time/1000.0, 1000/(1+(current_time - start_time)), grph_act_chr), True, (0,0,0)) r = image.get_rect() r.top = 5 r.left = 5 screen.blit(image, r) for switch in info_mgr.switches.values(): cell = switch[0] color = switch[1] alpha = float(cell.element.already_moved) / float(ca.MOVE_COOLDOWN) image = pygame.Surface((SQUARE_DIM+10, SQUARE_DIM+10)) image.set_alpha(alpha * 255) image.fill(color) rect = image.get_rect() rect.top = (cell.position[1] * (SQUARE_DIM + CELL_PADDING) + AUTOMATA_OFFSET_Y) * GRID_FRAC - 5 rect.left =(cell.position[0] * (SQUARE_DIM + CELL_PADDING) + AUTOMATA_OFFSET_X) * GRID_FRAC - 5 screen.blit(image, rect) for cell in automata.elements: image = pygame.Surface((SQUARE_DIM, SQUARE_DIM)) wl = min(automata.elements[cell].element.workload / automata.elements[cell].element.max_workload, 1.0) color = (int(wl*255), 0, int((1.0 -wl)*255)) if current_time > last_update_time + UPDATE_INT: node_name = position_name(automata.elements[cell].element) info_mgr.add_cell_wl(node_name, wl*100) # cell_wl_history[node_name].append(wl*100) # if len(cell_wl_history[node_name]) > MAX_WL_HISTORY: # cell_wl_history[node_name].pop(0) image.fill(color) rect = image.get_rect() rect.top = (automata.elements[cell].position[1] * (SQUARE_DIM + CELL_PADDING) + AUTOMATA_OFFSET_Y) * GRID_FRAC rect.left =(automata.elements[cell].position[0] * (SQUARE_DIM + CELL_PADDING) + AUTOMATA_OFFSET_X) * GRID_FRAC screen.blit(image, rect) rect = image.get_rect() rect.top = (automata.elements[cell].element.position[1] * (SQUARE_DIM + CELL_PADDING) + GEO_OFFSET_Y) * GRID_FRAC rect.left =(automata.elements[cell].element.position[0] * (SQUARE_DIM + CELL_PADDING) + GEO_OFFSET_X) * GRID_FRAC screen.blit(image, rect) wl_font = font.render("WL:{0}".format(str(automata.elements[cell].element.workload / automata.elements[cell].element.max_workload)), True, (255,255,255)) rect = wl_font.get_rect() rect.top = (automata.elements[cell].position[1] * (SQUARE_DIM + CELL_PADDING)) * GRID_FRAC + AUTOMATA_OFFSET_Y +1 rect.left = (automata.elements[cell].position[0] * (SQUARE_DIM + CELL_PADDING)) * GRID_FRAC + AUTOMATA_OFFSET_X +1 screen.blit(wl_font, rect) rect = image.get_rect() rect.top = (automata.elements[cell].element.position[1] * (SQUARE_DIM + CELL_PADDING) + GEO_OFFSET_Y) * GRID_FRAC +1 rect.left =(automata.elements[cell].element.position[0] * (SQUARE_DIM + CELL_PADDING) + GEO_OFFSET_X) * GRID_FRAC +1 screen.blit(wl_font, rect) wl_font = small_font.render("ID:{0},{1}".format(automata.elements[cell].element.position[0], automata.elements[cell].element.position[1]), True, (255,255,255)) rect = wl_font.get_rect() rect.top = (automata.elements[cell].position[1] * (SQUARE_DIM + CELL_PADDING) + AUTOMATA_OFFSET_Y) * GRID_FRAC +15 rect.left = (automata.elements[cell].position[0] * (SQUARE_DIM + CELL_PADDING) + AUTOMATA_OFFSET_X) * GRID_FRAC +1 screen.blit(wl_font, rect) rect = image.get_rect() rect.top = (automata.elements[cell].element.position[1] * (SQUARE_DIM + CELL_PADDING) + GEO_OFFSET_Y) * GRID_FRAC +15 rect.left =(automata.elements[cell].element.position[0] * (SQUARE_DIM + CELL_PADDING) + GEO_OFFSET_X) * GRID_FRAC +1 screen.blit(wl_font, rect) wl_font = font.render("CELLULAR AUTOMATA", True, (0,0,0)) rect = wl_font.get_rect() rect.top = ((math.sqrt(ca.MAX_CELLS)/2) * (SQUARE_DIM + CELL_PADDING)) * GRID_FRAC + AUTOMATA_OFFSET_Y +40 rect.left = SQUARE_DIM screen.blit(wl_font, rect) wl_font = font.render("REAL NET", True, (0,0,0)) rect = wl_font.get_rect() rect.top = ((math.sqrt(ca.MAX_CELLS)/2) * (SQUARE_DIM + CELL_PADDING)) * GRID_FRAC + AUTOMATA_OFFSET_Y +40 rect.left = ((math.sqrt(ca.MAX_CELLS)) * (SQUARE_DIM + CELL_PADDING)) + AUTOMATA_OFFSET_X/2 + SQUARE_DIM screen.blit(wl_font, rect) wl_font = font.render(cmd_str, True, (0,0,0)) rect = wl_font.get_rect() rect.top = 20 rect.left = 10 screen.blit(wl_font, rect) msg_y_offset = 0 for msg in msg_mgr.msgs: wl_font = font.render(msg, True, (0,0,0)) rect = wl_font.get_rect() rect.top = LOG_OFFSET_Y + msg_y_offset * (MSG_DIM + 5) rect.left= LOG_OFFSET_X msg_y_offset +=1 screen.blit(wl_font, rect) # wls = [automata.elements[cell].element.current_workload for cell in automata.elements] # tot_wl = numpy.average(wls) # # tot_wl_var = numpy.var(wls) if current_time > last_update_time + UPDATE_INT: info_mgr.add_cell_distance(automata.calc_geo_distance()) info_mgr.calc_frame_values() last_update_time = current_time # if i%C_INTERVAL == 0: # wl_history.append(tot_wl) # wl_variance_history.append(tot_wl_var) # new_jobs_history.append(new_jobs) # new_jobs = 0 # moved_jobs_history.append(moved_jobs) # moved_jobs = 0 # medium_distance_history.append(automata.calc_geo_distance()) # if len(wl_history) > MAX_WL_HISTORY: # wl_history.pop(0) # wl_variance_history.pop(0) # new_jobs_history.pop(0) # moved_jobs_history.pop(0) # medium_distance_history.pop(0) # wl_fig.clf() if visualize_graphs: plt.clf() ax1 = plt.subplot(6,1,1) ax1.set_title("Load average") ax1.plot(info_mgr.wl_history) for cell in automata.elements: node_name = position_name(automata.elements[cell].element) ax1.plot(info_mgr.cell_workload_history[node_name], c=(0,1,0,0.35)) ax1.plot(activate_line, c=(1.0,0,0)) ax1.plot(deactivate_line, c=(0.7, 0, 0)) pylab.ylim([-0.5, 100]) ax2 = plt.subplot(6,1,2, sharex=ax1) ax2.set_title("Load variance") ax2.plot(info_mgr.wl_variance_history) pylab.ylim([-0.5, 1000]) ax3 = plt.subplot(6,1,3, sharex=ax1) ax3.set_title("New Jobs") ax3.plot(info_mgr.new_jobs_history) pylab.ylim([-0.1,500]) ax4 = plt.subplot(6,1,4, sharex=ax1) ax4.set_title("Moved Jobs") ax4.plot(info_mgr.moved_jobs_history) pylab.ylim([-0.1, 150]) ax5 = plt.subplot(6,1,5, sharex=ax1) ax5.set_title("Average neighbor distance") ax5.plot(info_mgr.medium_distance_history) pylab.ylim([-0.1, math.sqrt(ca.MAX_CELLS)*2]) ax6 = plt.subplot(6,1,6, sharex=ax1) ax6.set_title("Average move before end") ax6.plot(info_mgr.average_moved_times) pylab.ylim([-0.1, 5]) pylab.xlim([0, MAX_WL_HISTORY]) # plt.tight_layout(0.4, 0.5, 1.0) ## wl_graph_canvas.draw() ## ## wl_renderer = wl_graph_canvas.get_renderer() ## wl_raw_data = wl_renderer.tostring_rgb() ## ## wl_size = wl_graph_canvas.get_width_height() ## wl_surf = pygame.image.fromstring(wl_raw_data, wl_size, "RGB") plt.draw() ## screen.blit(wl_surf, (650, 5)) pygame.display.update() start_time = current_time info_mgr.finalize_stats() return 0
def remove_switch(self, cell): cell_name = position_name(cell) if cell_name in self.switches: del self.switches[cell_name] else: msg_mgr.add_msg("[ERROR] Can't remove switch of {0}".format(cell_name))
def update(self, millisec): neighbor_in_help = [] if self.current_workload/self.max_workload < WL_DEACTIVATE_THRESHOLD: self.communicate = False elif self.current_workload/self.max_workload > WL_ACTIVATE_THRESHOLD: self.communicate = True # print self.cell.position, " has too many jobs" if self.already_moved >0: self.already_moved -=millisec if self.already_moved <=0: info_mgr.remove_switch(self.cell) elif (not DISABLE_JUMP_COMMUNICATIONS) and (not DISABLE_COMMUNICATIONS) and random.random() < MOVING_P and self.already_moved <=0: # chose a random element of the net possible_cells = [x for x in self.cell.net.elements.values() if x != self.cell and x.element.already_moved <= 0] if possible_cells: print possible_cells other_cell = random.choice(possible_cells) dist_self_here = [] for cell_neigh in self.cell.neighbor.values(): if cell_neigh: d = euclidean_dist(self, cell_neigh.element) dist_self_here.append(d) dist_self_there = [] for cell_neigh in other_cell.neighbor.values(): if cell_neigh: if cell_neigh.position != self.cell.position: d = euclidean_dist(self, cell_neigh.element) else: d = euclidean_dist(self, other_cell.element) dist_self_there.append(d) dist_other_here = [] for cell_neigh in self.cell.neighbor.values(): if cell_neigh: if cell_neigh.position != other_cell.position: d = euclidean_dist(other_cell.element, cell_neigh.element) else: d = euclidean_dist(other_cell.element, self) dist_other_here.append(d) dist_other_there = [] for cell_neigh in other_cell.neighbor.values(): if cell_neigh: d = euclidean_dist(other_cell.element, cell_neigh.element) dist_other_there.append(d) if len(dist_self_here) > 0 and len(dist_self_there) > 0 and len(dist_other_here) > 0 and len(dist_other_there) > 0: # print self.position, other_cell.element.position, numpy.average(dist_self_here), numpy.average(dist_self_there) if numpy.average(dist_self_there + dist_other_here) < numpy.average(dist_self_here + dist_other_there): self.cell.switch_with(other_cell) else: neighbor_in_help.append(other_cell) # elif min(dist_self_there) == min(dist_self_here): # if len(dist_self_there) > len(dist_self_here): # if numpy.average(dist_other_here) < numpy.average(dist_other_there): # self.cell.switch_with(other_cell) if (not DISABLE_COMMUNICATIONS) and self.communicate: # print "and want to communicate", self.cell.neighbor for n in self.cell.neighbor: cell_n = self.cell.neighbor[n] if cell_n: if cell_n.element.current_workload/cell_n.element.max_workload < self.current_workload/self.max_workload: neighbor_in_help.append(cell_n) c = "" for e in neighbor_in_help: c+= "({0},{1})\t".format(e.position[0], e.position[1]) # print "he communicate with ",c if neighbor_in_help: medium_workload_neigh = self.calc_neigh_workload(neighbor_in_help) moving_tries = MAX_MOVING_TRIES_FAIL if medium_workload_neigh < self.current_workload/self.max_workload: while self.calc_neigh_workload(neighbor_in_help) < WL_PERCENTAGE_TOLERATION*(self.current_workload/self.max_workload) and moving_tries>0: for n in neighbor_in_help: if self.jobs: try: job_to_move = random.choice(self.jobs.keys()) if self.jobs[job_to_move].will_move(): msg_mgr.add_msg("[INFO] JOB {0} moved {1} times".format(self.jobs[job_to_move].id, self.jobs[job_to_move].moved_times+1)) self.jobs[job_to_move].set_moved() n.element.add_job(self.jobs[job_to_move]) del self.jobs[job_to_move] n.element.calculate_workload(millisec) info_mgr.add_moved_job() else: moving_tries -= 1 except Exception as e: print self.jobs, len(self.jobs) msg_mgr.add_msg("[ERROR] random choice on self.jobs : {0}".format(e)) moving_tries -= 1 # moved_jobs += 1 # # key_to_remove = random.choice(self.jobs.keys()) # n.element.add_job(self.jobs[key_to_remove]) # del self.jobs[key_to_remove] # n.element.calculate_workload(millisec) self.calculate_workload(millisec) medium_workload_neigh = self.calc_neigh_workload(neighbor_in_help) for n in neighbor_in_help: n.element.calculate_workload(millisec) perc_work = 1.0 continue_jobs = {} ended_jobs = {} if self.current_workload > self.max_workload: perc_work = self.max_workload / self.current_workload for jk in self.jobs: job = self.jobs[jk] if job.end_request: job.update(perc_work * job.work_requested * float((millisec - job.start_time)) / float((job.end_request - job.start_time))) else: job.update(job.minimum_workload * perc_work) if job.end: ended_jobs[job.id] = job info_mgr.add_ended_job(job.moved_times) else: continue_jobs[job.id] = job self.jobs = continue_jobs return