Algebra der Verteilungen

Algebra der Verteilungen


Startseite » Ressourcen » Hier

Mathematische Distributionen und Verteilungen sind bei der Modellierung vieler Situationen im Unternehmen, besonders bei solchen, die mit Ungewissheit zusammenhängen, leistungsfähig und nützlich. Envision behandelt Distributionen und Verteilungen als Elemente erster Klasse und kann eine breite Auswahl an Berechnungen mit diesen ausführen. Auf all diese Operationen beziehen wir uns kollektiv als Algebra der Verteilungen, die von Envision unterstützt werden. Auf dieser Seite stellen wir den distribution-Datentyp vor und bieten einen Überblick über die verschiedenen Operatoren und Funktionen, die darauf zutreffen.

Vorwort

Lokads Prognose-Engine begann Anfang 2015 Quantiltabellen zu bieten. Diese Tabellen waren noch nicht genau, Wahrscheinlichkeitsverteilungen - nur interpolierte Quantilprognosen - doch wir waren schon ziemlich nahe. Bei der Arbeit mit unseren Kunden bemerkten wir das riesige Potential der Anwendung von probabilistischen Analysen auf quantitative Betriebsoptimierung. Doch unsere Tabellen war nur das: lange Tabellen, in denen alle Wahrscheinlichkeiten aufgelistet waren. Während diese Tabellen für unsere Kunden und auch für uns einen Durchbruch darstellten, merkten wir bald, dass die Verarbeitung der Wahrscheinlichkeiten in Form von Listen keine leichte Aufgabe war.

So musste beispielsweise die Auftragserfüllungsrate, wie folgt, berechnet werden:

Grid.Q = Grid.Max - Grid.Min + 1
Grid.Tau1 = cumsum(Grid.Probability, -Grid.Max, Id)
EX = sum(Grid.Probability * (Grid.Max + Grid.Min) / 2)
P = sum(Grid.Probability)
Grid.Y = Grid.Min == 0 ? 0 : \
	(Grid.Tau1 * Grid.Q - Grid.Probability * (Grid.Q-1) / 2) / EX
Grid.FillRate = cumsum(Grid.Y, Grid.Max, Id) * P

was mit Algebra der Verteilungen einfach so wäre:

Demand = distrib(Id, Grid.Probability, Grid.Min, Grid.Max)
FillRate = fillrate(Demand)

Natürlich hilft eine besondere fillrate()-Funktion deutlich, den Code kompakter und lesbarer zu gestalten, doch in der Praxis werden fast alle Berechnungen, die in der eigentlichen Tabelle ausgeführt werden, etwas kryptisch. Im Gegensatz hierzu bieten Verteilungen die Möglichkeit, dieselben Berechnungen (und noch mehr) mit weniger Umständen auszuführen, wodurch das Skript nicht nur schneller, sondern auch sicherer wird.

Der Datentyp Distribution

Mathematische Distributionen sind Objekte, die den Begriff der Funktion verallgemeinern. Unser Ziel in Envision ist etwas bescheidener und was wir Distributionen nennen, sind tatsächlich Funktionen $f: \mathbb{Z} \to \mathbb{R}$. Wir beziehen uns auf diese (mathematischen) Funktionen als Distributionen, da wir sie in Envision am häufigsten für Wahrscheinlichkeitsverteilungen verwenden, d.h. für positive Distributionen mit einer Masse gleich 1.

Außerdem sind Envision-Distributionen (in den nächsten Absätzen als Verteilungen bezeichnet)kompakt: sie lassen Werte ungleich null nur für eine endliche Anzahl von Werten zu. Diese Einschränkung wurde eingeführt, weil nicht-kompakte Verteilungen, obwohl sie möglich wären, eine ganze Reihe Komplikationen für wenig praktischen Nutzen mit sich bringen würde.

In Envision werden Verteilungen über einen bestimmten Datentyp, distribution genannt, umgesetzt. Andere Datentypen sind etwa number oder text. Der distribution-Datentyp bietet ein relativ komplexes Verhalten, gerade weil es mehr eine Funktion als ein Einzelwert ist. Zum Beispiel erstellen wir unten eine Delta-Distribution, also eine diskrete Funktion mit dem Wert 0 überall außer am Punkt 42, an dem der Wert bei 1 liegt.

d := dirac(42)

Envision bietet viele andere Arten, Verteilungen zu erstellen, wie in den folgenden Abschnitten beschrieben wird.

Punktweise Operationen

Die einfachsten Operationen bei Verteilungen sind als punktweise Operationen bekannt. Wenn beispielsweise $f$ und $g$ zwei Verteilungen $\mathbb{Z} \to \mathbb{R}$ darstellen, können wir die Addition, wie folgt, definieren:

