905 lines
26 KiB
Plaintext
905 lines
26 KiB
Plaintext
|
{
|
|||
|
"cells": [
|
|||
|
{
|
|||
|
"cell_type": "markdown",
|
|||
|
"id": "e02cd782",
|
|||
|
"metadata": {},
|
|||
|
"source": [
|
|||
|
"# Практика №2\n"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "markdown",
|
|||
|
"id": "48a6e585",
|
|||
|
"metadata": {},
|
|||
|
"source": [
|
|||
|
"## Операции над множествами. Свойства бинарных отношений. Замыкания отношений\n"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "markdown",
|
|||
|
"id": "2ae75977",
|
|||
|
"metadata": {},
|
|||
|
"source": [
|
|||
|
"Множества являются неопределяемыми понятиями и представляют собой неупорядоченную коллекцию уникальных элементов.\n",
|
|||
|
"То есть, что два множества совпадают, если содержат одинаковые элементы.\n",
|
|||
|
"Множества, состоящие из конечного числа элементов, называются конечными, в противном случае множества являются бесконечными. Конечное множество можно задать перечислением его элементов. Рассмотрим как можно работать с множествами средствами языка Python на примере конечных множеств.\n"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "markdown",
|
|||
|
"id": "ca4afee1",
|
|||
|
"metadata": {},
|
|||
|
"source": [
|
|||
|
"### Способы задания множеств\n"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "markdown",
|
|||
|
"id": "d848525f",
|
|||
|
"metadata": {},
|
|||
|
"source": [
|
|||
|
"перечисление элементов множества в фигурных скобках:\n"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "code",
|
|||
|
"execution_count": 1,
|
|||
|
"id": "569b7ff7",
|
|||
|
"metadata": {},
|
|||
|
"outputs": [
|
|||
|
{
|
|||
|
"name": "stdout",
|
|||
|
"output_type": "stream",
|
|||
|
"text": [
|
|||
|
"{'orange', 'apple', 'banana'}\n",
|
|||
|
"<class 'set'>\n"
|
|||
|
]
|
|||
|
}
|
|||
|
],
|
|||
|
"source": [
|
|||
|
"fruits = {\"banana\", \"apple\", \"orange\"}\n",
|
|||
|
"print(fruits)\n",
|
|||
|
"print(type(fruits))"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "markdown",
|
|||
|
"id": "b3e9458e",
|
|||
|
"metadata": {},
|
|||
|
"source": [
|
|||
|
"Единственное ограничение, что таким образом нельзя создать пустое множество. Вместо этого будет создан пустой словарь:\n"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "code",
|
|||
|
"execution_count": 2,
|
|||
|
"id": "d446184f",
|
|||
|
"metadata": {},
|
|||
|
"outputs": [
|
|||
|
{
|
|||
|
"name": "stdout",
|
|||
|
"output_type": "stream",
|
|||
|
"text": [
|
|||
|
"<class 'dict'>\n"
|
|||
|
]
|
|||
|
}
|
|||
|
],
|
|||
|
"source": [
|
|||
|
"wrong_empty_set = {}\n",
|
|||
|
"print(type(wrong_empty_set))"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "markdown",
|
|||
|
"id": "60a0a658",
|
|||
|
"metadata": {},
|
|||
|
"source": [
|
|||
|
"Для создания пустого множества нужно непосредственно использовать set():\n"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "code",
|
|||
|
"execution_count": 3,
|
|||
|
"id": "3b7ce4b6",
|
|||
|
"metadata": {},
|
|||
|
"outputs": [
|
|||
|
{
|
|||
|
"name": "stdout",
|
|||
|
"output_type": "stream",
|
|||
|
"text": [
|
|||
|
"<class 'set'>\n"
|
|||
|
]
|
|||
|
}
|
|||
|
],
|
|||
|
"source": [
|
|||
|
"correct_empty_set = set()\n",
|
|||
|
"print(type(correct_empty_set))"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "markdown",
|
|||
|
"id": "47b6bfac",
|
|||
|
"metadata": {},
|
|||
|
"source": [
|
|||
|
"Множество можно задать с помощью set(), если передать в нее какой-либо объект, по которому можно проитерироваться\n"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "code",
|
|||
|
"execution_count": 4,
|
|||
|
"id": "6d41db64",
|
|||
|
"metadata": {},
|
|||
|
"outputs": [
|
|||
|
{
|
|||
|
"name": "stdout",
|
|||
|
"output_type": "stream",
|
|||
|
"text": [
|
|||
|
"{'orange', 'apple', 'banana'}\n",
|
|||
|
"<class 'set'>\n"
|
|||
|
]
|
|||
|
}
|
|||
|
],
|
|||
|
"source": [
|
|||
|
"fruits_set = set({\"banana\", \"apple\", \"banana\", \"orange\"})\n",
|
|||
|
"print(fruits_set)\n",
|
|||
|
"print(type(fruits_set))"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "code",
|
|||
|
"execution_count": 5,
|
|||
|
"id": "99b8c1ea",
|
|||
|
"metadata": {},
|
|||
|
"outputs": [
|
|||
|
{
|
|||
|
"name": "stdout",
|
|||
|
"output_type": "stream",
|
|||
|
"text": [
|
|||
|
"True\n"
|
|||
|
]
|
|||
|
}
|
|||
|
],
|
|||
|
"source": [
|
|||
|
"fruits_set_1 = set({\"apple\", \"orange\", \"banana\", })\n",
|
|||
|
"print(fruits_set == fruits_set_1)"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "markdown",
|
|||
|
"id": "4b420cc2",
|
|||
|
"metadata": {},
|
|||
|
"source": [
|
|||
|
"### Подмножество и надмножество\n"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "code",
|
|||
|
"execution_count": 6,
|
|||
|
"id": "98eb8ea5",
|
|||
|
"metadata": {},
|
|||
|
"outputs": [
|
|||
|
{
|
|||
|
"name": "stdout",
|
|||
|
"output_type": "stream",
|
|||
|
"text": [
|
|||
|
"Подмножество!\n",
|
|||
|
"Надмножество!\n"
|
|||
|
]
|
|||
|
}
|
|||
|
],
|
|||
|
"source": [
|
|||
|
"# Множество чисел Фибоначчи меньших 100\n",
|
|||
|
"fibonacci_numbers = {0, 1, 2, 3, 34, 5, 8, 13, 21, 55, 89}\n",
|
|||
|
"\n",
|
|||
|
"# Множество натуральных чисел меньших 100\n",
|
|||
|
"natural_numbers = set(range(100))\n",
|
|||
|
"\n",
|
|||
|
"# Множество чисел Фибоначчи является подмножеством множества\n",
|
|||
|
"# натуральных чисел\n",
|
|||
|
"if fibonacci_numbers.issubset(natural_numbers):\n",
|
|||
|
" print(\"Подмножество!\")\n",
|
|||
|
"\n",
|
|||
|
"# В свою очередь множество натуральных чисел является\n",
|
|||
|
"# надмножеством множества чисел Фибоначчи\n",
|
|||
|
"if natural_numbers.issuperset(fibonacci_numbers):\n",
|
|||
|
" print(\"Надмножество!\")"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "markdown",
|
|||
|
"id": "6c861227",
|
|||
|
"metadata": {},
|
|||
|
"source": [
|
|||
|
"Пустое множество является подмножеством абсолютно любого множества.\n"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "code",
|
|||
|
"execution_count": 7,
|
|||
|
"id": "2946f658",
|
|||
|
"metadata": {},
|
|||
|
"outputs": [
|
|||
|
{
|
|||
|
"name": "stdout",
|
|||
|
"output_type": "stream",
|
|||
|
"text": [
|
|||
|
"True\n"
|
|||
|
]
|
|||
|
}
|
|||
|
],
|
|||
|
"source": [
|
|||
|
"empty = set()\n",
|
|||
|
"\n",
|
|||
|
"# Методы issubset и issuperset могут принимать любой iterable-объект\n",
|
|||
|
"print(\n",
|
|||
|
" empty.issubset(range(100))\n",
|
|||
|
" and empty.issubset([\"red\", \"green\", \"blue\"])\n",
|
|||
|
" and empty.issubset(set())\n",
|
|||
|
")"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "markdown",
|
|||
|
"id": "eb5a7764",
|
|||
|
"metadata": {},
|
|||
|
"source": [
|
|||
|
"Само множество является подмножеством самого себя.\n"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "code",
|
|||
|
"execution_count": 8,
|
|||
|
"id": "019bb3ac",
|
|||
|
"metadata": {},
|
|||
|
"outputs": [
|
|||
|
{
|
|||
|
"name": "stdout",
|
|||
|
"output_type": "stream",
|
|||
|
"text": [
|
|||
|
"Подмножество!\n"
|
|||
|
]
|
|||
|
}
|
|||
|
],
|
|||
|
"source": [
|
|||
|
"natural_numbers = set(range(100))\n",
|
|||
|
"\n",
|
|||
|
"if natural_numbers.issubset(natural_numbers):\n",
|
|||
|
" print(\"Подмножество!\")"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "markdown",
|
|||
|
"id": "effdf363",
|
|||
|
"metadata": {},
|
|||
|
"source": [
|
|||
|
"### Операции над множествами\n"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "markdown",
|
|||
|
"id": "1bc824be",
|
|||
|
"metadata": {},
|
|||
|
"source": [
|
|||
|
"Объединение множеств\n"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "code",
|
|||
|
"execution_count": 9,
|
|||
|
"id": "ce1f88c8",
|
|||
|
"metadata": {},
|
|||
|
"outputs": [
|
|||
|
{
|
|||
|
"name": "stdout",
|
|||
|
"output_type": "stream",
|
|||
|
"text": [
|
|||
|
"{'orange', 'pear', 'banana', 'apple'}\n"
|
|||
|
]
|
|||
|
}
|
|||
|
],
|
|||
|
"source": [
|
|||
|
"my_fruits = {\"apple\", \"orange\"}\n",
|
|||
|
"your_fruits = {\"orange\", \"banana\", \"pear\"}\n",
|
|||
|
"\n",
|
|||
|
"# Для объединения множеств (типа set) можно использовать оператор `|`,\n",
|
|||
|
"\n",
|
|||
|
"our_fruits = my_fruits | your_fruits\n",
|
|||
|
"print(our_fruits)"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "code",
|
|||
|
"execution_count": 10,
|
|||
|
"id": "36e34918",
|
|||
|
"metadata": {},
|
|||
|
"outputs": [
|
|||
|
{
|
|||
|
"name": "stdout",
|
|||
|
"output_type": "stream",
|
|||
|
"text": [
|
|||
|
"{'orange', 'pear', 'apple', 'banana'}\n"
|
|||
|
]
|
|||
|
}
|
|||
|
],
|
|||
|
"source": [
|
|||
|
"# Также можно использовать ментод union.\n",
|
|||
|
"# Отличие состоит в том, что метод union принимает не только\n",
|
|||
|
"# объект типа set, а любой iterable-объект\n",
|
|||
|
"you_fruit_list: list = list(your_fruits)\n",
|
|||
|
"our_fruits: set = my_fruits.union(you_fruit_list)\n",
|
|||
|
"print(our_fruits)"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "markdown",
|
|||
|
"id": "edb92d2a",
|
|||
|
"metadata": {},
|
|||
|
"source": [
|
|||
|
"Добавление элементов в множество.\n",
|
|||
|
"Добавление элементов в множество можно рассматривать как частный случай объединения множеств за тем исключением, что добавление элементов изменяет исходное множество, а не создает новый объект\n"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "code",
|
|||
|
"execution_count": 11,
|
|||
|
"id": "af8a9b6a",
|
|||
|
"metadata": {},
|
|||
|
"outputs": [
|
|||
|
{
|
|||
|
"name": "stdout",
|
|||
|
"output_type": "stream",
|
|||
|
"text": [
|
|||
|
"{'red', 'purple', 'green', 'blue'}\n"
|
|||
|
]
|
|||
|
}
|
|||
|
],
|
|||
|
"source": [
|
|||
|
"colors = {\"red\", \"green\", \"blue\"}\n",
|
|||
|
"\n",
|
|||
|
"# Метод add добаляет новый элемент в множество\n",
|
|||
|
"colors.add(\"purple\")\n",
|
|||
|
"# Добавление элемента, который уже есть в множестве, не изменяет\n",
|
|||
|
"# это множество\n",
|
|||
|
"colors.add(\"red\")\n",
|
|||
|
"print(colors)"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "code",
|
|||
|
"execution_count": 12,
|
|||
|
"id": "103d30b9",
|
|||
|
"metadata": {},
|
|||
|
"outputs": [
|
|||
|
{
|
|||
|
"name": "stdout",
|
|||
|
"output_type": "stream",
|
|||
|
"text": [
|
|||
|
"{1, 2, 3, 4, 9}\n"
|
|||
|
]
|
|||
|
}
|
|||
|
],
|
|||
|
"source": [
|
|||
|
"# Метод update принимает iterable-объект (список, словарь, генератор и т.п.)\n",
|
|||
|
"# и добавляет все элементы в множество\n",
|
|||
|
"numbers = {1, 2, 3}\n",
|
|||
|
"numbers.update(i**2 for i in [1, 2, 3])\n",
|
|||
|
"print(numbers)"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "markdown",
|
|||
|
"id": "765338fd",
|
|||
|
"metadata": {},
|
|||
|
"source": [
|
|||
|
"### Свойства множеств\n"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "markdown",
|
|||
|
"id": "8cb16831",
|
|||
|
"metadata": {},
|
|||
|
"source": [
|
|||
|
"К основным свойствам множеств, которые мы хотим проверять, относятся рефлексивность, антирефлексивность, симметричность, антисимметричность, транзитивность.\n",
|
|||
|
"Сгенерируем произвольное бинарное отношение\n"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "code",
|
|||
|
"execution_count": 7,
|
|||
|
"id": "fac374b1",
|
|||
|
"metadata": {},
|
|||
|
"outputs": [
|
|||
|
{
|
|||
|
"data": {
|
|||
|
"text/plain": [
|
|||
|
"[[1, 1, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [1, 1, 0, 0]]"
|
|||
|
]
|
|||
|
},
|
|||
|
"execution_count": 7,
|
|||
|
"metadata": {},
|
|||
|
"output_type": "execute_result"
|
|||
|
}
|
|||
|
],
|
|||
|
"source": [
|
|||
|
"import random\n",
|
|||
|
"x = 4\n",
|
|||
|
"y = 4\n",
|
|||
|
"array = [[random.randint(0, 1) for _ in range(x)] for _ in range(y)]\n",
|
|||
|
"array"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "markdown",
|
|||
|
"id": "71d50746",
|
|||
|
"metadata": {},
|
|||
|
"source": [
|
|||
|
"Проверим рефлексивность. Чтобы выявить наличие единиц на главной диагонали, сгенерируем единичную матрицу нужной размерности, и проверим включается ли она в исходное отношение. Но можно и напрямую проверить, что элементы с i=j в отношении равны 1\n"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "code",
|
|||
|
"execution_count": 8,
|
|||
|
"id": "23da8a2f",
|
|||
|
"metadata": {},
|
|||
|
"outputs": [
|
|||
|
{
|
|||
|
"data": {
|
|||
|
"text/plain": [
|
|||
|
"False"
|
|||
|
]
|
|||
|
},
|
|||
|
"execution_count": 8,
|
|||
|
"metadata": {},
|
|||
|
"output_type": "execute_result"
|
|||
|
}
|
|||
|
],
|
|||
|
"source": [
|
|||
|
"# ваш код\n",
|
|||
|
"def reflexivity_check(array: list[list[int]]) -> bool:\n",
|
|||
|
" return all(array[i][i] == 1 for i in range(max(len(array), len(array[0]))))\n",
|
|||
|
"\n",
|
|||
|
"\n",
|
|||
|
"reflexivity_check(array)"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "markdown",
|
|||
|
"id": "08976a67",
|
|||
|
"metadata": {},
|
|||
|
"source": [
|
|||
|
"Для проверки антирефлексивности необходимо проверить, что что элементы с i=j в отношении равны 0\n"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "code",
|
|||
|
"execution_count": 9,
|
|||
|
"id": "ab2ec981",
|
|||
|
"metadata": {},
|
|||
|
"outputs": [
|
|||
|
{
|
|||
|
"data": {
|
|||
|
"text/plain": [
|
|||
|
"False"
|
|||
|
]
|
|||
|
},
|
|||
|
"execution_count": 9,
|
|||
|
"metadata": {},
|
|||
|
"output_type": "execute_result"
|
|||
|
}
|
|||
|
],
|
|||
|
"source": [
|
|||
|
"# ваш код\n",
|
|||
|
"def antireflexivity_check(array: list[list[int]]) -> bool:\n",
|
|||
|
" return all(array[i][i] == 0 for i in range(max(len(array), len(array[0]))))\n",
|
|||
|
"\n",
|
|||
|
"\n",
|
|||
|
"antireflexivity_check(array)"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "markdown",
|
|||
|
"id": "7cbc0e84",
|
|||
|
"metadata": {},
|
|||
|
"source": [
|
|||
|
"Для проверки симметричности нужно проверить, что если в отношении i,j-ый элемент равен 1, то и j,i-ый элемент тоже равен единице\n"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "code",
|
|||
|
"execution_count": 6,
|
|||
|
"id": "434cfe13",
|
|||
|
"metadata": {},
|
|||
|
"outputs": [
|
|||
|
{
|
|||
|
"data": {
|
|||
|
"text/plain": [
|
|||
|
"False"
|
|||
|
]
|
|||
|
},
|
|||
|
"execution_count": 6,
|
|||
|
"metadata": {},
|
|||
|
"output_type": "execute_result"
|
|||
|
}
|
|||
|
],
|
|||
|
"source": [
|
|||
|
"# ваш код\n",
|
|||
|
"def symmetry_check(array: list[list[int]]) -> bool:\n",
|
|||
|
" return all(array[i][j] == array[j][i] for j in range(len(array[0])) for i in range(len(array)))\n",
|
|||
|
"\n",
|
|||
|
"\n",
|
|||
|
"symmetry_check(array)"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "markdown",
|
|||
|
"id": "a186d882",
|
|||
|
"metadata": {},
|
|||
|
"source": [
|
|||
|
"Для проверки антисимметричности нужно проверить, что если в отношении i,j-ый элемент равен единице, то и j,i-ый элемент равен нулю\n"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "code",
|
|||
|
"execution_count": 10,
|
|||
|
"id": "7727ec98",
|
|||
|
"metadata": {},
|
|||
|
"outputs": [
|
|||
|
{
|
|||
|
"data": {
|
|||
|
"text/plain": [
|
|||
|
"False"
|
|||
|
]
|
|||
|
},
|
|||
|
"execution_count": 10,
|
|||
|
"metadata": {},
|
|||
|
"output_type": "execute_result"
|
|||
|
}
|
|||
|
],
|
|||
|
"source": [
|
|||
|
"# ваш код\n",
|
|||
|
"def antisymmetry_check(array: list[list[int]]) -> bool:\n",
|
|||
|
" return all(array[i][j] != array[j][i] or i == j for j in range(len(array[0])) for i in range(len(array)))\n",
|
|||
|
"\n",
|
|||
|
"\n",
|
|||
|
"antisymmetry_check(array)"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "markdown",
|
|||
|
"id": "88678087",
|
|||
|
"metadata": {},
|
|||
|
"source": [
|
|||
|
"Для проверки транзитивности нужно проверить, что если i,j-ый и j,k-ый элементы принадлежат отношению, то и i,k-ый элемент тоже равен единице\n"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "code",
|
|||
|
"execution_count": 11,
|
|||
|
"id": "518a0e6c",
|
|||
|
"metadata": {},
|
|||
|
"outputs": [
|
|||
|
{
|
|||
|
"data": {
|
|||
|
"text/plain": [
|
|||
|
"True"
|
|||
|
]
|
|||
|
},
|
|||
|
"execution_count": 11,
|
|||
|
"metadata": {},
|
|||
|
"output_type": "execute_result"
|
|||
|
}
|
|||
|
],
|
|||
|
"source": [
|
|||
|
"# ваш код\n",
|
|||
|
"def transitivity_check(array: list[list[int]]) -> bool:\n",
|
|||
|
" x = len(array[0])\n",
|
|||
|
" y = len(array)\n",
|
|||
|
" for x_1 in range(x):\n",
|
|||
|
" for y_1 in range(y):\n",
|
|||
|
" for x_2 in range(x):\n",
|
|||
|
" if array[y_1][x_1] * array[x_1][x_2] and not array[y_1][x_2]:\n",
|
|||
|
" return False\n",
|
|||
|
" \n",
|
|||
|
" return True\n",
|
|||
|
"\n",
|
|||
|
"\n",
|
|||
|
"transitivity_check(array)"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "markdown",
|
|||
|
"id": "16f83129",
|
|||
|
"metadata": {},
|
|||
|
"source": [
|
|||
|
"### Множество всех подмножеств\n",
|
|||
|
"\n",
|
|||
|
"Алгоритм Грея генерирует последовательность всех подмножеств п-элементного множества, причём каждое следующее подмножество получается из предыдущего удалением или добавлением в точности одного элемента.\n"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "code",
|
|||
|
"execution_count": 21,
|
|||
|
"id": "f3f4a62f",
|
|||
|
"metadata": {},
|
|||
|
"outputs": [
|
|||
|
{
|
|||
|
"name": "stdout",
|
|||
|
"output_type": "stream",
|
|||
|
"text": [
|
|||
|
"\n",
|
|||
|
"Рефлективна - False\n",
|
|||
|
"Антирефлективна - False\n",
|
|||
|
"Симметрична - False\n",
|
|||
|
"Антисимметрична - False\n",
|
|||
|
"Транзитивна - True\n",
|
|||
|
"Замкнута - True\n",
|
|||
|
"\n"
|
|||
|
]
|
|||
|
}
|
|||
|
],
|
|||
|
"source": [
|
|||
|
"# ваш код\n",
|
|||
|
"def some_funtion(first_array: list[list[int]], second_array: list[list[int]]) -> list[list[int]]:\n",
|
|||
|
" if len(first_array) != len(second_array) or len(first_array[0]) != len(second_array[0]):\n",
|
|||
|
" return None\n",
|
|||
|
"\n",
|
|||
|
" x = len(first_array[0])\n",
|
|||
|
" y = len(first_array)\n",
|
|||
|
" new_matrix = [[0 for _ in range(x)] for _ in range(y)]\n",
|
|||
|
" \n",
|
|||
|
" for y_1 in range(y):\n",
|
|||
|
" for x_1 in range(x):\n",
|
|||
|
" for y_2 in range(y):\n",
|
|||
|
" new_matrix[y_1][x_1] = int(new_matrix[y_1][x_1] or\n",
|
|||
|
" first_array[y_1][y_2] * second_array[y_2][x_1])\n",
|
|||
|
" \n",
|
|||
|
" return new_matrix\n",
|
|||
|
"\n",
|
|||
|
"\n",
|
|||
|
"def some_function_check(array: list[list[int]]) -> bool:\n",
|
|||
|
" return some_funtion(some_funtion(array, array), array) == \\\n",
|
|||
|
" some_funtion(some_funtion(some_funtion(array, array), array), array)\n",
|
|||
|
"\n",
|
|||
|
"\n",
|
|||
|
"array = [[1, 1, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [1, 1, 0, 0]]\n",
|
|||
|
"\n",
|
|||
|
"print(f\"\"\"\n",
|
|||
|
"Рефлективна - {reflexivity_check(array)}\n",
|
|||
|
"Антирефлективна - {antireflexivity_check(array)}\n",
|
|||
|
"Симметрична - {symmetry_check(array)}\n",
|
|||
|
"Антисимметрична - {antisymmetry_check(array)}\n",
|
|||
|
"Транзитивна - {transitivity_check(array)}\n",
|
|||
|
"Замкнута - {some_function_check(array)}\n",
|
|||
|
"\"\"\")"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "markdown",
|
|||
|
"id": "dc2c6a7d",
|
|||
|
"metadata": {},
|
|||
|
"source": [
|
|||
|
"### Транзитивное замыкание\n"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "markdown",
|
|||
|
"id": "77642242",
|
|||
|
"metadata": {},
|
|||
|
"source": [
|
|||
|
"Транзитивное замыкание бинарного отношения, представленного в виде бинарной матрицы,\n",
|
|||
|
"представляет собой объединение положительных степеней (всех) исходного отношения\n"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "code",
|
|||
|
"execution_count": 24,
|
|||
|
"id": "7a3af8c2",
|
|||
|
"metadata": {},
|
|||
|
"outputs": [
|
|||
|
{
|
|||
|
"name": "stdout",
|
|||
|
"output_type": "stream",
|
|||
|
"text": [
|
|||
|
"[[0 0 1 0]\n",
|
|||
|
" [0 0 1 1]\n",
|
|||
|
" [1 0 0 0]\n",
|
|||
|
" [0 0 1 0]]\n"
|
|||
|
]
|
|||
|
}
|
|||
|
],
|
|||
|
"source": [
|
|||
|
"import numpy as np\n",
|
|||
|
"A = np.array([[0, 0, 1, 0],\n",
|
|||
|
" [0, 0, 1, 1],\n",
|
|||
|
" [1, 0, 0, 0],\n",
|
|||
|
" [0, 0, 1, 0]])\n",
|
|||
|
"print(A)"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "markdown",
|
|||
|
"id": "92d6fac0",
|
|||
|
"metadata": {},
|
|||
|
"source": [
|
|||
|
"Исходный алгоритм Уоршелла проще, поскольку он находит только транзитивное замыкание графа и не использует никакой информации о весах ребер. Алгоритм Флойда в основном является этим алгоритмом с дополнительными соображениями о таких весах. Алгоритм Флойда-Уоршалла решает проблему кратчайшего пути для всех пар. Соответственно, на вход алгоритма Флойда-Уоршалла нужно подавать взвешенноую матрицу бинарного отношения, в которой ненулевой элемент обозначает не только наличие отношения между i и j элементами, но и силу этой связи (выраженную положительным числом).\n"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "code",
|
|||
|
"execution_count": 21,
|
|||
|
"id": "f071103e",
|
|||
|
"metadata": {},
|
|||
|
"outputs": [],
|
|||
|
"source": [
|
|||
|
"def warshall(G):\n",
|
|||
|
" W = G\n",
|
|||
|
" n = len(G)\n",
|
|||
|
" for k in range(n):\n",
|
|||
|
" for i in range(n):\n",
|
|||
|
" for j in range(n):\n",
|
|||
|
" G[i, j] = G[i, j] or (G[i, k] and G[k, j])\n",
|
|||
|
" return W"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "code",
|
|||
|
"execution_count": 22,
|
|||
|
"id": "2c977eb9",
|
|||
|
"metadata": {},
|
|||
|
"outputs": [
|
|||
|
{
|
|||
|
"data": {
|
|||
|
"text/plain": [
|
|||
|
"array([[1, 0, 1, 0],\n",
|
|||
|
" [1, 0, 1, 1],\n",
|
|||
|
" [1, 0, 1, 0],\n",
|
|||
|
" [1, 0, 1, 0]])"
|
|||
|
]
|
|||
|
},
|
|||
|
"execution_count": 22,
|
|||
|
"metadata": {},
|
|||
|
"output_type": "execute_result"
|
|||
|
}
|
|||
|
],
|
|||
|
"source": [
|
|||
|
"warshall(A)"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "markdown",
|
|||
|
"id": "87b5bb3e",
|
|||
|
"metadata": {},
|
|||
|
"source": [
|
|||
|
"Так как транзитивное замыкание показывает, что если есть путь из i-ой вершины в k-ую и из k-ой вершины в j-ую, то есть путь и из i-ой вершины в j-ую. Соответственно сама матрица отношения это пути дляны 1, если мы строим композицию RR, то в итоге получаем наличие пути, длины 2, а если выполняем обычное возведение в степень, то за счет сложения будем видеть количество путей, длина которых соответствует степени.\n"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "code",
|
|||
|
"execution_count": 23,
|
|||
|
"id": "3a6c20c0",
|
|||
|
"metadata": {},
|
|||
|
"outputs": [
|
|||
|
{
|
|||
|
"data": {
|
|||
|
"text/plain": [
|
|||
|
"array([[2, 0, 3, 0],\n",
|
|||
|
" [4, 0, 5, 1],\n",
|
|||
|
" [3, 0, 2, 0],\n",
|
|||
|
" [2, 0, 3, 0]])"
|
|||
|
]
|
|||
|
},
|
|||
|
"execution_count": 23,
|
|||
|
"metadata": {},
|
|||
|
"output_type": "execute_result"
|
|||
|
}
|
|||
|
],
|
|||
|
"source": [
|
|||
|
"array_1 = ([[0, 0, 1, 0], [0, 0, 1, 1], [1, 0, 0, 0], [0, 0, 1, 0]])\n",
|
|||
|
"np.linalg.matrix_power(array_1, 1) + np.linalg.matrix_power(array_1, 2) + np.linalg.matrix_power(\n",
|
|||
|
" array_1, 3)+np.linalg.matrix_power(array_1, 4)+np.linalg.matrix_power(array_1, 5)"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "markdown",
|
|||
|
"id": "a52bca04",
|
|||
|
"metadata": {},
|
|||
|
"source": [
|
|||
|
"Поэтому встает закономерный вопрос, какой путь из предложенных будет иметь наименьшую длину?\n",
|
|||
|
"Ответ можно найти с помощью алгоритма Флойда-Уоршалла. Только зададим веса. Обратите внимание на нули, которые обозначают отсутствующие пути.\n"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "code",
|
|||
|
"execution_count": 43,
|
|||
|
"id": "dc53474a",
|
|||
|
"metadata": {},
|
|||
|
"outputs": [
|
|||
|
{
|
|||
|
"data": {
|
|||
|
"text/plain": [
|
|||
|
"array([[0, 3, 0, 7],\n",
|
|||
|
" [8, 0, 2, 0],\n",
|
|||
|
" [5, 0, 0, 1],\n",
|
|||
|
" [2, 0, 0, 0]])"
|
|||
|
]
|
|||
|
},
|
|||
|
"execution_count": 43,
|
|||
|
"metadata": {},
|
|||
|
"output_type": "execute_result"
|
|||
|
}
|
|||
|
],
|
|||
|
"source": [
|
|||
|
"# ваша матрица\n",
|
|||
|
"graph = np.array([\n",
|
|||
|
" [0, 3, 0, 7],\n",
|
|||
|
" [8, 0, 2, 0],\n",
|
|||
|
" [5, 0, 0, 1],\n",
|
|||
|
" [2, 0, 0, 0]\n",
|
|||
|
"])\n",
|
|||
|
"\n",
|
|||
|
"graph"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "code",
|
|||
|
"execution_count": 44,
|
|||
|
"id": "db277779",
|
|||
|
"metadata": {},
|
|||
|
"outputs": [
|
|||
|
{
|
|||
|
"data": {
|
|||
|
"text/plain": [
|
|||
|
"array([[0., 3., 5., 6.],\n",
|
|||
|
" [5., 0., 2., 3.],\n",
|
|||
|
" [3., 6., 0., 1.],\n",
|
|||
|
" [2., 5., 7., 0.]])"
|
|||
|
]
|
|||
|
},
|
|||
|
"execution_count": 44,
|
|||
|
"metadata": {},
|
|||
|
"output_type": "execute_result"
|
|||
|
}
|
|||
|
],
|
|||
|
"source": [
|
|||
|
"# ваш код\n",
|
|||
|
"def floyd_warshall(graph: np.ndarray) -> np.ndarray:\n",
|
|||
|
" num_vertices = len(graph)\n",
|
|||
|
" dist = np.array([[0 if i == j else graph[i][j] if graph[i][j] != 0 else np.inf for j in range(num_vertices)] for i in range(num_vertices)])\n",
|
|||
|
"\n",
|
|||
|
" for k in range(num_vertices):\n",
|
|||
|
" for i in range(num_vertices):\n",
|
|||
|
" for j in range(num_vertices):\n",
|
|||
|
" if dist[i][k] != np.inf and dist[k][j] != np.inf:\n",
|
|||
|
" dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j])\n",
|
|||
|
"\n",
|
|||
|
" return dist\n",
|
|||
|
"\n",
|
|||
|
"\n",
|
|||
|
"floyd_warshall(graph)"
|
|||
|
]
|
|||
|
}
|
|||
|
],
|
|||
|
"metadata": {
|
|||
|
"kernelspec": {
|
|||
|
"display_name": "Python 3 (ipykernel)",
|
|||
|
"language": "python",
|
|||
|
"name": "python3"
|
|||
|
},
|
|||
|
"language_info": {
|
|||
|
"codemirror_mode": {
|
|||
|
"name": "ipython",
|
|||
|
"version": 3
|
|||
|
},
|
|||
|
"file_extension": ".py",
|
|||
|
"mimetype": "text/x-python",
|
|||
|
"name": "python",
|
|||
|
"nbconvert_exporter": "python",
|
|||
|
"pygments_lexer": "ipython3",
|
|||
|
"version": "3.11.0"
|
|||
|
}
|
|||
|
},
|
|||
|
"nbformat": 4,
|
|||
|
"nbformat_minor": 5
|
|||
|
}
|