From 146a7c89dfdad89f49b23ade09c7dcf4553676e9 Mon Sep 17 00:00:00 2001 From: rhinemann Date: Sat, 9 Mar 2024 17:44:57 +0200 Subject: [PATCH] Initial commit --- Lab_1/initial_calculations.py | 11 ++ Lab_1/main.py | 251 +++++++++++++++++++++++++++++++ Lab_1/save.db | Bin 0 -> 16384 bytes Lab_1/simplified_calculations.py | 6 + Lab_1/window_1.py | 174 +++++++++++++++++++++ Lab_1/window_2.py | 104 +++++++++++++ Lab_1/window_3.py | 79 ++++++++++ Lab_1/window_4.py | 79 ++++++++++ Lab_1/window_5.py | 89 +++++++++++ Lab_1/z_calculations.py | 21 +++ Lab_2/dat/saved_sets | Bin 0 -> 16384 bytes Lab_2/main.py | 18 +++ Lab_2/style.css | 26 ++++ Lab_2/window_1.py | 116 ++++++++++++++ Lab_2/window_2.py | 132 ++++++++++++++++ Lab_2/window_3.py | 124 +++++++++++++++ Lab_2/window_4.py | 141 +++++++++++++++++ Lab_3/main.py | 95 ++++++++++++ Lab_3/style.css | 23 +++ Lab_3/table.txt | 4 + Lab_3/window_2.py | 227 ++++++++++++++++++++++++++++ Lab_4/main.py | 11 ++ Lab_4/style.css | 23 +++ Lab_4/table.txt | 10 ++ Lab_4/window.py | 228 ++++++++++++++++++++++++++++ 25 files changed, 1992 insertions(+) create mode 100644 Lab_1/initial_calculations.py create mode 100644 Lab_1/main.py create mode 100644 Lab_1/save.db create mode 100644 Lab_1/simplified_calculations.py create mode 100644 Lab_1/window_1.py create mode 100644 Lab_1/window_2.py create mode 100644 Lab_1/window_3.py create mode 100644 Lab_1/window_4.py create mode 100644 Lab_1/window_5.py create mode 100644 Lab_1/z_calculations.py create mode 100644 Lab_2/dat/saved_sets create mode 100644 Lab_2/main.py create mode 100644 Lab_2/style.css create mode 100644 Lab_2/window_1.py create mode 100644 Lab_2/window_2.py create mode 100644 Lab_2/window_3.py create mode 100644 Lab_2/window_4.py create mode 100644 Lab_3/main.py create mode 100644 Lab_3/style.css create mode 100644 Lab_3/table.txt create mode 100644 Lab_3/window_2.py create mode 100644 Lab_4/main.py create mode 100644 Lab_4/style.css create mode 100644 Lab_4/table.txt create mode 100644 Lab_4/window.py diff --git a/Lab_1/initial_calculations.py b/Lab_1/initial_calculations.py new file mode 100644 index 0000000..3010f1f --- /dev/null +++ b/Lab_1/initial_calculations.py @@ -0,0 +1,11 @@ +def initial_calculations(input_sets, u_set): + results = [] + results.append(input_sets[1] & (u_set - input_sets[2])) + results.append((u_set - input_sets[0]) & input_sets[2]) + results.append(input_sets[0] & input_sets[1]) + results.append(results[1] | results[2]) + results.append(results[0] | results[3]) + results.append((u_set - input_sets[2]) | results[4]) + results.append(input_sets[1] | results[5]) + results.append((u_set - input_sets[0]) | results[6]) + return results diff --git a/Lab_1/main.py b/Lab_1/main.py new file mode 100644 index 0000000..a2c1d13 --- /dev/null +++ b/Lab_1/main.py @@ -0,0 +1,251 @@ +import window_1, window_2, window_3, window_4, window_5 +from tkinter import * +from tkinter import messagebox +import random +import initial_calculations, simplified_calculations, z_calculations +import shelve + +class Screen_Handler(): + def get_universal_set(self): + u_boundaries = [window_1.lowest_entry.get(), window_1.highest_entry.get()] + + if (not all([item.strip("-").isdigit() for item in u_boundaries])): + messagebox.showerror("Помилка", "Межі універсальної множини мають бути цілими числами.") + return 0 + + u_boundaries = list(map(int, u_boundaries)) + + if (u_boundaries[0] >= u_boundaries[1]): + messagebox.showerror("Помилка", "Нижня межа універсальної множини має бути введена раніше першої.") + else: + self.u_boundaries = u_boundaries + self.set_universal_set() + self.universal_set = set(range(u_boundaries[0], u_boundaries[1]+1)) + + def get_manual_sets(self): + if (not self.check_universal()): + return 0 + + set_getters_list = [i.get for i in window_1.manual_entries] + sets_abc = [i() for i in set_getters_list] + sets_abc = [set(i().split()) for i in set_getters_list] + + if (not all([all([item.strip("-").isdigit() for item in arr]) for arr in sets_abc])): + messagebox.showerror("Помилка", "Множини мають складатися з чисел або бути пустими.") + return 0 + + sets_abc = [set(map(int, curr_set)) for curr_set in sets_abc] + + if (all(map(self.check_manual_sets, sets_abc))): + list(map(self.set_abc_set, sets_abc, window_1.set_labels)) + list(map(self.set_abc_set, sets_abc, window_2.set_labels)) + list(map(self.set_abc_set, sets_abc, window_3.set_labels)) + list(map(self.set_abc_set, sets_abc, window_4.set_labels)) + + self.sets_abc = sets_abc + + def get_generated_sets(self): + if (not self.check_universal()): + return 0 + + cardinalities = [item.get() for item in window_1.cardinality_entries] + + if (not all([item.isdigit() for item in cardinalities])): + messagebox.showerror("Помилка", "Потужності мають бути числами.") + return 0 + cardinalities = list(map(int, cardinalities)) + + if (max(cardinalities) > len(self.universal_set)): + messagebox.showerror("Помилка", "Потужності не можуть перевищувати кількість елементів в універсальній множині.") + return 0 + + sets_abc = [set(random.sample(range(min(self.universal_set), max(self.universal_set)+1), i)) for i in cardinalities] + + list(map(self.set_abc_set, sets_abc, window_1.set_labels)) + list(map(self.set_abc_set, sets_abc, window_2.set_labels)) + list(map(self.set_abc_set, sets_abc, window_3.set_labels)) + list(map(self.set_abc_set, sets_abc, window_4.set_labels)) + + self.sets_abc = sets_abc + + def check_manual_sets(self, curr_set): + if curr_set: + if (max(curr_set) > max(self.universal_set) or min(curr_set) < min(self.universal_set)): + messagebox.showerror("Помилка", "Вихід за межі універсальної множини.") + return False + else: + return True + else: + return True + + def initial_calculation_sets(self): + results = initial_calculations.initial_calculations(self.sets_abc, self.universal_set) + + result_labels = window_2.calculation_result_labels + + for i in range(len(results)): + results_text = set(map(str, results[i])) + + results_text = f"{{ {'; '.join(results_text)} }}" + + result_labels[i].configure(text=results_text) + + window_2.elements_D_label.configure(text=results_text) + + self.initial_D = results[-1] + + def simple_calculation_sets(self): + results = simplified_calculations.simplified_calculations(self.sets_abc, self.universal_set) + + result_labels = window_3.calculation_result_labels + + for i in range(len(results)): + results_text = set(map(str, results[i])) + + results_text = f"{{ {'; '.join(results_text)} }}" + + result_labels[i].configure(text=results_text) + + window_3.elements_D_label.configure(text=results_text) + + self.simple_D = results[-1] + + def z_calculations(self): + custom_results = z_calculations.z_calculations(self.sets_abc, self.universal_set) + + result_labels = window_4.step_results + + for i in range(len(custom_results)): + results_text = set(map(str, custom_results[i])) + + results_text = f"{{ {'; '.join(results_text)} }}" + + result_labels[i].configure(text=results_text) + + window_4.elements_Z_label.configure(text = results_text) + + self.custom_Z = custom_results[-1] + self.default_Z = z_calculations.z_calculations_in(self.sets_abc, self.universal_set) + + def set_universal_set(self): + lower_boundary, upper_boundary = map(str, self.u_boundaries) + universal_text = f"{{ {lower_boundary}; ...; {upper_boundary} }}" + window_1.elements_U_label.configure(text = universal_text) + + def set_abc_set(self, curr_set, curr_label): + curr_set = set(map(str, curr_set)) + curr_text = f"{{ {'; '.join(curr_set)} }}" + curr_label.configure(text = curr_text) + + def check_universal(self): + if (not hasattr(self, "universal_set")): + messagebox.showerror("Помилка", "Універсальна множина не задана.") + return False + else: + return True + + def save_initial_D(self): + if (not hasattr(self, "initial_D")): + messagebox.showerror("Помилка", "Множина D не знайдена.") + return 0 + + with shelve.open("save.db") as sh: + sh["initial_D"] = self.initial_D + + def save_simple_D(self): + if (not hasattr(self, "simple_D")): + messagebox.showerror("Помилка", "Множина D не знайдена.") + return 0 + + with shelve.open("save.db") as sh: + sh["simple_D"] = self.simple_D + + def save_Z(self): + if (not (hasattr(self, "custom_Z") or hasattr(self, "default_Z"))): + messagebox.showerror("Помилка", "Множина Z не знайдена.") + return 0 + + with shelve.open("save.db") as sh: + sh["custom_Z"] = self.custom_Z + sh["default_Z"] = self.default_Z + + def read_initial_D(self): + with shelve.open("save.db") as sh: + if ("initial_D" in sh.keys()): + initial_D = set(map(str, sh["initial_D"])) + initial_D = f"{{ {'; '.join(initial_D)} }}" + window_5.initial_D_elements.configure(text=initial_D) + else: + messagebox.showerror("Помилка", "Множина D не збережена.") + + def read_simple_D(self): + with shelve.open("save.db") as sh: + if ("simple_D" in sh.keys()): + simple_D = set(map(str, sh["simple_D"])) + simple_D = f"{{ {'; '.join(simple_D)} }}" + window_5.simplified_D_elements.configure(text=simple_D) + else: + messagebox.showerror("Помилка", "Множина D не збережена.") + + def read_default_Z(self): + with shelve.open("save.db") as sh: + if ("default_Z" in sh.keys()): + default_Z = set(map(str, sh["default_Z"])) + default_Z = f"{{ {'; '.join(default_Z)} }}" + window_5.python_Z_elements.configure(text=default_Z) + else: + messagebox.showerror("Помилка", "Множина Z не збережена.") + + def read_custom_Z(self): + with shelve.open("save.db") as sh: + if ("custom_Z" in sh.keys()): + custom_Z = set(map(str, sh["custom_Z"])) + custom_Z = f"{{ {'; '.join(custom_Z)} }}" + window_5.custom_Z_elements.configure(text=custom_Z) + else: + messagebox.showerror("Помилка", "Множина Z не збережена.") + + def compare_D(self): + with shelve.open("save.db") as sh: + if (sh["initial_D"] == sh["simple_D"]): + messagebox.showinfo("Порівняння D", "Множини D збігаються.") + else: + messagebox.showinfo("Порівняння D", "Множини D не збігаються.") + + def compare_Z(self): + with shelve.open("save.db") as sh: + if (sh["default_Z"] == sh["custom_Z"]): + messagebox.showinfo("Порівняння Z", "Множини Z збігаються") + else: + messagebox.showinfo("Порівняння Z", "Множини Z не збігаються.") + + def clear_saves(self): + sh = shelve.open("save.db", flag="n") + sh.close() + + def configure_buttons(self): + window_1.set_U_button.configure(command=self.get_universal_set) + window_1.set_manual_button.configure(command=self.get_manual_sets) + window_1.set_generation_button.configure(command=self.get_generated_sets) + + window_2.start_calculations_button.configure(command=self.initial_calculation_sets) + window_2.save_D_button.configure(command=self.save_initial_D) + + window_3.start_calculations_button.configure(command=self.simple_calculation_sets) + window_3.save_D_button.configure(command=self.save_simple_D) + + window_4.start_calculations_button.configure(command=self.z_calculations) + window_4.save_Z_button.configure(command=self.save_Z) + + window_5.clear_save_button.configure(command=self.clear_saves) + window_5.read_initial_D_button.configure(command=self.read_initial_D) + window_5.read_simplified_D_button.configure(command=self.read_simple_D) + window_5.read_default_Z_button.configure(command=self.read_default_Z) + window_5.read_custom_Z_button.configure(command=self.read_custom_Z) + window_5.compare_D_button.configure(command=self.compare_D) + window_5.compare_Z_button.configure(command=self.compare_Z) + +screens = Screen_Handler() +screens.configure_buttons() + +window_1.root.mainloop() diff --git a/Lab_1/save.db b/Lab_1/save.db new file mode 100644 index 0000000000000000000000000000000000000000..8eedda1d5287f157d93ebe5346431cbb5f74ad73 GIT binary patch literal 16384 zcmeI&u}Z^G6vpve8*8hBg5cufB*mdRISaa-$w?5T6m21rYO(2}OW(i_y7U2jjjV1y zi@RX&@!lbVf>5rs&A*VGkcOM&mvg^#=-c>g(`*>?wb-Jy=Ie{rBV8Hu;R8!hr@qynFphR}ePy6|4X!bi59B|0bkD~R%@V$QBkGs8npF>rPv1^y2IdH$^K#_BR z{-^&#^uO7AJ-rOF}-)r|-c6in9v>tNT`5!)^ z{TZJ;36UrB-dCDQaVu$_45R055A^s{7b7KElCngyEEQRis?=n4)X<;iN&BxyYtY_y uo9A}ywQpmWr7~)0%nXwBx3BY0i){oDKmY**5I_I{1Q0*~0R#}3MqmOHfc}C2 literal 0 HcmV?d00001 diff --git a/Lab_1/simplified_calculations.py b/Lab_1/simplified_calculations.py new file mode 100644 index 0000000..bd6896b --- /dev/null +++ b/Lab_1/simplified_calculations.py @@ -0,0 +1,6 @@ +def simplified_calculations(input_sets, u_set): + results = [] + results.append(u_set - input_sets[0]) + results.append(results[0] | input_sets[1]) + results.append(results[1] | (u_set - input_sets[2])) + return results diff --git a/Lab_1/window_1.py b/Lab_1/window_1.py new file mode 100644 index 0000000..dffed9f --- /dev/null +++ b/Lab_1/window_1.py @@ -0,0 +1,174 @@ +from tkinter import * + +root = Tk() +root.title("Головний екран") + +# Віджети ідентифікації студента +id_frame = Frame(root, bd=5) + +id_label = Label(id_frame, text="Ідентифікація") + +surname_label = Label(id_frame, text="Прізвище:") +surname_entry = Label(id_frame, text="Швед") + +name_label = Label(id_frame, text="Ім'я:") +name_entry = Label(id_frame, text="Андрій") + +parental_label = Label(id_frame, text="По-батькові:") +parental_entry = Label(id_frame, text="Дмитрович") + +group_number_name = Label(id_frame, text="Номер групи:") +group_number_entry = Label(id_frame, text="23") + +student_number_name = Label(id_frame, text="Номер у списку:") +student_number_entry = Label(id_frame, text="30") + +variant_label = Label(id_frame, text="Варіант:") +variant_result_label = Label(id_frame, text="24") + +# Пакувальники ідентифікації студента +id_frame.grid(row=0, column=0) + +id_label.grid(row=0, column=0, columnspan=2) + +surname_label.grid(row=1, column=0, sticky=E) +surname_entry.grid(row=1, column=1, sticky=W) + +name_label.grid(row=2, column=0, sticky=E) +name_entry.grid(row=2, column=1, sticky=W) + +parental_label.grid(row=3, column=0, sticky=E) +parental_entry.grid(row=3, column=1, sticky=W) + +group_number_name.grid(row=4, column=0, sticky=E) +group_number_entry.grid(row=4, column=1, sticky=W) + +student_number_name.grid(row=5, column=0, sticky=E) +student_number_entry.grid(row=5, column=1, sticky=W) + +variant_label.grid(row=6, column=0, sticky=E) +variant_result_label.grid(row=6, column=1, sticky=W) + +# Віджети універсальної множини +universal_set_frame = Frame(root, bd=5) + +universal_set_label = Label(universal_set_frame, text="Межі універсальної множини") + +lowest_label = Label(universal_set_frame, text="Від:") +highest_label = Label(universal_set_frame, text="До:") + +lowest_entry = Entry(universal_set_frame, width=20) +highest_entry = Entry(universal_set_frame, width=20) + +set_U_button = Button(universal_set_frame, text="Задати універсальну множину") + +set_U_label = Label(universal_set_frame, text="Множина U:") +elements_U_label = Label(universal_set_frame) + +# Пакувальники універсальної множини +universal_set_frame.grid(row=1, column=0) + +universal_set_label.grid(row=0, column=0, columnspan=4) + +lowest_label.grid(row=1, column=0) +lowest_entry.grid(row=1, column=1) + +highest_label.grid(row=1, column=2) +highest_entry.grid(row=1, column=3) + +set_U_button.grid(row=2, column=0, columnspan=4) + +set_U_label.grid(row=3, column=0, columnspan=2, sticky=E) +elements_U_label.grid(row=3, column=2, columnspan=2, sticky=W) + +# Віджети задання множин +set_declaration_frame = Frame(root, bd=5) + +set_declaration_label = Label(set_declaration_frame, text="Задання множин", bd=5) + +set_generation_label = Label(set_declaration_frame, text="Випадкова генерація", bd=5) + +cardinality_A_label = Label(set_declaration_frame, text="Потужність A:") +cardinality_A_entry = Entry(set_declaration_frame, width=20) + +cardinality_B_label = Label(set_declaration_frame, text="Потужність B:") +cardinality_B_entry = Entry(set_declaration_frame, width=20) + +cardinality_C_label = Label(set_declaration_frame, text="Потужність C:") +cardinality_C_entry = Entry(set_declaration_frame, width=20) + +cardinality_entries = [cardinality_A_entry, cardinality_B_entry, cardinality_C_entry] + +set_generation_button = Button(set_declaration_frame, text="Згенерувати множини") + +set_manual_label = Label(set_declaration_frame, text="Ручний ввід", bd=5) + +manual_A_label = Label(set_declaration_frame, text="Введіть множину A:") +manual_A_entry = Entry(set_declaration_frame, width=40) + +manual_B_label = Label(set_declaration_frame, text="Введіть множину B:") +manual_B_entry = Entry(set_declaration_frame, width=40) + +manual_C_label = Label(set_declaration_frame, text="Введіть множину C:") +manual_C_entry = Entry(set_declaration_frame, width=40) + +set_manual_button = Button(set_declaration_frame, text="Задати введені множини") + +manual_entries = [manual_A_entry, manual_B_entry, manual_C_entry] + +# Пакувальники задання множин +set_declaration_frame.grid(row=2, column=0) + +set_declaration_label.grid(row=0, column=0, columnspan=4) + +set_generation_label.grid(row=1, column=0, columnspan=2) + +cardinality_A_label.grid(row=2, column=0, sticky=E) +cardinality_A_entry.grid(row=2, column=1) + +cardinality_B_label.grid(row=3, column=0, sticky=E) +cardinality_B_entry.grid(row=3, column=1) + +cardinality_C_label.grid(row=4, column=0, sticky=E) +cardinality_C_entry.grid(row=4, column=1) + +set_generation_button.grid(row=5, column=0, columnspan=2) + +set_manual_label.grid(row=1, column=2, columnspan=2) + +manual_A_label.grid(row=2, column=2, sticky=E) +manual_A_entry.grid(row=2, column=3) + +manual_B_label.grid(row=3, column=2, sticky=E) +manual_B_entry.grid(row=3, column=3) + +manual_C_label.grid(row=4, column=2, sticky=E) +manual_C_entry.grid(row=4, column=3) + +set_manual_button.grid(row=5, column=2, columnspan=2) + +# Віджети множин +sets_frame = Frame(root, bd=5) + +set_A_label = Label(sets_frame, text="Множина A:") +elements_A_label = Label(sets_frame) + +set_B_label = Label(sets_frame, text="Множина B:") +elements_B_label = Label(sets_frame) + +set_C_label = Label(sets_frame, text="Множина C:") +elements_C_label = Label(sets_frame) + +set_labels = [elements_A_label, elements_B_label, elements_C_label] + +# Пакувальники множин +sets_frame.grid(row=3, column=0) + +set_A_label.grid(row=0, column=0, sticky=E) +elements_A_label.grid(row=0, column=1, sticky=W) + +set_B_label.grid(row=1, column=0, sticky=E) +elements_B_label.grid(row=1, column=1, sticky=W) + +set_C_label.grid(row=2, column=0, sticky=E) +elements_C_label.grid(row=2, column=1, sticky=W) diff --git a/Lab_1/window_2.py b/Lab_1/window_2.py new file mode 100644 index 0000000..82a556d --- /dev/null +++ b/Lab_1/window_2.py @@ -0,0 +1,104 @@ +from tkinter import * + +root = Tk() +root.title("Розрахунки початкового виразу") + +# Віджети введених множин +sets_frame = Frame(root, bd=5) + +set_A_label = Label(sets_frame, text="Множина A:", bd=5) +elements_A_label = Label(sets_frame) + +set_B_label = Label(sets_frame, text="Множина B:", bd=5) +elements_B_label = Label(sets_frame) + +set_C_label = Label(sets_frame, text="Множина C:", bd=5) +elements_C_label = Label(sets_frame) + +set_labels = [elements_A_label, elements_B_label, elements_C_label] + +# Пакувальники введених множин +sets_frame.grid(row=0, column=0) + +set_A_label.grid(row=0, column=0, sticky=E) +elements_A_label.grid(row=0, column=1, sticky=W) + +set_B_label.grid(row=1, column=0, sticky=E) +elements_B_label.grid(row=1, column=1, sticky=W) + +set_C_label.grid(row=2, column=0, sticky=E) +elements_C_label.grid(row=2, column=1, sticky=W) + +# Кнопка початку розрахунків +start_calculations_button = Button(root, text="Почати розрахунки") +start_calculations_button.grid(row=1, column=0) + +# Віджети покрокового розв'язання +calculations_frame = Frame(root, bd=5) + +expression_label = Label(calculations_frame, text="Вираз: D = ¬A ∪ B ∪ ¬C ∪ (B ∩ ¬C) ∪ (¬A ∩ C) ∪ (A ∩ B)", bd=5) + +first_step_label = Label(calculations_frame, text="(B ∩ ¬C) = ", bd=5) +first_step_result = Label(calculations_frame) + +second_step_label = Label(calculations_frame, text="(¬A ∩ C) = ", bd=5) +second_step_result = Label(calculations_frame) + +third_step_label = Label(calculations_frame, text="(A ∩ B) = ", bd=5) +third_step_result = Label(calculations_frame) + +fourth_step_label = Label(calculations_frame, text="(¬A ∩ C) ∪ (A ∩ B) = ", bd=5) +fourth_step_result = Label(calculations_frame) + +fifth_step_label = Label(calculations_frame, text="(B ∩ ¬C) ∪ (¬A ∩ C) ∪ (A ∩ B) = ", bd=5) +fifth_step_result = Label(calculations_frame) + +sixth_step_label = Label(calculations_frame, text="¬C ∪ (B ∩ ¬C) ∪ (¬A ∩ C) ∪ (A ∩ B) = ", bd=5) +sixth_step_result = Label(calculations_frame) + +seventh_step_label = Label(calculations_frame, text="B ∪ ¬C ∪ (B ∩ ¬C) ∪ (¬A ∩ C) ∪ (A ∩ B) = ", bd=5) +seventh_step_result = Label(calculations_frame) + +eighth_step_label = Label(calculations_frame, text="¬A ∪ B ∪ ¬C ∪ (B ∩ ¬C) ∪ (¬A ∩ C) ∪ (A ∩ B) = ", bd=5) +eighth_step_result = Label(calculations_frame) + +calculation_result_labels = [first_step_result, second_step_result, third_step_result, fourth_step_result, fifth_step_result, sixth_step_result, seventh_step_result, eighth_step_result] + +# Пакувальники покрокового розв'язання +calculations_frame.grid(row=2, column=0) + +expression_label.grid(row=0, column=0, columnspan=2) + +first_step_label.grid(row=1, column=0, sticky=E) +second_step_label.grid(row=2, column=0, sticky=E) +third_step_label.grid(row=3, column=0, sticky=E) +fourth_step_label.grid(row=4, column=0, sticky=E) +fifth_step_label.grid(row=5, column=0, sticky=E) +sixth_step_label.grid(row=6, column=0, sticky=E) +seventh_step_label.grid(row=7, column=0, sticky=E) +eighth_step_label.grid(row=8, column=0, sticky=E) + +first_step_result.grid(row=1, column=1, sticky=W) +second_step_result.grid(row=2, column=1, sticky=W) +third_step_result.grid(row=3, column=1, sticky=W) +fourth_step_result.grid(row=4, column=1, sticky=W) +fifth_step_result.grid(row=5, column=1, sticky=W) +sixth_step_result.grid(row=6, column=1, sticky=W) +seventh_step_result.grid(row=7, column=1, sticky=W) +eighth_step_result.grid(row=8, column=1, sticky=W) + +# Віджети множини D +d_frame = Frame(root, bd=5) + +set_D_label = Label(d_frame, text="Множина D:", bd=5) +elements_D_label = Label(d_frame) + +save_D_button = Button(d_frame, text="Зберегти D") + +# Пакувальники множини D +d_frame.grid(row=3, column=0) + +set_D_label.grid(row=0, column=0, sticky=E) +elements_D_label.grid(row=0, column=1, sticky=W) + +save_D_button.grid(row=1, column=0, columnspan=2) diff --git a/Lab_1/window_3.py b/Lab_1/window_3.py new file mode 100644 index 0000000..54e57b8 --- /dev/null +++ b/Lab_1/window_3.py @@ -0,0 +1,79 @@ +from tkinter import * + +root = Tk() +root.title("Розрахунки спрощеного виразу") + +# Віджети введених множин +sets_frame = Frame(root, bd=5) + +set_A_label = Label(sets_frame, text="Множина A:", bd=5) +elements_A_label = Label(sets_frame) + +set_B_label = Label(sets_frame, text="Множина B:", bd=5) +elements_B_label = Label(sets_frame) + +set_C_label = Label(sets_frame, text="Множина C:", bd=5) +elements_C_label = Label(sets_frame) + +# Пакувальники введених множин +sets_frame.grid(row=0, column=0) + +set_A_label.grid(row=0, column=0, sticky=E) +elements_A_label.grid(row=0, column=1, sticky=W) + +set_B_label.grid(row=1, column=0, sticky=E) +elements_B_label.grid(row=1, column=1, sticky=W) + +set_C_label.grid(row=2, column=0, sticky=E) +elements_C_label.grid(row=2, column=1, sticky=W) + +set_labels = [elements_A_label, elements_B_label, elements_C_label] + +# Кнопка початку розрахунків +start_calculations_button = Button(root, text="Почати розрахунки") +start_calculations_button.grid(row=1, column=0) + +# Віджети покрокового розв'язання +calculations_frame = Frame(root, bd=5) + +expression_label = Label(calculations_frame, text="Вираз: D = ¬A ∪ B ∪ ¬C", bd=5) + +first_step_label = Label(calculations_frame, text="¬A = ", bd=5) +first_step_result = Label(calculations_frame) + +second_step_label = Label(calculations_frame, text="¬A ∪ B = ", bd=5) +second_step_result = Label(calculations_frame) + +third_step_label = Label(calculations_frame, text="¬A ∪ B ∪ ¬C = ", bd=5) +third_step_result = Label(calculations_frame) + +calculation_result_labels = [first_step_result, second_step_result, third_step_result] + +# Пакувальники покрокового розв'язання +calculations_frame.grid(row=2, column=0) + +expression_label.grid(row=0, column=0, columnspan=2) + +first_step_label.grid(row=1, column=0, sticky=E) +second_step_label.grid(row=2, column=0, sticky=E) +third_step_label.grid(row=3, column=0, sticky=E) + +first_step_result.grid(row=1, column=1, sticky=W) +second_step_result.grid(row=2, column=1, sticky=W) +third_step_result.grid(row=3, column=1, sticky=W) + +# Віджети множини D +d_frame = Frame(root, bd=5) + +set_D_label = Label(d_frame, text="Множина D:", bd=5) +elements_D_label = Label(d_frame) + +save_D_button = Button(d_frame, text="Зберегти D") + +# Пакувальники множини D +d_frame.grid(row=3, column=0) + +set_D_label.grid(row=0, column=0) +elements_D_label.grid(row=0, column=1) + +save_D_button.grid(row=1, column=0, columnspan=2) diff --git a/Lab_1/window_4.py b/Lab_1/window_4.py new file mode 100644 index 0000000..174b3a5 --- /dev/null +++ b/Lab_1/window_4.py @@ -0,0 +1,79 @@ +from tkinter import * + +root = Tk() +root.title("Обчислення Z") + +# Віджети введених множин +sets_frame = Frame(root, bd=5) + +set_A_label = Label(sets_frame, text="Множина A:", bd=5) +elements_A_label = Label(sets_frame) + +set_B_label = Label(sets_frame, text="Множина B:", bd=5) +elements_B_label = Label(sets_frame) + +set_C_label = Label(sets_frame, text="Множина C:", bd=5) +elements_C_label = Label(sets_frame) + +# Пакувальники введених множин +sets_frame.grid(row=0, column=0) + +set_A_label.grid(row=0, column=0, sticky=E) +elements_A_label.grid(row=0, column=1, sticky=W) + +set_B_label.grid(row=1, column=0, sticky=E) +elements_B_label.grid(row=1, column=1, sticky=W) + +set_C_label.grid(row=2, column=0, sticky=E) +elements_C_label.grid(row=2, column=1, sticky=W) + +set_labels = [elements_A_label, elements_B_label, elements_C_label] + +# Кнопка початку розрахунків +start_calculations_button = Button(root, text="Почати розрахунки") +start_calculations_button.grid(row=1, column=0) + +# Віджети покрокового розв'язання +calculations_frame = Frame(root, bd=5) + +expression_label = Label(calculations_frame, text="Вираз: Z = X ∆ Y", bd=5) + +first_step_label = Label(calculations_frame, text="X = ¬B = ", bd=5) +first_step_result = Label(calculations_frame) + +second_step_label = Label(calculations_frame, text="Y = ¬A = ", bd=5) +second_step_result = Label(calculations_frame) + +third_step_label = Label(calculations_frame, text="Z = ", bd=5) +third_step_result = Label(calculations_frame) + +step_results = [first_step_result, second_step_result, third_step_result] + +# Пакувальники покрокового розв'язання +calculations_frame.grid(row=2, column=0, sticky=W) + +expression_label.grid(row=0, column=0, columnspan=2) + +first_step_label.grid(row=1, column=0, sticky=E) +second_step_label.grid(row=2, column=0, sticky=E) +third_step_label.grid(row=3, column=0, sticky=E) + +first_step_result.grid(row=1, column=1, sticky=W) +second_step_result.grid(row=2, column=1, sticky=W) +third_step_result.grid(row=3, column=1, sticky=W) + +# Віджети множини Z +z_frame = Frame(root, bd=5) + +set_Z_label = Label(z_frame, text="Множина Z:", bd=5) +elements_Z_label = Label(z_frame) + +save_Z_button = Button(z_frame, text="Зберегти Z") + +# Пакувальники множини Z +z_frame.grid(row=3, column=0) + +set_Z_label.grid(row=0, column=0) +elements_Z_label.grid(row=0, column=1) + +save_Z_button.grid(row=1, column=0, columnspan=2) diff --git a/Lab_1/window_5.py b/Lab_1/window_5.py new file mode 100644 index 0000000..07c22cf --- /dev/null +++ b/Lab_1/window_5.py @@ -0,0 +1,89 @@ +from tkinter import * + +root = Tk() +root.title("Збереження і відображення") + +# Віджети початкового виразу +read_initial_frame = Frame(root, bd=5) + +read_initial_D_button = Button(read_initial_frame, text="Зчитати результати\nобчислення початкового виразу") +initial_D_label = Label(read_initial_frame, text="D = ", bd=5) +initial_D_elements = Label(read_initial_frame) + +# Пакувальники початкового виразу +read_initial_frame.grid(row=0, column=0) + +read_initial_D_button.grid(row=0, column=0, columnspan=2) +initial_D_label.grid(row=1, column=0, sticky=E) +initial_D_elements.grid(row=1, column=1, sticky=W) + +# Віджети спрощеного виразу +read_simplified_frame = Frame(root, bd=5) + +read_simplified_D_button = Button(read_simplified_frame, text="Зчитати результати\nобчислення спрощеного виразу") +simplified_D_label = Label(read_simplified_frame, text="D = ", bd=5) +simplified_D_elements = Label(read_simplified_frame) + +# Пакувальники спрощеного виразу +read_simplified_frame.grid(row=0, column=1) + +read_simplified_D_button.grid(row=0, column=0, columnspan=2) +simplified_D_label.grid(row=1, column=0, sticky=E) +simplified_D_elements.grid(row=1, column=1, sticky=W) + +# Віджети Z вбудованої +read_python_z_frame = Frame(root, bd=5) + +read_default_Z_button = Button(read_python_z_frame, text="Зчитати Z обчислену\nвбудованими функціями") +python_Z_label = Label(read_python_z_frame, text="Z = ", bd=5) +python_Z_elements = Label(read_python_z_frame) + +# Пакувальники Z вбудованої +read_python_z_frame.grid(row=1, column=0) + +read_default_Z_button.grid(row=0, column=0, columnspan=2) +python_Z_label.grid(row=1, column=0, sticky=E) +python_Z_elements.grid(row=1, column=1, sticky=W) + +# Віджети Z написаної +read_custom_z_frame = Frame(root, bd=5) + +read_custom_Z_button = Button(read_custom_z_frame, text="Зчитати Z обчислену\nнаписаною функцією") +custom_Z_label = Label(read_custom_z_frame, text="Z = ", bd=5) +custom_Z_elements = Label(read_custom_z_frame) + +# Пакувальники Z написаної +read_custom_z_frame.grid(row=1, column=1) + +read_custom_Z_button.grid(row=0, column=0, columnspan=2) +custom_Z_label.grid(row=1, column=0, sticky=E) +custom_Z_elements.grid(row=1, column=1, sticky=W) + +# Віджети порівняння D +compare_D_frame = Frame(root, bd=5) + +compare_D_button = Button(compare_D_frame, text="Порівняти D") + +# Пакувальники порівняння D +compare_D_frame.grid(row=2, column=0) + +compare_D_button.grid(row=0, column=0) + +# Віджети порівняння Z +compare_Z_frame = Frame(root, bd=5) + +compare_Z_button = Button(compare_Z_frame, text="Порівняти Z") + +# Пакувальники порівняння Z +compare_Z_frame.grid(row=2, column=1) + +compare_Z_button.grid(row=0, column=0) + +# Очищення файлів +clear_save_frame = Frame(root, bd=5) + +clear_save_button = Button(clear_save_frame, text="Очистити збережені множини") + +clear_save_frame.grid(row=3, column=0, columnspan=2) + +clear_save_button.grid(row=0, column=0) diff --git a/Lab_1/z_calculations.py b/Lab_1/z_calculations.py new file mode 100644 index 0000000..dbbcbdd --- /dev/null +++ b/Lab_1/z_calculations.py @@ -0,0 +1,21 @@ +def z_calculations(input_sets, u_set): + x = u_set - input_sets[1] + y = u_set - input_sets[0] + results = set() + for curr_elem in x: + if (curr_elem not in y): + results.add(curr_elem) + + for curr_elem in y: + if (curr_elem not in x): + results.add(curr_elem) + + return [x, y, results] + +def z_calculations_in(input_sets, u_set): + x = u_set - input_sets[1] + y = u_set - input_sets[0] + + results = x ^ y + + return results diff --git a/Lab_2/dat/saved_sets b/Lab_2/dat/saved_sets new file mode 100644 index 0000000000000000000000000000000000000000..d38d3c308f83d6c67acc000dc23a32ca68b4104a GIT binary patch literal 16384 zcmeI!ziI+O5XbQ~L?IB8gS>!cs*pNZctWsA7f`TCl_s?hATg!j6{m%yPJI{z|Ddnn z_&$L+d%MLJVr9U{SGXNn_J-rb?}l5Cnl~mgCcm`Udg1GrtyQ}i^WzFD0tg_000Iag zfB*srAbeHZvVUl*gTMg?D?kp&0Xg73U=A<`m;=lK<^XemIlvq^u{lt1Z?$>5 zc7KNVe&Y|ynfCnE->%l|I~5$9Lsv@i^K1L%$>*`C+mCwTLr$Ck4mgAYs_6E0}28NAb (np.ndarray | None, str | None): + text_matrix = list(map(lambda x: x.split(" "), self.adjacency_input.toPlainText().splitlines())) + + if not is_square(text_matrix): + return None, "square_error" + elif not validate_values(text_matrix): + return None, "value_error" + else: + return np.array(list([list(map(int, row)) for row in text_matrix])), None + + def build_graphs(self): + adjacency_matrix, error = self.parse_matrix() + + if adjacency_matrix is None and error == "square_error": + self.show_error( + "Матриця суміжності має бути квадратною. Перевірте чи кожен елемент рядка відділений пробілом і чи " + "дорівнює кількість рядків кількості стовпців." + ) + elif adjacency_matrix is None and error == "value_error": + self.show_error( + "Матриця суміжності мусить складатись лише з нулів і одиниць розділених пробілом. Перевірте ваш ввід." + ) + else: + adjacency_graph = self.create_adjacency_graph(adjacency_matrix) + self.display_adjacency_matrix(adjacency_graph, self.adjacency_output) + incidence_nodes, incidence_edges, incidence_matrix = self.create_incidence_matrix(adjacency_graph) + self.display_incidence_matrix(incidence_nodes, incidence_edges, incidence_matrix, self.incidence_output) + incidence_graph = self.create_incidence_graph(incidence_nodes, incidence_edges) + self.draw_graph(adjacency_graph, incidence_graph) + self.display_edge_dictionary(adjacency_graph, self.edges_dictionary_output) + + @staticmethod + def show_error(error_text: str): + error_message = QtWidgets.QMessageBox() + error_message.setIcon(QtWidgets.QMessageBox.Critical) + error_message.setText("Помилка вводу") + error_message.setInformativeText(error_text) + error_message.setWindowTitle("Помилка") + error_message.exec_() + + @staticmethod + def create_adjacency_graph(adjacency_matrix: np.ndarray) -> nx.DiGraph: + graph = nx.DiGraph() + + nodes = [f"X{i}" for i in range(len(adjacency_matrix))] + edge_indices = np.argwhere(adjacency_matrix) + edges = [(nodes[edge_index[0]], nodes[edge_index[1]]) for edge_index in edge_indices] + graph.add_nodes_from(nodes) + graph.add_edges_from(edges) + + return graph + + @staticmethod + def create_incidence_graph(nodes: list, edges: list) -> nx.DiGraph: + graph = nx.DiGraph() + + graph.add_nodes_from(nodes) + graph.add_edges_from(edges) + + return graph + + def draw_graph(self, adjacency_graph: nx.DiGraph, incidence_graph: nx.DiGraph): + random.seed(0) + np.random.seed(0) + + self.figure.clf() + + pos = nx.planar_layout(adjacency_graph, scale=0.5) + + nx.draw( + adjacency_graph, pos=pos, with_labels=True, node_color="blueviolet", node_size=700, font_color="white", + font_size=14, font_family="Liberation Mono", font_weight="bold", width=2 + ) + + pos = nx.planar_layout(incidence_graph, scale=0.5) + + for i in pos: + pos[i][0] += 2 + + nx.draw( + adjacency_graph, pos=pos, with_labels=True, node_color="blueviolet", node_size=700, font_color="white", + font_size=14, font_family="Liberation Mono", font_weight="bold", width=2 + ) + + self.canvas.draw_idle() + + @staticmethod + def display_adjacency_matrix(graph: nx.DiGraph, label: QtWidgets.QLabel): + matrix = nx.adjacency_matrix(graph).todense().tolist() + + table = PrettyTable() + + nodes = [f"X{i}" for i in range(len(matrix))] + + table.field_names = [" "] + nodes + + for i in range(len(matrix)): + table.add_row([nodes[i]] + matrix[i]) + + label.setText(table.get_string()) + + @staticmethod + def display_incidence_matrix(nodes: list, edges: list, incidence_matrix: list, label: QtWidgets.QLabel): + table = PrettyTable() + + edge_names = [f"E{i}" for i in range(len(edges))] + + table.field_names = [" "] + edge_names + + for i in range(len(incidence_matrix)): + table.add_row([nodes[i]] + incidence_matrix[i]) + + label.setText(table.get_string()) + + @staticmethod + def create_incidence_matrix(graph: nx.DiGraph) -> (list, list, list): + nodes = list(graph.nodes) + edges = list(graph.edges) + + edge_names = [f"E{i}" for i in range(len(edges))] + + matrix = [["0" for j in range(len(edges))] for i in range(len(nodes))] + matrix = [ + ["1" if nodes[i] == edges[j][0] else matrix[i][j] for j in range(len(matrix[i]))] + for i in range(len(matrix))] + matrix = [ + ["-1" if nodes[i] == edges[j][1] else matrix[i][j] for j in range(len(matrix[i]))] + for i in range(len(matrix))] + matrix = [ + ["±1" if (nodes[i] == edges[j][0] and nodes[i] == edges[j][1]) + else matrix[i][j] for j in range(len(matrix[i]))] + for i in range(len(matrix))] + + return nodes, edges, matrix + + @staticmethod + def display_edge_dictionary(graph: nx.DiGraph, label: QtWidgets.QLabel): + edge_dictionary = "" + edges = list(graph.edges) + for i, edge in enumerate(edges): + edge_dictionary += f"E{i} = ({edge[0]} -> {edge[1]})\n" + label.setText(edge_dictionary) + + def browse_files(self): + file_name = QtWidgets.QFileDialog.getOpenFileName(self, "Відкрити файл", "~/", "Текстові файли (*.txt)") + with open(file_name[0]) as f: + text_read = f.read() + self.adjacency_input.setText(text_read) + + def set_functions(self): + self.build_graph_button.clicked.connect(lambda: self.build_graphs()) + self.open_file_button.clicked.connect(lambda: self.browse_files()) diff --git a/Lab_4/main.py b/Lab_4/main.py new file mode 100644 index 0000000..a20d3ac --- /dev/null +++ b/Lab_4/main.py @@ -0,0 +1,11 @@ +from PyQt5 import QtWidgets +from window import Window +import sys + +app = QtWidgets.QApplication(sys.argv) +app.setStyleSheet(open("style.css").read()) + +main_window = Window() +main_window.show() + +sys.exit(app.exec()) diff --git a/Lab_4/style.css b/Lab_4/style.css new file mode 100644 index 0000000..a99a233 --- /dev/null +++ b/Lab_4/style.css @@ -0,0 +1,23 @@ +QWidget{ + border-radius: 10px; + padding: 4px; + margin: 2px; + font-family: "JetBrains Mono"; + font-size: 12pt; +} +QPushButton{ + background-color: blueviolet; + color: white; +} +QPushButton:hover{ + background-color: #6f20b3; +} +QPushButton:pressed{ + background-color: #8f58c9; +} +QLabel{ + border: 3px solid blueviolet; +} +QTextEdit{ + border: 3px solid blueviolet; +} \ No newline at end of file diff --git a/Lab_4/table.txt b/Lab_4/table.txt new file mode 100644 index 0000000..4b5d06a --- /dev/null +++ b/Lab_4/table.txt @@ -0,0 +1,10 @@ +0 0 1 0 0 1 1 0 0 0 +0 0 1 0 0 0 1 1 0 0 +1 1 0 1 0 0 0 0 1 0 +0 0 1 0 1 0 0 0 1 0 +0 0 0 1 0 0 0 0 1 1 +1 0 0 0 0 0 1 0 0 0 +1 1 0 0 0 1 0 1 0 0 +0 1 0 0 0 0 1 0 1 0 +0 0 1 1 1 0 0 1 0 1 +0 0 0 0 1 0 0 0 1 0 \ No newline at end of file diff --git a/Lab_4/window.py b/Lab_4/window.py new file mode 100644 index 0000000..0dfc4ec --- /dev/null +++ b/Lab_4/window.py @@ -0,0 +1,228 @@ +from PyQt5 import QtCore, QtWidgets +import sys +import networkx as nx +import matplotlib.pyplot as plt +import matplotlib.colors as mcolours +import numpy as np +from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas + + +class Window(QtWidgets.QMainWindow): + + def __init__(self): + super().__init__() + + self.setWindowTitle("Вікно 1") + + central_widget = QtWidgets.QWidget(self) + + self.grid_layout = QtWidgets.QGridLayout(central_widget) + + self.id_grid_layout = QtWidgets.QGridLayout() + + self.full_name = QtWidgets.QLabel(central_widget) + self.full_name.setText("П. І. Б:") + self.full_name.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignTrailing | QtCore.Qt.AlignVCenter) + self.id_grid_layout.addWidget(self.full_name, 0, 0, 1, 1) + + self.full_name_answer = QtWidgets.QLabel(central_widget) + self.full_name_answer.setText("Швед Андрій Дмитрович") + self.id_grid_layout.addWidget(self.full_name_answer, 0, 1, 1, 1) + + self.group = QtWidgets.QLabel(central_widget) + self.group.setText("Група:") + self.group.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignTrailing | QtCore.Qt.AlignVCenter) + self.id_grid_layout.addWidget(self.group, 1, 0, 1, 1) + + self.group_answer = QtWidgets.QLabel(central_widget) + self.group_answer.setText("ІО-23") + self.id_grid_layout.addWidget(self.group_answer, 1, 1, 1, 1) + + self.list_number = QtWidgets.QLabel(central_widget) + self.list_number.setText("Номер в списку:") + self.list_number.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignTrailing | QtCore.Qt.AlignVCenter) + self.id_grid_layout.addWidget(self.list_number, 2, 0, 1, 1) + + self.list_number_answer = QtWidgets.QLabel(central_widget) + self.list_number_answer.setText("30") + self.id_grid_layout.addWidget(self.list_number_answer, 2, 1, 1, 1) + + self.task_number = QtWidgets.QLabel(central_widget) + self.task_number.setText("Номер завдання:") + self.task_number.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignTrailing | QtCore.Qt.AlignVCenter) + self.id_grid_layout.addWidget(self.task_number, 3, 0, 1, 1) + + self.task_number_answer = QtWidgets.QLabel(central_widget) + self.task_number_answer.setText("1") + self.id_grid_layout.addWidget(self.task_number_answer, 3, 1, 1, 1) + + self.grid_layout.addLayout(self.id_grid_layout, 0, 0, 1, 1) + + self.graph_grid_layout = QtWidgets.QGridLayout() + + self.adjacency_input_label = QtWidgets.QLabel(self) + self.adjacency_input_label.setText("Введіть матрицю суміжності графа") + self.graph_grid_layout.addWidget(self.adjacency_input_label, 0, 0, 1, 1) + + self.adjacency_input = QtWidgets.QTextEdit(self) + self.graph_grid_layout.addWidget(self.adjacency_input, 1, 0, 2, 1) + + self.graph_label = QtWidgets.QLabel(self) + self.graph_label.setText("Розфарбований граф") + self.graph_grid_layout.addWidget(self.graph_label, 0, 1, 1, 1) + + self.figure = plt.figure() + self.canvas = FigureCanvas(self.figure) + self.graph_grid_layout.addWidget(self.canvas, 1, 1, 1, 1) + + self.grid_layout.addLayout(self.graph_grid_layout, 1, 0, 1, 1) + + self.buttons_grid_layout = QtWidgets.QGridLayout() + + self.build_graph_button = QtWidgets.QPushButton(self) + self.build_graph_button.setText("Побудувати граф") + self.buttons_grid_layout.addWidget(self.build_graph_button, 0, 0, 1, 1) + + self.open_file_button = QtWidgets.QPushButton(self) + self.open_file_button.setText("Відкрити файл") + self.buttons_grid_layout.addWidget(self.open_file_button, 0, 1, 1, 1) + + self.grid_layout.addLayout(self.buttons_grid_layout, 2, 0, 1, 1) + + self.setCentralWidget(central_widget) + + self.menubar = QtWidgets.QMenuBar(self) + self.menubar.setGeometry(QtCore.QRect(0, 0, 362, 22)) + + self.menubar.setDefaultUp(False) + + self.menu_Windows = QtWidgets.QMenu(self.menubar) + self.menu_Windows.setTitle("Вікна") + self.setMenuBar(self.menubar) + + self.exit_action = QtWidgets.QAction(self) + self.exit_action.setText("Вихід") + self.menu_Windows.addAction(self.exit_action) + + self.menubar.addAction(self.menu_Windows.menuAction()) + + self.set_menu() + self.set_functions() + + QtCore.QMetaObject.connectSlotsByName(self) + + def set_menu(self): + self.exit_action.triggered.connect(lambda: sys.exit()) + + @staticmethod + def is_square(matrix: list) -> bool: + return all(len(row) == len(matrix) for row in matrix) + + @staticmethod + def validate_values(matrix: list) -> bool: + return all(all(("1" == element) or ("0" == element) for element in row) for row in matrix) + + def parse_matrix(self) -> (np.ndarray | None, str | None): + text_matrix = list(map(lambda x: x.split(" "), self.adjacency_input.toPlainText().splitlines())) + + if not self.is_square(text_matrix): + return None, "square_error" + elif not self.validate_values(text_matrix): + return None, "value_error" + elif not text_matrix: + return None, "empty_matrix" + else: + return np.array(list([list(map(int, row)) for row in text_matrix])), None + + def build_graphs(self): + adjacency_matrix, error = self.parse_matrix() + + if adjacency_matrix is None and error == "square_error": + self.show_error( + "Матриця суміжності має бути квадратною. Перевірте чи кожен елемент рядка відділений пробілом і чи " + "дорівнює кількість рядків кількості стовпців." + ) + elif adjacency_matrix is None and error == "value_error": + self.show_error( + "Матриця суміжності мусить складатись лише з нулів і одиниць розділених пробілом. Перевірте ваш ввід." + ) + elif adjacency_matrix is None and error == "empty_matrix": + self.show_error( + "Матриця суміжності не може бути пустою." + ) + elif type(adjacency_matrix) is np.ndarray and error is None: + adjacency_graph = self.create_adjacency_graph(adjacency_matrix) + colours = self.brute_force_colour(adjacency_graph) + self.draw_graph(adjacency_graph, colours) + + @staticmethod + def show_error(error_text: str): + error_message = QtWidgets.QMessageBox() + error_message.setIcon(QtWidgets.QMessageBox.Critical) + error_message.setText("Помилка вводу") + error_message.setInformativeText(error_text) + error_message.setWindowTitle("Помилка") + error_message.exec_() + + @staticmethod + def create_adjacency_graph(adjacency_matrix: np.ndarray) -> nx.Graph: + graph = nx.Graph() + + nodes = [f"{i}" for i in range(len(adjacency_matrix))] + edge_indices = np.argwhere(adjacency_matrix) + edges = [(nodes[edge_index[0]], nodes[edge_index[1]]) for edge_index in edge_indices] + graph.add_nodes_from(nodes) + graph.add_edges_from(edges) + + return graph + + def draw_graph(self, graph: nx.Graph, colour_map: list): + + self.figure.clf() + + nx.draw( + graph, with_labels=True, node_size=700, font_size=14, font_family="Ubuntu Mono", node_color=colour_map, + edgecolors="black", font_weight="bold", width=2 + ) + + plt.margins(0.2) + + self.canvas.draw_idle() + + @staticmethod + def previous_neighbors(graph: nx.Graph, node: str): + neighbours = list(graph.neighbors(node)) + + nodes = list(graph.nodes) + previous = nodes[:nodes.index(node)] + + res = [n for n in previous if n in neighbours] + + return res + + def brute_force_colour(self, graph: nx.Graph) -> list: + coloured_nodes = dict() + i = 0 + for node in graph: + previous_colours = [coloured_nodes[f'{n}'] for n in self.previous_neighbors(graph, node)] + nodes_difference = sorted(list(set(coloured_nodes.values()) - set(previous_colours))) + + if (not coloured_nodes) or (not nodes_difference): + coloured_nodes[f"{node}"] = i + i += 1 + else: + coloured_nodes[f"{node}"] = nodes_difference[0] + + colour_map = [list(mcolours.CSS4_COLORS.keys())[i] for i in coloured_nodes.values()] + + return colour_map + + def open_file(self): + file_name = QtWidgets.QFileDialog.getOpenFileName(self, "Відкрити файл", "~/", "Текстові файли (*.txt)") + with open(file_name[0]) as f: + text_read = f.read() + self.adjacency_input.setText(text_read) + + def set_functions(self): + self.build_graph_button.clicked.connect(lambda: self.build_graphs()) + self.open_file_button.clicked.connect(lambda: self.open_file())