\Title{Гудов Д.О.}{Исследование алгоритма разрешения зависимостей в ALT RPM} \section*{Введение} Одной из задач пакетного менеджера является проверка совместимости устанавливаемого программного обеспечения с уже имеющимися или одновременно устанавливаемыми библиотеками. Традиционная зависимость от имени библиотеки и номера её версии не всегда достаточна: отдельный экспортируемый символ может быть удалён без изменения SONAME, а библиотеки с одинаковым SONAME могут предоставлять различные программные интерфейсы. В результате формально удовлетворённая зависимость от версии ещё не гарантирует, что динамический загрузчик найдёт все символы, необходимые программе. В ALT RPM эта задача решается при помощи специальных версий зависимостей вида \texttt{set:} [\Ref{SETC}]. Для отношения \texttt{Provides} такая строка описывает множество символов, экспортируемых библиотекой, а для отношения \texttt{Requires} --- символы, требуемые программой от конкретной библиотеки. При проверке зависимости обычное сравнение версий заменяется проверкой включения множеств. Полные имена символов при этом не сохраняются: они заменяются усечёнными хеш-значениями, сортируются и кодируются в компактную строку, допустимую как версия RPM. Цель настоящей работы --- исследовать алгоритм построения и сравнения \texttt{set:}-строк, оценить вероятностные свойства хэша и вычислительную сложность алгоритма, а также определить направления оптимизации реализации. %% В первых разделах формализуется решаемая задача, рассматриваются реальные данные репозитория Sisyphus, формат строки и путь её построения в исходной реализации \texttt{lib/set.c}. \section{Постановка задачи и данные ALT Linux} \label{PROBLEM} Пусть $P$ --- множество символов, предоставляемых библиотекой, а $R$ --- множество символов, требуемых от неё программой. Обозначим $p=|P|$ и $r=|R|$. Зависимость выполнима тогда и только тогда, когда \[ R\subseteq P. \] Списки символов формируются механизмом автоматического определения зависимостей \texttt{rpm-build}. Для \texttt{Provides} из динамической таблицы библиотеки выбираются доступные извне определённые символы. Для \texttt{Requires} утилита \texttt{ldd --bindings} устанавливает соответствие между требуемым символом и конкретной библиотекой-поставщиком; слабые неопределённые символы исключаются. Таким образом, одна строка \texttt{Requires} содержит только множество, связанное с данным поставщиком. Явное хранение имён увеличивало бы RPM-метаданные пропорционально их суммарной длине. Поэтому используется усечённая хеш-функция c целым $b$, называемого в реализации \texttt{bpp}, \[ h_b(x)=h_{32}(x)\bmod 2^b, \qquad H_b(S)=\{h_b(x)\mid x\in S\}, \] где $h_{32}$ --- 32-битная функция Jenkins one-at-a-time. Фактически \texttt{lib/set.c} проверяет условие \[ H_b(R)\subseteq H_b(P). \] Такое представление сохраняет включение: из $R\subseteq P$ следует $H_b(R)\subseteq H_b(P)$. Следовательно, коллизия хешей не создаёт ложного отказа для корректной зависимости. Обратное утверждение неверно: отсутствующий символ из $R\setminus P$ может получить то же усечённое значение, что и один из символов $P$, и привести к ложному принятию зависимости. Тем самым предоставляемая гарантия имеет вероятностный характер. Для оценки реальной нагрузки был исследован срез репозитория Sisyphus для архитектур \texttt{x86\_64} и \texttt{noarch}. Объём рассмотренных метаданных на момент 2026-08-20 приведён в табл.~\Ref{CORPUS}. \begin{table}[H] \begin{center} \caption{\label{CORPUS}Объём исследованного среза Sisyphus} \small \begin{tabular}{|l|r|} \hline Объект & Количество \\ \hline Пакеты & 47\,654 \\ \hline Отношения \texttt{Provides} с \texttt{set:}-версией & 14\,859 \\ \hline Отношения \texttt{Requires} с \texttt{set:}-версией & 69\,153 \\ \hline Сопоставленные пары $P,R$ & 68\,492 \\ \hline \end{tabular} \end{center} \end{table} 661 отношений удовлетворены обычным неверсионированным \texttt{Provides}. Для каждой сопоставленной пары декодировались мощности множеств $p$ и $r$, а также вычислялось индивидуальное отношение $p/r$. Квантили этих величин показаны в табл.~\Ref{CARDINALITIES}. Квантили отношения вычислялись непосредственно по парам. \begin{table}[H] \begin{center} \caption{\label{CARDINALITIES}Мощности множеств в парах \texttt{Provides}/\texttt{Requires}} \small \begin{tabular}{|c|r|r|r|} \hline Квантиль & $p$ & $r$ & $p/r$ \\ \hline 0,50 & 480 & 13 & 28,1 \\ \hline 0,75 & 1\,886 & 37 & 80 \\ \hline 0,90 & 6\,219 & 104 & 257 \\ \hline \end{tabular} \end{center} \end{table} В 92,4\% сопоставленных пар выполняется $p/r\geq 4$. Следовательно, типичный проверяемый набор требований существенно разрежен относительно множества предоставляемых символов. Это наблюдение важно для алгоритма сравнения: последовательный симметричный просмотр двух массивов не всегда использует характерное различие их мощностей. \section{Устройство существующей \texttt{set:}-строки} \label{FORMAT} Построение \texttt{set:}-строки выполняется как последовательность преобразований \[ \begin{aligned} \text{имена символов} &\longrightarrow \text{усечённые хеши} \longrightarrow \text{сортировка},\\ &\longrightarrow \text{удаление повторов и вычисление дельт},\\ &\longrightarrow \text{код Голомба--Райса} \longrightarrow \text{Base62-представление}. \end{aligned} \] Итоговая версия имеет вид \[ \texttt{set:}\langle b\rangle\langle m\rangle\langle payload\rangle. \] Префикс \texttt{set:} распознаётся RPM как признак специальной версии. Следующие два символа кодируют параметры $b=\texttt{bpp}$ и $m=\texttt{Mshift}$ по правилу $c=v-7+\texttt{'a'}$. Допустимы $10\leq b\leq32$, $7\leq m\leq31$ и $m0)=1-\prod_{i=0}^{n-1}\left(1-\frac{i}{2^b}\right) \approx 1-\exp\left(-\frac{n(n-1)}{2^{b+1}}\right). \] Эти выражения являются модельными: Jenkins OAAT не является случайным оракулом, поэтому окончательная оценка должна дополняться измерением коллизий на реальном корпусе символов. Эвристическую верхнюю оценку ложного принятия при $k=|R\setminus P|$ отсутствующих символов можно записать как \[ \Pr\bigl(H_b(R)\subseteq H_b(P)\mid R\nsubseteq P\bigr) \lesssim \left(\frac{|H_b(P)|}{2^b}\right)^k. \] Увеличение $b$ снижает вероятность ошибки, но увеличивает кодируемые значения и длину строки. Поэтому выбор \texttt{bpp} представляет собой компромисс между компактностью метаданных и риском коллизий; при формировании \texttt{set:}-строки для \texttt{Requires} набора используется точность, определённая по числу символов соответствующего \texttt{Provides}, а не по обычно намного меньшему числу требований. \subsection{Кодирование Голомба--Райса} После сортировки уникальных значений \[ 0\leq x_1