Compare commits
2 Commits
2c98bb546d
...
50cf0b9b52
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
50cf0b9b52 | ||
|
|
e0cbf69759 |
@ -2,7 +2,6 @@ from SoSe24.algodat.foundation import AlgoDatArray, AlgoDatValue, read_int_seque
|
|||||||
from SoSe24.lec04_trees.bin_tree import BinTree, BinTreeNode
|
from SoSe24.lec04_trees.bin_tree import BinTree, BinTreeNode
|
||||||
from time import perf_counter as pfc
|
from time import perf_counter as pfc
|
||||||
|
|
||||||
|
|
||||||
class AVLTreeNode(BinTreeNode):
|
class AVLTreeNode(BinTreeNode):
|
||||||
def __init__(self, value: AlgoDatValue):
|
def __init__(self, value: AlgoDatValue):
|
||||||
super().__init__(value)
|
super().__init__(value)
|
||||||
|
|||||||
@ -12,7 +12,6 @@ class BTreeNode:
|
|||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "(" + " ".join([str(self.keys[i]) for i in range(self.n)]) + ")"
|
return "(" + " ".join([str(self.keys[i]) for i in range(self.n)]) + ")"
|
||||||
|
|
||||||
|
|
||||||
class BTree:
|
class BTree:
|
||||||
def __init__(self, m: int):
|
def __init__(self, m: int):
|
||||||
self.m = m
|
self.m = m
|
||||||
|
|||||||
@ -4,45 +4,36 @@ from time import perf_counter as pfc
|
|||||||
#Goldener Schnitt
|
#Goldener Schnitt
|
||||||
import math
|
import math
|
||||||
a = (math.sqrt(5) - 1) / 2
|
a = (math.sqrt(5) - 1) / 2
|
||||||
explore_steps = 0
|
|
||||||
|
|
||||||
def h(x, m):
|
def h(x, m):
|
||||||
return int(x*a - int(x*a) * m)
|
return int(x*a - int(x*a) * m)
|
||||||
|
|
||||||
|
|
||||||
def f(x, i, m):
|
def f(x, i, m):
|
||||||
return (h(x, m) + i + 14*i*i) % m
|
return (h(x, m) + i + 14*i*i) % m
|
||||||
|
|
||||||
|
|
||||||
def f1(x, i, m):
|
def f1(x, i, m):
|
||||||
if i % 2 == 0:
|
if i % 2 == 0:
|
||||||
return (h(x, m) + i*i) % m
|
return (h(x, m) + i*i) % m
|
||||||
return ((h(x, m) - i*i) % m + m) % m
|
return ((h(x, m) - i*i) % m + m) % m
|
||||||
|
|
||||||
|
|
||||||
class HashTable:
|
class HashTable:
|
||||||
def __init__(self, m, hash_function, exploratory_function=None):
|
def __init__(self, m, h, f=None):
|
||||||
self.m = m
|
self.m = m
|
||||||
self.h = hash_function
|
self.h = h
|
||||||
self.f = exploratory_function
|
self.f = f
|
||||||
self.n = 0
|
|
||||||
self.table = AlgoDatArray(m)
|
self.table = AlgoDatArray(m)
|
||||||
|
|
||||||
def insert(self, x):
|
def insert(self, x):
|
||||||
global explore_steps
|
|
||||||
i = 0
|
i = 0
|
||||||
while i < self.m:
|
while i < self.m:
|
||||||
j = self.f(x.value, i, self.m)
|
j = self.f(x.value, i, self.m)
|
||||||
if self.is_free(j):
|
if self.is_free(j):
|
||||||
self.table[j].value = x.value
|
self.table[j].value = x.value
|
||||||
self.n += 1
|
|
||||||
return True
|
return True
|
||||||
i += 1
|
i += 1
|
||||||
explore_steps += 1
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def search(self, x):
|
def search(self, x):
|
||||||
global explore_steps
|
|
||||||
i = 0
|
i = 0
|
||||||
while i < self.m:
|
while i < self.m:
|
||||||
j = f(x, i, self.m)
|
j = f(x, i, self.m)
|
||||||
@ -51,29 +42,30 @@ class HashTable:
|
|||||||
if self.table[j] == None:
|
if self.table[j] == None:
|
||||||
return False
|
return False
|
||||||
i += 1
|
i += 1
|
||||||
explore_steps += 1
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def delete(self, x):
|
def delete(self, x):
|
||||||
global explore_steps
|
|
||||||
i = 0
|
i = 0
|
||||||
while i < self.m:
|
while i < self.m:
|
||||||
j = f(x, i, self.m)
|
j = f(x, i, self.m)
|
||||||
if self.table[j].value == x:
|
if self.table[j].value == x:
|
||||||
self.table[j].value = "DELETED"
|
self.table[j].value = "DELETED"
|
||||||
self.n -= 1
|
|
||||||
return True
|
return True
|
||||||
if self.table[j].value is None:
|
if self.table[j].value is None:
|
||||||
return False
|
return False
|
||||||
i += 1
|
i += 1
|
||||||
explore_steps += 1
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return str(self.table)
|
return str(self.table)
|
||||||
|
|
||||||
def alpha(self):
|
def alpha(self):
|
||||||
return self.n / self.m
|
i=0
|
||||||
|
used = 0
|
||||||
|
while i < self.m:
|
||||||
|
used += 0 if self.is_free(i) else 1
|
||||||
|
i += 1
|
||||||
|
return used / self.m
|
||||||
|
|
||||||
def is_free(self, i):
|
def is_free(self, i):
|
||||||
if self.table[i] == None:
|
if self.table[i] == None:
|
||||||
@ -82,20 +74,18 @@ class HashTable:
|
|||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
z = read_int_sequence("../../seq1.txt")
|
z = read_int_sequence("../../seq1.txt")
|
||||||
start = pfc()
|
start = pfc()
|
||||||
hash = HashTable(31, h, f)
|
hash = HashTable(31, h, f)
|
||||||
for algodat_value in z:
|
for i in z:
|
||||||
hash.insert(algodat_value)
|
hash.insert(i)
|
||||||
print(hash)
|
print(hash)
|
||||||
print(f"Alpha: {hash.alpha()}")
|
print(f"Alpha: {hash.alpha()}")
|
||||||
hash.delete(11)
|
hash.delete(34)
|
||||||
hash.search(47)
|
hash.search(47)
|
||||||
hash.search(243)
|
hash.search(243)
|
||||||
print(hash)
|
print(hash)
|
||||||
print(f"Alpha: {hash.alpha()}")
|
print(f"Alpha: {hash.alpha()}")
|
||||||
print(f"Dauer: {pfc() - start:.4f}s")
|
print(f"Dauer: {pfc() - start:.4f}s")
|
||||||
print(f"Sondierungsschritte: {explore_steps}")
|
|
||||||
AlgoDatValue.summary()
|
AlgoDatValue.summary()
|
||||||
181
SoSe24/lec06_graph/bfs.py
Normal file
181
SoSe24/lec06_graph/bfs.py
Normal file
@ -0,0 +1,181 @@
|
|||||||
|
from collections import deque
|
||||||
|
from typing import List
|
||||||
|
import re
|
||||||
|
from enum import Enum
|
||||||
|
|
||||||
|
class NodeColor(Enum):
|
||||||
|
"""Enumeration for node colors in a graph traversal."""
|
||||||
|
WHITE = 1 # WHITE: not visited
|
||||||
|
GRAY = 2 # GRAY: visited but not all neighbors visited
|
||||||
|
BLACK = 3 # BLACK: visited and all neighbors visited
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class Vertex:
|
||||||
|
"""A vertex in a graph."""
|
||||||
|
def __init__(self, value):
|
||||||
|
self.value = value
|
||||||
|
|
||||||
|
class Graph:
|
||||||
|
"""A graph."""
|
||||||
|
def insert_vertex(self, name: str):
|
||||||
|
raise NotImplementedError("Please implement this method in subclass")
|
||||||
|
|
||||||
|
def connect(self, name1: str, name2: str):
|
||||||
|
raise NotImplementedError("Please implement this method in subclass")
|
||||||
|
|
||||||
|
def all_vertices(self) -> List[Vertex]:
|
||||||
|
raise NotImplementedError("Please implement this method in subclass")
|
||||||
|
|
||||||
|
def get_vertex(self, name: str) -> Vertex:
|
||||||
|
raise NotImplementedError("Please implement this method in subclass")
|
||||||
|
|
||||||
|
def get_adjacent_vertices(self, name: str) -> List[Vertex]:
|
||||||
|
raise NotImplementedError("Please implement this method in subclass")
|
||||||
|
|
||||||
|
def bfs(self, start_name: str):
|
||||||
|
"""
|
||||||
|
Perform a breadth-first search starting at the given vertex.
|
||||||
|
:param start_name: the name of the vertex to start at
|
||||||
|
:return: a tuple of two dictionaries, the first mapping vertices to distances from the start vertex,
|
||||||
|
the second mapping vertices to their predecessors in the traversal tree
|
||||||
|
"""
|
||||||
|
|
||||||
|
color_map = {} # maps vertices to their color
|
||||||
|
distance_map = {} # maps vertices to their distance from the start vertex
|
||||||
|
predecessor_map = {} # maps vertices to their predecessor in the traversal tree
|
||||||
|
|
||||||
|
# Initialize the maps
|
||||||
|
for vertex in self.all_vertices():
|
||||||
|
color_map[vertex] = NodeColor.WHITE
|
||||||
|
distance_map[vertex] = None
|
||||||
|
predecessor_map[vertex] = None
|
||||||
|
|
||||||
|
# Start at the given vertex
|
||||||
|
start_node = self.get_vertex(start_name)
|
||||||
|
color_map[start_node] = NodeColor.GRAY
|
||||||
|
distance_map[start_node] = 0
|
||||||
|
|
||||||
|
# Initialize the queue with the start vertex
|
||||||
|
queue = deque()
|
||||||
|
queue.append(start_node)
|
||||||
|
|
||||||
|
# Process the queue
|
||||||
|
while len(queue) > 0:
|
||||||
|
vertex = queue.popleft()
|
||||||
|
for dest in self.get_adjacent_vertices(vertex.value):
|
||||||
|
if color_map[dest] == NodeColor.WHITE:
|
||||||
|
color_map[dest] = NodeColor.GRAY
|
||||||
|
distance_map[dest] = distance_map[vertex] + 1
|
||||||
|
predecessor_map[dest] = vertex
|
||||||
|
queue.append(dest)
|
||||||
|
color_map[vertex] = NodeColor.BLACK
|
||||||
|
|
||||||
|
# Return the distance and predecessor maps
|
||||||
|
return distance_map, predecessor_map
|
||||||
|
|
||||||
|
def path(self, destination, map):
|
||||||
|
"""
|
||||||
|
Compute the path from the start vertex to the given destination vertex.
|
||||||
|
The map parameter is the predecessor map
|
||||||
|
"""
|
||||||
|
path = []
|
||||||
|
destination_node = self.get_vertex(destination)
|
||||||
|
while destination_node is not None:
|
||||||
|
path.insert(0, destination_node.value)
|
||||||
|
destination_node = map[destination_node]
|
||||||
|
return path
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class AdjacencyListGraph(Graph):
|
||||||
|
"""A graph implemented as an adjacency list."""
|
||||||
|
def __init__(self):
|
||||||
|
self.adjacency_map = {} # maps vertex names to lists of adjacent vertices
|
||||||
|
self.vertex_map = {} # maps vertex names to vertices
|
||||||
|
|
||||||
|
def insert_vertex(self, name: str):
|
||||||
|
if name not in self.vertex_map:
|
||||||
|
self.vertex_map[name] = Vertex(name)
|
||||||
|
if name not in self.adjacency_map:
|
||||||
|
self.adjacency_map[name] = []
|
||||||
|
|
||||||
|
def connect(self, name1: str, name2: str):
|
||||||
|
adjacency_list = self.adjacency_map[name1]
|
||||||
|
dest = self.vertex_map[name2]
|
||||||
|
adjacency_list.append(dest)
|
||||||
|
|
||||||
|
def all_vertices(self) -> List[Vertex]:
|
||||||
|
return list(self.vertex_map.values())
|
||||||
|
|
||||||
|
def get_vertex(self, name: str) -> Vertex:
|
||||||
|
return self.vertex_map[name]
|
||||||
|
|
||||||
|
def get_adjacent_vertices(self, name: str) -> List[Vertex]:
|
||||||
|
return self.adjacency_map[name]
|
||||||
|
|
||||||
|
class AdjacencyMatrixGraph(Graph):
|
||||||
|
"""A graph implemented as an adjacency matrix."""
|
||||||
|
def __init__(self):
|
||||||
|
self.index_map = {} # maps vertex names to indices
|
||||||
|
self.vertex_list = [] # list of vertices
|
||||||
|
self.adjacency_matrix = [] # adjacency matrix
|
||||||
|
|
||||||
|
def insert_vertex(self, name: str):
|
||||||
|
if name not in self.index_map:
|
||||||
|
self.index_map[name] = len(self.vertex_list)
|
||||||
|
self.vertex_list.append(Vertex(name))
|
||||||
|
for row in self.adjacency_matrix: # add a new column to each row
|
||||||
|
row.append(0)
|
||||||
|
self.adjacency_matrix.append([0] * len(self.vertex_list)) # add a new row
|
||||||
|
|
||||||
|
def connect(self, name1: str, name2: str):
|
||||||
|
index1 = self.index_map[name1]
|
||||||
|
index2 = self.index_map[name2]
|
||||||
|
self.adjacency_matrix[index1][index2] = 1
|
||||||
|
|
||||||
|
def all_vertices(self) -> List[Vertex]:
|
||||||
|
return self.vertex_list
|
||||||
|
|
||||||
|
def get_vertex(self, name: str) -> Vertex:
|
||||||
|
index = self.index_map[name]
|
||||||
|
return self.vertex_list[index]
|
||||||
|
|
||||||
|
def get_adjacent_vertices(self, name: str) -> List[Vertex]:
|
||||||
|
index = self.index_map[name]
|
||||||
|
result = []
|
||||||
|
for i in range(len(self.vertex_list)):
|
||||||
|
if self.adjacency_matrix[index][i] == 1:
|
||||||
|
name = self.vertex_list[i].value
|
||||||
|
result.append(self.get_vertex(name))
|
||||||
|
return result
|
||||||
|
|
||||||
|
def read_cave_into_graph(graph: Graph, filename: str):
|
||||||
|
"""Read a cave description from a file and insert it into the given graph."""
|
||||||
|
with open(filename, "r") as file:
|
||||||
|
lines = file.readlines()
|
||||||
|
for line in lines:
|
||||||
|
# match a line with two node names and an optional direction
|
||||||
|
m = re.match(r"(^\s*\"(.*)\"\s*([<>]*)\s*\"(.*)\"\s*)", line)
|
||||||
|
if m:
|
||||||
|
startnode = m.group(2)
|
||||||
|
endnode = m.group(4)
|
||||||
|
opcode = m.group(3)
|
||||||
|
graph.insert_vertex(startnode)
|
||||||
|
graph.insert_vertex(endnode)
|
||||||
|
if '>' in opcode:
|
||||||
|
graph.connect(startnode, endnode)
|
||||||
|
if '<' in opcode:
|
||||||
|
graph.connect(endnode, startnode)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
graph = AdjacencyListGraph()
|
||||||
|
#graph = AdjacencyMatrixGraph()
|
||||||
|
read_cave_into_graph(graph, "../../hoehle.txt")
|
||||||
|
_, predecessor_map = graph.bfs('Höhleneingang')
|
||||||
|
path = graph.path('Schatzkammer', predecessor_map)
|
||||||
|
print(path)
|
||||||
|
_, predecessor_map = graph.bfs('Schatzkammer')
|
||||||
|
path = graph.path('Höhleneingang', predecessor_map)
|
||||||
|
print(path)
|
||||||
Loading…
x
Reference in New Issue
Block a user