Блог пользователя Romka

Автор Romka, история, 7 лет назад, По-русски

Всем привет! :)

На случай, если вы пропустили рассылку, сообщаем, что сегодня в 10:00 UTC +3 стартовал второй раунд Оптимизационного трека. Как и первый раунд, он продлится 7 дней. Вам предложена одна задача, которая не предполагает наличие полного решения, но допускает множество подходов. По результатам двух раундов (смотрите раздел 3 в https://contest.yandex.ru/algorithm2018/rules/ — правила суммирования раундов одинаковы для алгоритмического и оптимизационного треков) будут определены победители трека и 128 будущих обладателей футболок с символикой конкурса.

Мы подготовили для вас задачу, которая симулирует работу поискового робота. Предлагаем вам ощутить на себе сложности индексации сайтов и постараться оптимизировать обход интернета — это всего лишь одна из задач, которую в Яндексе решают разработчики. Разумеется, задача была достаточно сильно упрощена, поскольку на её решение у вас всего неделя, но сможете ли вы научиться назначать сайты роботам достаточно оптимально?

Регистрация на конкурс еще открыта, так что всё в ваших руках — удачи!

  • Проголосовать: нравится
  • +66
  • Проголосовать: не нравится

»
7 лет назад, # |
Rev. 2   Проголосовать: нравится +25 Проголосовать: не нравится

Hi! When the final testing results are going to be published?

Also I really wonder what were the solutions that reach 8500+ on current standings. Could someone share one of those ideas, please?

Out of curiosity, one more question regarding the real-world application inspiration of the problem statement. I understand that it would make sense for robots to follow some kind of a repeating list of sites — to save memory, for example. However, why do robots' paths have to be cycles in the links graph and not just a repeating list of any sites, not necessary connected in a cycle?

  • »
    »
    7 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится

    Final standings are published!

  • »
    »
    7 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится

    Some 8300+ ideas:

    • 8150+: greedy solution constructing cycles one by one: pick starting site randomly and choose next site that has a topic with minimum current "score contribution" (*timeToIndex[site] / newsProb[site]). When I add a new site to a cycle I update scoreContribution(topic) += newsProb[site] / timeToIndex[site] for all topics published on that site. When there are enough (C = n/r/2) sites per cycle I use Dijkstra to finish the cycle (C doesn't seem to matter too much)

    • 8250+: repeat previous algorithm multiple times and pick the "best" solution. ("best" is not always the best because there is a lot of variance in the scores because of randomness)

    • 8300+: pick the topic TM with the lowest score and try the previous greedy algorithm ignoring TM (explanation: if a topic doesn't bring any points let the robots focus on other topics)

    • 8350: Fix one TLE by stopping slightly earlier :)

    I suspect one can get to 8500+ by speeding up the simulation step (currently only 10-30 random starting points can be tested because of slow list/sort/vector operations) and using an incremental approach where some sites are added only if they increase the overall score.

»
7 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится

If I didn't miss anything you can see your final score in your last submission before results will be published

  • »
    »
    7 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится

    Nice hacker skills! That's not the final scoreboard, but it's something.

    Now I know that my solution has Runtime Error only on 1 test out of 500. I guess I got that going for me which is nice. :D

»
7 лет назад, # |
  Проголосовать: нравится +22 Проголосовать: не нравится

Общая схема

Для начала заметим, что в 1/8 случаев робот всего один, поэтому научиться генерировать хотя бы один хороший цикл всё равно придётся. После того, как это сделано, оказывается, что неплохо работает Hill Climbing, на каждом шаге пытающийся обновить ответ, заменив произвольный цикл на случайно сгенерированный. Кроме этого, оказывается, что более сложные подходы, например отжиг вместо HC или попытка как-то достраивать имеющееся решение, работают плохо.

Генерация циклов

Это основная часть решения. От качества эвристики при генерации циклов зависит практически всё (скорость генерации и оценивания имеет гораздо меньший эффект, например). На среднего размера тесте HC у меня делает пару десятков обновлений ответа на несколько десятков тысяч итераций, т.е. мы ищем иголку в стоге сена, и направленность поиска предельно важна.

Будем каждый раз возвращать случайный цикл из какого-то контролируемого эвристиками распределения. Цикл генерируется без оглядки на уже имеющиеся, на количество роботов и на предыдущие попытки. Всё взаимодействие между роботами таким образом перекидывается на функцию оценки решения, а на этапе генерации можно считать, что робот один.

Цикл можно генерировать так: стартовав из случайной вершины, каждый раз переходить жадно в лучшую по набору параметров. Получится путь, из которого потом можно выбрать две случайных вершины u и v, взяв в ответ подпуть от u до v, если есть ссылка . Если её нет, можно выбрать другие случайные вершины. Необязательно делать так, чтобы u совпадала с началом пути. Одной и той же вершине можно запрещать появляться в пути дважды, а можно не запрещать. Это практически не влияет на результат.

Теперь об упомянутом "наборе параметров".

  • Путь нужно ограничивать по глубине каким-то небольшим числом, возможно, зависящим от количества тем в тесте.
  • Для начала заметим, что хорошая идея — идти жадно в сайт s с минимальным значением либо какой-то другой функции, возрастающей по indexingTime и убывающей по prob. Это даёт примерно 7700 очков.
  • Но всё время так делать нельзя, поскольку может оказаться, что робот индексирует новости по одним и тем же темам, которым повезло оказаться на хороших сайтах, когда на самом деле иногда нужно заходить и на плохие сайты за редкими темами. Здесь помогает просто поддерживание набора тем, которые ещё ни разу не индексировались. При этом не рассматриваются сайты, которые не увеличивают этот набор (пока он не состоит из всех тем). С этой эвристикой получаем уже 8200.
  • Предыдущее замечание можно сделать более количественным. Запомним для каждой темы, когда она индексировалась последний раз с точки зрения текущего пути, и разобьём оценку сайта на две составляющие — одна собственно о сайте (статическая, независящая от пути), другая о темах на нём (динамическая), и будем их комбинировать. Для динамической также полезно заметить, что какие-то темы есть на большом количестве сайтов, а какие-то — нет. Для этого можно посмотреть в код генератора, например. С такой эвристикой можно набрать около 8500. Ещё 150 очков добираются подкручиванием параметров и выбором различных монотонных функций вместо линейных.

Оценка решения

Лучше всего работает метод Монте-Карло, т.е. переписывание кода из чекера.

  • Вместо того, чтобы каждый раз заново генерировать новости, это можно сделать в самом начале один раз, раскидав все новостные события по их сайтам.
  • Код из условия можно существенно ускорить, переписав всё на связные списки. Итоговая сложность получается линейной по количеству событий и времени симуляции.
  • Как ни странно, с временем симуляции тоже лучше не играться, а брать именно то, которое дано в тесте.
  • Лучшее решение согласно этой функции оценки может оказаться в итоге не лучшим, т.к. в итоговой симуляции новости разлетятся по сайтам по-другому. С этим ничего не поделаешь, и остаётся надеяться на лучший в среднем результат. Повторение симуляции с разными распределениями новостей не помогает, попытка увеличить приоритет для сайтов с большими вероятностями, чтобы меньше зависеть от этого фактора, тоже не помогает.

Что ещё не работает

Вот ещё несколько идей, которые мне не удалось использовать для улучшения счёта.

  • На большинстве сайтов на самом деле ровно одна тема.
  • В том числе из-за ограничения путей по глубине, большинство сайтов оказываются вообще бесполезными.
  • Можно учитывать в качестве фактора популярности темы не просто количество сайтов, на которых она присутствует, а количество сайтов с этой темой, которые уже обходятся роботами из текущего решения.
  • Можно одновременно строить несколько циклов, но здесь оказывается очень сложно синхронизировать локальные часы роботов, чтобы понимать, как часто в среднем индексируются редкие темы.