Оглавление

Введение

Представьте типичный понедельник в отделе закупок производственного предприятия. Пришло пять коммерческих предложений на одну и ту же позицию – допустим, нужен стандартный компонент, который регулярно идёт в производство. Менеджер открывает таблицу, смотрит на столбец «Цена за штуку» и выбирает минимум. Это занимает десять минут. Решение кажется очевидным.

Через три недели выясняется, что на складе лежит втрое больше компонентов, чем нужно. Поставщик с самой низкой ценой работает только от крупной партии, а об этом менеджер не подумал, когда смотрел на цифру за штуку. Деньги заморожены на складе. Оборотные средства иммобилизованы. Реальная стоимость единицы нужного товара оказалась не самой низкой, а самой высокой среди всех предложений.

И это не исключение – это норма для большинства предприятий, где выбор поставщика до сих пор делается вручную, на глазок, без формализованной процедуры. Хуже того: даже если менеджер учитывает партионность, он всё равно не учитывает историю взаимодействия – сколько раз поставщик привозил вовремя, сколько раз приходилось оформлять рекламацию. Эта информация хранится в ERP-системе, но почти никогда не используется для принятия решений.

В этой статье мы разберём математическую модель, которая закрывает оба пробела. Три критерия – приведённая стоимость закупки с учётом минимальной партии, срок поставки и интегральный уровень доверия к поставщику, вычисленный из данных ERP. Один алгоритм, реализованный в Engee на языке Julia. И числовой пример, где поставщик с самой низкой каталожной ценой закономерно оказывается наихудшим выбором – а модель это выявляет автоматически.

В чём на самом деле проблема?

Задача выбора поставщика принадлежит к классу задач многокритериального принятия решений – MCDM (Multi-Criteria Decision Making). Это означает, что у каждого поставщика есть несколько характеристик, которые важны одновременно и между которыми нет однозначного доминирования: один дешевле, другой быстрее, третий надёжнее. Нужно как-то привести всё это к единому числу и выбрать лучшего.

На большинстве отечественных предприятий эту задачу решают одним из двух способов. Первый – выбрать по минимальной цене и не думать о прочих критериях. Второй – положиться на опыт менеджера, который «знает» поставщиков. Оба подхода дают систематические ошибки.

Ошибка первая: каталожная цена не равна реальной стоимости закупки. Почти каждый поставщик работает с минимальной партией – MOQ (Minimum Order Quantity). Если вам нужно 30 единиц, а минимальная партия – 100, вы платите за 100. Реальная стоимость единицы нужного вам товара – это каталожная цена, умноженная на отношение партии к потребности. Поставщик с ценой 95 руб/шт при MOQ = 100 шт обходится дороже поставщика с ценой 110 руб/шт при MOQ = 25 шт, если вам нужно 30 штук. Это простая арифметика, которую тем не менее игнорируют повсеместно.

Ошибка вторая: надёжность поставщика – субъективная величина. Одни менеджеры помнят инциденты, другие забывают. При смене сотрудника накопленные неформальные знания о поставщиках исчезают вместе с ним. При этом ERP-система хранит полный журнал закупочных операций: дата заказа, дата фактической поставки, наличие рекламаций, причины возвратов. Из этих данных можно автоматически вычислить объективный показатель надёжности каждого поставщика – и обновлять его после каждой новой поставки. Но в большинстве случаев эта статистика просто не используется.

Ошибка третья: отсутствие формализованной и воспроизводимой процедуры. Если решение зависит от конкретного человека, оно непрозрачно, невоспроизводимо и создаёт почву для злоупотреблений. Формализованная модель с явными критериями и проверяемыми весами – это не только инструмент оптимизации, но и элемент управленческой прозрачности.

Именно на устранение этих трёх ошибок направлена модель, которую мы разберём ниже.

Немного истории: от интуиции к формализации

Задача выбора поставщика существует столько же, сколько существует торговля. Но академическая история её формализации началась сравнительно недавно.

