
ЛАБ 2 / отчет 2 лр
.docxБаранов Вадим ИВТ-43 ЛАБА2
Задание 1.
Собрать модель подсчета количества дождливых, снежных и солнечных дней на планете Оз. Для этого:
1. Запустить MatLab.
2. Открыть Simulink и создать новую модель. (библиотека)
3. Объект Chart находится в браузере Simulink, раздел Stateflow.
4. Собрать модель согласно приведенной выше схеме.
Промоделировать систему с заданными начальными параметрами. Зафиксировать результаты.
Изменить вероятности перехода, зафиксировать полученные результаты.
Ход выполнения: написал код + загрузил PATCH
Установите Graphviz:
Перейдите на официальный сайт Graphviz и скачайте версию для Windows.
Установите Graphviz на свой компьютер, следуя инструкциям установщика.
Добавьте Graphviz в PATH:
Откройте "Панель управления" -> "Система и безопасность" -> "Система" -> "Дополнительные параметры системы".
Перейдите на вкладку "Дополнительно" и нажмите на кнопку "Переменные среды".
В разделе "Системные переменные" найдите переменную Path и нажмите "Изменить".
Нажмите "Создать" и добавьте путь к папке bin, где установлен Graphviz (например, C:\Program Files\Graphviz\bin).
import random import graphviz from collections import Counter import tkinter as tk from tkinter import messagebox from PIL import Image, ImageTk class WeatherStateMachine: def __init__(self, initial_state, transitions): self.state = initial_state self.transitions = transitions self.state_count = Counter() def step(self): current_state = self.state self.state_count[current_state] += 1 next_state = random.choices( population=list(self.transitions[current_state].keys()), weights=list(self.transitions[current_state].values()) )[0] self.state = next_state def run_simulation(self, steps): for _ in range(steps): self.step() def get_results(self): return dict(self.state_count) def get_current_state(self): return self.state def create_state_diagram(states, transitions, filename): f = graphviz.Digraph('finite_state_machine', filename='fsm.gv') f.attr(rankdir='LR', size='8,5') f.attr('node', shape='circle') # Добавление состояний и переходов for state in states: f.node(state) for state, transition_dict in transitions.items(): for next_state, probability in transition_dict.items(): f.edge(state, next_state, label=f'{probability * 100:.0f}%') f.render(filename, format='png', cleanup=False) print(f"Диаграмма состояний сохранена как '{filename}.png'") # GUI class WeatherApp: def __init__(self, root): self.root = root self.root.title("Weather Simulation") self.root.geometry("800x600") # Настройки переходов self.transitions = { 'Sunny': {'Sunny': 0.7, 'Rainy': 0.2, 'Snowy': 0.1}, 'Rainy': {'Sunny': 0.4, 'Rainy': 0.5, 'Snowy': 0.1}, 'Snowy': {'Sunny': 0.2, 'Rainy': 0.3, 'Snowy': 0.5} } self.initial_state = 'Sunny' self.weather_machine = WeatherStateMachine(self.initial_state, self.transitions) # Элементы интерфейса self.label = tk.Label(root, text="Weather Simulation", font=("Arial", 20)) self.label.pack(pady=10) self.run_button = tk.Button(root, text="Run Simulation", command=self.run_simulation) self.run_button.pack(pady=5) self.result_label = tk.Label(root, text="Results:", font=("Arial", 14)) self.result_label.pack(pady=10) self.diagram_button = tk.Button(root, text="Show State Diagram", command=self.show_diagram) self.diagram_button.pack(pady=5) # Placeholder для диаграммы self.image_label = tk.Label(root) self.image_label.pack(pady=10) def run_simulation(self): self.weather_machine.run_simulation(steps=100) results = self.weather_machine.get_results() result_text = f"Sunny: {results.get('Sunny', 0)}, Rainy: {results.get('Rainy', 0)}, Snowy: {results.get('Snowy', 0)}" self.result_label.config(text=f"Results: {result_text}") def show_diagram(self): create_state_diagram(['Sunny', 'Rainy', 'Snowy'], self.transitions, 'state_machine_diagram') self.display_image('state_machine_diagram.png') def display_image(self, filepath): try: img = Image.open(filepath) img = img.resize((500, 300), Image.Resampling.LANCZOS) # Исправление здесь photo = ImageTk.PhotoImage(img) self.image_label.config(image=photo) self.image_label.image = photo except Exception as e: messagebox.showerror("Error", f"Could not load image: {e}") # Запуск интерфейса if __name__ == "__main__": root = tk.Tk() app = WeatherApp(root) root.mainloop()
Задание заключалось в создании модели для подсчета количества дней с разной погодой (солнечные, дождливые и снежные дни) с использованием конечного автомата. Мы разработали класс WeatherStateMachine, который имитирует переходы между состояниями погоды в зависимости от заданных вероятностей
Картинка всегда одинаковая т.к просто показывает модель переходов между состояниями.
То есть, диаграмма отражает структуру системы (переходы и их вероятности), а не результаты симуляции. Симуляция же просто подсчитывает, сколько раз каждое состояние встречалось за заданное количество шагов.
У нас 100 шагов (step)
Задание 2.
Собрать модель нахождения наибольшего общего делителя. Привести примеры работы модели.
import tkinter as tk from tkinter import messagebox class GCDModel: def __init__(self, a, b): self.a = a self.b = b def calculate_gcd(self): # Евклида while self.b != 0: # Пока b не равно нулю # Обновляем a и b self.a, self.b = self.b, self.a % self.b # b становится a, а a становится остатком от деления a на b return self.a # Когда b становится 0, a содержит НОД class GCDApp: def __init__(self, master): self.master = master self.master.title("Нахождение НОД") self.master.geometry("700x500") # Создание элементов интерфейса self.label_title = tk.Label(master, text="Нахождение НОД двух чисел", font=("Arial", 14)) self.label_title.pack(pady=10) self.label_a = tk.Label(master, text="Введите первое число:") self.label_a.pack(pady=5) self.entry_a = tk.Entry(master) self.entry_a.pack(pady=5) self.label_b = tk.Label(master, text="Введите второе число:") self.label_b.pack(pady=5) self.entry_b = tk.Entry(master) self.entry_b.pack(pady=5) self.calculate_button = tk.Button(master, text="Вычислить НОД", command=self.handle_state) self.calculate_button.pack(pady=10) self.reset_button = tk.Button(master, text="Сбросить", command=self.reset_input) self.reset_button.pack(pady=5) self.result_label = tk.Label(master, text="", font=("Arial", 12)) self.result_label.pack(pady=10) # Canvas для рисования графика self.canvas = tk.Canvas(master, width=600, height=400, bg="white") self.canvas.pack(pady=10) self.state = "input" # Начальное состояние # Рисуем график self.draw_flowchart() def draw_flowchart(self): # Рисование графика структуры программы self.canvas.delete("all") # Очистка канваса # Блок "Ввод данных" self.canvas.create_rectangle(50, 20, 550, 60, fill="lightblue") self.canvas.create_text(300, 40, text="Ввод данных", font=("Arial", 12)) # Блок "Проверка ввода" self.canvas.create_rectangle(50, 80, 550, 120, fill="lightgreen") self.canvas.create_text(300, 100, text="Проверка ввода", font=("Arial", 12)) # Блок "Если (ввод корректный)" self.canvas.create_rectangle(50, 140, 550, 180, fill="lightyellow") self.canvas.create_text(300, 160, text="Если ввод корректный", font=("Arial", 12)) # Блок "Цикл" self.canvas.create_rectangle(50, 200, 550, 240, fill="lightcoral") self.canvas.create_text(300, 220, text="Цикл вычисления НОД", font=("Arial", 12)) # Блок "Вывод результата" self.canvas.create_rectangle(50, 260, 550, 300, fill="lightgreen") self.canvas.create_text(300, 280, text="Вывод результата", font=("Arial", 12)) # Рисуем стрелки self.canvas.create_line(300, 60, 300, 80, arrow=tk.LAST) # Ввод -> Проверка ввода self.canvas.create_line(300, 120, 300, 140, arrow=tk.LAST) # Проверка ввода -> Условие self.canvas.create_line(300, 180, 300, 200, arrow=tk.LAST) # Условие -> Цикл self.canvas.create_line(300, 240, 300, 260, arrow=tk.LAST) # Цикл -> Вывод результата # Стрелка для завершения цикла self.canvas.create_line(300, 240, 300, 100, arrow=tk.LAST, dash=(4, 2)) # Цикл -> Условие def handle_state(self): # Обработка текущего состояния if self.state == "input": self.process_input() elif self.state == "calculating": self.calculate_gcd() elif self.state == "result": self.show_result() def process_input(self): self.state = "calculating" try: a = int(self.entry_a.get()) b = int(self.entry_b.get()) self.gcd_model = GCDModel(a, b) self.result_label.config(text="Вычисление НОД...") self.handle_state() # Переход к следующему состоянию except ValueError: messagebox.showerror("Ошибка ввода", "Пожалуйста, введите целые числа.") self.state = "input" # Возврат к состоянию ввода def calculate_gcd(self): # Вычисление НОД с использованием метода calculate_gcd gcd_result = self.gcd_model.calculate_gcd() # Вызов метода для нахождения НОД self.result_label.config(text=f"НОД = {gcd_result}") # Отображение результата self.state = "result" # Переход к состоянию результата def show_result(self): self.calculate_button.config(text="Вычислить НОД") # Сброс текста кнопки def reset_input(self): self.entry_a.delete(0, tk.END) self.entry_b.delete(0, tk.END) self.result_label.config(text="") self.state = "input" # Переход к начальному состоянию self.calculate_button.config(text="Вычислить НОД") # Восстановление текста кнопки self.draw_flowchart() # Повторное рисование графика if __name__ == "__main__": root = tk.Tk() app = GCDApp(root) root.mainloop()
Задание 3.
Разработать модель усилителя, удовлетворяющую следующим требованиям.
Входные сигналы:
1. Любой входной сигнал (например синусоида).
2. Время задержки. Задается константной.
3. Коэффициент усиления.
import numpy as np import tkinter as tk from tkinter import messagebox class AmplifierModel: def __init__(self, input_signal, delay_time, gain): self.input_signal = input_signal self.delay_time = delay_time self.gain = gain self.output_signal = self.calculate_output_signal() def calculate_output_signal(self): output_signal = np.zeros_like(self.input_signal) # Условие времени задержки for t in range(len(self.input_signal)): if t < self.delay_time: output_signal[t] = 0 else: output_signal[t] = self.input_signal[t - self.delay_time] * self.gain return output_signal def get_output_data(self): # Возвращает данные выходного сигнала для вывода return self.output_signal class AmplifierUI: def __init__(self, master): self.master = master master.title("Amplifier Model") self.label_input_signal = tk.Label(master, text="Input Signal Frequency (Hz):") self.label_input_signal.pack() self.entry_input_signal = tk.Entry(master) self.entry_input_signal.pack() self.label_delay_time = tk.Label(master, text="Delay Time (samples):") self.label_delay_time.pack() self.entry_delay_time = tk.Entry(master) self.entry_delay_time.pack() self.label_gain = tk.Label(master, text="Gain:") self.label_gain.pack() self.entry_gain = tk.Entry(master) self.entry_gain.pack() self.button_run = tk.Button(master, text="Run", command=self.run_amplifier) self.button_run.pack() self.output_text = tk.Text(master, height=10, width=50) self.output_text.pack() def run_amplifier(self): try: frequency = float(self.entry_input_signal.get()) delay_time = int(self.entry_delay_time.get()) gain = float(self.entry_gain.get()) # Создание входного сигнала (синусоида) time = np.linspace(0, 1, 1000) input_signal = np.sin(2 * np.pi * frequency * time) # Модель усилителя amplifier = AmplifierModel(input_signal, delay_time, gain) output_signal = amplifier.get_output_data() # Отображение выходного сигнала в текстовом виджете self.output_text.delete(1.0, tk.END) # Очистка предыдущего вывода self.output_text.insert(tk.END, "Output Signal:\n") self.output_text.insert(tk.END, str(output_signal.tolist()) + "\n") except ValueError: messagebox.showerror("Input error", "Please enter valid values.") if __name__ == "__main__": root = tk.Tk() app = AmplifierUI(root) root.mainloop()
ВЫВОД:
Проект продемонстрировал основные принципы разработки GUI-приложений с использованием Python и Tkinter, а также реализацию алгоритмов для выполнения математических операций. Такой подход позволяет создавать удобные и интерактивные приложения для пользователей.