From 8a9933e4decb3b6a57b47b6409474bd476920c24 Mon Sep 17 00:00:00 2001
From: Hong-Phuc Bui <hong-phuc.bui@htwsaar.de>
Date: Fri, 27 Sep 2024 01:22:49 +0200
Subject: [PATCH] demo show image

---
 /dev/null                                       |  251 -------------------
 image-demo/README.md                            |   20 +
 image-demo/src/imgdemo/ui_mainwindow.py         |  111 ++++++++
 stundenplan/src/pygraph/graphdemo.py            |   18 
 stundenplan/src/pygraph/shortestpath.py         |   53 ++++
 image-demo/src/imgdemo/__init__.py              |    0 
 image-demo/pyproject.toml                       |   19 +
 stundenplan/tests/pygraph/shortestpath_tests.py |   53 +++
 bit_op_numpy_example.py                         |   41 +++
 image-demo/src/imgdemo/guimain.py               |   74 +++++
 image-demo/src/imgdemo/mainwindow.ui            |  107 ++++++++
 11 files changed, 475 insertions(+), 272 deletions(-)

diff --git a/bit_op_numpy_example.py b/bit_op_numpy_example.py
new file mode 100644
index 0000000..c80d8bb
--- /dev/null
+++ b/bit_op_numpy_example.py
@@ -0,0 +1,41 @@
+import numpy as np
+
+def print_binary_pattern_32(x):
+    pattern = bin(x)[2:].zfill(32)
+    print(x, ':', pattern[0:8], pattern[9:16], pattern[17:24], pattern[25:], len(pattern))
+
+def to32_np_fn(x: list[np.uint8,np.uint8,np.uint8,np.uint8]):
+    y = np.left_shift(x, [np.uint32(0), np.uint32(8), np.uint32(16), np.uint32(24)])
+    return y[0] | y[1] | y[2] | y[3]
+
+
+def to32_bit_op(x: list[np.uint8,np.uint8,np.uint8,np.uint8]):
+    # 1 0000_0000 0000_0000 0000_0000 0000_0000
+    mask = (2**32) | (x[3] << 24) | (x[2] << 16) | (x[1] << 8) | (x[0])
+    # remove the most significant bit
+    return mask & (2**32-1)
+
+
+def quaternary_8bit_to_unary_32bit(data, to32_fn):
+    four_group = np.array(data, dtype=np.uint8).reshape((-1, 4))
+    return np.array([to32_fn(x) for x in four_group])
+
+
+
+if __name__ == '__main__':
+    raw_data = [255,   0, 15, 170,
+                0b101, 0b1100, 0b1001101, 0b1000_0000,
+                9, 10, 11, 0b1000_0000]
+
+    print(f"Konvertierung jeweiliger 4er-Tuple in einem uint32")
+    print()
+    print("Mit Python built-int Left-Shift-Operator")
+    result = quaternary_8bit_to_unary_32bit(raw_data, to32_np_fn)
+    for r in result:
+        print_binary_pattern_32(r)
+
+    print()
+    print("Mit numpy left_shift Funktion")
+    result = quaternary_8bit_to_unary_32bit(raw_data, to32_bit_op)
+    for r in result:
+        print_binary_pattern_32(r)
\ No newline at end of file
diff --git a/image-demo/README.md b/image-demo/README.md
new file mode 100644
index 0000000..da86bd4
--- /dev/null
+++ b/image-demo/README.md
@@ -0,0 +1,20 @@
+# Demonstration von Zusammenspiel numpy/PIL und PySide6
+
+## Build python file from ui
+
+```shell
+pyside6-project build imgdemo.json
+```
+
+## Install as development mode (editable)
+
+``` 
+pip install -e .
+```
+
+## Run the application after install
+
+
+```
+imgdemo 
+```
\ No newline at end of file
diff --git a/image-demo/pyproject.toml b/image-demo/pyproject.toml
new file mode 100644
index 0000000..4f2fb7d
--- /dev/null
+++ b/image-demo/pyproject.toml
@@ -0,0 +1,19 @@
+[build-system]
+requires = ["setuptools"]
+build-backend = "setuptools.build_meta"
+
+[project]
+name = "image-demo"
+version = "0.0.1"
+dependencies = [
+    "numpy >= 2.0.0",
+    "matplotlib >= 3.9",
+    "PySide6 >= 6.7"
+]
+
+[tool.setuptools.packages.find]
+# All the following settings are optional:
+where = ["src"]
+
+[project.gui-scripts]
+imgdemo = "imgdemo.guimain:main"
diff --git a/image-demo/src/imgdemo/__init__.py b/image-demo/src/imgdemo/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/image-demo/src/imgdemo/__init__.py
diff --git a/image-demo/src/imgdemo/guimain.py b/image-demo/src/imgdemo/guimain.py
new file mode 100644
index 0000000..665f312
--- /dev/null
+++ b/image-demo/src/imgdemo/guimain.py
@@ -0,0 +1,74 @@
+import sys
+
+from PySide6.QtGui import QPixmap, QImage
+#from PIL.ImageQt import QPixmap, QImage
+
+from PySide6.QtWidgets import QApplication, QMainWindow, QFileDialog
+import numpy as np
+from PIL import Image
+
+from imgdemo.ui_mainwindow import Ui_MainWindow
+
+class MainWindow(QMainWindow):
+    def __init__(self):
+        super(MainWindow, self).__init__()
+        self.saved_file = ('', '')
+        self.chosen_file = ('', '')
+        self.ui = Ui_MainWindow()
+        self.ui.setupUi(self)
+        self.ui.actionChoose_Image.triggered.connect(self.choose_image)
+        self.ui.actionSave_Image.triggered.connect(self.save_image)
+
+    def choose_image(self):
+        self.chosen_file = ('', '') # reset (for safe)
+        self.chosen_file = QFileDialog.getOpenFileName(None, "Choose Image", "",
+                                                       "Images (*.png *.xpm *.jpg *.tiff) ;; All Filetypes (*.*)")
+        print(self.chosen_file)
+        if self.chosen_file[0] != '':  # user has chosen a file
+            self.display_image()
+
+
+    def save_image(self):
+        self.saved_file = ('', '') # reset for safe
+        self.saved_file = QFileDialog.getSaveFileName(None, "Choose Image", "",
+                                                       "All (*.*)")
+        print(self.saved_file)
+
+
+    def display_image(self):
+        pixmap = QPixmap(self.chosen_file[0])
+        self.ui.origin_img.setPixmap(pixmap)
+        # now read the image and show it via Image in other container
+        with Image.open(self.chosen_file[0]) as img:
+            image = np.asarray(img, dtype=np.uint8)
+            self.display_numpy_image(image)
+
+
+    def display_numpy_image(self, image):
+        height, width, channel = image.shape
+        print(height, width, channel)
+
+        bytes_per_line = channel * width  # color
+        img_format = QImage.Format.Format_RGBX8888
+        if channel == 4:
+            img_format =  QImage.Format.Format_ARGB32
+        elif channel == 3:
+            img_format = QImage.Format.Format_RGB888
+        qImg = QImage(image.data, width, height, bytes_per_line, img_format).rgbSwapped()
+        pixmap = QPixmap(qImg)
+        self.ui.result_img.setPixmap(pixmap)
+
+
+
+
+def main():
+    app = QApplication(sys.argv)
+    window = MainWindow()
+    window.show()
+
+    sys.exit(app.exec())
+    pass
+
+
+if __name__ == "__main__":
+    main()
diff --git a/image-demo/src/imgdemo/mainwindow.ui b/image-demo/src/imgdemo/mainwindow.ui
new file mode 100644
index 0000000..f0db623
--- /dev/null
+++ b/image-demo/src/imgdemo/mainwindow.ui
@@ -0,0 +1,107 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>MainWindow</class>
+ <widget class="QMainWindow" name="MainWindow">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>800</width>
+    <height>600</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Image Demo</string>
+  </property>
+  <widget class="QWidget" name="centralwidget">
+   <layout class="QVBoxLayout" name="verticalLayout_3">
+    <item>
+     <layout class="QHBoxLayout" name="horizontalLayout">
+      <item>
+       <widget class="QGroupBox" name="origin_container">
+        <property name="title">
+         <string>Origin Image</string>
+        </property>
+        <layout class="QVBoxLayout" name="verticalLayout_2">
+         <item>
+          <widget class="QLabel" name="origin_img">
+           <property name="text">
+            <string>Source</string>
+           </property>
+          </widget>
+         </item>
+        </layout>
+       </widget>
+      </item>
+      <item>
+       <widget class="QGroupBox" name="result_container">
+        <property name="title">
+         <string>Filtered Image</string>
+        </property>
+        <layout class="QVBoxLayout" name="verticalLayout">
+         <item>
+          <widget class="QLabel" name="result_img">
+           <property name="text">
+            <string>Result</string>
+           </property>
+          </widget>
+         </item>
+        </layout>
+       </widget>
+      </item>
+     </layout>
+    </item>
+    <item>
+     <widget class="QPushButton" name="pushButton">
+      <property name="text">
+       <string>Dummy Widget</string>
+      </property>
+     </widget>
+    </item>
+   </layout>
+  </widget>
+  <widget class="QMenuBar" name="menubar">
+   <property name="geometry">
+    <rect>
+     <x>0</x>
+     <y>0</y>
+     <width>800</width>
+     <height>22</height>
+    </rect>
+   </property>
+   <widget class="QMenu" name="menuFile">
+    <property name="title">
+     <string>&amp;File</string>
+    </property>
+    <addaction name="actionChoose_Image"/>
+    <addaction name="actionSave_Image"/>
+   </widget>
+   <addaction name="menuFile"/>
+  </widget>
+  <widget class="QStatusBar" name="statusbar"/>
+  <action name="actionChoose_Image">
+   <property name="icon">
+    <iconset theme="QIcon::ThemeIcon::FolderOpen"/>
+   </property>
+   <property name="text">
+    <string>Choose Image</string>
+   </property>
+   <property name="shortcut">
+    <string>Ctrl+O</string>
+   </property>
+  </action>
+  <action name="actionSave_Image">
+   <property name="icon">
+    <iconset theme="QIcon::ThemeIcon::DocumentSave"/>
+   </property>
+   <property name="text">
+    <string>Save Image</string>
+   </property>
+   <property name="shortcut">
+    <string>Ctrl+S</string>
+   </property>
+  </action>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/image-demo/src/imgdemo/ui_mainwindow.py b/image-demo/src/imgdemo/ui_mainwindow.py
new file mode 100644
index 0000000..6a997bd
--- /dev/null
+++ b/image-demo/src/imgdemo/ui_mainwindow.py
@@ -0,0 +1,111 @@
+# -*- coding: utf-8 -*-
+
+################################################################################
+## Form generated from reading UI file 'mainwindow.ui'
+##
+## Created by: Qt User Interface Compiler version 6.7.2
+##
+## WARNING! All changes made in this file will be lost when recompiling UI file!
+################################################################################
+
+from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale,
+    QMetaObject, QObject, QPoint, QRect,
+    QSize, QTime, QUrl, Qt)
+from PySide6.QtGui import (QAction, QBrush, QColor, QConicalGradient,
+    QCursor, QFont, QFontDatabase, QGradient,
+    QIcon, QImage, QKeySequence, QLinearGradient,
+    QPainter, QPalette, QPixmap, QRadialGradient,
+    QTransform)
+from PySide6.QtWidgets import (QApplication, QGroupBox, QHBoxLayout, QLabel,
+    QMainWindow, QMenu, QMenuBar, QPushButton,
+    QSizePolicy, QStatusBar, QVBoxLayout, QWidget)
+
+class Ui_MainWindow(object):
+    def setupUi(self, MainWindow):
+        if not MainWindow.objectName():
+            MainWindow.setObjectName(u"MainWindow")
+        MainWindow.resize(800, 600)
+        self.actionChoose_Image = QAction(MainWindow)
+        self.actionChoose_Image.setObjectName(u"actionChoose_Image")
+        icon = QIcon(QIcon.fromTheme(QIcon.ThemeIcon.FolderOpen))
+        self.actionChoose_Image.setIcon(icon)
+        self.actionSave_Image = QAction(MainWindow)
+        self.actionSave_Image.setObjectName(u"actionSave_Image")
+        icon1 = QIcon(QIcon.fromTheme(QIcon.ThemeIcon.DocumentSave))
+        self.actionSave_Image.setIcon(icon1)
+        self.centralwidget = QWidget(MainWindow)
+        self.centralwidget.setObjectName(u"centralwidget")
+        self.verticalLayout_3 = QVBoxLayout(self.centralwidget)
+        self.verticalLayout_3.setObjectName(u"verticalLayout_3")
+        self.horizontalLayout = QHBoxLayout()
+        self.horizontalLayout.setObjectName(u"horizontalLayout")
+        self.origin_container = QGroupBox(self.centralwidget)
+        self.origin_container.setObjectName(u"origin_container")
+        self.verticalLayout_2 = QVBoxLayout(self.origin_container)
+        self.verticalLayout_2.setObjectName(u"verticalLayout_2")
+        self.origin_img = QLabel(self.origin_container)
+        self.origin_img.setObjectName(u"origin_img")
+
+        self.verticalLayout_2.addWidget(self.origin_img)
+
+
+        self.horizontalLayout.addWidget(self.origin_container)
+
+        self.result_container = QGroupBox(self.centralwidget)
+        self.result_container.setObjectName(u"result_container")
+        self.verticalLayout = QVBoxLayout(self.result_container)
+        self.verticalLayout.setObjectName(u"verticalLayout")
+        self.result_img = QLabel(self.result_container)
+        self.result_img.setObjectName(u"result_img")
+
+        self.verticalLayout.addWidget(self.result_img)
+
+
+        self.horizontalLayout.addWidget(self.result_container)
+
+
+        self.verticalLayout_3.addLayout(self.horizontalLayout)
+
+        self.pushButton = QPushButton(self.centralwidget)
+        self.pushButton.setObjectName(u"pushButton")
+
+        self.verticalLayout_3.addWidget(self.pushButton)
+
+        MainWindow.setCentralWidget(self.centralwidget)
+        self.menubar = QMenuBar(MainWindow)
+        self.menubar.setObjectName(u"menubar")
+        self.menubar.setGeometry(QRect(0, 0, 800, 22))
+        self.menuFile = QMenu(self.menubar)
+        self.menuFile.setObjectName(u"menuFile")
+        MainWindow.setMenuBar(self.menubar)
+        self.statusbar = QStatusBar(MainWindow)
+        self.statusbar.setObjectName(u"statusbar")
+        MainWindow.setStatusBar(self.statusbar)
+
+        self.menubar.addAction(self.menuFile.menuAction())
+        self.menuFile.addAction(self.actionChoose_Image)
+        self.menuFile.addAction(self.actionSave_Image)
+
+        self.retranslateUi(MainWindow)
+
+        QMetaObject.connectSlotsByName(MainWindow)
+    # setupUi
+
+    def retranslateUi(self, MainWindow):
+        MainWindow.setWindowTitle(QCoreApplication.translate("MainWindow", u"Image Demo", None))
+        self.actionChoose_Image.setText(QCoreApplication.translate("MainWindow", u"Choose Image", None))
+#if QT_CONFIG(shortcut)
+        self.actionChoose_Image.setShortcut(QCoreApplication.translate("MainWindow", u"Ctrl+O", None))
+#endif // QT_CONFIG(shortcut)
+        self.actionSave_Image.setText(QCoreApplication.translate("MainWindow", u"Save Image", None))
+#if QT_CONFIG(shortcut)
+        self.actionSave_Image.setShortcut(QCoreApplication.translate("MainWindow", u"Ctrl+S", None))
+#endif // QT_CONFIG(shortcut)
+        self.origin_container.setTitle(QCoreApplication.translate("MainWindow", u"Origin Image", None))
+        self.origin_img.setText(QCoreApplication.translate("MainWindow", u"Source", None))
+        self.result_container.setTitle(QCoreApplication.translate("MainWindow", u"Filtered Image", None))
+        self.result_img.setText(QCoreApplication.translate("MainWindow", u"Result", None))
+        self.pushButton.setText(QCoreApplication.translate("MainWindow", u"Dummy Widget", None))
+        self.menuFile.setTitle(QCoreApplication.translate("MainWindow", u"&File", None))
+    # retranslateUi
+
diff --git a/num-int/src/numint/ui_mainwindow.py b/num-int/src/numint/ui_mainwindow.py
deleted file mode 100644
index 84d39bb..0000000
--- a/num-int/src/numint/ui_mainwindow.py
+++ /dev/null
@@ -1,251 +0,0 @@
-# -*- coding: utf-8 -*-
-
-################################################################################
-## Form generated from reading UI file 'mainwindow.ui'
-##
-## Created by: Qt User Interface Compiler version 6.7.2
-##
-## WARNING! All changes made in this file will be lost when recompiling UI file!
-################################################################################
-
-from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale,
-    QMetaObject, QObject, QPoint, QRect,
-    QSize, QTime, QUrl, Qt)
-from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor,
-    QFont, QFontDatabase, QGradient, QIcon,
-    QImage, QKeySequence, QLinearGradient, QPainter,
-    QPalette, QPixmap, QRadialGradient, QTransform)
-from PySide6.QtWidgets import (QApplication, QButtonGroup, QFormLayout, QGroupBox,
-    QHBoxLayout, QLabel, QLineEdit, QMainWindow,
-    QMenuBar, QPlainTextEdit, QPushButton, QRadioButton,
-    QSizePolicy, QSpacerItem, QStatusBar, QVBoxLayout,
-    QWidget)
-
-class Ui_MainWindow(object):
-    def setupUi(self, MainWindow):
-        if not MainWindow.objectName():
-            MainWindow.setObjectName(u"MainWindow")
-        MainWindow.resize(1411, 889)
-        self.centralwidget = QWidget(MainWindow)
-        self.centralwidget.setObjectName(u"centralwidget")
-        self.horizontalLayout_2 = QHBoxLayout(self.centralwidget)
-        self.horizontalLayout_2.setObjectName(u"horizontalLayout_2")
-        self.verticalLayout = QVBoxLayout()
-        self.verticalLayout.setObjectName(u"verticalLayout")
-        self.helpingText = QPlainTextEdit(self.centralwidget)
-        self.helpingText.setObjectName(u"helpingText")
-        sizePolicy = QSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum)
-        sizePolicy.setHorizontalStretch(0)
-        sizePolicy.setVerticalStretch(0)
-        sizePolicy.setHeightForWidth(self.helpingText.sizePolicy().hasHeightForWidth())
-        self.helpingText.setSizePolicy(sizePolicy)
-        font = QFont()
-        font.setFamilies([u"Noto Mono"])
-        self.helpingText.setFont(font)
-        self.helpingText.setReadOnly(True)
-
-        self.verticalLayout.addWidget(self.helpingText)
-
-        self.functionInfo = QGroupBox(self.centralwidget)
-        self.functionInfo.setObjectName(u"functionInfo")
-        self.formLayout_3 = QFormLayout(self.functionInfo)
-        self.formLayout_3.setObjectName(u"formLayout_3")
-        self.label_start = QLabel(self.functionInfo)
-        self.label_start.setObjectName(u"label_start")
-
-        self.formLayout_3.setWidget(0, QFormLayout.LabelRole, self.label_start)
-
-        self.function = QLineEdit(self.functionInfo)
-        self.function.setObjectName(u"function")
-
-        self.formLayout_3.setWidget(0, QFormLayout.FieldRole, self.function)
-
-        self.label_fn = QLabel(self.functionInfo)
-        self.label_fn.setObjectName(u"label_fn")
-
-        self.formLayout_3.setWidget(1, QFormLayout.LabelRole, self.label_fn)
-
-        self.startValue = QLineEdit(self.functionInfo)
-        self.startValue.setObjectName(u"startValue")
-
-        self.formLayout_3.setWidget(1, QFormLayout.FieldRole, self.startValue)
-
-        self.label_end = QLabel(self.functionInfo)
-        self.label_end.setObjectName(u"label_end")
-
-        self.formLayout_3.setWidget(2, QFormLayout.LabelRole, self.label_end)
-
-        self.endValue = QLineEdit(self.functionInfo)
-        self.endValue.setObjectName(u"endValue")
-
-        self.formLayout_3.setWidget(2, QFormLayout.FieldRole, self.endValue)
-
-
-        self.verticalLayout.addWidget(self.functionInfo)
-
-        self.breakRule = QGroupBox(self.centralwidget)
-        self.breakRule.setObjectName(u"breakRule")
-        self.formLayout_2 = QFormLayout(self.breakRule)
-        self.formLayout_2.setObjectName(u"formLayout_2")
-        self.label_4 = QLabel(self.breakRule)
-        self.label_4.setObjectName(u"label_4")
-
-        self.formLayout_2.setWidget(2, QFormLayout.LabelRole, self.label_4)
-
-        self.espilon = QLineEdit(self.breakRule)
-        self.espilon.setObjectName(u"espilon")
-        sizePolicy1 = QSizePolicy(QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Fixed)
-        sizePolicy1.setHorizontalStretch(0)
-        sizePolicy1.setVerticalStretch(0)
-        sizePolicy1.setHeightForWidth(self.espilon.sizePolicy().hasHeightForWidth())
-        self.espilon.setSizePolicy(sizePolicy1)
-
-        self.formLayout_2.setWidget(2, QFormLayout.FieldRole, self.espilon)
-
-        self.label_5 = QLabel(self.breakRule)
-        self.label_5.setObjectName(u"label_5")
-
-        self.formLayout_2.setWidget(3, QFormLayout.LabelRole, self.label_5)
-
-        self.section = QLineEdit(self.breakRule)
-        self.section.setObjectName(u"section")
-        sizePolicy1.setHeightForWidth(self.section.sizePolicy().hasHeightForWidth())
-        self.section.setSizePolicy(sizePolicy1)
-
-        self.formLayout_2.setWidget(3, QFormLayout.FieldRole, self.section)
-
-        self.breakMethodBox = QGroupBox(self.breakRule)
-        self.breakMethodBox.setObjectName(u"breakMethodBox")
-        self.horizontalLayout = QHBoxLayout(self.breakMethodBox)
-        self.horizontalLayout.setObjectName(u"horizontalLayout")
-        self.minEpsilonMethod = QRadioButton(self.breakMethodBox)
-        self.breakMethod = QButtonGroup(MainWindow)
-        self.breakMethod.setObjectName(u"breakMethod")
-        self.breakMethod.addButton(self.minEpsilonMethod)
-        self.minEpsilonMethod.setObjectName(u"minEpsilonMethod")
-
-        self.horizontalLayout.addWidget(self.minEpsilonMethod)
-
-        self.numberOfSectionsMethod = QRadioButton(self.breakMethodBox)
-        self.breakMethod.addButton(self.numberOfSectionsMethod)
-        self.numberOfSectionsMethod.setObjectName(u"numberOfSectionsMethod")
-
-        self.horizontalLayout.addWidget(self.numberOfSectionsMethod)
-
-
-        self.formLayout_2.setWidget(0, QFormLayout.FieldRole, self.breakMethodBox)
-
-
-        self.verticalLayout.addWidget(self.breakRule)
-
-        self.plotBtn = QPushButton(self.centralwidget)
-        self.plotBtn.setObjectName(u"plotBtn")
-
-        self.verticalLayout.addWidget(self.plotBtn)
-
-        self.verticalSpacer = QSpacerItem(20, 40, QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Expanding)
-
-        self.verticalLayout.addItem(self.verticalSpacer)
-
-        self.riemannSumGruppe = QGroupBox(self.centralwidget)
-        self.riemannSumGruppe.setObjectName(u"riemannSumGruppe")
-        self.formLayout = QFormLayout(self.riemannSumGruppe)
-        self.formLayout.setObjectName(u"formLayout")
-        self.label = QLabel(self.riemannSumGruppe)
-        self.label.setObjectName(u"label")
-
-        self.formLayout.setWidget(0, QFormLayout.LabelRole, self.label)
-
-        self.leftSum = QLineEdit(self.riemannSumGruppe)
-        self.leftSum.setObjectName(u"leftSum")
-        sizePolicy1.setHeightForWidth(self.leftSum.sizePolicy().hasHeightForWidth())
-        self.leftSum.setSizePolicy(sizePolicy1)
-        self.leftSum.setReadOnly(True)
-
-        self.formLayout.setWidget(0, QFormLayout.FieldRole, self.leftSum)
-
-        self.label_2 = QLabel(self.riemannSumGruppe)
-        self.label_2.setObjectName(u"label_2")
-
-        self.formLayout.setWidget(1, QFormLayout.LabelRole, self.label_2)
-
-        self.rightSum = QLineEdit(self.riemannSumGruppe)
-        self.rightSum.setObjectName(u"rightSum")
-        sizePolicy1.setHeightForWidth(self.rightSum.sizePolicy().hasHeightForWidth())
-        self.rightSum.setSizePolicy(sizePolicy1)
-        self.rightSum.setReadOnly(True)
-
-        self.formLayout.setWidget(1, QFormLayout.FieldRole, self.rightSum)
-
-        self.label_3 = QLabel(self.riemannSumGruppe)
-        self.label_3.setObjectName(u"label_3")
-
-        self.formLayout.setWidget(2, QFormLayout.LabelRole, self.label_3)
-
-        self.numOfSections = QLineEdit(self.riemannSumGruppe)
-        self.numOfSections.setObjectName(u"numOfSections")
-
-        self.formLayout.setWidget(2, QFormLayout.FieldRole, self.numOfSections)
-
-
-        self.verticalLayout.addWidget(self.riemannSumGruppe)
-
-
-        self.horizontalLayout_2.addLayout(self.verticalLayout)
-
-        self.plotBox = QGroupBox(self.centralwidget)
-        self.plotBox.setObjectName(u"plotBox")
-        self.plotBox.setEnabled(True)
-        sizePolicy2 = QSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding)
-        sizePolicy2.setHorizontalStretch(0)
-        sizePolicy2.setVerticalStretch(0)
-        sizePolicy2.setHeightForWidth(self.plotBox.sizePolicy().hasHeightForWidth())
-        self.plotBox.setSizePolicy(sizePolicy2)
-
-        self.horizontalLayout_2.addWidget(self.plotBox)
-
-        MainWindow.setCentralWidget(self.centralwidget)
-        self.menubar = QMenuBar(MainWindow)
-        self.menubar.setObjectName(u"menubar")
-        self.menubar.setGeometry(QRect(0, 0, 1411, 22))
-        MainWindow.setMenuBar(self.menubar)
-        self.statusbar = QStatusBar(MainWindow)
-        self.statusbar.setObjectName(u"statusbar")
-        MainWindow.setStatusBar(self.statusbar)
-
-        self.retranslateUi(MainWindow)
-
-        QMetaObject.connectSlotsByName(MainWindow)
-    # setupUi
-
-    def retranslateUi(self, MainWindow):
-        MainWindow.setWindowTitle(QCoreApplication.translate("MainWindow", u"Riemann Sum", None))
-        self.helpingText.setPlainText(QCoreApplication.translate("MainWindow", u"Die Funktion f(x) kann eine beliebige Kombination von arithmetischen Operationen und Python mathematische Funktion in Modul math sein. Einige Beispiele sind:\n"
-"\n"
-"x ** 2                               0    4\n"
-"x ** 3                               0    4\n"
-"tan(radians(x))                      0    45\n"
-"sin(x)**3 + cos(x)**3                0    2*pi\n"
-"", None))
-        self.functionInfo.setTitle(QCoreApplication.translate("MainWindow", u"Angabe der Funktion", None))
-        self.label_start.setText(QCoreApplication.translate("MainWindow", u"Funktion f(x) = ", None))
-        self.function.setText(QCoreApplication.translate("MainWindow", u"x ** 2", None))
-        self.label_fn.setText(QCoreApplication.translate("MainWindow", u"start", None))
-        self.startValue.setText(QCoreApplication.translate("MainWindow", u"0", None))
-        self.label_end.setText(QCoreApplication.translate("MainWindow", u"end", None))
-        self.endValue.setText(QCoreApplication.translate("MainWindow", u"4", None))
-        self.breakRule.setTitle(QCoreApplication.translate("MainWindow", u"Abbuchkriterium", None))
-        self.label_4.setText(QCoreApplication.translate("MainWindow", u"Epsilon", None))
-        self.label_5.setText(QCoreApplication.translate("MainWindow", u"Anzahl der Sektionen", None))
-        self.section.setText(QCoreApplication.translate("MainWindow", u"8", None))
-        self.breakMethodBox.setTitle(QCoreApplication.translate("MainWindow", u"Methoden", None))
-        self.minEpsilonMethod.setText(QCoreApplication.translate("MainWindow", u"Minimale Epsilon", None))
-        self.numberOfSectionsMethod.setText(QCoreApplication.translate("MainWindow", u"Anzahl der Sektionen", None))
-        self.plotBtn.setText(QCoreApplication.translate("MainWindow", u"Ok", None))
-        self.riemannSumGruppe.setTitle(QCoreApplication.translate("MainWindow", u"Riemann Summe", None))
-        self.label.setText(QCoreApplication.translate("MainWindow", u"linke Summe", None))
-        self.label_2.setText(QCoreApplication.translate("MainWindow", u"rechte Summe", None))
-        self.label_3.setText(QCoreApplication.translate("MainWindow", u"Anzahl der Iterationen", None))
-        self.plotBox.setTitle(QCoreApplication.translate("MainWindow", u"Plot", None))
-    # retranslateUi
-
diff --git a/stundenplan/src/pygraph/graphdemo.py b/stundenplan/src/pygraph/graphdemo.py
index 2a6cf7d..d8669be 100644
--- a/stundenplan/src/pygraph/graphdemo.py
+++ b/stundenplan/src/pygraph/graphdemo.py
@@ -2,6 +2,9 @@
 
 
 class Graph:
