def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # self.pos_to_switch is a dictionary that maps position values in a binary number to range(8) represented # as 3-digit binary strings: # {1: '000', 2: '001', 4: '010', 8: '011', 16: '100', 32: '101', 64: '110', 128: '111'} # The three digits are the rule components and the keys to the switches. # To see it, try: print(self.pos_to_switch) after executing the next line. # The function bin_str() is defined in utils.py self.pos_to_switch = dict( zip([2**i for i in range(8)], CA_World.bin_0_to_7)) # print(self.pos_to_switch) # The rule number used for this run, initially set to 110 as the default rule. # (You might also try rule 165.) # The following sets the local variable self.rule_nbr. It doesn't change the 'Rule_nbr' slider widget. self.rule_nbr = 110 # Set the switches and the binary representation of self.rule_nbr. self.set_switches_from_rule_nbr() self.set_binary_nbr_from_rule_nbr() self.init = None # self.ca_lines is a list of lines, each of which is a list of 0/1. Each line represents # a state of the CA, i.e., all the cells in the line. self.ca_list contains the entire # history of the CA. '''self.ca_lines is that cointains the rows of the 1d automaton, the : in pythion denotes the type that will be assigned to the variable in this case A list containing a list of integers. It is initializing this list as empty''' self.ca_lines: List[List[int]] = [] # gui.WINDOW['rows'].update(value=len(self.ca_lines)) '''this line is setting the number of ca_lines, (the number of rows) to the graphical representation of the CA, which in this case will be 0 since it is currently empty''' SimEngine.gui_set('rows', value=len(self.ca_lines))
def setup(self): """ Set up for state 1. Build the contraption piece by piece. """ self.top_spring = Braess_Link.vertical_linked_nodes(Braess_Link, self.x, Braess_World.top) self.top_cord = self.top_spring.extend_linked_nodes(Braess_Cord) self.bottom_spring = self.top_cord.extend_linked_nodes(Braess_Link) self.weight_cord = self.bottom_spring.extend_linked_nodes(Braess_Cord) # Make node_2 of the weight_cord the weight. Braess_World.weight_node = self.weight_cord.node_2 Braess_World.weight_node.shape_name = CIRCLE Braess_World.weight_node.color = Color('plum4') # ## Done with building state 1. ## # self.adjustable_links = [self.top_spring, self.top_cord, self.bottom_spring, self.weight_cord] SimEngine.gui_set(Braess_World.CUT_CORD, enabled=False) Braess_World.state = 1 Agent.some_agent_changed = True # In case we did the animation in slow motion and this is a second run. # Can't do this when animation ends because we want to stay # in slow motion as the springs contract and lift the weight. SimEngine.fps = 60
def step(self): # If we are doing animation: if Braess_World.state == 'a': if not Agent.key_step_done: Agent.run_an_animation_step() else: self.setup_2() return # We are not doing animation. We are in either state_1 or state_2. Process them normally. # If there was a change during the previous step, see if additional changes are needed. if Agent.some_agent_changed: # When a link changes length, Agent.some_agent_changed is set to True. Agent.some_agent_changed = False for lnk in self.adjustable_links: lnk.adjust_nodes() else: # Since no agent changed on the previous step, we're done with this state. # "Click" the STOP button. gui.WINDOW[GOSTOP].click() # Enable/disable the Cut-cord button depending on whether we are leaving state 1. SimEngine.gui_set(Braess_World.CUT_CORD, enabled=(Braess_World.state == 1))
def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # self.pos_to_switch is a dictionary that maps position values in a binary number to range(8) represented # as 3-digit binary strings: # {1: '000', 2: '001', 4: '010', 8: '011', 16: '100', 32: '101', 64: '110', 128: '111'} # The three digits are the rule components and the keys to the switches. # To see it, try: print(self.pos_to_switch) after executing the next line. # The function bin_str() is defined in utils.py # The following two lines do the same thing. Explain how both work. pos_to_switch_a = {2**i: bin_str(i, 3) for i in range(8)} pos_to_switch_b = dict(zip([2**i for i in range(8)], CA_World.bin_0_to_7)) assert pos_to_switch_a == pos_to_switch_b self.pos_to_switch = ... # pos_to_switch_a or pos_to_switch_b # The rule number used for this run, initially set to 110 as the default rule. # (You might also try rule 165.) # The following sets the local variable self.rule_nbr. It doesn't change the 'Rule_nbr' slider widget. self.rule_nbr = 110 # Set the switches and the binary representation of self.rule_nbr. self.set_switches_from_rule_nbr() self.set_binary_nbr_from_rule_nbr() self.init = None # self.ca_lines is a list of lines, each of which is a list of 0/1. Each line represents # a state of the CA, i.e., all the cells in the line. self.ca_list contains the entire # history of the CA. self.ca_lines: List[List[int]] = [] # gui.WINDOW['rows'].update(value=len(self.ca_lines)) SimEngine.gui_set('rows', value=len(self.ca_lines))
def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # self.pos_to_switch is a dictionary that maps position values in a binary number to range(8) represented # as 3-digit binary strings: # {1: '000', 2: '001', 4: '010', 8: '011', 16: '100', 32: '101', 64: '110', 128: '111'} # The three digits are the rule components and the keys to the switches. # To see it, try: print(self.pos_to_switch) after executing the next line. # The function bin_str() is defined in utils.py # self.pos_to_switch0 = {2**i: bin_str(i, 3) for i in range(8)} self.pos_to_switch = dict( zip([2**i for i in range(8)], CA_World.bin_0_to_7)) # print(self.pos_to_switch0 == self.pos_to_switch) # The rule number used for this run, initially set to 110 as the default rule. # (You might also try rule 165.) # The following sets the local variable self.rule_nbr. It doesn't change the 'Rule_nbr' slider widget. self.rule_nbr = 110 # Set the switches and the binary representation of self.rule_nbr. self.set_switches_from_rule_nbr() self.set_binary_nbr_from_rule_nbr() # self.ca_lines is a list of lines, each of which is a list or string of 0/1. Each line # representsa state of the CA, i.e., all the symbols in the line. self.ca_list contains # the entire history of the CA. self.lists = None self.padding_element = None self.ca_lines = [] SimEngine.gui_set('rows', value=len(self.ca_lines))
def setup(self): Agent.id = 0 Minority_Game_World.steps_to_win = SimEngine.gui_get(STEPS_TO_WIN) # Adjust how far one step is based on number of steps needed to win Minority_Game_World.one_step = (gui.PATCH_COLS - 2) * gui.BLOCK_SPACING() / Minority_Game_World.steps_to_win # For longer/shorter races, speed up/slow down frames/second gui.set_fps(round(6*Minority_Game_World.steps_to_win/50)) # self.done will be True if this a repeat game with the same agents. if self.done: self.reset_agents() return # This is the normal setup. Minority_Game_World.nbr_agents = SimEngine.gui_get(NBR_AGENTS) if Minority_Game_World.nbr_agents % 2 == 0: Minority_Game_World.nbr_agents += (1 if Minority_Game_World.nbr_agents < gui.WINDOW[NBR_AGENTS].Range[1] else (-1)) # gui.WINDOW[NBR_AGENTS].update(value=Minority_Game_World.nbr_agents) SimEngine.gui_set(NBR_AGENTS, value=Minority_Game_World.nbr_agents) Minority_Game_World.random_agent_ids = {0, Minority_Game_World.nbr_agents - 1} # Generate a random initial history self.history_length = SimEngine.gui_get(HISTORY_LENGTH) self.history = [choice([0, 1]) for _ in range(self.history_length)] self.generate_the_agents()
def step(self): """ Take one step in the simulation. (a) Generate an additional line for the ca. (Use a copy of self.ca_lines[-1].) (b) Extend all lines in ca_lines if the new line is longer (with additional 1's) than its predecessor. (c) Trim the new line and add it to the end of self.ca_lines. (d) Refresh display from values in self.ca_lines. """ # (a) new_line: str = self.generate_new_line_from_current_line( self.ca_lines[-1]) # (b) # Extend lines in self.ca_lines at each end as needed. (Don't extend for extra 0's at the ends.) # If either end is '1', add '0' to that end of all strings. # Can't drop the 0's first because we would lose track of which end was extended. ... # (c) # ==> String-specific <== # (Must compare to '1'. Can't just use character as boolean. '0' is treated as True.) start = 0 if new_line[0] == '1' else 1 end = len(new_line) if new_line[-1] == '1' else len(new_line) - 1 trimmed_new_line: str = new_line[start:end] # Add trimmed_new_line to the end of self.ca_lines self.ca_lines.append(trimmed_new_line) # (d) # Refresh the display from self.ca_lines self.set_display_from_lines() # Update the 'rows' widget. SimEngine.gui_set('rows', value=...)
def make_switches_and_rule_nbr_consistent(self): """ Make the Slider, the switches, and the bin number consistent: all should contain self.rule_nbr. """ # gui.WINDOW['Rule_nbr'].update(value=self.rule_nbr) SimEngine.gui_set('Rule_nbr', value=self.rule_nbr) self.set_switches_from_rule_nbr() self.set_binary_nbr_from_rule_nbr()
def step(self): self.check_middle() SimEngine.gui_set('ticks', value=World.ticks) spawn_rate = SimEngine.gui_get(SPAWN_RATE) self.spawn_commuters(spawn_rate) # if World.ticks % 15 == 0: for agent in World.agents: agent.commuter_move() for patch in BraessParadoxWorld.patch_vari: if patch['road_type'] == 0: self.determine_congestion(patch)
def set_binary_nbr_from_rule_nbr(self): """ Translate self.rule_nbr into a binary string and put it into the gui.WINDOW['bin_string'] widget. For example, if self.rule_nbr is 110, the string '(01101110)' is stored in gui.WINDOW['bin_string']. Include the parentheses around the binary number. Use gui.WINDOW['bin_string'].update(value=new_value) to update the value of the widget. Use SimEngine.gui_set('bin_string', value=new_value) to update the value of the widget. """ binary = self.int_to_8_bit_binary(self.rule_nbr, False) binary_str = ''.join(binary) SimEngine.gui_set('bin_string', value=binary)
def set_binary_nbr_from_rule_nbr(self): """ Translate self.rule_nbr into a binary string and put it into the gui.WINDOW['bin_string'] widget. For example, if self.rule_nbr is 110, the string '(01101110)' is stored in gui.WINDOW['bin_string']. Include the parentheses around the binary number. Use SimEngine.gui_set('bin_string', value=new_value) to update the value of the widget. """ binary_rule_nbr = bin_str(self.rule_nbr, 8) SimEngine.gui_set('Rule_nbr', value=self.rule_nbr) new_bin_value = binary_rule_nbr + ' (binary)' SimEngine.gui_set('bin_string', value=new_bin_value)
def set_switches_from_rule_nbr(self): """ Update the settings of the switches based on self.rule_nbr. Note that the 2^i position of self.rule_nbr corresponds to self.pos_to_switch[i]. That is, self.pos_to_switch[i] returns the key for the switch representing position 2^i. Set that switch as follows: gui.WINDOW[self.pos_to_switch[pos]].update(value=new_value). Set that switch as follows: SimEngine.gui_set(self.pos_to_switch[pos], value=new_value). (new_value will be either True or False, i.e., 1 or 0.) This is the inverse of get_rule_nbr_from_switches(). """ for rule_switch, enabled in zip(CA_World.bin_0_to_7, self.int_to_8_bit_binary(self.rule_nbr)): SimEngine.gui_set(rule_switch, value=(True if enabled=='1' else False))
def set_binary_nbr_from_rule_nbr(self): """ Translate self.rule_nbr into a binary string and put it into the gui.WINDOW['bin_string'] widget. For example, if self.rule_nbr is 110, the string '(01101110)' is stored in gui.WINDOW['bin_string']. Include the parentheses around the binary number. Use SimEngine.gui_set('bin_string', value=new_value) to update the value of the widget. """ binary_list = self.rule_nbr_to_binary_list() # [0, 0, 0, 1] # ['0', '0', '0', '1'] binary_list_to_strs = [str(x) for x in binary_list] rule_nbr_to_bin_str = ''.join(binary_list_to_strs) SimEngine.gui_set('bin_string', value=rule_nbr_to_bin_str)
def set_switches_from_rule_nbr(self): """ Update the settings of the switches based on self.rule_nbr. Note that the 2^i position of self.rule_nbr corresponds to self.pos_to_switch[i]. That is, self.pos_to_switch[i] returns the key for the switch representing position 2^i. Set that switch as follows: SimEngine.gui_set(self.pos_to_switch[pos], value=new_value). (new_value will be either True or False, i.e., 1 or 0.) This is the inverse of get_rule_nbr_from_switches(). """ rule_nbr = self.rule_nbr for pos in self.pos_to_switch: SimEngine.gui_set(self.pos_to_switch[pos], value=rule_nbr % 2) rule_nbr = rule_nbr // 2
def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # self.pos_to_switch is a dictionary that maps position values in a binary number to range(8) represented # as 3-digit binary strings: # {1: '000', 2: '001', 4: '010', 8: '011', 16: '100', 32: '101', 64: '110', 128: '111'} # The three digits are the rule components and the keys to the switches. # To see it, try: print(self.pos_to_switch) after executing the next line. # The function bin_str() is defined in utils.py self.pos_to_switch = dict(zip([2**i for i in range(8)], CA_World.bin_0_to_7)) # print(self.pos_to_switch) # The rule number used for this run, initially set to 110 as the default rule. # (You might also try rule 165.) # The following sets the local variable self.rule_nbr. It doesn't change the 'Rule_nbr' slider widget. self.rule_nbr = 110 # Set the switches and the binary representation of self.rule_nbr. # self.set_switches_from_rule_nbr() # self.set_binary_nbr_from_rule_nbr() # self.set_slider_from_rule_nbr() self.make_switches_and_rule_nbr_consistent() self.init = None # self.ca_lines is a list of lines, each of which is a list of 0/1. Each line represents # a state of the CA, i.e., all the cells in the line. self.ca_list contains the entire # history of the CA. self.ca_lines: List[List[int]] = [] self.ca_left_lines: List[List[int]] = [] self.ca_right_lines: List[List[int]] = [] #For testing --- REMOVE self.ca_lines.append([]) while len(self.ca_lines[0]) < 151: self.ca_lines[0].append(0) self.ca_lines[0][75] = 1 self.ca_left_lines.append([0,0]) self.ca_right_lines.append([0,0]) #end of test code # gui.WINDOW['rows'].update(value=len(self.ca_lines)) SimEngine.gui_set('rows', value=len(self.ca_lines))
def handle_event(self, event): """ This is called when a GUI widget is changed and the change isn't handled by the system. The key of the widget that changed is in event. """ # Handle color change requests. super().handle_event(event) # Handle rule nbr change events, either switches or rule_nbr slider if event in ['Rule_nbr'] + CA_World.bin_0_to_7: self.make_switches_and_rule_nbr_consistent() # When the user checks the 'Random?' box, the Input line area should disappear. # When the user unchecks the 'Random?' box, the Input line area should re-appear. elif event == 'Random?': disabled = SimEngine.gui_get('Random?') SimEngine.gui_set('init_line', visible=not disabled, value='1')
def step(self): """ Take one step in the simulation. (a) Generate an additional line for the ca. (Use a copy of self.ca_lines[-1].) (b) Extend all lines in ca_lines if the new line is longer (with additional 1's) than its predecessor. (c) Trim the new line and add it to the end of self.ca_lines. (d) Refresh display from values in self.ca_lines. """ # (a) new_line: str = self.generate_new_line_from_current_line( copy(self.ca_lines[-1])) # (b) # Extend lines in self.ca_lines at each end as needed. (Don't extend for extra 0's at the ends.) if self.lists: self.extend_ca_lines_if_needed(new_line) else: # Strings line_end = {'1': '0', '0': ''} # If either end is '1', add '0' to that end of all strings. # Can't drop the 0's first because we would lose track of which end was extended. if '1' in (new_line[0], new_line[-1]): # Use the line_end dictionary to look up values for left_end and right_end left_end = line_end[new_line[0]] right_end = line_end[new_line[-1]] self.ca_lines = [ left_end + line + right_end for line in self.ca_lines ] # (c) if self.lists: trimmed_new_line = self.drop_extraneous_0s_from_ends_of_new_line( new_line) else: # Strings start = 0 if new_line[0] == '1' else 1 end = len(new_line) if new_line[-1] == '1' else len(new_line) - 1 trimmed_new_line: str = new_line[start:end] # Add trimmed_new_line to the end of self.ca_lines self.ca_lines.append(trimmed_new_line) # (d) # Refresh the display from self.ca_lines self.set_display_from_lines() # Update the 'rows' widget. SimEngine.gui_set('rows', value=len(self.ca_lines))
def end_commute(self, agent): travel_time = (World.ticks - agent.birth_tick) / 450 smoothing = SimEngine.gui_get('smoothing') World.travel_time = travel_time if World.avg == 0: World.avg = travel_time else: World.avg = ((len(World.agents) - 1) * World.avg + travel_time) / len(World.agents) SimEngine.gui_set(AVERAGE, value=World.avg) if agent.route == 0: if World.top == 0: World.top = travel_time self.fastest_top = travel_time else: World.top = ((travel_time + (smoothing - 1) * World.top) / smoothing) if travel_time < self.fastest_top: self.fastest_top = travel_time World.num_top = World.num_top - 1 elif agent.route == 1: if World.bot == 0: World.bot = travel_time self.fastest_bot = travel_time else: World.bot = ((travel_time + (smoothing - 1) * World.bot) / smoothing) if travel_time < self.fastest_bot: self.fastest_bot = travel_time World.num_bot = World.num_bot - 1 else: if World.middle == 0: World.middle = travel_time self.fastest_mid = travel_time else: World.middle = ((travel_time + (smoothing - 1) * World.middle) / smoothing) if travel_time < self.fastest_mid: self.fastest_mid = travel_time World.num_mid = World.num_mid - 1 print( f"Tick:{World.ticks} T_time:{World.travel_time} Avg:{World.avg} \n" f"Mid_Time:{World.middle} Top_Time:{World.top} Bot_Time:{World.bot}\n" ) SimEngine.gui_set(FASTEST_TOP, value=self.fastest_top) SimEngine.gui_set(FASTEST_BOTTOM, value=self.fastest_bot) SimEngine.gui_set(FASTEST_MIDDLE, value=self.fastest_mid) self.despawn_list.append(agent)
def set_switches_from_rule_nbr(self): """ Update the settings of the switches based on self.rule_nbr. Note that the 2^i position of self.rule_nbr corresponds to self.pos_to_switch[i]. That is, self.pos_to_switch[i] returns the key for the switch representing position 2^i. Set that switch as follows: gui.WINDOW[self.pos_to_switch[pos]].update(value=new_value). Set that switch as follows: SimEngine.gui_set(self.pos_to_switch[pos], value=new_value). (new_value will be either True or False, i.e., 1 or 0.) This is the inverse of get_rule_nbr_from_switches(). """ # List of 0s and 1s... based off of rule number (binary) # [0, 1, 1, 0, 1, 1, 1, 0] rule_nbr_to_binary = list(reversed(self.rule_nbr_to_binary_list())) for i in range(8): # for every element in range(8) -> [0,1,2,3,4,5,6,7] dec_value = 2 ** i SimEngine.gui_set(self.pos_to_switch[dec_value], value=rule_nbr_to_binary[i])
def disable_enable_buttons(self): # 'enabled' is a pseudo attribute. gui.gui_set replaces it with 'disabled' and negates the value. SimEngine.gui_set('Delete random node', enabled=bool(World.agents)) SimEngine.gui_set('Delete random link', enabled=bool(World.links)) SimEngine.gui_set('Create random link', enabled=len(World.links) < len(World.agents) * (len(World.agents) - 1) / 2) SimEngine.gui_set('Delete shortest-path link', enabled=self.shortest_path_links)
def set_results(self): """ Find and display the best individual. """ # noinspection PyNoneFunctionAssignment current_best_ind = self.get_best_individual() if self.best_ind is None or current_best_ind.discrepancy < self.best_ind.discrepancy: self.best_ind = current_best_ind SimEngine.gui_set('best_fitness', value=round(self.best_ind.fitness, 1)) SimEngine.gui_set('discrepancy', value=round(self.best_ind.discrepancy, 1)) SimEngine.gui_set('generations', value=self.generations)
def set_results(self): current_best_ind = self.get_best_individual() if self.best_ind is None or current_best_ind.discrepancy < self.best_ind.discrepancy: self.best_ind = current_best_ind SimEngine.gui_set('best_fitness', value=round(self.best_ind.fitness, 1)) SimEngine.gui_set('discrepancy', value=round(self.best_ind.discrepancy, 1)) SimEngine.gui_set('generations', value=self.generations)
def resume_ga(self): if self.done: self.done = False self.best_ind = None SimEngine.gui_set('best_fitness', value=None) go_stop_button = gui.WINDOW[GOSTOP] SimEngine.gui_set(GOSTOP, enabled=True) SimEngine.gui_set(GO_ONCE, enabled=True) go_stop_button.click() self.set_results()
def disable_enable_buttons(self): # 'enabled' is a pseudo attribute. gui.gui_set replaces it with 'disabled' and negates the value. SimEngine.gui_set(DELETE_RANDOM_NODE, enabled=bool(World.agents)) SimEngine.gui_set(DELETE_RANDOM_LINK, enabled=bool(World.links)) SimEngine.gui_set(CREATE_RANDOM_LINK, enabled=len(World.links) < len(World.agents) * (len(World.agents) - 1) / 2) SimEngine.gui_set(DELETE_SHORTEST_PATH_LINK, enabled=self.shortest_path_links and len(self.selected_nodes) == 2) # Show node id's or not as requested. show_labels = SimEngine.gui_get(SHOW_NODE_IDS) for node in World.agents: node.label = str(node.id) if show_labels else None
def resume_ga(self): """ This is used when one of the parameters changes dynamically. It is called from handle_event. (See above.) """ if self.done: self.done = False self.best_ind = None SimEngine.gui_set('best_fitness', value=None) go_stop_button = gui.WINDOW[GOSTOP] SimEngine.gui_set(GOSTOP, enabled=True) SimEngine.gui_set(GO_ONCE, enabled=True) go_stop_button.click() self.set_results()
def step(self): SimEngine.gui_set(key='ticks', value=self.ticks) commuters_finished = [] nbr_commuters = 0 nbr_commuters_dynamic = 0 nbr_commuters_static = 0 nbr_commuters_middle = 0 # Constantly check the middle in case it's activated mid-go # self.check_middle() # Keep spawning commuters self.spawn_commuters() for commuter in self.agents: nbr_commuters += 1 if commuter.route == dynamic_road: nbr_commuters_dynamic += 1 elif commuter.route == static_road: nbr_commuters_static += 1 else: nbr_commuters_middle += 1 current_patch = commuter.current_patch() if commuter.last_patch != current_patch: if current_patch == self.top_right: commuter.move_to_xy(self.top_right_center_pixel) if commuter.route == middle_road: commuter.speed = 25.0 commuter.move( turn_towards=self.bottom_left_center_pixel) else: commuter.move( turn_towards=self.bottom_right_center_pixel) elif current_patch == self.bottom_left: if commuter.route == middle_road: commuter.speed = commuter.base_speed commuter.move_to_xy(self.bottom_left_center_pixel) commuter.move(turn_towards=self.bottom_right_center_pixel) elif current_patch == self.bottom_right: SimEngine.gui_set(key='top', value=self.ticks - commuter.birth_tick) commuters_finished.append(commuter) else: commuter.move() commuter.last_patch = current_patch for finished_commuter in commuters_finished: nbr_commuters -= 1 finished_commuter.die() SimEngine.gui_set(key='nbr_commuters', value=nbr_commuters) SimEngine.gui_set(key='nbr_commuters_dynamic', value=nbr_commuters_dynamic) SimEngine.gui_set(key='nbr_commuters_static', value=nbr_commuters_static) SimEngine.gui_set(key='nbr_commuters_middle', value=nbr_commuters_middle)
def update_gui_data(self): SimEngine.gui_set(AVERAGE, value=str(self.avg)) SimEngine.gui_set(FASTEST_TOP, value=str(self.top)) SimEngine.gui_set(FASTEST_MIDDLE, value=str(self.middle)) SimEngine.gui_set(FASTEST_BOTTOM, value=str(self.bottom))
def update_ticks(self): SimEngine.gui_set(TICKS, value=str(self.ticks))
def update_gui_data(self): SimEngine.gui_set(AVERAGE, value=str(self.avg_time)) SimEngine.gui_set(FASTEST_TOP, value=str(self.latest_top_time)) SimEngine.gui_set(FASTEST_MIDDLE, value=str(self.latest_middle_time)) SimEngine.gui_set(FASTEST_BOTTOM, value=str(self.latest_bottom_time))
def setup_a(self): """ Set up for the drop weight animation. """ # Move out by a small amount so that the two lines can be seen. step = 5 if SimEngine.gui_get('Pause?') else 0 self.top_spring.move_by_dxdy((step, 0)) self.top_spring.set_target_by_dxdy((self.x_offset-step, 0)) self.weight_cord.set_target_by_dxdy((0, Braess_World.cord_slack)) center_bar_node = self.bottom_spring.node_2 # Construct the full bar. bar_y = center_bar_node.y left_bar_node = Braess_Node(Pixel_xy( (self.x, bar_y) ) ) right_bar_node = Braess_Node(Pixel_xy( (self.x, bar_y) ) ) # By convention, the position of node_1 determines node_2's position. # In this case, since we will be pulling the bar up by its ends, # make the ends the controlling nodes. self.bar_right = Braess_Bar(right_bar_node, center_bar_node) self.bar_left = Braess_Bar(left_bar_node, center_bar_node) # Attach the bottom spring to the left end of the bar. self.bottom_spring.node_2 = left_bar_node left_bar_node.move_by_dxdy(Velocity((-step, 0))) right_bar_node.move_by_dxdy(Velocity((step, 0))) left_bar_node.set_target_by_dxdy(Velocity((-self.x_offset+step, Braess_World.cord_slack))) right_bar_node.set_target_by_dxdy(Velocity((self.x_offset-step, Braess_World.cord_slack))) # Attach the top cord to the right end of the bar rather than the center. self.top_cord.node_2 = right_bar_node # The left cord is a new element in state 2. It is offset to the left. x_coord = self.x cord_length = self.bottom_spring.node_1.y - Braess_World.top self.left_cord = Braess_Link.vertical_linked_nodes(Braess_Cord, x_coord, Braess_World.top, length=cord_length) # The left cord is offset to the left. self.left_cord.move_by_dxdy((-step, 0)) self.left_cord.node_1.set_target_by_dxdy(Velocity((-self.x_offset + step, 0))) self.left_cord.node_2.set_target_by_dxdy(Velocity((-self.x_offset + step, Braess_World.cord_slack))) self.left_cord.color = Color('yellow2') self.top_cord.color = Color('yellow2') # Make the left_cord's bottom node the top node of the bottom spring. World.agents.remove(self.bottom_spring.node_1) self.bottom_spring.node_1 = self.left_cord.node_2 # Add the new cord and bars to the adjustable links. self.adjustable_links.extend([self.left_cord, self.bar_right, self.bar_left]) Agent.key_step_done = False # ## Done with the setup for the animation. ## # SimEngine.gui_set(Braess_World.CUT_CORD, enabled=False) SimEngine.gui_set(GO_ONCE, enabled=True) SimEngine.gui_set(GOSTOP, enabled=True) if SimEngine.gui_get('Slow?'): SimEngine.fps = 15 if not SimEngine.gui_get('Pause?'): gui.WINDOW['GoStop'].click() Braess_World.state = 'a'