В 1966 году американский исследователь Гэри Диксон опубликовал первую систематическую работу по критериям выбора поставщика. Он опросил 273 менеджера по закупкам из разных отраслей и выявил 23 критерия, которые те реально используют при оценке контрагентов. Цена, качество и надёжность поставок ожидаемо оказались в тройке лидеров. Однако Диксон зафиксировал нечто важное: качество и надёжность поставщика менеджеры называли важнее цены – хотя на практике именно цена почти всегда оказывалась единственным реально используемым критерием. Разрыв между декларируемыми приоритетами и реальными решениями был очевиден уже тогда.

В 1980 году математик Томас Саати предложил инструмент, которого не хватало для решения задач подобного класса, метод анализа иерархий (AHP, Analytic Hierarchy Process). Его идея проста и элегантна: вместо того чтобы напрямую спрашивать эксперта «насколько важна цена?» (на что невозможно дать содержательный ответ), спросить его попарно: «что важнее – цена или срок, и во сколько раз?». Из матрицы таких парных сравнений математически выводятся веса критериев, а согласованность суждений эксперта проверяется количественно. Несогласованный эксперт – тот, кто говорит, что А важнее Б, Б важнее В, но В важнее А – выявляется автоматически. Это принципиально: хорошая модель не должна молча принимать противоречивые суждения.

Рисунок 1 – Здислав Павлак
Рисунок 1 – Томас Саати

Параллельно развивались другие подходы. В 1981 году появился метод TOPSIS – выбор альтернативы, ближайшей к идеальному и наиболее удалённой от антиидеального решения.

В 1960-е –1970-е Лотфи Заде заложил основы теории нечётких множеств, которая позволила работать с лингвистическими оценками вроде «поставщик достаточно надёжен» и переводить их в числа.

К 2010-м годам число публикаций по теме выбора поставщика исчислялось тысячами. Обзорная работа систематизировала более 60 методов и их комбинаций. Но при всём богатстве академического арсенала два практических пробела оставались незакрытыми: MOQ по-прежнему трактовался как бинарный фильтр, а не как экономический критерий, а статистика ERP-систем о реальном поведении поставщиков в расчётах почти не использовалась.

Именно эти два пробела и закрывает модель, которую мы разберём дальше.

Постановка задачи

Пусть отдел закупок сформировал запрос на приобретение Q единиц некоторого товара и получил n коммерческих предложений от поставщиков.

S = \{s_1,\, s_2,\, \ldots,\, s_n\}

Каждый поставщик s_i описывается вектором характеристик:

s_i = \bigl(c_i,\; m_i,\; t_i,\; N_i,\; N_i^t,\; N_i^q\bigr)

гдеc_i – каталожная цена единицы товара, руб./шт.;
m_i – минимальная партия поставки (MOQ), шт.;
t_i – срок поставки, рабочих дней;
N_i – общее число ранее выполненных заказов согласно данным ERP;
N_i^t – число заказов, выполненных в срок;
N_i^q – число заказов без рекламаций по качеству.

Требуется найти поставщика t_i, оптимального по совокупности трёх критериев: приведённой стоимости закупки, сроку поставки и уровню доверия.

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

Математическая модель

Блок 1. Приведённая цена с учётом MOQ

Это ключевое нововведение модели. Поставщик s_i может отгрузить не менее m_i единиц, поэтому реальный объём закупки составит:

Q_i^{real} = \max\!\bigl(Q,\; m_i\bigr)

Если m_i \leq Q – предприятие берёт ровно сколько нужно. Если m_i > Q – приходится брать лишнее. Чтобы корректно сравнивать поставщиков с разными условиями партионности, вводится приведённая цена – фактические затраты на единицу действительно нужного товара:

c_i^{real} = c_i \cdot \frac{\max(Q,\, m_i)}{Q}

Развёрнуто по случаям:

c_i^{real} = \begin{cases} c_i,  m_i \leq Q ;\\ \displaystyle c_i \cdot \frac{m_i}{Q}, m_i > Q \end{cases}

Когда m_i > Q, предприятие вынуждено приобрести \Delta_i = m_i - Q лишних единиц. Их стоимость c_i \cdot \Delta_i – это деньги, замороженные на складе. Именно они превращают «самого дешёвого» поставщика в самого дорогого.