$$f+g: k \to f(k) + g(k)$$ Aus Envisions Sicht, wenn man davon ausgeht, dass sowohl X als auch Y Verteilungsvektoren sind, wird dieselbe Operation, wie folgt, geschrieben:
Z = X + Y
Dabei muss hervorgehoben werden, dass sogar, wenn es um Verteilungen geht, Envision weiterhin eine Vektorsprache bleibt. So wird gewöhnlich nicht nur eine einzige Verteilung zu einem Zeitpunkt verarbeitet, sondern ein ganzer Vektor von Verteilungen gleichzeitig. Dieselbe Operation kann auch aus einer Skalar-Perspektive so durchgeführt werden:
Z := X + Y
In diesem und in den nächsten Abschnitten, gehen wir, immer wenn wir X und Y in den Skript-Beispielen benutzen, davon aus, dass es sich bei diesen zwei Variablen um Verteilungen handelt.

Dann werden die punktweise Multiplikation und Subtraktion so definiert: $$f \times g: k \to f(k) \times g(k)$$ $$f-g: k \to f(k)-g(k)$$ was recht verständlich zur folgenden Syntax in Envision führt:
Z = X * Y
Z = Z - Y
Aus der Perspektive, dass eine Zahl $\alpha$ implizit zu einer konstanten Funktion $f_{\alpha}: k \to \alpha$ assimiliert werden kann, erlaubt Envision, Zahlen und Verteilungen zu kombinieren - allerdings nur, wenn die Verteilung kompakt ist.
Z = 2 * X // OK, es ist kompakt
Z = X / 2 // nicht durch Null teilen ist OK
Z = X + 1 // falsch, keine kompakte Verteilung
Z = X / Y // falsch, Y ist kompakt und hat Null-Werte

Verteilungen erstellen

Verteilungen können auf viele verschiedene Arten erstellt werden. Lokads Prognose-Engine erstellt Verteilungen für künftige Durchlaufzeiten oder den künftigen Bedarf. Wenn diese Verteilungen als Tabelle (*) serialisiert werden, ist es möglich, die Verteilung über die distrib()-Funktion zu erstellen. Die relevante Syntax hierfür lautet:
Demand = distrib(Id, Grid.Probability, Grid.Min, Grid.Max)
Die Variable Demand, die daraus entsteht, ist eine Verteilung. Wenn die Originaltabelle Segmente enthält, die länger als 1 sind, teilt distrib() gleichmäßig über das Segment aus. Die Masse der Verteilung wird durch die distrib()-Funktion gehalten.

(*) Die Serialisierung einer Verteilung stellt den Prozess dar, über den die Verteilungsdaten in ein regelmäßiges tabellarisches Format verwandelt werden, der als Flatfile gespeichert werden kann. Um die Verteilung auch als eine tatsächliche Verteilung - und nicht als Tabelle - zu behandeln, muss die Tabelle zuerst serialisiert werden. Dies ist genau das, was durch die distrib()-Funktion geschieht.

Zusätzlich bietet Envision auch die Möglichkeit, eine Distribution direkt aus einem Set beobachteter Zahlenwerte zu erstellen. Dafür ist der ranvar()-Aggregator zuständig:
X = ranvar(Orders.Quantity)
Der ranvar()-Aggregator gibt eine Zufallsvariable zurück, die mit der beobachteten Häufigkeit der Aggregationsgruppen übereinstimmt. Wenn nichts zum Aggregieren vorliegt, gibt ranvar() dirac(0) zurück.

Verteilung in eine Tabelle erweitern

In den vorangehenden Abschnitten haben wir gesehen, wie eine Tabelle in eine Verteilung aggregiert werden kann. Der umgekehrte Prozess, also die Erweiterung einer Verteilung auf Tabellenzeilen, ist auch möglich. In diesem Abschnitt analysieren wir die extend.distrib()-Funktion, die genau dafür gedacht ist. Die Syntax wird, wie folgt, veranschaulicht:
X = poisson(1)
table Grid = extend.distrib(X)
show table "My Grid" with Id, Grid.Min, Grid.Max, Grid.Probability
Wobei X der Verteilungsvektor, der in Zeile 1 als Poisson-Verteilung erstellt wurde, ist. In Zeile 2 werden die Verteilungen in eine Tabelle namens Grid erweitert. Diese Tabelle hat eine Affinität (Id, *) und, wie in Zeile 3 dargestellt wird, wird die Tabelle mit den numerischen Spalten Grid.Min, Grid.Max und Grid.Probability ausgefüllt. Sowohl Grid.Min als auch Grid.Max sind inklusive Ränder.

Wenn relativ kompakte Verteilungen erweitert werden, enthält die entstehende Tabelle gewöhnlich Zeile mit +1 Erhöhungen - also Grid.Min und Grid.Max um +1 von einer Zeile in die nächste erhöht. Doch gehen wir von Verteilungen mit hohen Werten aus, z.B. dirac(1000000), wäre es äußerst ineffizient Millionen von Zeilen zu erstellen. Daher aggregiert die Funktion extend.distrib() große Verteilungen in dichtere Buckets. Dies erklärt, weshalb sowohl Grid.Min als auch Grid.Max vorliegen, die die inklusiven Ränder des Behälters darstellen.

