Exemplo n.º 1
0
    def flock(self, showing_flockmates):
        # NetLogo allows one to specify the units within the Gui widget.
        # Here we do it explicitly by multiplying by BLOCK_SPACING().
        vision_limit_in_pixels = SimEngine.gui_get('vision') * BLOCK_SPACING()

        flockmates = self.agents_in_radius(vision_limit_in_pixels)

        if len(flockmates) > 0:

            # If showing_flockmates, create links to flockmates if they don't already exist.
            if showing_flockmates:
                for flockmate in flockmates:
                    # Don't make a link if it already exists.
                    if not link_exists(self, flockmate):
                        Link(self, flockmate, color=Color('skyblue3'))

            nearest_neighbor = min(flockmates, key=lambda flockmate: self.distance_to(flockmate))

            min_separation = SimEngine.gui_get('minimum separation') * BLOCK_SPACING()
            if self.distance_to(nearest_neighbor) < min_separation:
                self.separate(nearest_neighbor)
            else:
                self.align(flockmates)
                self.cohere(flockmates)
Exemplo n.º 2
0
    def adjust_distances(self, velocity_adjustment):
        #get from gui what the base distance units
        dist_unit = SimEngine.gui_get(('dist_unit'))

        #define how many distance units exist per screen
        screen_distance_unit = sqrt(SCREEN_PIXEL_WIDTH()**2 +
                                    SCREEN_PIXEL_HEIGHT()**2) / dist_unit

        #define initial Veolocity as (0,0), forces act in the x and y directions
        repulsive_force: Velocity = Velocity((0, 0))

        #for all other agents excluding this instance
        for agent in (World.agents - {self}):
            #add their respective influence of each other element towards this element, calculate using
            #this center pixel, elements center pixel and using defined units (optional repulsove flag)
            repulsive_force += self.force_as_dxdy(self.center_pixel,
                                                  agent.center_pixel,
                                                  screen_distance_unit,
                                                  repulsive=True)

        # Also consider repulsive force from walls.
        repulsive_wall_force: Velocity = Velocity((0, 0))

        horizontal_walls = [
            Pixel_xy((0, 0)),
            Pixel_xy((SCREEN_PIXEL_WIDTH(), 0))
        ]
        x_pixel = Pixel_xy((self.center_pixel.x, 0))
        for h_wall_pixel in horizontal_walls:
            repulsive_wall_force += self.force_as_dxdy(x_pixel,
                                                       h_wall_pixel,
                                                       screen_distance_unit,
                                                       repulsive=True)

        vertical_walls = [
            Pixel_xy((0, 0)),
            Pixel_xy((0, SCREEN_PIXEL_HEIGHT()))
        ]
        y_pixel = Pixel_xy((0, self.center_pixel.y))
        for v_wall_pixel in vertical_walls:
            repulsive_wall_force += self.force_as_dxdy(y_pixel,
                                                       v_wall_pixel,
                                                       screen_distance_unit,
                                                       repulsive=True)

        #calculate the attractive force generated by all the nodes connected by a link
        attractive_force: Velocity = Velocity((0, 0))
        for agent in (World.agents - {self}):
            if link_exists(self, agent):
                attractive_force += self.force_as_dxdy(self.center_pixel,
                                                       agent.center_pixel,
                                                       screen_distance_unit,
                                                       repulsive=False)

        #find the final force, find out what velocity adjustment is
        net_force = repulsive_force + repulsive_wall_force + attractive_force
        normalized_force: Velocity = net_force / max(
            [net_force.x, net_force.y, velocity_adjustment])
        normalized_force *= 10

        #print force values if selected
        if SimEngine.gui_get('Print force values'):
            print(f'{self}. \n'
                  f'rep-force {tuple(repulsive_force.round(2))}; \n'
                  f'rep-wall-force {tuple(repulsive_wall_force.round(2))}; \n'
                  f'att-force {tuple(attractive_force.round(2))}; \n'
                  f'net-force {tuple(net_force.round(2))}; \n'
                  f'normalized_force {tuple(normalized_force.round(2))}; \n\n')

        #set the velocity of this object
        self.set_velocity(normalized_force)
        #take a step
        self.forward()