Дополнительно вводится пороговый коэффициент \alpha \geq 1, определяющий максимально допустимое превышение объёма закупки над потребностью. Поставщики, нарушающие это ограничение, исключаются из рассмотрения:

S^* = \left\{s_i \in S \;\middle|\; \frac{\max(Q,\, m_i)}{Q} \leq \alpha\right\}

Это допустимое множество поставщиков. Дальнейшая работа ведётся только с ним.

Блок 2. Интегральный уровень доверия

Цена и срок поставки – это намерения поставщика. Уровень доверия – это оценка его способности эти намерения реализовать, вычисленная по реальной истории взаимодействия.

Из данных ERP-системы для каждого поставщика извлекаются два частных показателя надёжности.

Доля заказов, выполненных в срок:

p_i^t = \frac{N_i^t}{N_i} \in [0,\,1]

Доля заказов без рекламаций по качеству:

p_i^q = \frac{N_i^q}{N_i} \in [0,\,1]

Интегральный уровень доверия – взвешенная сумма:

r_i = \beta_1\, p_i^t + \beta_2\, p_i^q, \qquad \beta_1 + \beta_2 = 1,\quad \beta_j > 0

Если поставщик новый и история взаимодействия отсутствует (N_i = 0), ему присваивается нейтральный балл:

r_i = r_0 = 0{,}5

Это разумное решение: новый контрагент не наказывается за отсутствие истории, но и не получает незаслуженного преимущества.

Остаётся открытым вопрос о весах \beta_1 и \beta_2. Их произвольное назначение лишило бы показатель объективности. Применяется двухэтапная процедура.

Шаг первый экспертное соотношение. Эксперт указывает, во сколько раз своевременность важнее качества: «показатель p_i^t важнее p_i^q в p раз». Из условия нормировки:

\beta_1^{exp} = \frac{p}{1+p}, \qquad \beta_2^{exp} = \frac{1}{1+p}

Шаг второй объективные веса методом энтропии Шеннона. По накопленной статистике n поставщиков вычисляются нормированные значения:

p_{ij} = \frac{x_{ij}}{\displaystyle\sum_{l=1}^{n} x_{lj}}, \qquad x_{i1} = p_i^t,\quad x_{i2} = p_i^q

Энтропия j-го показателя:

H_j = -\frac{1}{\ln n}\sum_{i=1}^{n} p_{ij}\ln p_{ij}

Показатель с высокой энтропией – тот, по которому поставщики почти одинаковы – несёт мало информации и получает меньший вес. Объективные веса:

\beta_j^{ent} = \frac{1 - H_j}{\left(1-H_1\right)+\left(1-H_2\right)}

Комбинированные веса объединяют экспертное знание с данными статистики:

\beta_j = \frac{\beta_j^{exp}\cdot\beta_j^{ent}}{\beta_1^{exp}\cdot\beta_1^{ent} + \beta_2^{exp}\cdot\beta_2^{ent}}

Такой подход обеспечивает содержательную обоснованность (эксперт задаёт приоритет) и объективность (данные корректируют его).

Блок 3. Метод анализа иерархий: веса целевой функции

Теперь нужно определить, насколько цена, срок и доверие важны относительно друг друга в итоговой целевой функции. Для этого применяется метод анализа иерархий (AHP).

Эксперт заполняет матрицу парных сравнений 3 \times 3:

A = \begin{pmatrix} 1 & a_{12} & a_{13} \\ 1/a_{12} & 1 & a_{23} \\ 1/a_{13} & 1/a_{23} & 1 \end{pmatrix}

где a_{ij} – относительная важность критерия i над критерием j по шкале Саати (от 1 до 9).

Веса критериев вычисляются нормировкой столбцов матрицы. Сумма элементов j-го столбца:

\sigma_j = \sum_{i=1}^{k} a_{ij}

Нормированная матрица:

\bar{a}_{ij} = \frac{a_{ij}}{\sigma_j}

Вес j-го критерия – среднее по j-й строке нормированной матрицы:

