From cba010a56235c1c55976ca1986bbf982933619c2 Mon Sep 17 00:00:00 2001
From: hbui <hong-phuc.bui@htwsaar.de>
Date: Wed, 17 Jul 2024 11:50:17 +0200
Subject: [PATCH] graph demo

---
 stundenplan/tests/__init__.py                |    0 
 stundenplan/src/pygraph/__init__.py          |    0 
 stundenplan/src/pygraph/graphdemo.py         |   88 +++++++++++++++++++++++++++++
 stundenplan/tests/pygraph/__init__.py        |    0 
 stundenplan/tests/pygraph/graphdemo.tests.py |   40 +++++++++++++
 stundenplan/pyproject.toml                   |   16 +++++
 stundenplan/Readme.md                        |    1 
 7 files changed, 145 insertions(+), 0 deletions(-)

diff --git a/stundenplan/Readme.md b/stundenplan/Readme.md
new file mode 100644
index 0000000..fa3014b
--- /dev/null
+++ b/stundenplan/Readme.md
@@ -0,0 +1 @@
+Beispielanwendung von Graph
diff --git a/stundenplan/pyproject.toml b/stundenplan/pyproject.toml
new file mode 100644
index 0000000..60a79dd
--- /dev/null
+++ b/stundenplan/pyproject.toml
@@ -0,0 +1,16 @@
+[build-system]
+requires = ["setuptools"]
+build-backend = "setuptools.build_meta"
+
+[project]
+name = "stundenplan"
+version = "0.0.1"
+
+[tool.setuptools.packages.find]
+# All the following settings are optional:
+where = ["src"]
+
+# [project.scripts]
+# To be done
+# ttgeo = "turtlegeo.main:main"
+
diff --git a/stundenplan/src/pygraph/__init__.py b/stundenplan/src/pygraph/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/stundenplan/src/pygraph/__init__.py
diff --git a/stundenplan/src/pygraph/graphdemo.py b/stundenplan/src/pygraph/graphdemo.py
new file mode 100644
index 0000000..202e779
--- /dev/null
+++ b/stundenplan/src/pygraph/graphdemo.py
@@ -0,0 +1,88 @@
+class Graph:
+    def __init__(self):
+        self.adjacent: dict[int, set] = {}
+        self.vertex_attribute: dict[int, dict] = {}
+
+    def add_vertex(self, vertex):
+        if vertex not in self.adjacent:
+            if not isinstance(vertex, int):
+                raise TypeError(f"Argument {vertex} is not a valid vertex")
+            self.adjacent[vertex] = set()
+
+        pass
+
+    def add_edge(self, u, v):
+        self.add_vertex(u)
+        self.add_vertex(v)
+        v_neighbor = self.adjacent[v]
+        if u not in v_neighbor:
+            v_neighbor.add(u)
+        u_neighbor = self.adjacent[u]
+        if v not in u_neighbor:
+            u_neighbor.add(v)
+        pass
+
+    def merge_attribute(self, vertex: int, properties: dict):
+        """
+        merge a dict of attribute to a vertex. Usage example:
+        ```
+        g = Graph();
+        g.add_vertex(1);
+        g.mergeAttribute(1, {'color': 0});
+        ```
+        :param vertex:
+        :param properties:
+        :return: self
+        """
+        if vertex not in self.adjacent:
+            raise ValueError(f"Graph does not include vertex {vertex}")
+        old_attributes = self.vertex_attribute[vertex]
+        self.vertex_attribute[vertex] = old_attributes | properties
+        return self
+        pass
+
+    def get_attribute(self, vertex):
+        if vertex in self.adjacent:
+            return self.vertex_attribute[vertex]
+        else:
+            raise ValueError(f"Graph does not include vertex {vertex}")
+        pass
+
+    def vertices(self):
+        return self.adjacent.keys()
+
+    def for_each_vertices(self, action):
+        for v in self.vertices():
+            action(v)
+
+    def adjacent_of(self, vertex):
+        if vertex not in self.adjacent:
+            raise ValueError(f"Graph does not include vertex {vertex}")
+        return self.adjacent.get(vertex)
+
+    def for_each_edges(self, action):
+        visited_edges: dict[int, set] = {}
+        for start in self.vertices():
+            for end in self.adjacent_of(start):
+                (first, second) = (start, end) if (start > end) else (end, start)
+            if first in visited_edges:
+                visited_adjacent = visited_edges.get(first)
+                if second not in visited_adjacent:
+                    visited_adjacent.add(second)
+                    action(start, end)
+            else:
+                adjacent = set()
+                visited_edges[first] = adjacent
+                adjacent.add(second)
+                action(start, end)
+
+    def __repr__(self):
+        text = ""
+        sorted_key = sorted(self.adjacent.keys())
+        last_key = sorted_key.pop()
+        def adjacent_fn(vertex): return "[" + ", ".join( [str(v) for v in self.adjacent[vertex]] ) + "]"
+        for key in sorted_key:
+            text += f"{key} → {adjacent_fn(key)}\n"
+        text += f"{last_key} → {adjacent_fn(last_key)}"
+        return text
+
diff --git a/stundenplan/tests/__init__.py b/stundenplan/tests/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/stundenplan/tests/__init__.py
diff --git a/stundenplan/tests/pygraph/__init__.py b/stundenplan/tests/pygraph/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/stundenplan/tests/pygraph/__init__.py
diff --git a/stundenplan/tests/pygraph/graphdemo.tests.py b/stundenplan/tests/pygraph/graphdemo.tests.py
new file mode 100644
index 0000000..164c4ac
--- /dev/null
+++ b/stundenplan/tests/pygraph/graphdemo.tests.py
@@ -0,0 +1,40 @@
+import unittest
+
+from pygraph.graphdemo import Graph
+
+
+class GraphTestCase(unittest.TestCase):
+    def test_construct_a_graph(self):
+        g = Graph()
+        g.add_edge(1, 2)
+        g.add_edge(1, 3)
+        g.add_edge(2, 3)
+        g.add_edge(2, 4)
+        txt = str(g)
+        expected = '''1 → [2, 3]
+2 → [1, 3, 4]
+3 → [1, 2]
+4 → [2]'''
+        self.assertEqual(expected, txt)
+        vertices = [1, 2, 3, 4]
+        # def action(v): self.assertTrue(v in vertices)
+        g.for_each_vertices(lambda v : self.assertTrue(v in vertices))
+
+    def test_iterate_all_edges(self):
+        g = Graph()
+        g.add_edge(1, 2)
+        g.add_edge(1, 3)
+        g.add_edge(2, 3)
+        g.add_edge(2, 4)
+        edges = [
+            "1-2", "1-3", "2-3", "2-4"
+        ]
+        def action(a, b):
+            (s,e) = (a,b) if a < b else (b,a)
+            edge = f"{s}-{e}"
+            self.assertTrue(edge in edges)
+        g.for_each_edges(action)
+
+
+if __name__ == '__main__':
+    unittest.main()

--
Gitblit v1.10.0-SNAPSHOT