146 lines
5.6 KiB
Python
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()
|