w_j = \frac{1}{k}\sum_{i=1}^{k}\bar{a}_{ji}

После вычисления весов обязательно проверяется согласованность суждений эксперта. Максимальное собственное значение матрицы:

\lambda_{max} = \frac{1}{k}\sum_{j=1}^{k}\frac{(Aw)_j}{w_j}

Индекс согласованности:

CI = \frac{\lambda_{max} - k}{k - 1}

Отношение согласованности:

CR = \frac{CI}{RI(k)} < 0{,}1

где RI – случайный индекс, зависящий от размерности матрицы:

k

1

2

3

4

5

6

7

RI

0,00

0,00

0,58

0,90

1,12

1,24

1,32

Если CR < 0{,}1 – суждения достаточно согласованы. Если нет – эксперт пересматривает матрицу. Это принципиальное отличие от практики «назначить веса по ощущению»: математически несогласованная система суждений отвергается и подлежит пересмотру.

Блок 4. Нормировка и целевая функция

Три критерия имеют разные единицы измерения и разные диапазоны значений. Прямое суммирование рублей, дней и безразмерных баллов лишено смысла. Поэтому все критерии нормируются к единой шкале [0,1].

Для множества S^* определим экстремальные значения:

x_j^{min} = \min_{s_i \in S^*} x_{ij}, \qquad x_j^{max} = \max_{s_i \in S^*} x_{ij}

Для критериев типа «меньше – лучше» (приведённая цена, срок поставки):

\tilde{x}_{ij} = \frac{x_j^{max} - x_{ij}}{x_j^{max} - x_j^{min}}

Для критериев типа «больше – лучше» (уровень доверия):

\tilde{x}_{ij} = \frac{x_{ij} - x_j^{min}}{x_j^{max} - x_j^{min}}

Вырожденный случай – все поставщики одинаковы по критерию:

x_j^{max} = x_j^{min} \;\Rightarrow\; \tilde{x}_{ij} = 1 \quad \forall\, s_i \in S^*

После нормировки значение 1 соответствует лучшему показателю среди допустимых поставщиков, значение 0 – худшему.

Целевая функция – взвешенная аддитивная свёртка нормированных критериев:

F(s_i) = w_1\,\tilde{c}_i^{real} + w_2\,\tilde{t}_i + w_3\,\tilde{r}_i, \qquad w_1 + w_2 + w_3 = 1,\quad F(s_i) \in [0,\,1]

Поскольку значение 1 соответствует наилучшему показателю, оптимальный поставщик определяется максимизацией целевой функции:

s^* = \arg\max_{s_i \in S^*} F(s_i)

Реализация в Engee

Всю описанную математику мы реализовали в среде Engee на языке Julia. Engee – это облачная среда динамического моделирования, доступная бесплатно прямо в браузере. Никакой установки, никаких зависимостей – открыл и считаешь. Именно поэтому порог входа минимальный: если вы знакомы с основами программирования, разобраться в коде не составит труда.

Код разбит на десять логических блоков, каждый из которых соответствует определённому шагу алгоритма. Разберём структуру.

Блок 1–3. Входные данные

Входные данные Все параметры задачи собраны в одном месте. Чтобы изменить условие задачи, не нужно лезть вглубь кода – достаточно отредактировать три матрицы в самом начале файла.

Q         = 30      # Требуемое количество, шт.
α         = 3.0     # Порог допустимого избытка MOQ
p_expert  = 1.5     # Экспертное соотношение β₁/β₂

suppliers = ["ООО Альфа", "ИП Бета", "АО Гамма",
             "ООО Дельта", "ЗАО Эпсилон"]

# Столбцы: цена (руб/шт), MOQ (шт), срок (дней)
offers = [
    120.0   10   14;
     95.0  100   21;
    110.0   25   10;
    130.0    1    7;
    100.0   50   30;
]

# Столбцы: всего заказов, в срок, без рекламаций
history = [
    10   9  10;
     5   3   4;
     8   8   7;
    15  15  15;
     2   1   2;
]

Блок 4. Защита входных данных