Um mehr Kontrolle über die Granularität des erhaltenen Behälters zu erlangen, bietet die Funktion extend.distrib() die erste Überladung:
table Grid = extend.distrib(X, S)
wobei S ein Zahlenvektor ist. Die entstehende Tabelle bietet Behälter, die an die Segmente [0;0] [1;S] [S+1; S+M] [S+M+1;S+2*M] ... ausgerichtet ist, wo M die standardmäßige Behältergröße ist, die auch Multiplikator genannt wird. Diese Überladung tritt gewöhnlicherweise dann ein, wenn der Bedarf über dem gesamten Bestand berücksichtigt werden muss.

Zuletzt bietet die zweite Überladung von extend.distrib() mehr Kontrolle mit:
table Grid = extend.distrib(X, S, M)
wobei M eine zwingende Behältergröße ist. Wenn M gleich null ist, fällt es auf die standardmäßige Behältergröße zurück, die von Envision automatisch angepasst wird. Diese zweite Überladung ist besonders nützlich, wenn Multiplikatoren für Losgrößen im Bestellprozess berücksichtigt werden müssen, da der Bedarf in Behälter einer bestimmten Größe aufgeteilt werden muss.

Achten Sie darauf, dass extend.distrib(X, S, M) je nach der Kapazität Ihres Lokad-Kontos fehlschlagen können, wen Sie versuchen, eine Verteilung mit hohem Wert zu erweitern, während Sie einen kleinen Multiplikator erzwingen.

Parametrische Verteilungen

Envision bietet auch verschiedene parametrische Verteilungen, also, Funktionen, die eine Zahl als Argument nehmen, den Parameter, und eine Verteilung zurückgeben.

  • dirac(n) gibt eine Funktion mit einem Nullwert überall außer bei n, wo die Funktion den Wert 1 hat, zurück.
  • identity(n) gibt die Funktion $\text{id}: k \to k$ zurück, aber eingeschränkt auf das Segment [0;n] und 0 anderswo.
  • uniform(n) gibt die Funktion $\text{unif}: k \to 1$ zurück, aber eingeschränkt auf das Segment [0;n] und 0 anderswo.
  • poisson(a) gibt die Poisson-Verteilung des Parameters a ($\lambda$ in der Literatur) zurück.

Funktionen auf Verteilungen

Numerische Indikatoren können auch aus Verteilungen erlangt werden.

  • crps(X, A) wo A ganze Zahlen den Continuous Ranked Probability Score (CRPS) zurückgeben.
  • mean(X) gibt den statistischen Mittelwert zurück.
  • mass(X) gibt die Masse der Verteilung zurück, also $\sum_{k=-\infty}^{\infty}f(k)$
  • isranvar(X) gibt einen Boolean zurück, der true ist, wenn die Verteilung eine Zufallsvariable ist.
  • int(X, A, B) wobei A und B ganze Zahlen sind, gibt das Integral von X über das inklusive Segment [A;B] zurück.
  • quantile(X, tau) gibt das Quantil der Verteilung zurück; das kleinste $x$ wie etwa $\mathbf{P}[X \leq x] \geq \tau$.
  • spark(X) gibt einen Textwert zurück, der in einer kompakten ASCII-Zeichnung die Verteilung darstellt.

Transformation der Verteilung

Eine Verteilung kann in eine andere Verteilung transformiert werden.

  • reflect(X) gibt die gespiegelte Verteilung zurück $k \to f(-k)$.
  • transform(X,a) gibt eine Verteilung zurück, die sich durch Interpolation nähert $k \to f(k / a)$.
  • fillrate(X) gibt die Grenze der Auftragserfüllungsrate zurück. Erwartet eine Zufallsvariable als Eingabe und gibt eine Zufallsvariable wieder.

Faltung von Wahrscheinlichkeitsverteilungen

Faltungen stellen eine fortgeschrittenere Art von Operationen mit Verteilungen dar. Die Hauptanwendung von Faltungen hängen mit Zufallsvariablen zusammen. Im Gegensatz zu den punktweisen Operationen, bieten Faltungen probabilistische Interpretationen, wie die Summe oder Multiplikation von Zufallsvariablen. Faltungen können in Envision an ihren zwei Operatoren, die mit * enden, erkannt werden. nämlich:
Z = X +* Y // additive Faltung
Z = X ** Y // multiplikative Faltung
Z = X ^* Y // Faltungspotenz
Die additive Faltung kann als Summe zweier unabhängiger Zufallsvariablen $X+Y$ gedeutet werden. Die multiplikative Faltung, auch als Dirichlet-Faltung bezeichnet, kann als das Produkt zweier unabhängiger Zufallsvariablen interpretiert werden.

Die Faltungspotenz ist etwas komplexer und stellt Folgendes dar: $$X ^ Y = \sum_{k=0}^{\infty} X^k \mathbf{P}[Y=k] \text{ wo } X^k = X + \dots + X \text{ ($k$ Mal)}$$ Diese letzte Operation ist aufgrund ihres Bezugs zum Prozess der integrierten Bedarfsprognose interessant, bei der $X$ den täglichen Bedarf, der als stationär betrachtet wird, und $Y$ die probabilistischen Durchlaufzeiten darstellt.