distributed-computing/tasks/nikiforova-ts/Lab_6/work/Lab6.py
2023-12-18 17:42:12 +04:00

146 lines
5.6 KiB
Python

import tkinter as tk
from tkinter import ttk
import numpy as np
from multiprocessing import cpu_count, Pool
import time
class DeterminantCalculator:
def __init__(self, root):
self.root = root
self.root.title("Determinant Calculator")
self.matrix_size_label = ttk.Label(root, text="Matrix Size:")
self.matrix_size_label.grid(row=0, column=0, padx=10, pady=10)
self.matrix_size_entry = ttk.Entry(root)
self.matrix_size_entry.grid(row=0, column=1, padx=10, pady=10)
self.algorithm_label = ttk.Label(root, text="Algorithm:")
self.algorithm_label.grid(row=1, column=0, padx=10, pady=10)
self.algorithm_var = tk.StringVar()
self.algorithm_var.set("Normal")
self.algorithm_menu = ttk.Combobox(root, textvariable=self.algorithm_var, values=["Normal", "Parallel"])
self.algorithm_menu.grid(row=1, column=1, padx=10, pady=10)
self.num_threads_label = ttk.Label(root, text="Number of Threads:")
self.num_threads_label.grid(row=2, column=0, padx=10, pady=10)
self.num_threads_entry = ttk.Entry(root)
self.num_threads_entry.insert(0, str(cpu_count()))
self.num_threads_entry.grid(row=2, column=1, padx=10, pady=10)
self.generate_and_calculate_button = ttk.Button(root, text="Generate Matrix and Calculate Determinant", command=self.generate_and_calculate_determinant)
self.generate_and_calculate_button.grid(row=3, column=0, columnspan=2, pady=10)
self.result_label = ttk.Label(root, text="Result:")
self.result_label.grid(row=4, column=0, padx=10, pady=10)
self.time_label = ttk.Label(root, text="Time (s):")
self.time_label.grid(row=5, column=0, padx=10, pady=10)
self.matrix_label = ttk.Label(root, text="")
self.matrix_label.grid(row=6, column=0, columnspan=2, pady=10)
self.det_result = None # Глобальная переменная для хранения результата
def generate_matrix(self, size):
matrix = np.random.randint(1, 10, size=(size, size))
return matrix
def show_random_matrix(self, matrix):
self.matrix_label.config(text=f"Random Matrix:\n{matrix}")
def calculate_determinant_parallel(self, matrix, num_threads):
size = len(matrix)
if size == 1:
return matrix[0, 0], 0
result = RawArray('d', [0.0]) # Разделяемый массив для хранения результата
lock_object = np.ones(1) # Использование numpy для создания объекта блокировки
def calculate_submatrix(i):
nonlocal result
sub_matrix = self.get_submatrix(matrix, i)
sub_determinant = matrix[0, i] * self.calculate_determinant(sub_matrix)
with lock_object.get_lock():
result[0] += (-1) ** i * sub_determinant
with Pool(processes=num_threads) as pool:
start_time = time.time()
pool.map(calculate_submatrix, range(size))
end_time = time.time()
return result[0], end_time - start_time
# ваш существующий код
def get_submatrix(self, matrix, column_index):
size = len(matrix)
sub_matrix = np.zeros((size - 1, size - 1))
for i in range(1, size):
for j in range(size):
if j < column_index:
sub_matrix[i - 1, j] = matrix[i, j]
elif j > column_index:
sub_matrix[i - 1, j - 1] = matrix[i, j]
return sub_matrix
def calculate_determinant_group(self, matrix, row, col):
sign = (-1) ** (row + col)
minor = np.delete(np.delete(np.array(matrix), row, axis=0), col, axis=1)
det_minor = self.calculate_determinant(minor)
return sign * matrix[row][col] * det_minor
def calculate_determinant(self, matrix=None):
if matrix is None:
matrix_size = int(self.matrix_size_entry.get())
matrix = self.generate_matrix(matrix_size)
size = len(matrix)
if size == 1:
return matrix[0][0]
elif size == 2:
return matrix[0][0] * matrix[1][1] - matrix[0][1] * matrix[1][0]
else:
det = 0
for col in range(size):
sign = (-1) ** col
minor = np.delete(np.array(matrix), 0, axis=0)
minor = np.delete(minor, col, axis=1)
det += sign * matrix[0][col] * self.calculate_determinant(minor)
return det
def generate_and_calculate_determinant(self):
matrix_size = int(self.matrix_size_entry.get())
algorithm = self.algorithm_var.get()
num_threads = int(self.num_threads_entry.get())
random_matrix = self.generate_matrix(matrix_size)
self.show_random_matrix(random_matrix)
if algorithm == "Parallel":
det, time_taken = self.calculate_determinant_parallel(random_matrix, num_threads)
else:
start_time = time.time()
det = self.calculate_determinant(random_matrix)
time_taken = time.time() - start_time
result_str = f"Determinant: {det}"
self.result_label.config(text=result_str)
time_str = f"Time (s): {time_taken:.6f}"
self.time_label.config(text=time_str)
# Используем глобальную переменную для отображения результата в методе generate_and_calculate_determinant
self.det_result = det
if __name__ == "__main__":
root = tk.Tk()
app = DeterminantCalculator(root)
root.mainloop()