scoring-matrix( a=filePath, b=function, c, [d, e, ...]
Gruppe |
Diese Funktion ist veraltet (deprecated).
Diese Funktion gibt eine Scoring-Entscheidung zurück, welche auf der Grundlage einer CSV-Matrix getroffen wird. Ziel ist es, aus einer Menge von Anbietern den günstigsten zu finden, abhängig von konkreten Parameter-Werten. Als praktisches Beispiel könnte man aus einer Menge von Spediteuren den für ein konkretes Transportgut besten Spediteur suchen, abhängig von den konkreten Eigenschaften des Transportgutes (Kühlung erforderlich, Gewicht, Expresstransport, .).
Die Gesamtentscheidung kann aus mehreren Einzelentscheidungen zusammengesetzt werden, wobei jede Einzelentscheidung einem Funktions-Parameter (ab c) zugeordnet wird. Jede Einzelentscheidung liefert einen nicht-negativen Zahlenwert für jeden Anbieter. Diese Zahlenwerte werden multipliziert und liefern für jeden Anbieter einen Scoring-Wert.
Der Anbieter mit dem höchsten Scoring "gewinnt". Sein Name oder Schlüsselwert aus der ersten Spalte der Matrix, ist das Ergebnis des Funktionsaufrufs.
Wenn kein Anbieter einen Score > 0 erreicht, wird ein leerer Wert zurück gegeben.
Kurzbeschreibung des Scoring an einem Beispiel
Vier Spediteure (Sp1, Sp2, Sp3, Sp4) bieten Transportdienste an. Es gibt dabei unterschiedliche Leistungsmerkmale.
K |
Kühltransport möglich. |
A |
Fährt auch ins europäische Ausland. |
S |
Garantierte Zustellung in 8 oder in 24 oder in 48 Stunden oder ohne Garantie, kodiert als S08, S24, S48, STD. |
Um nun den günstigsten Anbieter zu finden, müssen wir für ein Transportgut die Anforderungen definieren, z. B. als Funktionsparameter c, d und e.
c |
Kühlung erforderlich, Boolean (false/true). |
d |
Adressat ist im Ausland, Boolean (false/true). |
e |
Geschwindigkeitsanforderung, String mit den möglichen Werten S08, S24, S48, STD. |
Wir haben drei Einzel-Entscheidungen, die mit den drei Parametern c, d und e getroffen werden. Die beiden booleschen Paramete r c und d h aben jeweils 2 mögliche Zustände, true oder false. Param eter e k ann 4 mögliche Zustände haben. Zu jedem dieser Zustände der Entscheidungen müssen wir jedem Anbieter eine Bewertung geben. Das stellen wir als Matrix dar.
Anbieter |
K.false |
K.true |
A.false |
A.true |
S08 |
S24 |
S48 |
STD |
Sp1 |
1 |
1 |
1 |
1 |
0 |
2 |
1 |
1 |
Sp2 |
1 |
0 |
1 |
2 |
0 |
0 |
1 |
1 |
Sp3 |
1 |
0 |
1 |
0 |
1 |
1 |
0 |
1 |
Sp4 |
0 |
2 |
1 |
0 |
1 |
1 |
0 |
1 |
Sp1 bietet Kühltransporte und ungekühlte Transporte an. Sp4 bietet nur Kühltransporte an, zu einem besseren Preis als SP1. SP2 und SP3 können keine Kühlung bieten.
Alle Anbieter liefern im Inland, Sp1 und SP2 liefern auch ins Ausland, Sp2 hat den besseren Preis bei Lieferung ins Ausland.
Analog die Geschwindigkeit: Alle bieten STD, usw…
Die Entscheidung c (Kühlung) wird durch die Spaltengrupp e 2 + 3 darg estellt, Entscheidung d (Ausland) durc h 4 + 5 un d e (Geschwindigkeit) durch Spa lten 6 + 7 + 8 + 9.
Wenn wir nun einen Anbieter suchen, der innerhalb 24 Stunden Kühlgut ins Ausland fährt, müssen wir Spalt en 3, 5, 7 b erücksichtigen. Die dort hinterlegten Bewertungen werden multipliziert und ergeben den Score. Bei der ersten 0 wird für diesen Anbieter das Scoring abgebrochen. Nur Sp1 erfüllt alle Leistungsmerkmale.
Anbieter |
K.false |
K.true |
A.false |
A.true |
S08 |
S24 |
S48 |
STD |
SCORE |
|
Sp1 |
1 |
1 |
1 |
1 |
0 |
2 |
1 |
1 |
2 |
|
Sp2 |
1 |
0 |
1 |
2 |
0 |
0 |
1 |
1 |
0 |
|
Sp3 |
1 |
0 |
1 |
0 |
1 |
1 |
0 |
1 |
0 |
|
Sp4 |
0 |
2 |
1 |
0 |
1 |
1 |
0 |
1 |
0 |
Nun wollen wir ungekühlte Ware im Inland mit Garantie innerhalb 24 Stunden befördern.
Anbieter |
K.false |
K.true |
A.false |
A.true |
S08 |
S24 |
S48 |
STD |
SCORE |
Sp1 |
1 |
1 |
1 |
1 |
0 |
2 |
1 |
1 |
2 |
Sp2 |
1 |
0 |
1 |
2 |
0 |
0 |
1 |
1 |
0 |
Sp3 |
1 |
0 |
1 |
0 |
1 |
1 |
0 |
1 |
1 |
Sp4 |
0 |
2 |
1 |
0 |
1 |
1 |
0 |
1 |
0 |
Sp2 und Sp4 können ein Leistungsmerkmal nicht. Es bleiben Sp1 und Sp3. Sp3 gewinnt weil er für S24 bessere Konditionen bietet.
Methoden (Parameter b)
Der Parameter b bestimmt die Methode der Funktion. Aktuell wird max und col unterstützt. Default: max.
Methode max entspricht der normalen Funktion: Ergebnis ist der Anbieter der den höchsten Score erreicht, oder ein leerer Wert, wenn kein Anbieter passt.
Methode col wurde zum Debugging bzw. für Fehlermeldungen konzipiert. Ergebnis ist eine Aufzählung der Matrix-Spalten, die für das Scoring verwendet werden. Im obigen Beispiel ist das Ergebnis [3, 5, 7].
Aufbau der Konfigurationsdatei der Funktion
Die Konfigurationsdatei, deren Dateipfad als Parameter a erwartet wird, kann eine CSV-Datei oder eine Excel-Datei (xls oder xslx) sein.
Bei einer Excel-Datei mit mehreren Tabs kann man den Tab explizit angeben. Default ist der erste Tab. (Index=0):
Syntax: |
directory/excel_file.xlsx?0 |
In dieser Datei wird sowohl die Entscheidungs-Matrix erwartet, als auch die Gruppen-Definition. Beide Bereiche werden jeweils durch eine Kommando-Zeile begonnen, die mit !/cmd/, direkt am Zeilenanfang, beginnt.
Kommando |
Bedeutung |
!/cmd/matrix |
Nachfolgend stehen die Zeilen der Entscheidungs-Matrix. |
!/cmd/conf |
Nachfolgend stehen die Zeilen der Gruppen-Definition. |
Der Modus am Beginn der Datei entspricht !/cmd/matrix. Deshalb kann dieses Kommando entfallen, wenn am Dateianfang die Entscheidungs-Matrix steht.
Zeilen, die mit # beginnen, sind Kommentare, die ignoriert werden.
Die Entscheidungs-Matrix
Die Matrix besteht aus CSV-Zeilen, wobei jede Zeile einen Anbieter repräsentiert. Die Felder innerhalb der Zeile sind durch Komma getrennt. Im ersten Feld steht die eindeutige Bezeichnung des Anbieters. Die Felder ab Position 2 entsprechen den Diensten bzw. Leistungen des Anbieters, wobei der im Feld stehende numerische Wert dem Gewicht dieses Dienstes entspricht, also seiner Wertigkeit im Scoring. Negative Werte sind verboten. Positive Ganzzahlen oder Dezimalzahlen mit Dezimal-Punkt sind erlaubt.
Wert 0 bedeutet: Der Anbieter kann diesen Dienst nicht erbringen.
Wert > 0 bedeutet: Der Anbieter kann diesen Dienst erbringen.
Je größer der Wert im Vergleich zu den Werten der anderen Anbieter in der selben Matrix-Spalte ist, um so mehr wird dieser Anbieter bevorzugt.
Welche Matrix-Spalten im konkreten Aufruf für das Scoring der Anbieter verwendet werden, hängt von der Konfiguration der Gruppen und den zugeordneten Aufrufparametern c bis z ab. Das Scoring erfolgt auf der Basis einer oder mehrerer Entscheidungen. Jede Einzelentscheidung bezieht sich auf einen Funktionsparameter (ab c). Jede Einzelentscheidung wird als Gruppe zusammenhängender Matrix-Spalten dargestellt. Die Zuordnung der Gruppen zu den Funktionsparametern erfolgt im zweiten Teil der Konfigurationsdatei in der Gruppen-Definition.
Die Entscheidung (Einzelentscheidung) besteht in der Auswahl der richtigen Spalte innerhalb einer Gruppe in Abhängigkeit vom Wert des Funktionsparameters, der dieser Gruppe zugeordnet ist. Aus dieser Spalte werden die numerischen Werte aller Anbieter für das Scoring verwendet. Die anderen Spalten der Gruppe bleiben unberücksichtigt.
Die Gruppen-Definition
Eine Gruppe besteht aus mehreren zusammenhängenden Spalten der Matrix. Sie ist mit einem Funktionsparameter verbunden und führt eine Entscheidung aus, die vom Wert dieses Parameters abhängt. Die Entscheidung besteht darin, dass immer nur genau eine Spalte der Gruppe verwendet wird. Die anderen Spalten dieser Gruppe werden in diesem Funktionsaufruf nicht berücksichtigt. Je nach Parameterwert kann es in einem anderen Funktionsaufruf eine andere Spalte dieser Gruppe sein.
Pro Gruppe gibt es in jedem Aufruf genau eine ausgewählte Spalte. Für jeden Anbieter (jede Zeile der Matrix) existiert in dieser Spalte ein Wert. Das ist die Bewertung des Anbieters bezüglich des Leistungsmerkmales das der Gruppe entspricht.
Innerhalb der Gruppen-Definition werden Zeilen erwartet, die im ersten Feld group enthalten. Jede Zeile ordnet einen Funktionsparameter zu einer zusammenhängenden Gruppe von Spalten der Entscheidungs-Matrix zu, die wir nachfolgend ColGroup nennen. Eine ColGroup besteht je nach Typ aus zwei oder mehr zusammenhängenden Matrix-Spalten.
Die ColGroups dürfen sich nicht überlappen, das bedeutet: Eine Spalte der Matrix darf nicht zu zwei ColGroups gehören. Das wird durch richtige Festlegung des Offset erreicht.
Aufbau einer Zeile der Gruppen-Definition
group |
offset |
typ |
parameter |
defEnum |
defFactor |
values… |
offset: Im zweiten Feld steht der ganzzahlige Offset der ColGroup. Das ist der Spalten-Index der ersten Spalte, die zur ColGroup gehört.
typ: Im dritten Feld steht der Typ der ColGroup.
parameter: Im vierten Feld steht der Funktionsparameter als Kleinbuchstabe, der mit der ColGroup verbunden wird.
values und defEnum und defFactor: Nur bei Typ enum: Wird unten bei diesem Typ beschrieben.
Folgende Typen werden akzeptiert (Anfangsuchstabe reicht).
ColGroup-Typ |
Beschreibung. |
boolean |
Definiert eine logische Entscheidung. Parameter muss vom Typ Boolean sein (false/true). Die ColGroup hat zwei Spalten, die erste wird bei Wert false verwendet, die zweite bei Wert true. |
enum |
Definiert eine Aufzählung möglicher Werte. Die Werte werden als values in der Definition einer enum festgelegt. Wenn der verbundene Funktionsparameter einen dieser Werte trifft, wird die zugeordnete Spalte der ColGroup verwendet. Wenn der Parameter-Wert keinen der enum-Werte trifft, wird als Parameter-Wert defEnum angenommen. Falls defEnum keinen der values trifft oder leer ist, wird als Ergebnis-Faktor der Teilentscheidung (die dieser ColGroup entspricht) der Wert defFactor verwendet. Wenn auch dieser nicht existiert, wird eine Exception geworfen. |
Es ist möglich, aber wahrscheinlich nicht sinnvoll, mehrere ColGroups zum gleichen Parameter zu verbinden.
Wichtiger Hinweis: Wenn sich zwei ColGroups überlappen, wird der Funktionsaufruf mit einer Exception beendet.
Festlegung der Key-Spalte
Per Default ist die erste Spalte der Matrix die Spalte, die den eindeutigen Schlüsselwert des Anbieters enthält. Normalerweise ist das auch ausreichend. Falls eine andere Spalte als Key verwendet werden soll, kann man mit dem Property keycol in der Konfigurationsdatei den Index ändern.
# Definition der 3. Spalte als Key
keycol=3
Die Werte in der Schlüsselspalte müssen eindeutig (unique) sein. Die Spalte muss in jeder Zeile der Matrix existieren und einen nicht-leeren Wert haben.
Muster der Konfigurationsdatei für das oben beschriebene Beispiel
!/cmd/matrix
Sp1,1,1,1,1,0,2,1,1
Sp2,1,0,1,2,0,0,1,1
Sp3,1,0,1,0,1,1,0,1
Sp4,0,2,1,0,1,1,0,1
!/cmd/conf
group,2,boolean,c
group,4,boolean,d
group,6,enum,e,STD,,S08,S24,S48,STD
Vorrangregel bei gleichem Score
Eventuell kann es vorkommen, dass zwei oder mehrere Anbieter den gleichen Score erreichen. In diesem Fall muss aus der Menge der besten Anbieter ein einzelner Anbieter ausgewählt werden. Grundsätzlich sind zwei Strategien denkbar.
Zufällige Auswahl eines Anbieters aus der Menge.
Reproduzierbare Auswahl aus der Menge.
Die Funktion verwendet die reproduzierbare Auswahl. Der in der Entscheidungs-Matrix am weitesten oben stehende Anbieter aus der Menge der besten (mit gleichem, höchstem Score) wird ausgewählt. Um einem anderen Anbieter den Vorzug zu geben, kann man dessen Bewertung in einer der relevanten Spalten von 1 zu 1.0001 ändern und ihm damit einen geringfügig höheren Score geben.
Fehlerfälle und deren Vermeidung
ColGroups dürfen sich nicht überlappen. Folgende Gruppendefinition wäre ein Fehler.
# Fehler: für c=true und d=false wird die selbe Matrix-Spalte (Index 3) referenziert
group,2,boolean,c
group,3,boolean,d
In diesem Fall wird die Ausführung der Funktion mit einer IllegalArgumentException conflicting ColGroups: beendet.
Dieser Fehler kann z.B. entstehen, wenn zu einer enum ColGroup ein zusätzlicher Wert hinzugefügt wird, ohne dafür in der Matrix eine zusätzliche Spalte einzufügen. Eine ColGroup vom Typ boolean hat immer zwei Spalten, nur bei enum ist es variabel. Deshalb empfehlen wir, beim Design die boolean-Gruppen alle bei kleinen Offset-Werten zu definieren und die enum-Gruppen dahinter. Falls eine spätere Erweiterung einer enum-Gruppe erwartet wird, sollte sie am Ende (bei höchstem Offset) definiert werden. Eventuell kann man auch eine oder mehrere Spalten frei lassen. Die bisher noch nicht verwendeten Matrix-Spalten dürfen leer bleiben. Beispiel:
Sp1,1,1,1,1,0,2,1,1,,,9,4
Sp2,1,0,1,2,0,0,1,1,,,5,7
!/cmd/conf
group,2,boolean,c
group,4,boolean,d
group,6,enum,e,STD,,S08,S24,S48,STD
group,12,enum,f,,,C,N
Die enum bei Offset 6 hat nur 4 Werte. Sie reicht bis zum Index 9. Die folgende enum beginnt bei Offset 12 und lässt dadurch zwei Spalten frei, die auch in der Matrix nicht mit Werten gefüllt sein müssen.
ColGroups dürfen keinen Spaltenindex referenzieren, der in der Matrix gar nicht definiert ist.
# Fehler: enum referenziert Spalten, die in der Matrix nicht definiert sind
Sp1,1,1,1,1,0,2,1,1
Sp2,1,0,1,2,0,0,1,1
!/cmd/conf
group,2,boolean,c
group,4,boolean,d
group,6,enum,e,STD,,S08,S24,S48,STD,S12,N04
Die Enum-Gruppe definiert 6 Werte (S08 bis N04) und beginnt bei Index 6. Der höchste Index ist also 11. Die Matrix hat aber nur 9 Spalten.
In diesem Fall wird eine IllegalArgumentException illegal column index: 11 zum Fehlerabbruch führen.
Die Schlüsselwerte in der Key-Spalte müssen über alle Anbieter eindeutig (unique) sein.
Die Schlüsselspalte dient zur eindeutigen Identifizierung des Anbieters. Das Ergebnis des Funktionsaufrufs (mit Methode b=max) ist der Key des Anbieters mit dem höchsten Score. Dopplungen in dieser Spalte sind daher verboten. Wenn ein doppelter Key auftritt, wird der Funktionsaufruf mit einer IllegalArgumentException duplicate key in matrix line … beendet.