SophZoe / Genetic_Algorithm

A study/portfolio case for university (:
https://moodle.hs-duesseldorf.de/pluginfile.php/461132/mod_resource/content/0/Projektauftrag_Genetic_algorithm.pdf
Apache License 2.0
3 stars 3 forks source link

Reconfigure "search_food" #53

Closed Jxshyz closed 7 months ago

Jxshyz commented 7 months ago

At the moment we use a double for loop to search the whole board for food. Instead, we could use np.argmin to store the distance between the agent and the food and use the respective visibility as a trigger so that the agent recognizes the food and moves towards it.

julietteyek commented 7 months ago

hi, I tried around and thought of something like this:

def search_food(self, board):
        visibilityrange = self.genetic["Visibilityrange"]

        #creates a mesh grid for coords within the cisibility range
        dx, dy = np.meshgrid(range(-visibilityrange, visibilityrange + 1), range(-visibilityrange, visibilityrange + 1))

        # finds the index of the minimum distance
        min_distance = np.argmin(distances)

        # calculates the difference (or "offset") in x and y based on the FLATTENED min_distance index
        num_cols = distances.shape[1]
        diff_x = min_distance // num_cols
        diff_y = min_distance % num_cols

        #this calculates the nearest food, transforms the relative position to the absolute placement on the board
        x, y = self.position[0] + diff_x, self.position[1] + diff_y

        if 0 <= x < WIDTH and 0 <= y < HEIGHT and board.food[x][y] != 0:
            #here just as before....
        return None

and for the move function:

if self_sick is True:
  [#code as before]
  else:
      #get the relative position of the nearest food to the agent (as returned in the previous def"search_food")
      relative_food_pos = self.search_food(board)

      #and then if food is within visibility range do this
      if relative_food_pos is not None:
                    dx, dy = relative_food_pos
                    new_x = max(0, min(WIDTH - 1, self.position[0] + dx))
                    new_y = max(0, min(HEIGHT - 1, self.position[1] + dy))
                    self.position = (new_x, new_y)
                    self.covered_distance += 1
      else:
                    #do a random move

What do you think?

Jxshyz commented 7 months ago

Thats a really good idea to use more efficient data structures for this heavy method.

What do you think about my following shot on calculating the distances: def search_food_efficient(self, board): visibilityrange = self.genetic["Visibilityrange"]

# Erstelle ein Gitter (Grid) aller Punkte innerhalb der Sichtbarkeitsreichweite
y_range, x_range = np.ogrid[-visibilityrange:visibilityrange+1, -visibilityrange:visibilityrange+1]

# Berechne die Distanz von jedem Punkt im Gitter zur aktuellen Position des Agenten
distances = np.sqrt(x_range**2 + y_range**2)

# Erstelle ein Boolesches Gitter, das True ist, wo Nahrung vorhanden ist
food_mask = np.zeros_like(distances, dtype=bool)

# Prüfe, welche Punkte innerhalb der Grenzen liegen und wo Nahrung ist
for dy in range(-visibilityrange, visibilityrange + 1):
    for dx in range(-visibilityrange, visibilityrange + 1):
        x, y = self.position[0] + dx, self.position[1] + dy
        if 0 <= x < WIDTH and 0 <= y < HEIGHT and board.food[x][y] != 0:
            food_mask[dy + visibilityrange, dx + visibilityrange] = True

# Wende die Nahrungsmaske auf die Distanzen an, setze alle anderen auf unendlich
distances = np.where(food_mask, distances, np.inf)

# Finde die Position der minimalen Distanz
min_distance_idx = np.argmin(distances)
if distances.flat[min_distance_idx] == np.inf:
    return None  # Keine Nahrung gefunden

# Berechne die relative Position der nächstgelegenen Nahrungsquelle
dy, dx = np.unravel_index(min_distance_idx, distances.shape)
closest_food = (dx - visibilityrange, dy - visibilityrange)

return closest_food
Jxshyz commented 7 months ago

also i figured that agents might infinitely circle around food - what do you think about my attempt on stopping this:

relative_food_pos = self.search_food_efficient(board) if relative_food_pos is not None: dx, dy = relative_food_pos

Berechne die neue Position unter Berücksichtigung der maximalen Bewegungsdistanz

                step_size = self.genetic["Kondition"]  # Angenommen, dies bestimmt die maximale Bewegungsdistanz
                # Adjust movement to ensure the agent stops at the food
                dx = max(min(dx, step_size), -step_size) if dx != 0 else 0     # Makes sure that step size adjusts to the agent - food distance
                dy = max(min(dy, step_size), -step_size) if dy != 0 else 0

                new_x = max(0, min(WIDTH - 1, self.position[0] + dx))
                new_y = max(0, min(HEIGHT - 1, self.position[1] + dy))
                self.position = (new_x, new_y)
                self.covered_distance += 1

                # Überprüfe, ob die neue Position Nahrung enthält und konsumiere diese
                if board.food[new_x][new_y] != 0:
                    self.consuming_food(board.food[new_x][new_y])
                    board.food[new_x][new_y] = 0  # Entferne die Nahrung von der Karte
            else:
                # Führe einen zufälligen Zug aus, wenn keine Nahrung gefunden wird
                dx = random.choice([-1, 1]) * step_size
                dy = random.choice([-1, 1]) * step_size
                new_x = max(0, min(WIDTH - 1, self.position[0] + dx))
                new_y = max(0, min(HEIGHT - 1, self.position[1] + dy))
                self.position = (new_x, new_y)
                self.covered_distance += 1
julietteyek commented 7 months ago

implemented it