@assert all(isfinite, offers)   "Таблица КП содержит NaN или Inf!"
@assert all(isfinite, history)  "Таблица истории содержит NaN или Inf!"
@assert Q > 0                   "Потребность Q должна быть > 0!"
@assert α >= 1.0                "Порог α должен быть >= 1!"

Блок 5. Уровень доверия

Здесь реализован комбинированный метод весообразования – энтропия Шеннона плюс экспертное соотношение. Обратите внимание на защиту от деления на ноль при N_i = 0 и на защиту от \log(0) через \varepsilon = 10^{-12}.

p_t = zeros(n_sup)
p_q = zeros(n_sup)
r   = zeros(n_sup)

for i in 1:n_sup
    N, Nt, Nq = history[i, 1], history[i, 2], history[i, 3]
    if N == 0
        r[i] = 0.5   # нейтральный балл для нового поставщика
    else
        p_t[i] = Nt / N
        p_q[i] = Nq / N
    end
end

function entropy_weights(x1, x2)
    n  = length(x1)
    ε  = 1e-12
    s1 = sum(x1);  s2 = sum(x2)
    p1 = (s1 > 0) ? x1 ./ s1 : ones(n) ./ n
    p2 = (s2 > 0) ? x2 ./ s2 : ones(n) ./ n
    H1 = -sum(p1 .* log.(p1 .+ ε)) / log(n)
    H2 = -sum(p2 .* log.(p2 .+ ε)) / log(n)
    d1, d2 = 1 - H1, 1 - H2
    total  = d1 + d2
    return (total > 0) ? (d1/total, d2/total) : (0.5, 0.5)
end

β1_exp = p_expert / (1 + p_expert)
β2_exp = 1.0      / (1 + p_expert)

has_history = history[:, 1] .> 0
β1_ent, β2_ent = (sum(has_history) >= 2) ?
    entropy_weights(p_t[has_history], p_q[has_history]) : (0.5, 0.5)

denom = β1_exp * β1_ent + β2_exp * β2_ent
β1 = (denom > 0) ? (β1_exp * β1_ent) / denom : 0.5
β2 = (denom > 0) ? (β2_exp * β2_ent) / denom : 0.5

for i in 1:n_sup
    if history[i, 1] > 0
        r[i] = β1 * p_t[i] + β2 * p_q[i]
    end
end

Блок 6. Приведённая цена и фильтрация

c_real   = zeros(n_sup)
Q_real   = zeros(Int, n_sup)
excluded = falses(n_sup)

for i in 1:n_sup
    c_i, m_i  = offers[i, 1], offers[i, 2]
    Q_real[i] = max(Q, m_i)
    c_real[i] = c_i * Q_real[i] / Q
    if Q_real[i] / Q > α
        excluded[i] = true
    end
end

active = findall(.!excluded)
@assert length(active) >= 1  "Все поставщики исключены! Увеличьте α."

Блок 7. МАИ

Функция ahp_weights вычисляет веса и проверяет согласованность. Таблица случайных индексов встроена в словарь.

A_ahp = [1.0  2.0  3.0;
         0.5  1.0  2.0;
         1/3  0.5  1.0]

function ahp_weights(A)
    k        = size(A, 1)
    col_sums = sum(A, dims=1)
    A_norm   = A ./ col_sums
    w        = vec(mean(A_norm, dims=2))
    λ_max    = sum((A * w) ./ w) / k
    CI       = (λ_max - k) / (k - 1)
    RI_table = Dict(1=>0.00, 2=>0.00, 3=>0.58,
                    4=>0.90, 5=>1.12, 6=>1.24, 7=>1.32)
    RI = get(RI_table, k, 1.49)
    CR = (RI > 0) ? CI / RI : 0.0
    return w, λ_max, CI, CR
end

w, λ_max, CI, CR = ahp_weights(A_ahp)

