#prog #article
Статья о PubGrub — алгоритме разрешения ограничений, который используется в
pub — пакетном менеджере для Dart — для выбора версий зависимостей.
Во главе алгоритма лежит идея
несовместимостей (
incompatibilities) — набор ограничений на версии, которые не могут быть удовлетворены все одновременно. Замечательной особенностью несовместимостей является то, что они являются фактами конкретного набора ограничений: неважно, какие именно версии будут выбраны в процессе разрешения зависимостей, они не могут инвалидировать уже обнаруженные несовместимости.
Алгоритм состоит из двух частей: unit propagation и decision making (
нет, я не смог придумать перевода, который бы звучал не коряво). Unit propagation анализирует несовместимости и выводит конкретные факты (то бишь ограничение на версии), которые должны быть справедливы при текущем выборе версий. Так как эти факты зависят от принятых решений, в базу знаний они добавляются не напрямую, а в виде несовместимостей. Эта фаза продолжается до тех пор, пока получение новых фактов возможно.
Вторая фаза, decision making, вступает в силу, если unit propagation закончил работу, но в отношении конкретных выбранных версий ещё осталась неопределённость. Алгоритм
пробует одну из возможных альтернатив для выбора версии и пытается вывести версии, исходя из этого решения. Важным тут является то, что когда выбор альтернативы приводит к конфликту ограничений, этот факт записывается в базу знаний в виде несовместимости. Это позволяет не терять полученную информацию и и использовать её при выборе альтернатив, существенно снижая список альтернатив для проб за счёт пропуска диапазонов версий, которые заведомо не приведут к решению.
Так как несовместимости могут выводиться из других несовместимостей, их набор представляет собой не просто множество, а направленный ациклический граф (DAG), где направленные рёбра являются логической импликацией. Само по себе это не влияет на работу алгоритма, но позволяет серьёзно улучшить диагностику для случаев, когда набор ограничений на версии несовместим: вместо того, чтобы просто сказать "я не могу, у меня лапки", PubGrub показывает пошаговое объяснение, почему выбрать удовлетворяющий ограничениям набор версий зависимостей не удалось.
P. S.: не смотря на мои объяснения, советую прочитать оригинальную статью: мало того, что я мог понять что-то неправильно, так ещё и там работа алгоритма демонстрируется на наглядном конкретном примере.