Theseus

“Theseus” noemde de wiskundige en bedenker van de informatietheorie Claude Shannon in 1950 zijn muis, die zelfstandig zijn weg zocht door een labyrint en zo de eerste zelflerende machine werd. Met relais die destijds werden gebruikt in telefooncentrales bouwde hij een apparaat dat ons ook vandaag nog perplex doet staan.

Als het mechanische muisje op een willekeurige plek in het labyrint wordt gezet, zoekt hij systematisch naar de uitgang. De weg daarheen wordt in relais onder het labyrint opgeslagen. Dus als de muis vervolgens weer ergens wordt neergezet, kan hij de opgeslagen weg oproepen en zonder verder zoeken zijn doel bereiken.

Daar was tamelijk makkelijk een simulatie van te maken geschreven in Python. Het was even klooien met de definitie van het doolhof. Dat zijn uiteindelijk 25 cellen geworden met elk de muren true/ false gedefinieerd (top, right, bottom, left).

import pygame
import sys
import random
from collections import deque

maze_walls = {
    "A5": [True, False, False, True], "B5": [True, False, True, False], "C5": [True, False, True, False], "D5": [True, False, False, False], "E5": [True, True, True, False],
    "A4": [False, False, True, True], "B4": [True, True, False, False], "C4": [True, False, True, True], "D4": [False, True, False, False], "E4": [False, True, False, True],
    "A3": [True, False, False, True], "B3": [False, True, False, False], "C3": [True, True, False, True], "D3": [False, True, True, True], "E3": [False, True, False, True],
    "A2": [False, True, False, True], "B2": [False, False, True, True], "C2": [False, False, True, False], "D2": [True, False, True, False], "E2": [False, True, True, False],
    "A1": [False, False, True, True], "B1": [True, False, True, False], "C1": [True, False, True, False], "D1": [True, False, True, False], "E1": [True, True, True, False]
}

CELL_SIZE = 80
ROWS, COLS = 5, 5
WIDTH, HEIGHT = 800, CELL_SIZE * ROWS
FPS = 2
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
BLUE = (0, 0, 255)
RED = (255, 0, 0)
GREEN = (0, 200, 0)
GRAY = (220, 220, 220)

pygame.init()
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Theseus Mouse Simulation")
clock = pygame.time.Clock()
font = pygame.font.SysFont(None, 36)

nodes = {}
for r in range(ROWS):
    for c in range(COLS):
        label = chr(65 + c) + str(ROWS - r)
        x = c * CELL_SIZE + CELL_SIZE // 2
        y = r * CELL_SIZE + CELL_SIZE // 2
        nodes[label] = (x, y)

graph = {node: [] for node in nodes}
for node, walls in maze_walls.items():
    col = ord(node[0]) - 65
    row = ROWS - int(node[1])
    if not walls[0] and row > 0:
        neighbor = chr(65 + col) + str(ROWS - (row - 1))
        graph[node].append(neighbor)
    if not walls[1] and col < COLS - 1:
        neighbor = chr(65 + (col + 1)) + str(ROWS - row)
        graph[node].append(neighbor)
    if not walls[2] and row < ROWS - 1:
        neighbor = chr(65 + col) + str(ROWS - (row + 1))
        graph[node].append(neighbor)
    if not walls[3] and col > 0:
        neighbor = chr(65 + (col - 1)) + str(ROWS - row)
        graph[node].append(neighbor)

def bfs_shortest_path(start, goal):
    queue = deque([[start]])
    visited = set()
    while queue:
        path = queue.popleft()
        node = path[-1]
        if node == goal:
            return path
        if node not in visited:
            visited.add(node)
            for neighbor in graph[node]:
                new_path = list(path)
                new_path.append(neighbor)
                queue.append(new_path)
    return []

class Mouse:
    def __init__(self, start, goal):
        self.start = start
        self.goal = goal
        self.reset()

    def reset(self):
        self.current = self.start
        self.visited = {self.start}
        self.path = [self.start]
        self.finished = False
        self.shortest_path = []
        self.following_shortest = False
        self.step_index = 0

    def move(self):
        if self.following_shortest:
            if self.step_index < len(self.shortest_path):
                self.current = self.shortest_path[self.step_index]
                self.visited.add(self.current)
                self.step_index += 1
            else:
                self.finished = True
        else:
            neighbors = [n for n in graph[self.current] if n not in self.visited]
            if neighbors:
                next_node = random.choice(neighbors)
                self.current = next_node
                self.visited.add(next_node)
                self.path.append(next_node)
            else:
                if len(self.path) > 1:
                    self.path.pop()
                    self.current = self.path[-1]
            if self.current == self.goal:
                self.finished = True

    def draw(self):
        x, y = nodes[self.current]
        pygame.draw.circle(screen, RED, (x, y), 12)

def draw_maze():
    for node, walls in maze_walls.items():
        col = ord(node[0]) - 65
        row = ROWS - int(node[1])
        x = col * CELL_SIZE
        y = row * CELL_SIZE
        if walls[0]:
            pygame.draw.line(screen, BLACK, (x, y), (x + CELL_SIZE, y), 4)
        if walls[1]:
            pygame.draw.line(screen, BLACK, (x + CELL_SIZE, y), (x + CELL_SIZE, y + CELL_SIZE), 4)
        if walls[2]:
            pygame.draw.line(screen, BLACK, (x, y + CELL_SIZE), (x + CELL_SIZE, y + CELL_SIZE), 4)
        if walls[3]:
            pygame.draw.line(screen, BLACK, (x, y), (x, y + CELL_SIZE), 4)

def draw_learning_map(visited):
    offset_x = WIDTH // 2
    for node in visited:
        x, y = nodes[node]
        pygame.draw.circle(screen, BLUE, (x + offset_x, y), 8)

def draw_mouse_path(path):
    offset_x = WIDTH // 2
    for i in range(len(path) - 1):
        x1, y1 = nodes[path[i]]
        x2, y2 = nodes[path[i + 1]]
        pygame.draw.line(screen, RED, (x1 + offset_x, y1), (x2 + offset_x, y2), 2)

mouse = Mouse("E5", "E1")
start_simulation = False
show_button = False
running = True

while running:
    screen.fill(WHITE)
    for event in pygame.event.get():
        if event.type == pygame.KEYDOWN and event.key == pygame.K_SPACE:
            start_simulation = True
        if event.type == pygame.QUIT:
            running = False

    draw_maze()
    for node, (x, y) in nodes.items():
        color = GREEN if node == mouse.goal else BLACK
        pygame.draw.circle(screen, color, (x, y), 6)

    if start_simulation and not mouse.finished:
        mouse.move()

    mouse.draw()
    draw_learning_map(mouse.visited)
    draw_mouse_path(mouse.path)

    pygame.display.flip()
    clock.tick(FPS)

pygame.quit()
sys.exit()

Geef een reactie

Je e-mailadres wordt niet gepubliceerd. Vereiste velden zijn gemarkeerd met *

Previous post Beflix
Next post ASCII Art