Exemplo n.º 3
0
    def adjust_distances(self, velocity_adjustment):
        dist_unit = 8
        screen_distance_unit = sqrt(SCREEN_PIXEL_WIDTH()**2 +
                                    SCREEN_PIXEL_HEIGHT()**2) / dist_unit

        repulsive_force: Velocity = Velocity((0, 0))

        for agent in (World.agents - {self}):
            repulsive_force += self.force_as_dxdy(self.center_pixel,
                                                  agent.center_pixel,
                                                  screen_distance_unit,
                                                  repulsive=True)

        # Also consider repulsive force from walls.
        repulsive_wall_force: Velocity = Velocity((0, 0))

        horizontal_walls = [
            Pixel_xy((0, 0)),
            Pixel_xy((SCREEN_PIXEL_WIDTH(), 0))
        ]
        x_pixel = Pixel_xy((self.center_pixel.x, 0))
        for h_wall_pixel in horizontal_walls:
            repulsive_wall_force += self.force_as_dxdy(x_pixel,
                                                       h_wall_pixel,
                                                       screen_distance_unit,
                                                       repulsive=True)

        vertical_walls = [
            Pixel_xy((0, 0)),
            Pixel_xy((0, SCREEN_PIXEL_HEIGHT()))
        ]
        y_pixel = Pixel_xy((0, self.center_pixel.y))
        for v_wall_pixel in vertical_walls:
            repulsive_wall_force += self.force_as_dxdy(y_pixel,
                                                       v_wall_pixel,
                                                       screen_distance_unit,
                                                       repulsive=True)

        attractive_force: Velocity = Velocity((0, 0))
        for agent in (World.agents - {self}):
            if link_exists(self, agent):
                attractive_force += self.force_as_dxdy(self.center_pixel,
                                                       agent.center_pixel,
                                                       screen_distance_unit,
                                                       repulsive=False)

        net_force = repulsive_force + repulsive_wall_force + attractive_force
        normalized_force: Velocity = net_force / max(
            [net_force.x, net_force.y, velocity_adjustment])
        normalized_force *= 10

        if SimEngine.gui_get('Print force values'):
            print(f'{self}. \n'
                  f'rep-force {tuple(repulsive_force.round(2))}; \n'
                  f'rep-wall-force {tuple(repulsive_wall_force.round(2))}; \n'
                  f'att-force {tuple(attractive_force.round(2))}; \n'
                  f'net-force {tuple(net_force.round(2))}; \n'
                  f'normalized_force {tuple(normalized_force.round(2))}; \n\n')

        self.set_velocity(normalized_force)
        self.forward()
Exemplo n.º 4
0
    def link_nodes_for_graph(self, graph_type, nbr_nodes, ring_node_list):
        """
        Link the nodes to create the requested graph.

        Args:
            graph_type: The name of the graph type.
            nbr_nodes: The total number of nodes the user requested.
                       (Will be > 0 or this method won't be called.)
            ring_node_list: The nodes that have been arranged in a ring.
                            Will contain either:
                            nbr_nodes - 1 if graph type is STAR or WHEEL
                            or nbr_nodes otherwise

        Returns: None

        Overrides this function from graph_framework.
        """
        if graph_type is RANDOM:
            link_chance = SimEngine.gui_get(LINK_PROB) / 100.0
            not_checked_nodes = set(ring_node_list)
            for first_node in ring_node_list:
                not_checked_nodes = not_checked_nodes - {first_node}
                for second_node in not_checked_nodes:
                    if random.random() < link_chance and not link_exists(
                            first_node, second_node):
                        Link(first_node, second_node)

        type = [RING, STAR, WHEEL]
        if graph_type in type:
            for i in range(len(ring_node_list) - 1):
                Link(ring_node_list[i], ring_node_list[i + 1])
            Link(ring_node_list[-1], ring_node_list[0])

            if graph_type is STAR or graph_type is WHEEL:
                # implement shape if asked, needs to be a non static method to implement
                # center_node = self.agent_class(shape_name=SimEngine.gui_get(SHAPE))
                center_node = self.agent_class()
                for node in ring_node_list:
                    Link(center_node, node)

        if graph_type is SMALL_WORLD:
            # neighborhood_size = SimEngine.gui_get(NEIGHBORHOOD_SIZE)
            # for i, node in ring_node_list:
            #     for j in range(1, neighborhood_size + 1):
            #         if not link_exists(node, ring_node_list[(i + j]):
            #             Link(node, ring_node_list[i + j])

            for i in range(len(ring_node_list)):
                for j in range(1,
                               int(SimEngine.gui_get(NEIGHBORHOOD_SIZE)) + 1):
                    # makes sure to loop back if over list size
                    # only taking into account undirected links
                    # make sure to not connect nodes to themselves
                    if not link_exists(ring_node_list[i], ring_node_list[(i + j) % len(ring_node_list)]) and \
                            ring_node_list[i] is not ring_node_list[(i + j) % len(ring_node_list)]:
                        Link(ring_node_list[i],
                             ring_node_list[(i + j) % len(ring_node_list)])

            # rewire chance for each link
            # get rewire chance
            rewire_chance = SimEngine.gui_get(LINK_PROB) / 100.0

            old_links = []
            # deep copy the links
            for l in self.links:
                old_links.append(l)
            for l in old_links:
                # generate random number to see if it gets rewired
                if random.random() < rewire_chance:

                    # pick the first node in the link
                    # find all the nodes neigbors
                    # cosider yourself as a neighbor
                    neighbors = [l.agent_1]
                    for n_link in l.agent_1.all_links():
                        neighbors.append(n_link.other_side(l.agent_1))

                    # check to see if there exists any agent not considered a neighbor
                    if len(neighbors) < len(self.agents):
                        new_neighbor = choice(
                            list(self.agents - set(neighbors)))
                        # print(new_neighbor)
                        # remove the current link
                        self.links.remove(l)
                        # create the new link add it to the list of links to ignore
                        Link(l.agent_1, new_neighbor)

        ###preferential attachment written by Ricardo
        if graph_type is PREF_ATTACHMENT:
            #make a link first
            Link(ring_node_list[0], ring_node_list[1])
            for node in ring_node_list[2:]:
                self.pref_attachment(node)