Exemplo n.º 1
0
    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 to 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])
        )  # The new state derived from 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.)
        # Can't do step (c) first because we would lose track of which end was extended.
        self.extend_ca_lines_if_needed(new_line)

        # (c)
        # Drop extraneous 0s at the end of new_line
        trimmed_new_line = self.drop_extraneous_0s_from_ends_of_new_line(
            new_line)
        # 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.
        gui_set('rows', value=len(self.ca_lines))
    def setup(self):
        Agent.id = 0
        Minority_Game_World.steps_to_win = 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
        SimEngine.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 = 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_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 = gui_get(HISTORY_LENGTH)
        self.history = [choice([0, 1]) for _ in range(self.history_length)]

        self.generate_the_agents()
Exemplo n.º 3
0
    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.
        # 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))

        # 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()
        gui_set('Rule_nbr', value=self.rule_nbr)

        # 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.
        # !  List of ines that is initialized to an empty list. The values from the nested list get copied to patches for each line
        self.ca_lines: List[List[int]] = []
        # ! Sets the rows number based on how many lists are nested inside of self.ca_lines
        gui_set('rows', value=len(self.ca_lines))
Exemplo n.º 4
0
    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.
        gui_set('rows', value=...)
Exemplo n.º 5
0
    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.
            gui_set(Braess_World.CUT_CORD, enabled=(Braess_World.state == 1))
Exemplo n.º 6
0
    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]

        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
Exemplo n.º 7
0
    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_set('bin_string', value=new_value) to update the value of the widget.
        """

        gui_set('bin_string', value=bin(self.rule_nbr)[2:].zfill(8))
Exemplo n.º 8
0
    def make_switches_and_rule_nbr_consistent(self):
        """
        Make the Slider, the switches, and the bin number consistent: all should contain self.rule_nbr.
        """
        current_switches_nbr = self.get_rule_nbr_from_switches()

        # ** switches number and rule number are not the same
        if current_switches_nbr != self.rule_nbr:
            self.rule_nbr = current_switches_nbr
            gui_set('Rule_nbr', value=self.rule_nbr)
        else:
            # ** the slider changed
            self.rule_nbr = gui_get('Rule_nbr')
            self.set_switches_from_rule_nbr()
        # ** update the binary number for any change in rule number
        self.set_binary_nbr_from_rule_nbr()
Exemplo n.º 9
0
    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 = gui_get('Random?')
            gui_set('init_line', visible=not disabled, value=1)
Exemplo n.º 10
0
 def setup(self):
     GA_World.individual_class = Cycle_Individual
     GA_World.chromosome_class = Cycle_Chromosome
     Cycle_World.cycle_length = gui_get('cycle_length')
     gui_set('Max generations', value=float('inf'))
     gui_set('pop_size', value=100)
     self.pop_size = 100
     gui_set('prob_random_parent', value=20)
     Cycle_World.cycle_length = gui_get('cycle_length')
     super().setup()
Exemplo n.º 11
0
    def set_results(self):
        """ Find and display the best individual. """
        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

        gui_set('best_fitness', value=round(self.best_ind.fitness, 1))
        gui_set('discrepancy', value=round(self.best_ind.discrepancy, 1))
        gui_set('generations', value=self.generations)

        if self.best_ind.discrepancy == 0 or self.generations >= gui_get('Max generations'):
            self.done = True
Exemplo n.º 12
0
    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 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. ##                            #

        gui_set(Braess_World.CUT_CORD, enabled=False)
        gui_set(GO_ONCE, enabled=True)
        gui_set(GOSTOP, enabled=True)
        if gui_get('Slow?'):
            SimEngine.fps = 15
        if not gui_get('Pause?'):
            gui.WINDOW['GoStop'].click()
        Braess_World.state = 'a'