+    """
+    represents an undirected and unweighted Graph
+    """
     def __init__(self):
         self._adjacent: dict[int, set] = {}
         self._vertex_attribute: dict[int, dict] = {}
@@ -25,7 +28,7 @@
             u_neighbor.add(v)
         pass
 
-    def add_edges(self, u: int, adjacent:[int]):
+    def add_edges(self, u: int, adjacent: list[int]):
         for v in adjacent:
             self.add_edge(u, v)
         pass
@@ -44,7 +47,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[vertex]
         self._vertex_attribute[vertex] = old_attributes | properties
         return self
         pass
@@ -75,7 +78,7 @@
     def adjacent_of(self, vertex: int):
         if vertex not in self._adjacent:
             raise ValueError(f"Graph does not include vertex {vertex}")
-        return sorted( self._adjacent.get(vertex) )
+        return sorted( self._adjacent[vertex] )
 
     def for_each_edges(self, action: Callable[[int, int], Any]):
         """
@@ -87,21 +90,18 @@
             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)
+                #visited_adjacent = visited_edges.get(first)
+                visited_adjacent = visited_edges[first]
                 if second not in visited_adjacent:
                     visited_adjacent.add(second)
                     action(start, end)
             else:
-                adjacent = set()
+                adjacent: set[int] = set()
                 visited_edges[first] = adjacent
                 adjacent.add(second)
                 action(start, end)
 
-    def get_lecture_name(self, vertex: int):
-        pass
 
-    def set_lecture_name(self, vertex: int, name: str):
-        pass
 
     def __repr__(self):
         text = ""
diff --git a/stundenplan/src/pygraph/shortestpath.py b/stundenplan/src/pygraph/shortestpath.py
index 4426f95..5d3e2af 100644
--- a/stundenplan/src/pygraph/shortestpath.py
+++ b/stundenplan/src/pygraph/shortestpath.py
@@ -1,9 +1,10 @@
 import collections
+from typing import Mapping
 
 from pygraph.graphdemo import Graph
 
 
-def bfs(g: Graph, start: int) -> {int:int|None}:
+def bfs(g: Graph, start: int) -> Graph:
     """
 
     :param g:
@@ -26,3 +27,53 @@
                 g.merge_attribute(v, visited)
                 queue.append(v)
     return tree
+
+
+def bfs_dict(g: Graph, start: int) -> Mapping[int, int|None]:
+    tree = {start:None}
+    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[v] = u
+                g.merge_attribute(v, visited)
+                queue.append(v)
+    return tree
+    pass
+
+
+def find_path(g: Graph, u: int, v: int) -> list[int]:
+    tree = bfs_dict(g, v)
+    path = [u]
+    while (current := path[-1]) != v:
+        precedent = tree[current]
+        path.append(precedent)
+    return path
+
+
+def find_path_gpt(g: Graph, u: int, v: int) -> list[int]:
+    # Erstelle einen BFS-Baum, beginnend bei Knoten v
+    bfs_tree = bfs_dict(g, v)
+
+    # Wenn u nicht in bfs_tree ist, gibt es keinen Pfad von u nach v
+    if u not in bfs_tree:
+        return []  # Kein Pfad gefunden
+
+    # Den Pfad von u nach v rekonstruieren
+    path = []
+    current = u
+    while current is not None:
+        path.append(current)
+        current = bfs_tree[current]
+
+    # Den Pfad umkehren, da wir rückwärts von u nach v gehen
+    path.reverse()
+
+    return path
\ No newline at end of file
diff --git a/stundenplan/tests/pygraph/shortestpath_tests.py b/stundenplan/tests/pygraph/shortestpath_tests.py
index 6b9b2de..dc914a1 100644
--- a/stundenplan/tests/pygraph/shortestpath_tests.py
+++ b/stundenplan/tests/pygraph/shortestpath_tests.py
@@ -1,26 +1,57 @@
 import unittest
 
 from pygraph.graphdemo import Graph
