Алгебра распределения


Главная » Ресурсы » Здесь

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


Типы данных для распределения

Математическое распределение представляет собой объект, который обобщает понятие функции. Цель Envision гораздо скромнее: такие объекты по сути представляют собой функции $f: \mathbb{Z} \to \mathbb{R}$. Мы называем эти (математические) функции
распределением, потому что в Envision они чаще всего используются для обработки распределения вероятностей, то есть чаще всего используется строго положительное распределение с массой 1.

Распределение в Envision материализовано в виде особого типа данных, который называется
распределение. Другие типы данных — это число и текст. Данные типа «распределение» работают достаточно сложно, и это объясняется тем, что они представляют собой функции, а не отдельные значения. Например, ниже мы создаем дельта-функцию — дискретную функцию, равную 0 во всех точках, кроме 42, где она равна единице.

d := dirac(42)

Распределение можно экспортировать в файл с расширением ion. Однако распределение нельзя экспортировать в формат CSV или Excel
как есть.

В Envision существуют и другие способы создания функции распределения. Мы рассмотрим их в следующих разделах.

Графическое представление распределения

Распределение можно визуализировать с помощью гистограмм . Возьмем простое распределение Пуассона:

Image

Данный график создан в Envision с помощью одной строчки кода, показанной ниже:
show histogram "My first distribution!" tomato with
  poisson(21)
Использование ячейки histogram подразумевает, что после ключевого слова with должно быть единое скалярное распределение.

Точечные операции

Самые простые операции распределения —
точечные операции. Например, пусть $f$ и $g$ представляют собой две функции распределения $\mathbb{Z} \to \mathbb{R}$. Таким образом, мы можем выразить операцию сложения так:

$$f+g: k \to f(k) + g(k)$$ С точки зрения Envision, если X и Y — это векторы распределения, то та же самая операция будет выражена следующим образом:
Z = X + Y
Нужно отметить, что даже при работе с функциями распределения Envision остается
векторным языком. Из-за этого мы обычно не обрабатываем по одной функции распределения за раз, но весь вектор распределения сразу. Ту же самую операцию можно выполнить со скалярной точки зрения по следующей формуле:
Z := X + Y
В этом и следующих разделах мы используем в сценариях переменные X и Y как фактическое распределение.

Тогда точечное умножение и вычитание выражаются следующим образом: $$f \times g: k \to f(k) \times g(k)$$ $$f-g: k \to f(k)-g(k)$$ Эти формулы можно легко преобразовать в синтаксис Envision:
Z = X * Y
Z = Z - Y
Если число $\alpha$ может быть воспринято как постоянная функция $f_{\alpha}: k \to \alpha$, то Envision позволяет комбинировать числа и функции распределения, но только при условии, что в результате получится компактная функция распределения.
// допустимо, компактная функция
Z = 2 * X
// нет деления на ноль — допустимо
Z = X / 2
// недопустимо, некомпактная функция распределения
Z = X + 1
// недопустимо, Y — компактная функция, а значит, она может быть равна нулю
Z = X / Y
Распределения также могут сдвигаться. Оператор сдвига обычно записывается так:

$$f_{n}: k \to f(k+n)$$ Синтаксис Envision для данной функции выглядит так:
Z = X << n // левый сдвиг
Z = X >> n // правый сдвиг
Если n является отрицательным числом, то операторы сдвига будут работать, но левый сдвиг становится правым и наоборот.

Создание функций распределения

Функции распределения можно создавать по-разному. Система прогнозирования Lokad создает функции распределения для времени выполнения заказов или спроса в будущем. После преобразования этих функций распределения в решетку (*) можно восстановить функцию распределения через функцию distrib(). Можно использовать следующий синтаксис:
Demand = distrib(Id, G.Probability, G.Min, G.Max)
Полученная переменная Demand представляет собой функцию распределения. Если исходная решетка содержит сегменты длиннее 1, функция distrib() равномерно распределяет массу по всему сегменту. Масса распределения сохраняется функцией distrib().

(*) Сериализация функции распределения — это процесс превращения данных распределения в обычную таблицу, которую можно хранить в виде простого файла. Для работы с функцией распределения как таковой (а не как с таблицей) нужно произвести обратную сериализацию таблицы. В сценарии выше это выполняется с помощью функции distrib().

Кроме того, Envision дает возможность создать функцию распределения непосредственно из набора полученных числовых значений. Для этого используется агрегатор ranvar():
X = ranvar(Orders.Quantity)
Агрегатор ranvar() возвращает
случайное значение, которое совпадает с частотой, обнаруженной в группе агрегации. Если данных для объединения недостаточно, ranvar() возвращает dirac(0).

Наконец, можно создать распределение из
временных рядов с помощью агрегатора ranvar.segment().
D = ranvar.segment(
      // первая дата для каждого элемента
      start: Items.Start         
      // последняя дата для каждого элемента (включительно)
      end: Items.End             
      // длительность периода для каждого элемента
      horizon: Items.Horizon 
      // целое число для пропущенных элементов
      step: Items.Step           
      // дата для каждого события
      date: Orders.Date        
      // количество для каждого события
      quantity: Orders.Quantity) 
Для каждого элемента рассчитывается распределение суммы объемов по периодам с горизонтами от первой до последней даты для соответствующего элемента. Как правило, длительность горизонта соответствует времени выполнения заказа для соответствующего элемента.

