Programmiersprache Kotlin bekommt eine Library für mehrdimensionale Arrays

Multik bildet unter anderem Einheitsmatrizen und Arrays mit bis zu vier Dimensionen ab. Version 0.1 führt zusätzliche Funktionen und komplexe Zahlen ein.

In Pocket speichern vorlesen Druckansicht 23 Kommentare lesen

(Bild: Blackboard/Shutterstock.com)

Lesezeit: 3 Min.
Von
  • Rainald Menge-Sonnentag
Inhaltsverzeichnis

JetBrains hat Version 0.1 der Library Multik für die Programmiersprache Kotlin veröffentlicht. Die Bibliothek bildet multidimensionale Arrays ab und kennt unter anderem Matrizen und Arrays mit bis zu vier Dimensionen. Sie kann mathematische Operationen sowohl über einzelne Elemente als auch über die Arrays ausführen.

Die nun veröffentlichte Version 0.1 erweitert die im Februar erstmals angekündigte Bibliothek um erweiterte Funktionen und Konstrukte wie komplexe Zahlen und LU-Faktorisierung. Außerdem bringt sie Methoden zum Schreiben und Lesen der Inhalte in CSV-Dateien mit.

Laut einem Blogbeitrag vom Februar hatte JetBrains ursprünglich geplant, die Library auf der Basis von NumPy oder ähnlichen Ansätzen aufzusetzen. Allerdings war der damit verbundene Overhead wohl zu groß, sodass Multik als eigenständige Library entstand. Die Datenstrukturen sind getrennt von den Operationen implementiert und müssen als individuelle Dependencies in Projekte eingefügt werden.

Derzeit bietet Multik drei unterschiedliche Engines: multik-jvm ist eine Implementierung der mathematischen Operationen auf der Java Virtual Machine mit Kotlin/JVM, multik-native ist eine C++-Implementierung, die für lineare Algebra auf die Library OpenBLAS setzt, und multik-default ist eine Kombination aus der nativen und der JVM-Umsetzung. Letztere ist, wie der Name vermuten lässt, die standardmäßige Implementierung.

Als einfachste Konstrukte kann die Library einen Vektor oder eine Matrix als zweidimensionales Array aus einer Collection erstellen, wie in folgendem Codebeispiel aus dem Blogbeitrag zur Vorstellung der Library:

val myList = listOf(1, 2, 3)
val a = mk.ndarray(myList)
/* [1, 2, 3] */

val m = mk.ndarray(mk[myList, myList])
/*
[[1, 2, 3],
[1, 2, 3]]
*/

Daneben existieren unter anderem die mk.identity für eine Einheits- oder Identitätsmatrix, die auf der Hauptachse Einsen und im restlichen Bereich Nullen hat, und mk.empty für eine mehrdimensionale Anordnung von Nullen.

Die mehrdimensionalen Arrays lassen sich miteinander addieren, subtrahieren, multiplizieren und dividieren:

val a = mk.ndarray(mk[mk[1.0,2.0], mk[3.0,4.0]])
val b = mk.identity<Double>(2)

a + b
/*
[[2.0, 2.0],
[3.0, 5.0]]
*/

b / a
/*
[[1.0, 0.0],
[0.0, 0.25]]
*/

Daneben erlaubt die Library das direkte Verwenden mathematischer Funktionen auf die jeweiligen Elemente wie mk.math.sin(a). Auch Aggregat-Funktionen zum Bestimmen des Durchschnitts, der Summe oder des Maximums lassen sich verwenden. Die Inhalte lassen sich filtern, gruppieren und sortieren. Schließlich existieren Funktionen zum Indizieren und zum Slicen der Arrays.

Version 0.1 führt zusätzliche Konstrukte und Operationen ein, darunter die Zerlegung einer Matrix in eine untere und eine obere Dreiecksmatrix über LU-Faktorisierung:

Zerlegen einer Matrix in eine Permutations-Matrix sowie eine obere und eine untere Dreiecksmatrix.

(Bild: JetBrains)

Die zusätzliche neu eingeführte Methode solve dient zum Lösen linearer Gleichungssysteme, wie folgendes Beispiel aus dem Blogbeitrag zur Veröffentlichung der jüngsten Version demonstriert:

val a = mk.ndarray(mk[mk[2, 5, 1], mk[7, 3, 1], mk[8, 9, 4]])
val b = mk.ndarray(mk[3, 1, 2])
mk.linalg.solve(a, b)
// [-0.036363636363636265, 0.9090909090909091, -1.4727272727272729]

Weitere Neuzugänge sind die QR-Faktorisierung und die Inverse Matrix. Daneben existieren nun Funktionen zum Zusammenfügen beziehungsweise Kombinieren von Arrays über append und stack.

Außerdem kann die Library neuerdings komplexe Zahlen abbilden, die als re + i * im beschrieben sind, wobei re den Realteil beschreibt und i * im den Part, bei dem i die imaginäre Einheit ist, deren Quadratzahl -1 ergibt ( = -1):

val cf = ComplexFloat(1f, 2f) // 1.0+(2.0)i
val cd = ComplexDouble.one // 1.0+(0.0)i

Die beiden neuen Klassen für komplexe Zahlen als Float- beziehungsweise Double-Umsetzungen lassen sich wohl ebenso verwenden wie die Number-Klassen, sodass die mathematischen Operatoren sich direkt nutzen lassen.

Weitere Details zu der Library und den Neuerungen in Version 0.1 lassen sich dem Kotlin-Blog bei JetBrains entnehmen.

(rme)