forked from hofmannol/AlgoDatSoSe25
elektro
This commit is contained in:
parent
6868e089a4
commit
add4091b5d
32
praktika/10_electro/electro.py
Normal file
32
praktika/10_electro/electro.py
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
from vorlesung.L08_graphen.graph import Graph, AdjacencyMatrixGraph
|
||||||
|
from utils.project_dir import get_path
|
||||||
|
import re
|
||||||
|
|
||||||
|
def read_elektro_into_graph(graph: Graph, filename: str):
|
||||||
|
pattern = re.compile(r'"([^"]+)";"([^"]+)";(\d+)')
|
||||||
|
with (open(filename, "r") as file):
|
||||||
|
for line in file:
|
||||||
|
m = pattern.match(line)
|
||||||
|
if m:
|
||||||
|
start_name = m.group(1)
|
||||||
|
end_name = m.group(2)
|
||||||
|
cost = int(m.group(3))
|
||||||
|
graph.insert_vertex(start_name)
|
||||||
|
graph.insert_vertex(end_name)
|
||||||
|
graph.connect(start_name, end_name, cost)
|
||||||
|
graph.connect(end_name, start_name, cost)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
graph = AdjacencyMatrixGraph()
|
||||||
|
read_elektro_into_graph(graph, get_path("data/elektro.txt"))
|
||||||
|
|
||||||
|
parents, cost = graph.mst_prim()
|
||||||
|
print(f"Kosten nach Prim: {cost}")
|
||||||
|
for node, parent in parents.items():
|
||||||
|
if parent is not None:
|
||||||
|
print(f"{node} - {parent}")
|
||||||
|
|
||||||
|
edges, cost = graph.mst_kruskal()
|
||||||
|
print(f"Kosten nach Kruskal: {cost}")
|
||||||
|
for start_name, end_name, _ in edges:
|
||||||
|
print(f"{start_name} - {end_name}")
|
@ -2,9 +2,12 @@ from collections import deque
|
|||||||
from typing import List
|
from typing import List
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
import graphviz
|
import graphviz
|
||||||
|
import math
|
||||||
|
import heapq
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from utils.project_dir import get_path
|
from utils.project_dir import get_path
|
||||||
from utils.priority_queue import PriorityQueue
|
from utils.priority_queue import PriorityQueue
|
||||||
|
from vorlesung.L09_mst.disjoint import DisjointValue
|
||||||
|
|
||||||
|
|
||||||
class NodeColor(Enum):
|
class NodeColor(Enum):
|
||||||
@ -205,6 +208,68 @@ class Graph:
|
|||||||
relax(vertex, dest, weight)
|
relax(vertex, dest, weight)
|
||||||
return distance_map, predecessor_map
|
return distance_map, predecessor_map
|
||||||
|
|
||||||
|
def mst_prim(self, start_name: str = None):
|
||||||
|
""" Compute the minimum spanning tree of the graph using Prim's algorithm. """
|
||||||
|
|
||||||
|
distance_map = {} # maps vertices to their current distance from the spanning tree
|
||||||
|
parent_map = {} # maps vertices to their predecessor in the spanning tree
|
||||||
|
|
||||||
|
Vertex.__lt__ = lambda self, other: distance_map[self] < distance_map[other]
|
||||||
|
|
||||||
|
queue = []
|
||||||
|
|
||||||
|
if start_name is None:
|
||||||
|
start_name = self.all_vertices()[0].value
|
||||||
|
|
||||||
|
# Initialize the maps
|
||||||
|
for vertex in self.all_vertices():
|
||||||
|
distance_map[vertex] = 0 if vertex.value == start_name else math.inf
|
||||||
|
parent_map[vertex] = None
|
||||||
|
queue.append(vertex)
|
||||||
|
|
||||||
|
heapq.heapify(queue) # Convert the list into a heap
|
||||||
|
|
||||||
|
# Process the queue
|
||||||
|
cost = 0 # The cost of the minimum spanning tree
|
||||||
|
while len(queue) > 0:
|
||||||
|
vertex = heapq.heappop(queue)
|
||||||
|
cost += distance_map[vertex] # Add the cost of the edge to the minimum spanning tree
|
||||||
|
for (dest, w) in self.get_adjacent_vertices_with_weight(vertex.value):
|
||||||
|
if dest in queue and distance_map[dest] > w:
|
||||||
|
# Update the distance and parent maps
|
||||||
|
queue.remove(dest)
|
||||||
|
distance_map[dest] = w
|
||||||
|
parent_map[dest] = vertex
|
||||||
|
queue.append(dest) # Add the vertex back to the queue
|
||||||
|
heapq.heapify(queue) # Re-heapify the queue
|
||||||
|
|
||||||
|
# Return the distance and predecessor maps
|
||||||
|
return parent_map, cost
|
||||||
|
|
||||||
|
def mst_kruskal(self, start_name: str = None):
|
||||||
|
""" Compute the minimum spanning tree of the graph using Kruskal's algorithm. """
|
||||||
|
|
||||||
|
cost = 0
|
||||||
|
result = []
|
||||||
|
edges = self.all_edges()
|
||||||
|
|
||||||
|
# Create a disjoint set for each vertex
|
||||||
|
vertex_map = {v.value: DisjointValue(v) for v in self.all_vertices()}
|
||||||
|
|
||||||
|
# Sort the edges by weight
|
||||||
|
edges.sort(key=lambda edge: edge[2])
|
||||||
|
|
||||||
|
# Process the edges
|
||||||
|
for edge in edges:
|
||||||
|
start_name, end_name, weight = edge
|
||||||
|
# Check if the edge creates a cycle
|
||||||
|
if not vertex_map[start_name].same_set(vertex_map[end_name]):
|
||||||
|
result.append(edge)
|
||||||
|
vertex_map[start_name].union(vertex_map[end_name])
|
||||||
|
cost += weight
|
||||||
|
|
||||||
|
return result, cost
|
||||||
|
|
||||||
|
|
||||||
class AdjacencyListGraph(Graph):
|
class AdjacencyListGraph(Graph):
|
||||||
"""A graph implemented as an adjacency list."""
|
"""A graph implemented as an adjacency list."""
|
||||||
@ -243,8 +308,6 @@ class AdjacencyListGraph(Graph):
|
|||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class AdjacencyMatrixGraph(Graph):
|
class AdjacencyMatrixGraph(Graph):
|
||||||
"""A graph implemented as an adjacency matrix."""
|
"""A graph implemented as an adjacency matrix."""
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
0
vorlesung/L09_mst/__init__.py
Normal file
0
vorlesung/L09_mst/__init__.py
Normal file
18
vorlesung/L09_mst/disjoint.py
Normal file
18
vorlesung/L09_mst/disjoint.py
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
|
||||||
|
|
||||||
|
class DisjointValue():
|
||||||
|
|
||||||
|
def __init__(self, value):
|
||||||
|
self.value = value
|
||||||
|
self.parent = None
|
||||||
|
|
||||||
|
def canonical(self):
|
||||||
|
if self.parent:
|
||||||
|
return self.parent.canonical()
|
||||||
|
return self
|
||||||
|
|
||||||
|
def same_set(self, other):
|
||||||
|
return self.canonical() == other.canonical()
|
||||||
|
|
||||||
|
def union(self, other):
|
||||||
|
self.canonical().parent = other.canonical()
|
Loading…
x
Reference in New Issue
Block a user