Auswahl der Methode is eindeutig gestaltet
| | |
| | | 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() |
| | |
| | | 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) |
| | |
| | | <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"> |
| | |
| | | </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"> |
| | |
| | | </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> |
| | |
| | | </widget> |
| | | <resources/> |
| | | <connections/> |
| | | <buttongroups> |
| | | <buttongroup name="breakMethod"/> |
| | | </buttongroups> |
| | | </ui> |
| | |
| | | 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)] |
| | |
| | | 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)] |
| | |
| | | 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): |
| | |
| | | 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") |
| | |
| | | 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) |
| | |
| | | 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)) |
| | |
| | | |
| | | 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) |
| | | |
| | | |
| | | |
| | |
| | | from typing import Any, Callable |
| | | |
| | | |
| | | class Graph: |
| | | def __init__(self): |
| | | self._adjacent: dict[int, set] = {} |
| | |
| | | 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: |
| | |
| | | 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): |
| | |
| | | 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): |