Initial commit
This commit is contained in:
@@ -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())
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
+228
@@ -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())
|
||||
Reference in New Issue
Block a user