diff --git a/readme.md b/readme.md
index 2d8b453e7..3abf58db6 100644
--- a/readme.md
+++ b/readme.md
@@ -18,7 +18,8 @@
| № | ФИО | Directory name | #0 | #1 | #2 | #3 | #4 | #5 | #6 | #7 | Рейтинг |
|----|------------------------------------------------------|-------------------------|----|-----|----|----|----|----|----|----|---------|
-| 1 | [Бусень Артём](https:github.com/hudshiy1) |[ii02301](trunk/ii02301) | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | | | 8|
+
+| 1 | [Бусень Артём](https://github.com/hudshiy1) |[ii02301](trunk/ii02301) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | | | 8|
| 2 | [Волкогон Никита](https://github.com/VolkogonNikita) |[ii02302](trunk/II02302) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | | | 9|
| 3 | [Вышинский Артём](https://github.com/arciomwww) |[ii02303](trunk/ii02303) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | | | 8|
| 4 | [Гавришук Владислав](https://github.com/VLadGavrishuk)|[ii02304](trunk/ii02304)| ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | | | 7|
diff --git a/trunk/ii02301/task_03/doc/1.png b/trunk/ii02301/task_03/doc/1.png
new file mode 100644
index 000000000..4da5ff806
Binary files /dev/null and b/trunk/ii02301/task_03/doc/1.png differ
diff --git a/trunk/ii02301/task_03/doc/2.png b/trunk/ii02301/task_03/doc/2.png
new file mode 100644
index 000000000..f8cbf6c85
Binary files /dev/null and b/trunk/ii02301/task_03/doc/2.png differ
diff --git a/trunk/ii02301/task_03/doc/3.png b/trunk/ii02301/task_03/doc/3.png
new file mode 100644
index 000000000..4efd5a0c8
Binary files /dev/null and b/trunk/ii02301/task_03/doc/3.png differ
diff --git a/trunk/ii02301/task_03/doc/4.png b/trunk/ii02301/task_03/doc/4.png
new file mode 100644
index 000000000..72065cfe3
Binary files /dev/null and b/trunk/ii02301/task_03/doc/4.png differ
diff --git a/trunk/ii02301/task_03/doc/5.png b/trunk/ii02301/task_03/doc/5.png
new file mode 100644
index 000000000..e795ed231
Binary files /dev/null and b/trunk/ii02301/task_03/doc/5.png differ
diff --git a/trunk/ii02301/task_03/doc/6.png b/trunk/ii02301/task_03/doc/6.png
new file mode 100644
index 000000000..81fbbf343
Binary files /dev/null and b/trunk/ii02301/task_03/doc/6.png differ
diff --git a/trunk/ii02301/task_03/doc/7.png b/trunk/ii02301/task_03/doc/7.png
new file mode 100644
index 000000000..4d13af4e9
Binary files /dev/null and b/trunk/ii02301/task_03/doc/7.png differ
diff --git a/trunk/ii02301/task_03/doc/8.png b/trunk/ii02301/task_03/doc/8.png
new file mode 100644
index 000000000..4ba789e30
Binary files /dev/null and b/trunk/ii02301/task_03/doc/8.png differ
diff --git a/trunk/ii02301/task_03/doc/report.md b/trunk/ii02301/task_03/doc/report.md
new file mode 100644
index 000000000..c7e9bdbda
--- /dev/null
+++ b/trunk/ii02301/task_03/doc/report.md
@@ -0,0 +1,104 @@
+
Министерство образования Республики Беларусь
+Учреждение образования
+“Брестский Государственный технический университет”
+Кафедра ИИТ
+
+Лабораторная работа №3
+По дисциплине “Общая теория интеллектуальных систем”
+Тема: “Разработка редактора графов”
+
+Выполнил:
+Студент 2 курса
+Группы ИИ-23
+Бусень А.Д..
+Проверил:
+Иванюк Д. С.
+
+Брест 2023
+
+
+---
+# Задание: #
+1. Разработать и реализовать программный продукт позволяющий
+редактировать графовые конструкции различных видов и производить над
+ними различные действия. Язык программирования - любой.
+
+2. Редактор должен позволять (задания со **[\*]** являются необязательными):
+ a) одновременно работать с несколькими графами (MDI);
+ b) **[\*]** выделение одновременно нескольких элементов графа, копирование
+выделенного фрагмента в clipboard и восстановление из него;
+ c) задавать имена графам;
+ d) сохранять и восстанавливать граф во внутреннем формате программы;
+ e) экспортировать и импортировать граф в текстовый формат (описание
+см. ниже);
+ f) создавать, удалять, именовать, переименовывать, перемещать узлы;
+ g) создавать ориентированные и неориентированные дуги, удалять дуги;
+ h) добавлять, удалять и редактировать содержимое узла (содержимое в
+виде текста и ссылки на файл);
+ i) задавать цвет дуги и узла, образ узла;
+ j) **[\*]** создавать и отображать петли;
+ k) **[\*]** создавать и отображать кратные дуги.
+
+3. Программный продукт должен позволять выполнять следующие операции:
+ a) выводить информацию о графе:
+
+ + количество вершин, дуг;
+ + степени для всех вершин и для выбранной вершины;
+ + матрицу инцидентности;
+ + матрицу смежности;
+ + является ли он деревом, полным, связанным, эйлеровым, **[\*]** планарным;
+
+ b) поиск всех путей (маршрутов) между двумя узлами и кратчайших;
+ c) вычисление расстояния между двумя узлами;
+ d) вычисление диаметра, радиуса, центра графа;
+ e) **[\*]** вычисление векторного и декартово произведения двух графов;
+ f) **[\*]** раскраска графа;
+ g) нахождения эйлеровых, [*] гамильтоновых циклов;
+ h) **[\*]** поиск подграфа в графе, со всеми или некоторыми неизвестными
+ узлами;
+ i) **[\*]** поиск узла по содержимому;
+ j) **[\*]** объединение, пересечение, сочетание и дополнение графов;
+ k) **[\*]** приведение произвольного графа к определенному типу с
+ минимальными изменениями:
+
+ + бинарное и обычное дерево;
+ + полный граф;
+ + планарный граф;
+ + связанный граф;
+
+4. Формат текстового представления графа:
+<ГРАФ> ::= <ИМЯ ГРАФА> : UNORIENT | ORIENT ; <ОПИСАНИЕ УЗЛОВ> ;
+<ОПИСАНИЕ СВЯЗЕЙ> .
+<ИМЯ ГРАФА> ::= <ИДЕНТИФИКАТОР>
+<ОПИСАНИЕ УЗЛОВ> ::= <ИМЯ УЗЛА> [ , <ИМЯ УЗЛА> …]
+<ИМЯ УЗЛА> ::= <ИДЕНТИФИКАТОР>
+<ОПИСАНИЕ СВЯЗЕЙ> ::= <ИМЯ УЗЛА> -> <ИМЯ УЗЛА> [ , <ИМЯ УЗЛА> …] ;
+[<ОПИСАНИЕ СВЯЗЕЙ> …]
+
+5. Написать отчет по выполненной лабораторной работе в .md формате (readme.md). Разместить его в следующем каталоге: **trunk\ii0xxyy\task_03\doc** (где **xx** - номер группы, **yy** - номер студента, например **ii02301**).
+
+6. Исходный код разработанной программы разместить в каталоге: **trunk\ii0xxyy\task_03\src**
+7. Данная задача реализована на языке python.
+# Описание работы программы: #
+## Главное окно программы
+![Окно программы](1.png)
+
+## Создаение вершины
+![Создание вершин](2.png)
+
+## Соединение вершины ребрами
+![Соединение ребрами](3.png)
+![Соединение ребрами](4.png)
+
+## Изменение цвета вершин, ребер и передвижение их
+![Изменение цвета, передвижение](5.png)
+
+## Можем сохранить граф во внутреннем формате или экспортировать в текстовый файл
+![Сохранение, экспорт](6.png)
+
+## Можем применить алгоритмы
+![Алгоритмы](7.png)
+
+## Можем построить граф по матрице смежности
+![Построение по матрице смежности](8.png)
+
diff --git a/trunk/ii02301/task_03/src/CMakeLists.txt b/trunk/ii02301/task_03/src/CMakeLists.txt
new file mode 100644
index 000000000..59d2f9e54
--- /dev/null
+++ b/trunk/ii02301/task_03/src/CMakeLists.txt
@@ -0,0 +1,7 @@
+cmake_minimum_required(VERSION 3.6)
+
+project(OTIS_03)
+
+set(SOURCES otis03.cpp)
+
+add_executable(MExecutable3 ${SOURCES})
diff --git a/trunk/ii02301/task_03/src/main.py b/trunk/ii02301/task_03/src/main.py
new file mode 100644
index 000000000..caab5f414
--- /dev/null
+++ b/trunk/ii02301/task_03/src/main.py
@@ -0,0 +1,290 @@
+import tkinter as tk
+from tkinter import messagebox, simpledialog
+import tkinter.colorchooser as colorchooser
+
+click_number = 0
+id_of_the_edge = 0
+oval_id = None
+ovals = []
+edges = []
+i = 0
+id_text = 0
+tag = 0
+x1, y1, x2, y2 = 0, 0, 0, 0
+button_1=""
+text_on_vertex='text on vertex'
+id_text='id text'
+num_of_vertex='num of vertex'
+root = tk.Tk()
+canvas=tk.canvas(root)
+main_label =tk.Label()
+cord_edge2 = {'id_vertex1': [], 'id_vertex2': []}
+cord_edge = {'id_edge_text': [], 'id_vertex1': [], 'id_vertex2': []}
+cord = {'id': [], id_text: [], text_on_vertex: [], 'textID': [], num_of_vertex: [], 'coordinatesX': [],
+ 'coordinatesY': []}
+visited = []
+matrix = []
+
+
+def draw_vertex():
+ main_label.configure(text="Выбрано создание вершин, нажмите на пустое для создания вершины")
+ canvas.unbind(button_1)
+ canvas.bind(button_1, draw_canvas1)
+
+
+def draw_canvas1(event):
+ global oval_id, i, tag, id_text
+ id_text += 1
+ i += 1
+ itext = str(i)
+ x, y = event.x, event.y
+ tag = 'oval' + str(id_text)
+ texttag = 'text' + str(id_text)
+ cord["num of vertex"].append(id_text)
+ cord[id_text].append(tag)
+ cord["coordinatesX"].append(x)
+ cord["coordinatesY"].append(y)
+ oval_id = canvas.create_oval(x - 15, y - 15, x + 15, y + 15, fill='red', tags=tag)
+ ovals.append(oval_id)
+ cord['id'].append(oval_id)
+ canvas.create_text(x, y, text=itext, font="Arial 13", tags=texttag)
+ cord['textID'].append(texttag)
+ cord[text_on_vertex].append(itext)
+
+
+def draw_edge():
+ main_label.configure(text="Выбрано создание ребер, нажмите на вершину для создания ребра")
+ canvas.unbind(button_1)
+ canvas.bind(button_1, draw_canvas2)
+
+
+def draw_canvas2(event):
+ global click_number, x1, y1, x2, y2, id_of_the_edge
+ if click_number == 0:
+ for x in ovals:
+ if canvas.find_overlapping(event.x, event.y, event.x, event.y)[0] == x:
+ x1 = cord['coordinatesX'][cord['id'].index(x)]
+ y1 = cord['coordinatesY'][cord['id'].index(x)]
+ cord_edge['id_vertex1'].append(x)
+ cord_edge2['id_vertex1'].append(x)
+ click_number = 1
+ main_label.configure(text="Выбор второй вершины для рисования ребра графа")
+ elif click_number == 1:
+ for x in ovals:
+ if canvas.find_overlapping(event.x, event.y, event.x, event.y)[0] == x:
+ x2 = cord['coordinatesX'][cord['id'].index(x)]
+ y2 = cord['coordinatesY'][cord['id'].index(x)]
+ cord_edge['id_vertex2'].append(x)
+ cord_edge2['id_vertex2'].append(x)
+ tag_edge = 'edge' + str(id_of_the_edge)
+ line = canvas.create_line(x1, y1, x2, y2, width=4, tags=tag_edge)
+ edges.append(id_of_the_edge)
+ cord_edge['id_edge_text'].append(tag_edge)
+ id_of_the_edge += 1
+ canvas.tag_lower(line)
+ click_number = 0
+ main_label.configure(text="Выберите нужную вершину для рисования ребра графа")
+
+
+def delete_vertex():
+ main_label.configure(text="Выбрано удаление вершины или ребра, нажмите на вершину или ребро для удаления")
+ canvas.unbind(button_1)
+ canvas.bind(button_1, delete_canvas)
+
+
+def delete_canvas(event):
+ for x in ovals:
+ if canvas.find_overlapping(event.x, event.y, event.x, event.y)[0] == x:
+ canvas.delete(x)
+ canvas.delete(cord['textID'][cord['id'].index(x)])
+ ovals.remove(x)
+ cord[num_of_vertex].remove(cord[num_of_vertex][cord['id'].index(x)])
+ canvas.delete(cord[id_text][cord['id'].index(x)])
+ cord['textID'].remove(cord['textID'][cord['id'].index(x)])
+ cord[id_text].remove(cord[id_text][cord['id'].index(x)])
+ cord["coordinatesX"].remove(cord['coordinatesX'][cord['id'].index(x)])
+ cord["coordinatesY"].remove(cord['coordinatesY'][cord['id'].index(x)])
+ cord[text_on_vertex].remove(cord[text_on_vertex][cord['id'].index(x)])
+ cord['id'].remove(x)
+ break
+ for y in edges:
+ tag_edge = 'edge' + str(y)
+ if canvas.find_overlapping(event.x, event.y, event.x, event.y)[0] == canvas.find_withtag(tag_edge)[0]:
+ canvas.delete(tag_edge)
+ cord_edge['id_vertex1'].remove(cord_edge['id_vertex1'][edges.index(y)])
+ cord_edge['id_vertex2'].remove(cord_edge['id_vertex2'][edges.index(y)])
+ edges.remove(y)
+ break
+
+
+def rename_vertex():
+ main_label.configure(text="Выбрано переименование вершины, нажмите на вершину для переименования")
+ canvas.unbind(button_1)
+ canvas.bind(button_1, rename)
+
+
+def rename(event):
+ for x in ovals:
+ if canvas.find_overlapping(event.x, event.y, event.x, event.y)[0] == x:
+ new_name = simpledialog.askstring("Rename", "Enter new name")
+ canvas.delete(cord['textID'][cord['id'].index(x)])
+ canvas.create_text(cord['coordinatesX'][cord['id'].index(x)], cord['coordinatesY'][cord['id'].index(x)],
+ text=new_name, font="Arial 13", tags=(cord['textID'][cord['id'].index(x)]))
+ cord[text_on_vertex][cord['id'].index(x)] = new_name
+ break
+
+
+def change_color():
+ main_label.configure(text="Вы выбрали изменение цвета вершины, нажмите на вершину для изменения её цвета")
+ canvas.unbind(button_1)
+ canvas.bind(button_1, color)
+
+
+def color(event):
+ for x in ovals:
+ if canvas.find_overlapping(event.x, event.y, event.x, event.y)[0] == x:
+ new_color = colorchooser.askcolor()
+ color_hex = new_color[1]
+ canvas.itemconfig(x, fill=color_hex)
+ break
+
+
+def change_text_color():
+ main_label.configure(text="Вы выбрали изменение цвета текста, нажмите на вершину для изменения цвета её текста")
+ canvas.unbind(button_1)
+ canvas.bind(button_1, text_color)
+
+
+def text_color(event):
+ for x in ovals:
+ if canvas.find_overlapping(event.x, event.y, event.x, event.y)[0] == x:
+ new_color = colorchooser.askcolor()
+ color_hex = new_color[1]
+ canvas.itemconfig(cord['textID'][cord['id'].index(x)], fill=color_hex)
+ break
+
+
+def change_edge_color():
+ main_label.configure(text="Вы выбрали изменение цвета ребер, нажмите на ребро для изменения его цвета")
+ canvas.unbind(button_1)
+ canvas.bind(button_1, edge_color)
+
+
+def edge_color(event):
+ for x in edges:
+ tag_edge = 'edge' + str(x)
+ if canvas.find_overlapping(event.x, event.y, event.x, event.y)[0] == canvas.find_withtag(tag_edge)[0]:
+ new_color = colorchooser.askcolor()
+ color_hex = new_color[1]
+ canvas.itemconfig(tag_edge, fill=color_hex)
+ break
+
+
+def adjacency_matrix():
+ k = 0
+ adj_matrix = tk.Tk()
+ adj_matrix.title("Adjacency matrix")
+ adj_matrix.geometry("150x150")
+ matrix = [[0 for _ in range(len(ovals))] for _ in range(len(ovals))]
+ for index in enumerate(cord_edge['id_vertex1']):
+ matrix[cord['id'].index(cord_edge['id_vertex1'][index])][cord['id'].index(cord_edge['id_vertex2'][index])] = 1
+ matrix[cord['id'].index(cord_edge['id_vertex2'][index])][cord['id'].index(cord_edge['id_vertex1'][index])] = 1
+
+ for row in matrix:
+ adj_matrix_label = tk.Label(adj_matrix, text=str(row))
+ adj_matrix_label.grid(row=k, column=0)
+ k += 1
+
+
+def incidence_matrix():
+ k = 0
+ inc_matrix = tk.Tk()
+ inc_matrix.title("Incidence matrix")
+ inc_matrix.geometry("150x150")
+ matrix = [[0 for _ in range(len(edges))] for _ in range(len(ovals))]
+ for index in enumerate(cord_edge['id_vertex1']):
+ matrix[cord['id'].index(cord_edge['id_vertex1'][index])][edges.index(cord_edge['id_edge_text'].index(
+ cord_edge['id_edge_text'][index]))] = 1
+ matrix[cord['id'].index(cord_edge['id_vertex2'][index])][edges.index(cord_edge['id_edge_text'].index(
+ cord_edge['id_edge_text'][index]))] = 1
+
+ for row in matrix:
+ inc_matrix_label = tk.Label(inc_matrix, text=str(row))
+ inc_matrix_label.grid(row=k, column=0)
+ k += 1
+
+
+def dfs():
+ visited = [False] * len(ovals)
+
+ def dfs_rec(vert):
+ visited[vert] = True
+ for u in range(len(ovals)):
+ if matrix[vert][u] == 1 and not visited[u]:
+ dfs_rec(u)
+
+ count = 0
+ for v in range(len(ovals)):
+ if not visited[v]:
+ dfs_rec(v)
+ count += 1
+ if count == 1:
+ messagebox.showinfo("DFS", "Graph is connected")
+ else:
+ messagebox.showinfo("DFS", "Graph is not connected")
+
+
+def bfs():
+ visited = [False] * len(ovals)
+
+ def bfs_rec(vert):
+ visited[vert] = True
+ for u in range(len(ovals)):
+ if matrix[vert][u] == 1 and not visited[u]:
+ bfs_rec(u)
+
+ count = 0
+ for v in range(len(ovals)):
+ if not visited[v]:
+ bfs_rec(v)
+ count += 1
+ if count == 1:
+ messagebox.showinfo("BFS", "Graph is connected")
+ else:
+ messagebox.showinfo("BFS", "Graph is not connected")
+
+
+root = tk.Tk()
+root.geometry("800x600")
+
+frame = tk.Frame(root)
+frame.pack(fill=tk.BOTH, expand=True)
+
+canvas = tk.Canvas(frame, width=1920, height=1080)
+canvas.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
+
+menubar = tk.Menu(root)
+root.config(menu=menubar)
+
+
+graphmenu = tk.Menu(menubar, tearoff=0)
+menubar.add_cascade(label="Граф", menu=graphmenu)
+graphmenu.add_command(label="Рисование вершины", command=draw_vertex)
+graphmenu.add_command(label="Рисование ребра", command=draw_edge)
+graphmenu.add_command(label="Удаление вершины или ребера", command=delete_vertex)
+
+redmenu = tk.Menu(menubar, tearoff=0)
+menubar.add_cascade(label="Редактирование графа", menu=redmenu)
+redmenu.add_command(label="Переименование вершины", command=rename_vertex)
+redmenu.add_command(label="Перекрашивание вершины", command=change_color)
+redmenu.add_command(label="Перекрашивание текста", command=change_text_color)
+redmenu.add_command(label="Перекрашивание ребра", command=change_edge_color)
+
+algmenu = tk.Menu(menubar, tearoff=0)
+menubar.add_cascade(label="Алгоритмы графа", menu=algmenu)
+algmenu.add_command(label="Вывод матрицы смежности", command=adjacency_matrix)
+algmenu.add_command(label="Вывод матрицы инцидентности", command=incidence_matrix)
+algmenu.add_command(label="Поиск в глубину по графу", command=dfs)
+algmenu.add_command(label="Поиск в ширину по графу", command=bfs)
+
+root.mainloop()
diff --git a/trunk/ii02301/task_03/src/otis03.cpp b/trunk/ii02301/task_03/src/otis03.cpp
new file mode 100644
index 000000000..c1c6d92f4
--- /dev/null
+++ b/trunk/ii02301/task_03/src/otis03.cpp
@@ -0,0 +1,6 @@
+#include
+
+int main() {
+ std::system("python main.py");// c++
+ return 0;
+}
\ No newline at end of file