From 273021dcef9c23610790e47a109fcbf476b829ec Mon Sep 17 00:00:00 2001
From: Hong-Phuc Bui <hong-phuc.bui@htwsaar.de>
Date: Sun, 25 Aug 2024 19:11:08 +0200
Subject: [PATCH] example about graph
---
.gitignore | 3 -
num-int/src/numint/mainwindow.ui | 2
stundenplan/src/pygraph/graphdemo.py | 30 ++++++++++++---
stundenplan/src/pygraph/shortestpath.py | 28 ++++++++++++++
stundenplan/tests/pygraph/shortestpath_tests.py | 26 +++++++++++++
5 files changed, 79 insertions(+), 10 deletions(-)
diff --git a/.gitignore b/.gitignore
index 6f12ec8..e019710 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,7 +1,4 @@
-sandbox*
-queens*
*.venv*
__pycache__/
.idea/
-htw-python-kurs-2024-mmb/
*.egg-info/
\ No newline at end of file
diff --git a/num-int/src/numint/mainwindow.ui b/num-int/src/numint/mainwindow.ui
index 8f1f47f..e8f8a18 100644
--- a/num-int/src/numint/mainwindow.ui
+++ b/num-int/src/numint/mainwindow.ui
@@ -11,7 +11,7 @@
</rect>
</property>
<property name="windowTitle">
- <string>Riemann Sum</string>
+ <string>Riemann Sums</string>
</property>
<widget class="QWidget" name="centralwidget">
<layout class="QHBoxLayout" name="horizontalLayout_2">
diff --git a/stundenplan/src/pygraph/graphdemo.py b/stundenplan/src/pygraph/graphdemo.py
index c0e3df9..2a6cf7d 100644
--- a/stundenplan/src/pygraph/graphdemo.py
+++ b/stundenplan/src/pygraph/graphdemo.py
@@ -6,7 +6,7 @@
self._adjacent: dict[int, set] = {}
self._vertex_attribute: dict[int, dict] = {}
- def add_vertex(self, vertex):
+ def add_vertex(self, vertex:int):
if vertex not in self._adjacent:
if not isinstance(vertex, int):
raise TypeError(f"Argument {vertex} is not a valid vertex")
@@ -14,7 +14,7 @@
self._vertex_attribute[vertex] = {}
pass
- def add_edge(self, u, v):
+ def add_edge(self, u: int, v: int):
self.add_vertex(u)
self.add_vertex(v)
v_neighbor = self._adjacent[v]
@@ -25,6 +25,11 @@
u_neighbor.add(v)
pass
+ def add_edges(self, u: int, adjacent:[int]):
+ for v in adjacent:
+ self.add_edge(u, v)
+ pass
+
def merge_attribute(self, vertex: int, properties: dict):
"""
merge a dict of attribute to a vertex. Usage example:
@@ -39,7 +44,7 @@
"""
if vertex not in self._adjacent:
raise ValueError(f"Graph does not include vertex {vertex}")
- old_attributes = self._vertex_attribute.get[vertex]
+ old_attributes = self._vertex_attribute.get(vertex)
self._vertex_attribute[vertex] = old_attributes | properties
return self
pass
@@ -52,20 +57,33 @@
pass
def vertices(self):
+ """
+ returns the set of vertices in not defined order.
+ :return:
+ """
return self._adjacent.keys()
def for_each_vertices(self, action: Callable[[int], Any]):
- for v in self.vertices():
+ """
+ iterates over all vertices in this graph in ascending order.
+ :param action:
+ :return:
+ """
+ for v in sorted( self.vertices() ):
action(v)
def adjacent_of(self, vertex: int):
if vertex not in self._adjacent:
raise ValueError(f"Graph does not include vertex {vertex}")
- return self._adjacent.get(vertex)
+ return sorted( self._adjacent.get(vertex) )
def for_each_edges(self, action: Callable[[int, int], Any]):
+ """
+ iterates over all edges of the graph, executes the action on each edge.
+ :param action: a binary function, its parameters are start and end vertices of the visited edges
+ """
visited_edges: dict[int, set] = {}
- for start in self.vertices():
+ for start in sorted( self.vertices() ):
for end in self.adjacent_of(start):
(first, second) = (start, end) if (start >= end) else (end, start)
if first in visited_edges:
diff --git a/stundenplan/src/pygraph/shortestpath.py b/stundenplan/src/pygraph/shortestpath.py
new file mode 100644
index 0000000..4426f95
--- /dev/null
+++ b/stundenplan/src/pygraph/shortestpath.py
@@ -0,0 +1,28 @@
+import collections
+
+from pygraph.graphdemo import Graph
+
+
+def bfs(g: Graph, start: int) -> {int:int|None}:
+ """
+
+ :param g:
+ :param start:
+ :return:
+ """
+ tree = Graph()
+ queue = collections.deque()
+ VISITED = "visited"
+ not_visited = {VISITED: False}
+ visited = {VISITED: True}
+ g.for_each_vertices(lambda v : g.merge_attribute(v, not_visited))
+ queue.append(start) # append() is the enqueue() operation of a Queue
+ g.merge_attribute(start, visited)
+ while queue:
+ u = queue.popleft() # popleft() is the dequeue() operation of a Queue
+ for v in g.adjacent_of(u):
+ if not g.get_attribute(v)[VISITED]:
+ tree.add_edge(u, v)
+ g.merge_attribute(v, visited)
+ queue.append(v)
+ return tree
diff --git a/stundenplan/tests/pygraph/shortestpath_tests.py b/stundenplan/tests/pygraph/shortestpath_tests.py
new file mode 100644
index 0000000..6b9b2de
--- /dev/null
+++ b/stundenplan/tests/pygraph/shortestpath_tests.py
@@ -0,0 +1,26 @@
+import unittest
+
+from pygraph.graphdemo import Graph
+from pygraph.shortestpath import bfs
+
+
+class ShortestPathTestCase(unittest.TestCase):
+ def test_bfs(self):
+ g = Graph()
+ g.add_edges(0, [1, 2])
+ g.add_edges(1, [0, 3, 4])
+ g.add_edges(2, [0, 4, 6, 7])
+ g.add_edges(3, [1])
+ g.add_edges(4, [1, 2, 5])
+ g.add_edges(5, [4])
+ g.add_edges(6, [2])
+ g.add_edges(7, [2])
+ #print(g)
+ # self.assertEqual(True, False) # add assertion here
+
+ tree = bfs(g, 0)
+ print(tree)
+
+
+if __name__ == '__main__':
+ unittest.main()
--
Gitblit v1.10.0