@printf("  w₁ (цена)    = %.4f\n", w[1])
@printf("  w₂ (срок)    = %.4f\n", w[2])
@printf("  w₃ (доверие) = %.4f\n", w[3])
@printf("  λ_max = %.4f,  CI = %.4f,  CR = %.4f\n", λ_max, CI, CR)
CR < 0.1 ? println("  ✅ Суждения согласованы") :
           println("  ❌ Пересмотрите матрицу A!")

Блок 8–9. Нормировка и целевая функция

data_active = hcat(c_real[active],
                   Float64.(offers[active, 3]),
                   r[active])

dirs       = [:min, :min, :max]
n_active   = length(active)
normalized = zeros(n_active, 3)

for j in 1:3
    v     = data_active[:, j]
    v_min = minimum(v);  v_max = maximum(v)
    for i in 1:n_active
        if v_max ≈ v_min
            normalized[i, j] = 1.0
        elseif dirs[j] == :min
            normalized[i, j] = (v_max - v[i]) / (v_max - v_min)
        else
            normalized[i, j] = (v[i] - v_min) / (v_max - v_min)
        end
    end
end

F_scores    = normalized * w
best_local  = argmax(F_scores)
best_idx    = active[best_local]
order_local = sortperm(F_scores, rev=true)

println("\nРанжирование:")
for (rank, idx_local) in enumerate(order_local)
    idx    = active[idx_local]
    marker = (idx == best_idx) ? "← ОПТИМАЛЬНЫЙ" : ""
    @printf("  %d. %-16s F = %.4f  %s\n",
            rank, suppliers[idx], F_scores[idx_local], marker)
end

Блок 10. Анализ чувствительности

scenarios = [
    "Базовый (МАИ)"      w[1]   w[2]   w[3];
    "Приоритет цены"     0.70   0.20   0.10;
    "Приоритет срока"    0.20   0.60   0.20;
    "Приоритет доверия"  0.20   0.20   0.60;
    "Равные веса"        0.333  0.333  0.333;
]

println("\nАнализ чувствительности:")
for row in eachrow(scenarios)
    ws     = Float64.([row[2], row[3], row[4]])
    ws   ./= sum(ws)
    f_sens = normalized * ws
    winner = suppliers[active[argmax(f_sens)]]
    @printf("  %-22s | w=(%.2f, %.2f, %.2f) | Победитель: %s\n",
            row[1], ws[1], ws[2], ws[3], winner)
end

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

Результат и интерпретация

Чтобы продемонстрировать все ключевые эффекты модели, подберём условия задачи так, чтобы каждый из трёх блоков математики дал содержательный, нетривиальный результат. Потребность: Q = 30 шт., порог допустимого избытка \alpha = 3{,}0.

Исходные данные:

Поставщик

ci, руб/шт

MOQ, шт

Срок, дн

Заказов

В срок

Без рекл.

ООО Альфа

120

10

14

10

9

10

ИП Бета

95

100

21

5

3

4

АО Гамма

110

25

10

8

8

7

ООО Дельта

130

1

7

15

15

15

ЗАО Эпсилон

100

50

30

2

1

2

На первый взгляд картина ясна: ИП Бета предлагает самую низкую цену – 95 руб/шт. При интуитивном подходе выбор очевиден. Посмотрим, что скажет модель.

Шаг 1. Фильтрация по MOQ

Для каждого поставщика вычисляем реальный объём закупки и приведённую цену.

ИП Бета имеет MOQ = 100 шт при потребности 30. Приведённая цена:

c_\beta^{real} = 95 \cdot \frac{100}{30} = 316{,}67 \;\text{руб/шт}

Коэффициент избытка:

\frac{100}{30} = 3{,}33 > \alpha = 3{,}0

Ограничение нарушено – ИП Бета исключается из рассмотрения. Если бы менеджер выбрал этого поставщика по минимальной каталожной цене, предприятие приобрело бы 70 лишних единиц стоимостью 95 \times 70 = 6,650 руб., замороженных на складе.

ЗАО Эпсилон проходит фильтр (избыток 1,67 < 3,0), однако его приведённая цена вырастает с каталожных 100 до 166,67 руб/шт – рост на 66,7%.

Результаты фильтрации:

Поставщик

MOQ

Qireal

Коэф. избытка