-from pygraph.shortestpath import bfs
+from pygraph.shortestpath import bfs, bfs_dict, find_path, find_path_gpt
 
 
 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
-
+        g.add_edges(1, [3, 4])
+        g.add_edges(2, [4, 6, 7])
+        g.add_edges(4, [5])
+        print(g)
+        print("#")
         tree = bfs(g, 0)
         print(tree)
 
+    def test_bfs_dict(self):
+        g = Graph()
+        g.add_edges(0, [1, 2])
+        g.add_edges(1, [3, 4])
+        g.add_edges(2, [4, 6, 7])
+        g.add_edges(4, [5])
+        print(g)
+        tree = bfs_dict(g, 6)
+        print("Tree from Vertex 6")
+        print(tree)
+
+    def test_find_path(self):
+        g = Graph()
+        g.add_edges(0, [1, 2])
+        g.add_edges(1, [3, 4])
+        g.add_edges(2, [4, 6, 7])
+        g.add_edges(4, [5])
+        print(g)
+        (u, v) = (6, 5)
+        path = find_path(g, 6, 5)
+        print(f"path from {u} to {v}")
+        print(path)
+
+    def test_find_path_gpt(self):
+        g = Graph()
+        g.add_edges(0, [1, 2])
+        g.add_edges(1, [3, 4])
+        g.add_edges(2, [4, 6, 7])
+        g.add_edges(4, [5])
+        print(g)
+        (u, v) = (6, 5)
+        path = find_path_gpt(g, 6, 5)
+        print(f"path from {u} to {v}")
+        print(path)
+
+
 
 if __name__ == '__main__':
     unittest.main()

--
Gitblit v1.10.0-SNAPSHOT