From 11beed44c78847c91b25d8b4c9d8b3c7ada8de35 Mon Sep 17 00:00:00 2001 From: hbui <hong-phuc.bui@htwsaar.de> Date: Thu, 25 Jul 2024 03:01:12 +0200 Subject: [PATCH] Auswahl der Methode is eindeutig gestaltet --- num-int/src/numint/guimain.py | 33 +++++++++- num-int/src/numint/mainwindow.ui | 40 ++++++++++++- stundenplan/src/pygraph/graphdemo.py | 15 +++-- num-int/src/numint/ui_mainwindow.py | 41 +++++++++++-- num-int/src/numint/riemann_sum.py | 21 ++++++ num-int/tests/numint/expression_test.py | 29 ++++++++- 6 files changed, 149 insertions(+), 30 deletions(-) diff --git a/num-int/src/numint/guimain.py b/num-int/src/numint/guimain.py index 3f90199..076d851 100644 --- a/num-int/src/numint/guimain.py +++ b/num-int/src/numint/guimain.py @@ -35,24 +35,30 @@ layout.addWidget(self.canvas) self.ui.plotBox.setLayout(layout) self.ui.plotBtn.clicked.connect(self._update_plot) + self.ui.breakMethod.buttonClicked.connect(self._activate_break_rule) + self.ui.numberOfSectionsMethod.click() def _update_plot(self): fn_expr = self.ui.function.text() self.fn_expr = fn_expr start = self.ui.startValue.text() end = self.ui.endValue.text() - epsilon = self.ui.espilon.text() + try: f = parse_function(fn_expr) (a, b) = (parse_value(start), parse_value(end)) - if epsilon is not None and len(epsilon.strip()) > 0: - eps = parse_value(epsilon) + method_id = self.ui.breakMethod.checkedId() + if method_id == self.ui.breakMethod.id(self.ui.minEpsilonMethod): + epsilon = self.ui.espilon.text() + eps = abs(parse_value(epsilon)) + self.ui.espilon.setText(f"{eps}") print(f"plot f(x) = {fn_expr}, {a}, {b}, epsilon = {eps}") (self.x, self.y, self.left, self.right, self.num_of_iterations, *_) = numint_epsilon(f, a, b, eps) self._update_plot_eps() - else: + elif method_id == self.ui.breakMethod.id(self.ui.numberOfSectionsMethod): section = self.ui.section.text() - sec = parse_value(section) + sec = int(abs(parse_value(section))) + self.ui.section.setText(f"{sec}") print(f"plot f(x) = {fn_expr}, {a}, {b}, section = {sec}") (self.x, self.y, self.left, self.right, self.num_of_iterations, *_) = numint_section(f, a, b, sec) self._update_plot_eps() @@ -74,6 +80,23 @@ self.ui.rightSum.setText(f"{self.right}") self.ui.numOfSections.setText(f"{self.num_of_iterations}") + def _activate_break_rule(self): + method_id = self.ui.breakMethod.checkedId() + print(method_id) + if method_id == self.ui.breakMethod.id(self.ui.numberOfSectionsMethod): + print("activate num of sec") + self.ui.section.setEnabled(True) + self.ui.section.setFocus() + self.ui.espilon.setEnabled(False) + + elif method_id == self.ui.breakMethod.id(self.ui.minEpsilonMethod): + print("activate minimum epsilon method") + self.ui.section.setEnabled(False) + self.ui.espilon.setEnabled(True) + self.ui.espilon.setFocus() + + + def main(): app = QApplication(sys.argv) diff --git a/num-int/src/numint/mainwindow.ui b/num-int/src/numint/mainwindow.ui index c5069ba..8f1f47f 100644 --- a/num-int/src/numint/mainwindow.ui +++ b/num-int/src/numint/mainwindow.ui @@ -101,14 +101,14 @@ <string>Abbuchkriterium</string> </property> <layout class="QFormLayout" name="formLayout_2"> - <item row="0" column="0"> + <item row="2" column="0"> <widget class="QLabel" name="label_4"> <property name="text"> <string>Epsilon</string> </property> </widget> </item> - <item row="0" column="1"> + <item row="2" column="1"> <widget class="QLineEdit" name="espilon"> <property name="sizePolicy"> <sizepolicy hsizetype="Minimum" vsizetype="Fixed"> @@ -118,14 +118,14 @@ </property> </widget> </item> - <item row="1" column="0"> + <item row="3" column="0"> <widget class="QLabel" name="label_5"> <property name="text"> <string>Anzahl der Sektionen</string> </property> </widget> </item> - <item row="1" column="1"> + <item row="3" column="1"> <widget class="QLineEdit" name="section"> <property name="sizePolicy"> <sizepolicy hsizetype="Minimum" vsizetype="Fixed"> @@ -138,6 +138,35 @@ </property> </widget> </item> + <item row="0" column="1"> + <widget class="QGroupBox" name="breakMethodBox"> + <property name="title"> + <string>Methoden</string> + </property> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <widget class="QRadioButton" name="minEpsilonMethod"> + <property name="text"> + <string>Minimale Epsilon</string> + </property> + <attribute name="buttonGroup"> + <string notr="true">breakMethod</string> + </attribute> + </widget> + </item> + <item> + <widget class="QRadioButton" name="numberOfSectionsMethod"> + <property name="text"> + <string>Anzahl der Sektionen</string> + </property> + <attribute name="buttonGroup"> + <string notr="true">breakMethod</string> + </attribute> + </widget> + </item> + </layout> + </widget> + </item> </layout> </widget> </item> @@ -254,4 +283,7 @@ </widget> <resources/> <connections/> + <buttongroups> + <buttongroup name="breakMethod"/> + </buttongroups> </ui> diff --git a/num-int/src/numint/riemann_sum.py b/num-int/src/numint/riemann_sum.py index 250f073..f0b997d 100644 --- a/num-int/src/numint/riemann_sum.py +++ b/num-int/src/numint/riemann_sum.py @@ -17,7 +17,16 @@ pass -def numint_epsilon(f:Callable[[float], float], a: float, b: float, epsilon: float = 1e-3): +def numint_epsilon(f: Callable[[float], float], a: float, b: float, epsilon: float = 1e-3): + """ + a not very stupid implementation of Riemann sum for a function, + left sum and right sum are calculated as long as their difference less than the given epsilon. + :param f: + :param a: + :param b: + :param epsilon: + :return: + """ dx = b - a x = [a, b] # debug only y = [f(a), f(b)] @@ -36,7 +45,15 @@ return x, y, s_left, s_right, n -def numint_section(f:Callable[[float], float], a: float, b: float, section_count: int = 8): +def numint_section(f: Callable[[float], float], a: float, b: float, section_count: int = 8): + """ + a stupid implementation of Riemann sum for a function with a fixed number of sections in interval [a, b] + :param f: + :param a: + :param b: + :param section_count: + :return: + """ dx = b - a x = [a, b] y = [f(a), f(b)] diff --git a/num-int/src/numint/ui_mainwindow.py b/num-int/src/numint/ui_mainwindow.py index b47fd6b..84d39bb 100644 --- a/num-int/src/numint/ui_mainwindow.py +++ b/num-int/src/numint/ui_mainwindow.py @@ -15,10 +15,11 @@ QFont, QFontDatabase, QGradient, QIcon, QImage, QKeySequence, QLinearGradient, QPainter, QPalette, QPixmap, QRadialGradient, QTransform) -from PySide6.QtWidgets import (QApplication, QFormLayout, QGroupBox, QHBoxLayout, - QLabel, QLineEdit, QMainWindow, QMenuBar, - QPlainTextEdit, QPushButton, QSizePolicy, QSpacerItem, - QStatusBar, QVBoxLayout, QWidget) +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): @@ -89,7 +90,7 @@ self.label_4 = QLabel(self.breakRule) self.label_4.setObjectName(u"label_4") - self.formLayout_2.setWidget(0, QFormLayout.LabelRole, self.label_4) + self.formLayout_2.setWidget(2, QFormLayout.LabelRole, self.label_4) self.espilon = QLineEdit(self.breakRule) self.espilon.setObjectName(u"espilon") @@ -99,19 +100,40 @@ sizePolicy1.setHeightForWidth(self.espilon.sizePolicy().hasHeightForWidth()) self.espilon.setSizePolicy(sizePolicy1) - self.formLayout_2.setWidget(0, QFormLayout.FieldRole, self.espilon) + 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(1, QFormLayout.LabelRole, self.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(1, QFormLayout.FieldRole, self.section) + 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) @@ -216,6 +238,9 @@ 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)) diff --git a/num-int/tests/numint/expression_test.py b/num-int/tests/numint/expression_test.py index 1846d74..7301169 100644 --- a/num-int/tests/numint/expression_test.py +++ b/num-int/tests/numint/expression_test.py @@ -9,27 +9,46 @@ def test_prio_product_exponent(self): parser = Lark_StandAlone() - tree = parser.parse("x ** -3 * sin(12)") # => (x^3) * sin(12) - print(tree.pretty()) + tree = parser.parse("x ** -3 * sin(12)") + self.assertEqual('''mul + exponent + var x + neg + number 3 + function + sin + argv + number 12 +''', tree.pretty(indent_str=' ')) def test_prio_product_exponent_revert(self): parser = Lark_StandAlone() tree = parser.parse("sin(12) * x ** sqrt(4)") # => sin(12) * (x ** sqrt(4)) - print(tree.pretty()) + print(f">{tree.pretty()}<") + self.assertEqual('''mul + function + sin + argv + number 12 + exponent + var x + function + sqrt + argv + number 4 +''', tree.pretty(indent_str=' ')) def test_use_transform(self): parser = Lark_StandAlone(transformer=ExpressionTransformer()) tree = parser.parse("log(-12, 5) * x ** sqrt(4)") # => sin(12) * (x^sqrt(4)) self.assertEqual(tree, 'math.log(-12, 5) * x ** math.sqrt(4)') - print(tree) def test_use_function_in_function(self): parser = Lark_StandAlone(transformer=ExpressionTransformer()) tree = parser.parse("tan(radians(x))") # => self.assertEqual(tree, 'math.tan(math.radians(x))') - print(tree) diff --git a/stundenplan/src/pygraph/graphdemo.py b/stundenplan/src/pygraph/graphdemo.py index 2371fd4..c0e3df9 100644 --- a/stundenplan/src/pygraph/graphdemo.py +++ b/stundenplan/src/pygraph/graphdemo.py @@ -1,3 +1,6 @@ +from typing import Any, Callable + + class Graph: def __init__(self): self._adjacent: dict[int, set] = {} @@ -41,7 +44,7 @@ return self pass - def get_attribute(self, vertex): + def get_attribute(self, vertex: int): if vertex in self._adjacent: return self._vertex_attribute[vertex] else: @@ -51,16 +54,16 @@ def vertices(self): return self._adjacent.keys() - def for_each_vertices(self, action): + def for_each_vertices(self, action: Callable[[int], Any]): for v in self.vertices(): action(v) - def adjacent_of(self, vertex): + 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) - def for_each_edges(self, action): + def for_each_edges(self, action: Callable[[int, int], Any]): visited_edges: dict[int, set] = {} for start in self.vertices(): for end in self.adjacent_of(start): @@ -76,10 +79,10 @@ adjacent.add(second) action(start, end) - def get_lecture_name(self, vertex): + def get_lecture_name(self, vertex: int): pass - def set_lecture_name(self, vertex, name): + def set_lecture_name(self, vertex: int, name: str): pass def __repr__(self): -- Gitblit v1.10.0-SNAPSHOT