Разложение распределения в таблице

В предыдущем разделе мы увидели, как можно объединять данные таблицы и создавать распределение. Можно выполнить и обратный процесс, то есть разложить распределение по строкам таблицы. В данном разделе мы рассмотрим функцию extend.distrib(), которая выполняет данную задачу. Синтаксис данной функции выглядит так:
X = poisson(1)
table G = extend.distrib(X)
G.Probability = int(X, G.Min, G.Max)
show table "My Grid" with
  Id
  G.Min
  G.Max
  G.Probability
Где X — вектор распределения, заданный в строке 1 как распределение Пуассона. В строке 2 данные распределения включаются в таблицу с названием G («Решетка»). Эта таблица привязана к (Id, *), и, как видно из строк 3–7, таблица также автоматически заполняется числовыми значениями в столбцах G.Min и G.Max. Значения G.Min и G.Max представляют собой допустимые предельные значения.

При разложении сравнительно компактного распределения таблица обычно состоит из строк, различающихся на 1 единицу (то есть от G.Min до G.Max с шагом +1 между соседним строками). Тем не менее, если бы нам пришлось выполнять разложение распределения при большом количестве значений, например dirac(1000000), то создавать таблицы из миллиона строк было бы крайне неэффективно. Именно поэтому функция extend.distrib() объединяет данные большого распределения в группы. Для этого и нужны допустимые предельные значения групп G.Min и G.Max.

Для большего контроля за детализацией таких групп функция extend.distrib() позволяет использовать первую перегрузку:
table G = extend.distrib(X, S)
Где S представляет собой числовой вектор. В результате в таблице отражаются группы, соответствующие сегментам [0;0] [1;S] [S+1; S+M] [S+M+1;S+2*M] ..., где M является размером группы по умолчанию (также называется
коэффициентом). Данная перегрузка часто используется, когда нужно учесть уровень спроса, который выше общего запаса.

Наконец, вторая перегрузка extend.distrib() дает еще больший контроль:
table G = extend.distrib(X, S, M)
Где M — обязательный размер группы. Если M равен нулю, то при разложении используется размер группы по умолчанию, который настраивается Envision автоматически. Вторая перегрузка очень полезна при использовании
коэффициентов партий при размещении заказов, так как спрос нужно сопоставить с партиями определенного размера.

Помните, что extend.distrib(X, S, M) может выдать ошибку из-за ограничений вашей учетной записи Lokad, если вы попытаетесь разложить большое распределение при малом коэффициенте партий.

Свертка распределения вероятности

Свертка — это сложная операция, применяемая в функциях распределения. В основном такие операции используются для
случайных переменных. В отличие от точечных операций свертка позволяет выполнять такие операции, как сложение или умножение независимых случайных переменных. Свертки в Envision состоят из двух символов и оканчиваются на *, например:
// свертка сложения
Z = X +* Y
// свертка вычитания; то же самое, что X +* отриц. (Y)
Z = X -* Y
// свертка умножения
Z = X ** Y
// свертка показателя степени
Z = X ^* Y
Свертка сложения (и вычитания) может быть представлена в виде суммы (разности) двух независимых случайных переменных $X+Y$ (или $X–Y$). Свертка умножения, также известная как свертка Дирихле, может быть представлена как произведение двух независимых случайных переменных.

Порядок свертки более сложен и представляет собой следующие расчеты: $$X ^ Y = \sum_{k=0}^{\infty} X^k \mathbf{P}[Y=k] \text{ where } X^k = X + \dots + X \text{ ($k$ times)}$$ Последняя операция особенно интересна из-за связи с процессом, ведущим к интегрированному прогнозированию спроса, где $X$ представляет собой ежедневный спрос (предположительно постоянный), а $Y$ — вероятное время выполнения заказа.

См. статью о порядке свертки.

Историческая справка

Система прогнозирования Lokad начала работать с
квантильными схемами в начале 2015 г. Эти схемы не были непосредственным представлением распределения вероятности тех или иных событий (это были просто интерполированные квантильные прогнозы), но мы все ближе подходили к распределению. Работая с клиентами, мы начали понимать, какой огромный потенциал заключен в анализе вероятностей, если применять его для количественной оптимизации цепей поставок. Наши решетки представляли собой большие таблицы, в которых была отражена вероятность всех событий. И хотя эти решетки и были прорывом как для клиентов, так и для нас самих, мы быстро осознали, что обработка вероятности событий, представленных в виде списка, отнимает много времени и сил.

Под «алгеброй распределения» понимается широкий набор технологических наработок Lokad для решения проблемы неопределенности будущего в цепях поставок. Для работы с указанными ситуациями требуется не просто среднестатистический прогноз, но полноценный анализ рисков с учетом всех возможных вариантов развития событий. В основе Envision лежит идея о том, что необходимо рассматривать
все варианты, а не только немногие специально отобранные. С этой целью в сценарии Envision вводятся случайные величины, которые обрабатываются с помощью соответствующих операций, таких как свертки'’ — более подробное описание приводится далее. На практике алгебра распределения представляет собой элегантный способ моделировать сложных ситуаций в цепях поставок, когда ни спрос, ни время выполнения заказа в будущем не могут быть четко определены.