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