{"id":15797522,"url":"https://github.com/pavlovdog/algorithms_part_2","last_synced_at":"2025-03-31T19:44:15.830Z","repository":{"id":94100790,"uuid":"71608167","full_name":"pavlovdog/Algorithms_part_2","owner":"pavlovdog","description":null,"archived":false,"fork":false,"pushed_at":"2016-10-22T20:48:44.000Z","size":1650,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2024-10-12T00:34:13.171Z","etag":null,"topics":["algorithm","graph","python"],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/pavlovdog.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2016-10-22T01:03:06.000Z","updated_at":"2016-10-22T01:04:09.000Z","dependencies_parsed_at":"2023-03-13T17:07:34.810Z","dependency_job_id":null,"html_url":"https://github.com/pavlovdog/Algorithms_part_2","commit_stats":{"total_commits":38,"total_committers":2,"mean_commits":19.0,"dds":0.2894736842105263,"last_synced_commit":"26281ad54920c840247b132152c9f7497924953d"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pavlovdog%2FAlgorithms_part_2","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pavlovdog%2FAlgorithms_part_2/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pavlovdog%2FAlgorithms_part_2/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pavlovdog%2FAlgorithms_part_2/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pavlovdog","download_url":"https://codeload.github.com/pavlovdog/Algorithms_part_2/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246531986,"owners_count":20792735,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["algorithm","graph","python"],"created_at":"2024-10-05T00:09:28.154Z","updated_at":"2025-03-31T19:44:15.811Z","avatar_url":"https://github.com/pavlovdog.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Второе домашнее задание\r\n### Потехин Сергей, 156 группа\r\n\r\n## Структура репозитория\r\n+ profiler - самописная утилита для тестирования производительности\r\n+ samples - наборы данных для запуска программ\r\n+ profiler.first.csv (profiler.second.csv) - таблица с результатами тестирования для первого (второго) пункта\r\n+ source.first.cpp (source.second.cpp) - исходники для первого (второго) пункта\r\n+ x.first (x.second) - исполняемые файлы для первого (второго) пункта\r\n+ plot.first.py (plot.second.py) - скрипт для отрисовки данных из profiler.first.csv (profiler.second.csv)\r\n\r\n## Первый пункт\r\n\r\n### Код\r\nИспользуем vector used_nodes для хранения уже посещенных вершин и vector answer для хранения ребер финального паросочетания. После ввода, будем просто идти по списку ребер и если вершин из этого ребра нет в used, то добавим ребро в answer, а вершины ребра в used. Ответом будет answer.\r\n\r\nP.S. В первом и втором пункте ввод реализован через std::cin, для быстрого ввода файла можно использовать\r\n```bash\r\ncat data.example | ./x.first\r\n```\r\n\r\n### Ассимптотика\r\nБудем считать, что вершин у нас x, а ребер - y. Тогда:\r\n\r\n1. Считать x и y \u003cb\u003eO(1)\u003c/b\u003e\r\n2. m раз считать ребро и добавить его в vector \u003cb\u003eO(m)\u003c/b\u003e\r\n3. Инициализируем вектор использованных вершин \u003cb\u003eO(n)\u003c/b\u003e\r\n4. Идем по списку ребер \u003cb\u003eO(m)\u003c/b\u003e\r\n5. Проверяем начало и конец ребра на наличие в used_nodes \u003cb\u003eO(1)\u003c/b\u003e\r\n6. Добавляем ребро в answer, а вершины в used \u003cb\u003eO(1)\u003c/b\u003e\r\n\r\nИтог: \u003cb\u003eO(m + n)\u003c/b\u003e\r\n\r\n### Доказательство\r\nПусть есть паросочетание, найденное нашим алгоритмом (А), и оптимальное паросочетание (Б) - сравним их. Возьмем какое-то ребро из А - оно может либо совпадать с каким-то ребром из Б (неинтересно), либо пересекаться с пересекаться к какими-то ребрами из Б.\r\n\r\n1. Ребро может пересечься с одним ребром из Б (a.б)\r\n2. Ребро может пересечься с двумя ребрами из Б (б.а.б)\r\n\r\nЗаметим, что ребро из А не может пересекаться с тремя и более ребрами из Б, тк тогда в Б присутствуют пересекающиеся ребра, что противоречит определению паросочетания. Следовательно, каждому ребру из А, можно поставить в соответствие максимум два ребра из Б, следовательно - Б больше чем А максимум в два раза.\r\n\r\n### График зависимости времени работы (Y) от числа ребер (Х) при фиксированном числе вершин\r\nДля графика использовался набор данных, полученных в результате тестирования командой (работает несколько минут, ~5000 тестов). Описание профайлера дано внизу страницы.\r\n```bash\r\n$ ./profiler --first True --nodes 100 100 --edges 10 5000\r\n```\r\n\r\nВидно, что за исключением несольких аномальных точек, время работы зависит линейно от числа ребер. График также соответствует найденной ассимптотике.\r\n\r\n![first](https://github.com/pavlovdog/Algorithms_part_2/blob/master/first.plot.png \"First plot\")\r\n\r\n## Второй пункт\r\n\r\n### Код\r\n\u003cb\u003eОбщая идея\u003c/b\u003e - пройдем через список всех вершин (= строк). На каждой итерации будем смотреть, были ли мы уже в данной вершине и если нет - это значит, что мы нашли новый кластер. В этом случае увеличиваем число кластеров на 1 и запускаем BFS из этой вершины чтобы найти все оставшиеся вершины этого кластера и пометить их, как использованные.\r\n\r\n\u003cb\u003eРеализация\u003c/b\u003e - заведем set \u003cb\u003eraws\u003c/b\u003e для хранения вершин графа. В нашем случае вершина - это то же самое что строка. Также заведем map \u003cb\u003eused_raws\u003c/b\u003e, где для каждой вершины будем отмечать, были ли мы уже в этой вершине. После ввода данных будем итерироваться по \u003cb\u003eraws\u003c/b\u003e и смотреть, отмечена ли эта вершина в \u003cb\u003eused_raws\u003c/b\u003e, как уже посещенная. Если нет - увеличиваем счетчик кластеров \u003cb\u003eclusters\u003c/b\u003e на 1 и запускаем \u003cb\u003eBFS\u003c/b\u003e от этой вершины. Внутри \u003cb\u003eBFS\u003c/b\u003e мы отмечаем выбранную вершину как посещенную и начинаем искать ее соседей. Согласно условию - ее соседом будет строка, которая отличается от нашей на 1 или 2 символа. Будем искать соседей простым перебором. Будем перебирать все варианты нашей строки, измененной в одной или двух позициях сразу, и, если такая строка существует в \u003cb\u003eraws\u003c/b\u003e и еще не посещена - запустим \u003cb\u003eBFS\u003c/b\u003e от нее.\r\n\r\n### Ассимптотика\r\n\r\n1. Ввод данных. n строк, операция вставки в set и вставки в map занимает logn - \u003cb\u003eO(n*logn)\u003c/b\u003e\r\n2. Итерируемся по raws и проверяем на значение в map \u003cb\u003e(logn)\u003c/b\u003e\r\n3. Перебор всех возможных значений новых строк внутри BFS занимает O(m^2) (два вложенных цикла длиной m), генерация новой строки проиходит за O(1)\r\n4. Проверка на вхождение новой строки в set занимает O(m)*O(logn). \r\n5. Следовательно BFS имееет сложность \u003cb\u003eO(m^3 * logn)\u003c/b\u003e\r\n6. Максимум можно вызвать BFS n раз (т.к. после каждого вызова вершина будет добавляться в уже использованные).\r\n\r\nСледовательно \u003cb\u003eO(n*m^3*logn)\u003c/b\u003e\r\n\r\n### График зависимости времени работы (Y) от числа строк (X) при фиксированной длине строки\r\n![second](https://github.com/pavlovdog/Algorithms_part_2/blob/master/second.plot.png \"Second plot\")\r\n\r\nОпять же видно, что найденная ассимптотика подходит под график.\r\n\r\n## Профайлинг\r\nПрофайлер написан на Python 2.7, для корректной работы необходимо установить несколько библиотек.\r\n```bash\r\n$ sudo pip install pandas termcolor\r\n$ ./profiler --help\r\nusage: profiler [-h] [--first FIRST] [--second SECOND]\r\n                [--nodes NODES [NODES ...]] [--edges EDGES [EDGES ...]]\r\n                [--raws RAWS [RAWS ...]] [--lenght LENGHT [LENGHT ...]]\r\n\r\nProfiler for HW, part 2. Profiler works good right out of the box, so just\r\ntype \"./profiler --first True -- second True\"\r\n\r\noptional arguments:\r\n  -h, --help            \t\tshow this help message and exit\r\n  --first FIRST         \t\tProfile first problem; default = False\r\n  --second SECOND       \t\tProfile second problem; default = False\r\n  --nodes NODES [NODES ...]\t\tNodes range for the first problem; default = 10 15\r\n  --edges EDGES [EDGES ...]\t\tEdges range for the first problem; default = 20 25\r\n  --raws RAWS [RAWS ...]\t\tNumber of raws range for the second problem; default = 100 110\r\n  --lenght LENGHT [LENGHT ...]\tRaw's lenght for the second problem; default = 10 15\r\n```\r\nВ принципе все неплохо работает на дефолтных настройках, достаточно запустить\r\n```bash\r\n$ ./profiler --first True --second True\r\n```\r\nНо при желании можно изменить параметры, в --help все достаточно подробно описано. Отчеты в репозитории созданы командой (работает долго, 1600 и 2000 тестов соответственно)\r\n```bash\r\n$ ./profiler --first True --second True --nodes 10 30 --edges 20 100 --raws 100 300 --lenght 10 20\r\n```\r\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpavlovdog%2Falgorithms_part_2","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpavlovdog%2Falgorithms_part_2","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpavlovdog%2Falgorithms_part_2/lists"}