cireal, руб/шт

Статус

ООО Альфа

10

30

1,00

120,00

допустим

ИП Бета

100

100

3,33

316,67

исключён

АО Гамма

25

30

1,00

110,00

допустим

ООО Дельта

1

30

1,00

130,00

допустим

ЗАО Эпсилон

50

50

1,67

166,67

допустим

Допустимое множество S* = {ООО Альфа, АО Гамма, ООО Дельта, ЗАО Эпсилон}.

Шаг 2. Уровень доверия

Экспертное соотношение p = 1{,}5: своевременность поставки важнее качества в полтора раза. Это типичная расстановка приоритетов для производства с непрерывным циклом – задержка останавливает линию, тогда как дефект выявляется на входном контроле и допускает замену партии.

В таком случае коэффициенты рассчитываются следующим образом:

\beta_1^{exp} = \frac{1{,}5}{1 + 1{,}5} = 0{,}600, \qquad \beta_2^{exp} = \frac{1}{1 + 1{,}5} = 0{,}400

Энтропийный анализ выявляет, что значения p_i^t варьируются в широком диапазоне – от 0,500 (ЗАО Эпсилон) до 1,000 (АО Гамма, ООО Дельта). Значения p_i^q сосредоточены в узком диапазоне 0,875–1,000 и почти не различают поставщиков. Энтропийные веса: \beta_1^{ent} = 0{,}900, \beta_2^{ent} = 0{,}100.

Данные объективно подтверждают и усиливают экспертное суждение. Комбинированные веса по формуле:

\beta_1 = 0{,}931, \qquad \beta_2 = 0{,}069

Результаты расчёта уровня доверия:

Поставщик

pit

piq

ri

Примечание

ООО Альфа

0,900

1,000

0,907

10 заказов

АО Гамма

1,000

0,875

0,991

8 заказов

ООО Дельта

1,000

1,000

1,000

15 заказов

ЗАО Эпсилон

0,500

1,000

0,535

2 заказа

Обратите внимание на ЗАО Эпсилон: идеальное качество (p_i^q = 1{,}000), но каждый второй заказ приходил с опозданием. При высоком весе своевременности интегральный балл доверия оказывается низким – 0,535. Модель это улавливает автоматически.

Шаг 3. Веса МАИ

Руководитель отдела закупок формирует матрицу парных сравнений: цена важнее срока в 2 раза, цена важнее доверия в 3 раза, срок важнее доверия в 2 раза.

A = \begin{pmatrix} 1 & 2 & 3 \\ 1/2 & 1 & 2 \\ 1/3 & 1/2 & 1 \end{pmatrix}

По формулам (21)–(23): w_1 = 0{,}539, w_2 = 0{,}297, w_3 = 0{,}164.

Проверка согласованности:

\lambda_{max} = 3{,}009, \quad CI = 0{,}005, \quad CR = 0{,}008 \ll 0{,}1

Суждения высококогерентны. Логика весов производственно обоснована: цена напрямую влияет на себестоимость и получает наибольший вес; срок определяет ритмичность производственного цикла и стоит на втором месте; доверие замыкает тройку, но не исключается – ненадёжный контрагент создаёт системные риски даже при привлекательной цене.

Шаг 4. Итоговое ранжирование

После нормировки по формулам (17)–(18) и вычисления целевой функции по формуле (27):

Поставщик

cireal

ti

ri

F(si)

Ранг

АО Гамма

1,000

0,870

0,978

0,958

1

ООО Дельта

0,656

1,000

1,000

0,810

2

ООО Альфа

0,820

0,696

0,798

0,782

3

ЗАО Эпсилон

0,000

0,000

0,000

0,000

4

АО Гамма побеждает с итоговым баллом 0,958. Это результат сбалансированного сочетания трёх факторов: наименьшая приведённая цена среди допустимых поставщиков (110 руб/шт, максимальная нормированная оценка 1,000), второй по скорости срок поставки (10 дней), высокий уровень доверия (0,991) на основе 8 заказов.

ООО Дельта занимает второе место, демонстрируя абсолютно лучшие значения по двум критериям из трёх: минимальный срок поставки (7 дней) и максимальный уровень доверия (1,000), подкреплённый наиболее обширной статистической базой в 15 заказов. Однако наибольшая приведённая цена (130 руб/шт) при доминирующем весе ценового критерия w_1 = 0{,}539 не позволяет ему выйти на первое место.

ЗАО Эпсилон получает нулевой итоговый балл. Он является наихудшим сразу по всем трём критериям: наибольшая приведённая цена (166,67 руб/шт), наибольший срок поставки (30 дней), наименьший уровень доверия (0,535). При нормировке min-max поставщик с наихудшим значением по каждому критерию получает нулевые нормированные оценки, а их взвешенная сумма обращается в ноль. Это не артефакт – это корректный результат: данный контрагент проигрывает остальным по всем параметрам одновременно.

Анализ чувствительности

Единственная рекомендация – недостаточно. Хорошая модель должна позволять лицу, принимающему решение, видеть условия, при которых правильный ответ меняется. Для этого проводится анализ чувствительности: фиксируем нормированные оценки поставщиков и варьируем только веса целевой функции.

Сценарий

w1

w2

w3

Победитель

Базовый (МАИ)

0,539

0,297

0,164

АО Гамма

Приоритет цены

0,700

0,200

0,100

АО Гамма

Приоритет срока

0,200

0,600

0,200

ООО Дельта

Приоритет доверия

0,200

0,200

0,600

АО Гамма

Равные веса

0,333

0,333

0,333

АО Гамма

АО Гамма сохраняет статус оптимального поставщика в четырёх из пяти сценариев. Это свидетельствует о высокой робастности полученного решения: рекомендация модели не является следствием конкретного набора весов – она отражает объективное преимущество данного поставщика по совокупности критериев.

Единственный сценарий, в котором победитель меняется – «Приоритет срока» (w_2 = 0{,}6). В этом случае первым становится ООО Дельта благодаря минимальному сроку поставки (7 дней против 10 у АО Гамма). Это имеет самостоятельную практическую интерпретацию: если предприятие работает в режиме срочного восполнения критически дефицитного компонента и производственный простой недопустим – приоритет срока поставки закономерно возрастает, и выбор в пользу ООО Дельта будет экономически обоснованным, несмотря на более высокую цену.

Именно это и есть главная ценность анализа чувствительности: модель не просто выдаёт ответ, она показывает, при каких условиях ответ меняется. Это качественно повышает обоснованность и прозрачность закупочного решения.

Заключение

Мы прошли путь от простой управленческой проблемы – как не ошибиться при выборе поставщика – до полной математической модели с реализацией в Engee.

Каталожная ценане та цена, которую вы платите. Пока не учтена минимальная партия, сравнивать предложения поставщиков по столбцу «цена за штуку» не имеет смысла. Приведённая цена, которая переводит MOQ из дискретного ограничения в непрерывный экономический критерий, даёт корректную базу для сравнения. В численном примере это превратило «лучшего» поставщика в исключённого.

ERP-статистика это готовый инструмент оценки надёжности. Данные о сроках и качестве поставок уже есть на каждом предприятии. Комбинированный метод весообразования (энтропия Шеннона плюс экспертное соотношение) позволяет превратить эти данные в объективный интегральный показатель доверия, который обновляется автоматически после каждой новой поставки и не зависит от того, кто сидит на месте менеджера.

Согласованность суждений обязательное условие. МАИ с проверкой CR < 0{,}1 гарантирует внутреннюю непротиворечивость экспертных суждений. Это принципиально отличает предложенный подход от распространённой практики произвольного назначения весов.

Алгоритм реализован в Engee на языке Julia и пригоден для интеграции в информационные системы управления закупочной деятельностью предприятия.

Направления дальнейшего развития: распределение заказа сразу между несколькими поставщиками одновременно (стратегия multi-sourcing); динамическое обновление показателя доверия методом скользящего окна; включение в модель санкционных и логистических рисков как дополнительных критериев оценки.

Полезные ссылки

Готовая модель в Engee