"# Arrays, Vektoren, Matrizen und Lineare Algebra"
]
},
{
"cell_type": "markdown",
"id": "0e2d205f-2d14-4f9f-ac94-9addc71dd662",
"metadata": {},
"source": [
"## Arrays\n",
"\n",
"Ein Array ist eine Folge von Werten, die jeden beliebigen Typs sein können. Die Werte in einem Array werden Elemente oder manchmal auch Items genannt.\n",
"\n",
"Es gibt mehrere Möglichkeiten, ein neues Array zu erstellen; die einfachste besteht darin, die Elemente in eckige Klammern (`[ ]`) einzuschließen:\n"
"Das erste Beispiel ist ein Array von vier Ganzzahlen. Das zweite ist ein Array von fünf Zeichenketten. Die Elemente eines Arrays müssen nicht denselben Typ haben. Das folgende Array enthält eine Zeichenkette, eine Gleitkommazahl, eine Ganzzahl und ein weiteres Array:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "52cb6c55-90c0-459b-86cf-ae35ab43abcf",
"metadata": {},
"outputs": [],
"source": [
"a3 = [\"spam\", 2.0, 5, [10, 20]]\n"
]
},
{
"cell_type": "markdown",
"id": "9b2b7f36-e8a4-4d5a-afd8-e0598dca60bc",
"metadata": {},
"source": [
"Ein Array innerhalb eines anderen Arrays kann verschachtelt sein.\n",
"Ein Array, das keine Elemente enthält, wird als leeres Array bezeichnet; es kann mit leeren Klammern, d.h. `[]`, erstellt werden.\n"
"Die Art des Arrays wird zwischen geschweiften Klammern angegeben und besteht aus einem Typ und einer Zahl. Die Zahl gibt die Dimensionen an. Das leere Array enthält Werte vom Typ `Any`, d.h. es kann Werte aller Typen aufnehmen.\n",
"\n",
"Die Syntax zum Zugriff auf die Elemente eines Arrays ist der eckige Klammernoperator. Der Ausdruck innerhalb der Klammern gibt den Index an. Beachten Sie, dass die Indizes bei 1 beginnen:\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "0ab05daa-9cb1-4dcd-9a01-03dda978de6f",
"metadata": {},
"outputs": [],
"source": [
"cheeses[1]\n"
]
},
{
"cell_type": "markdown",
"id": "d927a90b-f602-4e02-9183-3d96233f0e9d",
"metadata": {},
"source": [
"Im Gegensatz zu Tupeln sind Arrays **veränderlich**. Wenn der eckige Klammernoperator auf der linken Seite einer Zuweisung erscheint, identifiziert er das Element des Arrays, das zugewiesen wird:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "01a4d81f-ddd4-4fa0-a1de-e5cfa13b496f",
"metadata": {},
"outputs": [],
"source": [
"cheeses[2] = \"Gorgonzola\"\n",
"print(cheeses)\n"
]
},
{
"cell_type": "markdown",
"id": "1f6ef27c-3265-4fb1-95ef-cd782d67c529",
"metadata": {},
"source": [
"Die Regeln für Array-Indizes lauten wie folgt:\n",
" - Jeder ganzzahlige Ausdruck kann als Index verwendet werden.\n",
" - Wenn Sie versuchen, auf ein Element, das nicht existiert, zuzugreifen oder zu überschreiben, erhalten Sie einen `BoundsError`.\n",
" - Das Schlüsselwort `end` zeigt auf den letzten Index des Arrays.\n",
"\n",
"Der Operator `∈` (oder `in`) funktioniert auch bei Arrays:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "576fd3ae-aa20-4178-a52c-ac8e4b4fed29",
"metadata": {},
"outputs": [],
"source": [
"@show \"Gouda\" ∈ cheeses\n",
"@show \"Brie\" in cheeses;\n"
]
},
{
"cell_type": "markdown",
"id": "7b1e1fab-3c3e-405c-b7dd-f03d4a23d200",
"metadata": {},
"source": [
"### Durchlaufen eines Arrays\n",
"\n",
"Die häufigste Methode, um die Elemente eines Arrays zu durchlaufen, ist mit einer for-Schleife. Die Syntax ist die gleiche wie bei Zeichenketten:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "51885e2d-3055-4433-b0f8-e561c88f888b",
"metadata": {},
"outputs": [],
"source": [
"for cheese in cheeses\n",
" println(cheese)\n",
"end\n"
]
},
{
"cell_type": "markdown",
"id": "512d919e-cb7a-483c-aa61-0ef08baab3ad",
"metadata": {},
"source": [
"Dies funktioniert gut, wenn Sie nur die Elemente des Arrays lesen müssen, da Sie nur Kopien der Elemente erhalten und das Ändern der Kopien das Array nicht verändert. Wenn Sie jedoch die Elemente überschreiben oder aktualisieren möchten, benötigen Sie die Indizes. Eine gängige Methode, dies zu tun, ist die Verwendung der integrierten Funktion `eachindex`:\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "00b187f3-7a0d-4741-82e3-7dc286dcf34f",
"metadata": {},
"outputs": [],
"source": [
"for i in eachindex(numbers)\n",
" numbers[i] = numbers[i] * 2\n",
"end\n"
]
},
{
"cell_type": "markdown",
"id": "f4a5928a-fcc0-4121-b117-fc6a66b7aa78",
"metadata": {},
"source": [
"Eine `for`-Schleife über ein leeres Array führt niemals den Körper aus:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "17ebecd7-63cc-46d8-b2c5-8721aa616e26",
"metadata": {},
"outputs": [],
"source": [
"for x in []\n",
" println(\"This can never happens.\")\n",
"end\n"
]
},
{
"cell_type": "markdown",
"id": "7938c983-b5a4-420c-88b4-c1c9a5c5cc90",
"metadata": {},
"source": [
"`length` gibt die Anzahl der Elemente im Array zurück.\n",
"Obwohl ein Array ein anderes Array enthalten kann, zählt das verschachtelte Array immer noch als ein einzelnes Element. Die Länge dieses Arrays beträgt vier:"
"Der Slice-Operator ermöglicht es Ihnen, Teile eines Arrays auszuwählen."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "7d31afed-81c8-42ef-bbb3-18d1c1d16548",
"metadata": {},
"outputs": [],
"source": [
"t = ['a', 'b', 'c', 'd', 'e', 'f']\n",
"print(t[1:3])\n",
"print(t[3:end])\n"
]
},
{
"cell_type": "markdown",
"id": "406a15ee-6bd8-45eb-a03b-fed62fe7f99a",
"metadata": {},
"source": [
"Der Slice-Operator `[:]` erstellt eine Kopie des gesamten Arrays. Beachten Sie, dass `t2 = t` keine Kopie erstellt. \n",
"Da Arrays veränderlich sind, ist es oft nützlich, eine Kopie zu erstellen, bevor Operationen durchgeführt werden, die Arrays verändern."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "c73d80ff-ab60-418f-a0a4-0b2fae76f42e",
"metadata": {},
"outputs": [],
"source": [
"t1 = t[:]\n",
"@show t1 === t\n",
"\n",
"t2 = t\n",
"@show t2 === t;\n"
]
},
{
"cell_type": "markdown",
"id": "ba8b2dcc-0f00-42f1-a850-579448a86d8e",
"metadata": {},
"source": [
"Ein Slice-Operator auf der linken Seite einer Zuweisung kann mehrere Elemente aktualisieren:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "c75b53ad-a98b-451c-be5a-9e0d939e23c3",
"metadata": {},
"outputs": [],
"source": [
"t[2:3] = ['x', 'y']\n",
"print(t)\n"
]
},
{
"cell_type": "markdown",
"id": "1ce6853d-6d8e-4bea-a342-4969c63352d5",
"metadata": {},
"source": [
"### Array-Bibliothek\n",
"Julia stellt Funktionen bereit, die auf Arrays wirken. Zum Beispiel fügt `push!` ein neues Element am Ende eines Arrays hinzu (beachten Sie das Ausrufezeichen, da es veränderlich ist). `pushfirst!` fügt ein neues Element am Anfang des Arrays hinzu."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "680e7967-fffb-4112-afb2-422e8e6b87ba",
"metadata": {},
"outputs": [],
"source": [
"t = ['a', 'b', 'c']\n",
"push!(t, 'd')\n",
"pushfirst!(t, '0')\n",
"print(t)\n"
]
},
{
"cell_type": "markdown",
"id": "4770945a-ff8e-4c60-82a2-0b545f569f47",
"metadata": {},
"source": [
"`append!` fügt die Elemente des zweiten Arrays am Ende des ersten hinzu:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "b614b4ef-f34a-4aad-8b6d-973ffc8e16de",
"metadata": {},
"outputs": [],
"source": [
"t1 = ['a', 'b', 'c']\n",
"t2 = ['d', 'e']\n",
"append!(t1, t2)\n",
"print(t1)\n"
]
},
{
"cell_type": "markdown",
"id": "769aee98-5aeb-402b-81d7-23d81d596966",
"metadata": {},
"source": [
"Die Funktion `insert!` fügt ein Element an einem bestimmten Index ein:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "a1cb2569-4b2b-4e8c-a9bd-2bb0a14bfbca",
"metadata": {},
"outputs": [],
"source": [
"t = ['a', 'b', 'c']\n",
"print(insert!(t, 2, 'x'))\n"
]
},
{
"cell_type": "markdown",
"id": "2e5a4efd-a107-4129-b3ee-de9af8ce0284",
"metadata": {},
"source": [
"`sort!` ordnet die Elemente des Arrays von niedrig nach hoch, während `sort` eine Kopie der Elemente des Arrays in sortierter Reihenfolge zurückgibt:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "81fa98e2-4bad-4db9-a784-411069ab167b",
"metadata": {},
"outputs": [],
"source": [
"t1 = ['d', 'c', 'e', 'b', 'a']\n",
"t2 = ['d', 'c', 'e', 'b', 'a']\n",
"\n",
"sort!(t1)\n",
"println(t1)\n",
"\n",
"t3 = sort(t2)\n",
"println(t3)\n",
"@show t3 === t2;\n"
]
},
{
"cell_type": "markdown",
"id": "c3e790e9-fa20-41d1-b43b-67ba30f89229",
"metadata": {},
"source": [
"Es gibt mehrere Möglichkeiten, Elemente aus einem Array zu löschen. Wenn Sie den Index des zu löschenden Elements kennen, können Sie `splice!` verwenden. `splice!` ändert das Array und gibt das entfernte Element zurück. `deleteat!` tut dasselbe, gibt jedoch das Element nicht zurück."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "f391ab7c-2890-4b70-904a-8e606ec424f2",
"metadata": {},
"outputs": [],
"source": [
"t = ['a', 'b', 'c']\n",
"element = splice!(t, 2)\n",
"println(t)\n",
"println(element)\n"
]
},
{
"cell_type": "markdown",
"id": "b74c89cd-8d90-459f-a403-5276474736ee",
"metadata": {},
"source": [
"`pop!` löscht das letzte Element und gibt es zurück:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "47cee6d5-78c2-4f44-af74-054e05fb0d2c",
"metadata": {},
"outputs": [],
"source": [
"t = ['a', 'b', 'c']\n",
"element = pop!(t)\n",
"println(t)\n",
"println(element)\n"
]
},
{
"cell_type": "markdown",
"id": "4c08249e-8340-424a-8ce2-4469df29e8ed",
"metadata": {},
"source": [
"### Übung\n",
" - Die Kernfunktionalität bietet mehrere andere Funktionen, die auf ein Array wirken. Versuchen Sie die folgenden Funktionen mit einem Array `x` und versuchen Sie zu erraten, was sie tun: `ndims(x)`, `eltype(x)`, `length(x)`, `size(x)`, `size(x, 1)`, `reshape(x, 3, 3)`."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "2c6e8e00-924b-4c88-8d8c-dfbcd18c6733",
"metadata": {},
"outputs": [],
"source": [
"x = [1, 2, 3, 4, 5, 6, 7, 8, 9];\n",
"# TODO implement your code here\n"
]
},
{
"cell_type": "markdown",
"id": "cc1d4b7f-5639-4638-aea3-52e2d52f8fd4",
"metadata": {},
"source": [
"### Punkt-Syntax\n",
"Für jeden binären Operator wie `^` gibt es einen entsprechenden Punktoperator `.^`, der automatisch definiert ist, um ^ elementweise auf Arrays anzuwenden. Zum Beispiel ist `[1, 2, 3]^3` nicht definiert, aber `[1, 2, 3].^3` ist definiert und berechnet das ergebnis für jedes Element `[1^3, 2^3, 3^3]`:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "0aa2e922-aa84-455c-8737-dcaee139a1ba",
"metadata": {},
"outputs": [],
"source": [
"print([1, 2, 3] .^ 3)\n"
]
},
{
"cell_type": "markdown",
"id": "7a18830c-f3cd-469d-a0b9-f206ee7aec7b",
"metadata": {},
"source": [
"Jede Julia-Funktion `f` kann mit der Punkt-Syntax elementweise auf jedes Array angewendet werden. Zum Beispiel, um ein Array von Zeichenketten zu großzügig machen, benötigen wir keine explizite Schleife:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "ea7d08d7-1417-47e1-be71-abeb8ba80c1e",
"metadata": {},
"outputs": [],
"source": [
"t = uppercase.([\"abc\", \"def\", \"ghi\"])\n",
"print(t)\n"
]
},
{
"cell_type": "markdown",
"id": "073001cf-0661-4827-b693-a08ca06967b7",
"metadata": {},
"source": [
"### Arrays und Zeichenketten\n",
"\n",
"Eine Zeichenkette ist eine Folge von Zeichen und ein Array ist eine Folge von Werten, aber ein Array von Zeichen ist nicht dasselbe wie eine Zeichenkette. Um von einer Zeichenkette zu einem Array von Zeichen zu konvertieren, können Sie die Funktion `collect` verwenden:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "a6e467ca-3130-449d-b876-f77720b515b5",
"metadata": {},
"outputs": [],
"source": [
"print(collect(\"spam\"))\n"
]
},
{
"cell_type": "markdown",
"id": "72c17230-0d1b-46ba-9711-1eb3328839c5",
"metadata": {},
"source": [
"Wenn Sie eine Zeichenkette in Wörter zerlegen möchten, können Sie die Funktion `split` verwenden. Das Standardtrennzeichen ist das Leerzeichen, aber Sie können ein benutzerdefiniertes Trennzeichen als zweites Argument übergeben."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "96a09506-444f-4733-b047-f5de500fbfc2",
"metadata": {},
"outputs": [],
"source": [
"@show split(\"building an array of strings\")\n",
"@show split(\"02.11.2023\", \".\");\n"
]
},
{
"cell_type": "markdown",
"id": "51981f83-608f-4c41-9321-13de5facb204",
"metadata": {},
"source": [
"Schließlich ist `join` die Umkehrung von split. Es nimmt ein Array von Strings und verkettet die Elemente:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "43e7272d-2a32-441f-86c0-2fa532411ff6",
"metadata": {},
"outputs": [],
"source": [
"t = [\"building\", \"a\", \"string\"]\n",
"@show join(t)\n",
"@show join(t, \" \")\n",
"@show join(t, \"-\");\n"
]
},
{
"cell_type": "markdown",
"id": "acf522cd-0297-4f5c-873a-3309ce68b9d8",
"metadata": {},
"source": [
"### Übungen\n",
" - Schreiben Sie eine Funktion namens `reverse_array(x)`, die als Eingabe ein Array nimmt und ein **neues** Array mit den Elementen in umgekehrter Reihenfolge zurückgibt."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "45c7bffe-c8df-440f-9db0-7923969c20fb",
"metadata": {},
"outputs": [],
"source": [
"# TODO: implement your code here\n"
]
},
{
"cell_type": "markdown",
"id": "927e6892-cc03-452f-bd65-ec895cae47ff",
"metadata": {},
"source": [
" - Schreiben Sie eine Funktion namens `reverse_array!(x)`, die das Array vor Ort ändert, indem sie seine Elemente umkehrt."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "19607e02-107e-4edd-90a8-abdca24fae6f",
"metadata": {},
"outputs": [],
"source": [
"# TODO: implement your code here\n"
]
},
{
"cell_type": "markdown",
"id": "b0311dcb-964b-457c-b041-789673f732ca",
"metadata": {},
"source": [
" - Schreiben Sie eine Funktion namens `even_numbers(x)`, die als Eingabe ein Array von Ganzzahlen nimmt und ein neues Array zurückgibt, das nur die geraden Elemente enthält."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "9babe5e0-2c11-4481-9938-42ec2f697e6b",
"metadata": {},
"outputs": [],
"source": [
"# TODO: implement your code here\n"
]
},
{
"cell_type": "markdown",
"id": "d4b62fae-5d5d-46ac-94d8-b99b9f8aeb13",
"metadata": {},
"source": [
"## Vektoren und Matrizen\n",
"\n",
"Im Allgemeinen können Arrays beliebig viele Dimensionen haben. Mit dieser Zeile instantiieren wir ein 2x3x4-Array aus ganzen Nullen."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "af571cb0-92be-4876-9a66-6217620c9671",
"metadata": {},
"outputs": [],
"source": [
"A = zeros(Int, 2, 3, 4)\n",
"@show typeof(A);\n"
]
},
{
"cell_type": "markdown",
"id": "d806b78a-e97f-47b1-9ecb-409bf5a2c1c2",
"metadata": {},
"source": [
"Wenn jedoch die Dimension des Arrays 1 oder 2 ist, ist der Typ entsprechend `Vector` oder `Matrix`."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "46f3c7e3-e592-47df-abf4-3b9d650fb68d",
"metadata": {},
"outputs": [],
"source": [
"v = [1, 2, 3, 4, 5]\n",
"@show typeof(v)\n",
"m = [1 2 3; 4 5 6; 7 8 9]\n",
"@show typeof(m);\n"
]
},
{
"cell_type": "markdown",
"id": "3e29c3ab-1fdb-4e74-b4fc-ca77690a33f1",
"metadata": {},
"source": [
"**Hinweis:** Zur Instantiierung einer Matrix sind keine Kommas zwischen den Elementen erforderlich. Die folgende Zeile wird eine 1x3-Matrix und nicht einen Vektor erzeugen."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "490491f2-313b-41e2-9015-1ef7687beded",
"metadata": {},
"outputs": [],
"source": [
"m = [1 2 3]\n",
"@show typeof(m);\n"
]
},
{
"cell_type": "markdown",
"id": "62dfd73b-dd75-4dcc-970d-02c9881627bf",
"metadata": {},
"source": [
"Sie können auch explizit überprüfen, dass ein Vektor einfach ein eindimensionales Array ist und dass eine Matrix einfach ein zweidimensionales Array ist."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "7c19aca9-a3ab-4ae7-9ecf-021ef89e73c8",
"metadata": {},
"outputs": [],
"source": [
"@show Vector{Any} === Array{Any, 1}\n",
"@show Matrix{Any} === Array{Any, 2}\n",
"@show Matrix{Any} === Array{Any, 3};\n"
]
},
{
"cell_type": "markdown",
"id": "a2957207-e7b7-43d4-9015-c2649bcc4183",
"metadata": {},
"source": [
"**Hinweis:** `Array` und `Vector` sind immer konkrete Typen, unabhängig von der Art der Elemente. Daher geben die üblichen Typbeziehungen nicht die erwarteten Ergebnisse:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "c94e645f-1e50-4999-be3b-e97de198b2d9",
"metadata": {},
"outputs": [],
"source": [
"@show Vector{Float32} <: Vector{Real}\n",
"@show Vector{Real} <: Vector{Any};\n"
]
},
{
"cell_type": "markdown",
"id": "a101372e-20c1-4ff6-87c7-99ac21ac9f88",
"metadata": {},
"source": [
"### Vektoren\n",
"\n",
"Vektoren können mit eckigen Klammern `[]` erstellt werden oder durch Verwendung des `Vector`-Konstrukts. Der Datentyp kann explizit angegeben werden."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "e9049f28-4a9f-4416-9f80-664e7d786bc1",
"metadata": {},
"outputs": [],
"source": [
"v1 = [1, 2, 3]\n",
"v2 = Float32[1, 2, 3]\n",
"@show typeof(v1)\n",
"@show typeof(v2);\n"
]
},
{
"cell_type": "markdown",
"id": "a312114c-525c-42e5-8676-40e382a789c0",
"metadata": {},
"source": [
"Es gibt auch andere schnelle Möglichkeiten, Arrays mit üblichen Inhalten wie Nullen, Einsen oder Zufallszahlen zu erzeugen."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "0331ed6e-b857-4074-84bf-dc9eb9c95fc1",
"metadata": {},
"outputs": [],
"source": [
"v1 = zeros(5)\n",
"v2 = ones(5)\n",
"v3 = rand(5)\n",
"@show v1 v2 v3;\n"
]
},
{
"cell_type": "markdown",
"id": "59c0734e-99e9-4450-a9e1-e970233d5b44",
"metadata": {},
"source": [
"Es ist auch möglich, einen bestimmten Datentyp zu erzwingen."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "a0b81571-1044-48ab-9cf6-639c32b4738f",
"metadata": {},
"outputs": [],
"source": [
"v1 = zeros(Integer, 5)\n",
"v2 = ones(Float32, 5)\n",
"v3 = rand(Float32, 10)\n",
"@show v1 v2 v3;\n"
]
},
{
"cell_type": "markdown",
"id": "28a32ca8-3eb2-4113-a293-822e95f96b81",
"metadata": {},
"source": [
"Standardmäßige mathematische Operationen können mit der üblichen Notation durchgeführt werden."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "53a0f9b1-83ea-4914-9546-db5c248c7852",
"metadata": {},
"outputs": [],
"source": [
"v1 = [1, 2, 3]\n",
"v2 = [1, 1, 1]\n",
"\n",
"@show v1 - v2\n",
"@show v1 + 2*v2;\n"
]
},
{
"cell_type": "markdown",
"id": "43b66537-bb2c-487f-8144-d3774f6d8cdf",
"metadata": {},
"source": [
"Das Skalarprodukt kann mit der `dot`-Funktion berechnet werden, die Teil des `LinearAlgebra`-Pakets ist."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "a98bac2e-9b09-4b6e-9666-f19eeddf2f67",
"metadata": {},
"outputs": [],
"source": [
"using LinearAlgebra\n",
"v = [1, 2, 3]\n",
"@show dot(v, v);\n"
]
},
{
"cell_type": "markdown",
"id": "15727030-afce-436e-98ec-e1703b793f2c",
"metadata": {},
"source": [
"Schließlich kann die Transponierte mit dem `'`-Operator abgerufen werden."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "91541224-d1ff-4b07-850f-7fc168851b39",
"metadata": {},
"outputs": [],
"source": [
"@show typeof(v) v\n",
"@show typeof(v') v';\n"
]
},
{
"cell_type": "markdown",
"id": "8996d0f1-a663-4489-8cde-d81110e093b5",
"metadata": {},
"source": [
"### Matrizen\n",
"\n",
"Matrizen können wieder auf verschiedene Arten initialisiert werden."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "cb41a853-5ce9-4c37-8cd4-62f54ff6312b",
"metadata": {},
"outputs": [],
"source": [
"m1 = zeros(Integer, 3, 3)\n",
"m2 = ones(Float32, 3, 3)\n",
"m3 = rand(Float32, 3, 3)\n",
"m4 = Float32[1 2 3; 4 5 6]\n",
"@show m1 m2 m3 m4;\n"
]
},
{
"cell_type": "markdown",
"id": "7339ad4b-fe9b-4161-9eeb-2bad5df510c0",
"metadata": {},
"source": [
"Wenn Sie die Diagonale (als Vektor) haben und eine Diagonalmatrix konstruieren möchten, können Sie die Funktion `diagm` verwenden."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "906b5a91-3a29-4c9c-947a-d8a88a06dec2",
"metadata": {},
"outputs": [],
"source": [
"@show diagm([1, 2, 3]);\n"
]
},
{
"cell_type": "markdown",
"id": "e591d680-3ba9-43a6-a014-5799dfcc1959",
"metadata": {},
"source": [
"Die Einheitsmatrix wird als `I` dargestellt. **Hinweis**: Dies ist eigentlich keine Matrix, sondern eher eine `UniformScaling`, die die Wirkung der Identitätsoperation ohne die Notwendigkeit von alloziertem Speicher bringt. Die einheitlichen Skalierungen passen sich automatisch an die Größe der Matrizen an, auf die sie wirken."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "73a7cd9e-1586-4215-8623-cccd465f6979",
"metadata": {},
"outputs": [],
"source": [
"m1 = [1 2 3; 3 4 5; 6 7 8]\n",
"@show I*m1;\n"
]
},
{
"cell_type": "markdown",
"id": "77643776-b23a-4b2e-b6ee-b84304541d9a",
"metadata": {},
"source": [
"Auch die Operationen `+` und `-` können problemlos auf Matrizen angewendet werden, aber in diesem Fall ist auch die Operation `*` definiert."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "1cbcd610-9cbd-4c73-9632-c4a6d47b374a",
"metadata": {},
"outputs": [],
"source": [
"m1 = [1 2 3; 3 4 5; 6 7 8]\n",
"m2 = [1 0 0; 0 0 0; 0 0 0]\n",
"@show m1 * m2;\n"
]
},
{
"cell_type": "markdown",
"id": "03daee60-cf26-4d80-87a4-18ddebedb8b7",
"metadata": {},
"source": [
"Um die Matrizen zu invertieren, können Sie die Funktion `inv` oder die subtilere Operation `/` verwenden."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "70de8ba6-6f63-4a43-9ff2-efff2b9a1368",
"metadata": {},
"outputs": [],
"source": [
"m1 = [1 2; -1 2]\n",
"@show I/m1;\n",
"@show inv(m1);\n"
]
},
{
"cell_type": "markdown",
"id": "11e3d462-b24f-4099-9590-3ae27af92985",
"metadata": {},
"source": [
"Die Transponierte funktioniert auch bei Matrizen, und beachten Sie, dass bei komplexen Zahlen eine Adjunkte vorliegt."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "e3bbc37c-0bcd-4a54-891f-ec94ee437724",
"metadata": {},
"outputs": [],
"source": [
"m1 = [0 -1im ; 2im 0];\n",
"@show m1\n",
"@show m1';\n"
]
},
{
"cell_type": "markdown",
"id": "a9429302-aeb6-4207-880d-d87ebf87974e",
"metadata": {},
"source": [
"Schließlich ist es auch möglich, die Determinante und die Spur mithilfe der Funktionen `det` bzw. `tr` zu berechnen."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "9b52aabb-fc61-4006-99a8-73bd418e810a",
"metadata": {},
"outputs": [],
"source": [
"m1 = [1 2 3; 3 4 5; 6 7 8]\n",
"@show det(m1);\n",
"@show tr(m1);\n"
]
},
{
"cell_type": "markdown",
"id": "8c1cc9db-da30-4ffd-828c-3fdc1611e113",
"metadata": {},
"source": [
"## Weiterführende Lineare Algebra\n",
"\n",
"Das Paket `LinearAlgebra` implementiert verschiedene fortgeschrittenere Operationen."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "787b534f-57c4-47da-9eb2-cf5c8f8a8344",
"metadata": {},
"outputs": [],
"source": [
"m = [3 0.5 0.1; 0.1 5 0.2; 0.2 0.1 3]\n"
]
},
{
"cell_type": "markdown",
"id": "ff83a09a-6ede-44df-8151-96e7ce961489",
"metadata": {},
"source": [
" - Eigenvalue decomposition"
]
},
{
"cell_type": "markdown",
"id": "026f77af-fb87-4d41-88e3-a5f27f2e7305",
"metadata": {},
"source": [
" - Eigenwertzerlegung"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "d0ac2f75-02c4-482a-b668-baff9aac3128",
"metadata": {},
"outputs": [],
"source": [
"λ, V = eigen(m)\n",
"m1 = V * diagm(λ) * inv(V)\n"
]
},
{
"cell_type": "markdown",
"id": "e9ef9a44-6305-4549-b93e-10b77d2dcd0c",
"metadata": {},
"source": [
" - Singulärwertzerlegung"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "4724ed84-0ac8-41e9-affd-d3ed0b44172b",
"metadata": {},
"outputs": [],
"source": [
"U, λ, V = svd(m)\n",
"m1 = U * diagm(λ) * V'\n"
]
},
{
"cell_type": "markdown",
"id": "039a8cfb-0b4f-42e2-ab13-be9cda23fe0f",
"metadata": {},
"source": [
" - LU-Zerlegung"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "4cfd0965-7f29-473c-86ab-24a50fb4e327",
"metadata": {},
"outputs": [],
"source": [
"L, U = lu(m)\n",
"m1 = L * U\n",
"@show L\n",
"@show U\n",
"@show m1;\n"
]
},
{
"cell_type": "markdown",
"id": "b90bc471-03a2-4257-8f91-aafcf70f9bfb",
"metadata": {},
"source": [
" - Cholesky-Zerlegung (erfordert eine hermitesche Matrix)"
" - Schreiben Sie eine Funktion, die die Quadratwurzel einer Matrix berechnet.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "5553cb6e-c0e4-49c6-b75b-586e14d89426",
"metadata": {},
"outputs": [],
"source": [
"# TODO: implement your code here\n"
]
},
{
"cell_type": "markdown",
"id": "4b1c5ca6-06c7-458f-ad36-1fbf2b8da387",
"metadata": {},
"source": [
" - Implementieren Sie einen Solver für lineare Systeme, der die [Jacobi-Methode](https://de.wikipedia.org/wiki/Jacobi-Verfahren) verwendet. Vergleichen Sie dann das Ergebnis mit der Standardlösung unter Verwendung der Matrixinversion."
Das erste Beispiel ist ein Array von vier Ganzzahlen. Das zweite ist ein Array von fünf Zeichenketten. Die Elemente eines Arrays müssen nicht denselben Typ haben. Das folgende Array enthält eine Zeichenkette, eine Gleitkommazahl, eine Ganzzahl und ein weiteres Array:
Die Art des Arrays wird zwischen geschweiften Klammern angegeben und besteht aus einem Typ und einer Zahl. Die Zahl gibt die Dimensionen an. Das leere Array enthält Werte vom Typ `Any`, d.h. es kann Werte aller Typen aufnehmen.
Die Syntax zum Zugriff auf die Elemente eines Arrays ist der eckige Klammernoperator. Der Ausdruck innerhalb der Klammern gibt den Index an. Beachten Sie, dass die Indizes bei 1 beginnen:
Im Gegensatz zu Tupeln sind Arrays **veränderlich**. Wenn der eckige Klammernoperator auf der linken Seite einer Zuweisung erscheint, identifiziert er das Element des Arrays, das zugewiesen wird:
Dies funktioniert gut, wenn Sie nur die Elemente des Arrays lesen müssen, da Sie nur Kopien der Elemente erhalten und das Ändern der Kopien das Array nicht verändert. Wenn Sie jedoch die Elemente überschreiben oder aktualisieren möchten, benötigen Sie die Indizes. Eine gängige Methode, dies zu tun, ist die Verwendung der integrierten Funktion `eachindex`:
`length` gibt die Anzahl der Elemente im Array zurück.
Obwohl ein Array ein anderes Array enthalten kann, zählt das verschachtelte Array immer noch als ein einzelnes Element. Die Länge dieses Arrays beträgt vier:
Julia stellt Funktionen bereit, die auf Arrays wirken. Zum Beispiel fügt `push!` ein neues Element am Ende eines Arrays hinzu (beachten Sie das Ausrufezeichen, da es veränderlich ist). `pushfirst!` fügt ein neues Element am Anfang des Arrays hinzu.
Es gibt mehrere Möglichkeiten, Elemente aus einem Array zu löschen. Wenn Sie den Index des zu löschenden Elements kennen, können Sie `splice!` verwenden. `splice!` ändert das Array und gibt das entfernte Element zurück. `deleteat!` tut dasselbe, gibt jedoch das Element nicht zurück.
- Die Kernfunktionalität bietet mehrere andere Funktionen, die auf ein Array wirken. Versuchen Sie die folgenden Funktionen mit einem Array `x` und versuchen Sie zu erraten, was sie tun: `ndims(x)`, `eltype(x)`, `length(x)`, `size(x)`, `size(x, 1)`, `reshape(x, 3, 3)`.
Für jeden binären Operator wie `^` gibt es einen entsprechenden Punktoperator `.^`, der automatisch definiert ist, um ^ elementweise auf Arrays anzuwenden. Zum Beispiel ist `[1, 2, 3]^3` nicht definiert, aber `[1, 2, 3].^3` ist definiert und berechnet das ergebnis für jedes Element `[1^3, 2^3, 3^3]`:
Jede Julia-Funktion `f` kann mit der Punkt-Syntax elementweise auf jedes Array angewendet werden. Zum Beispiel, um ein Array von Zeichenketten zu großzügig machen, benötigen wir keine explizite Schleife:
Eine Zeichenkette ist eine Folge von Zeichen und ein Array ist eine Folge von Werten, aber ein Array von Zeichen ist nicht dasselbe wie eine Zeichenkette. Um von einer Zeichenkette zu einem Array von Zeichen zu konvertieren, können Sie die Funktion `collect` verwenden:
Wenn Sie eine Zeichenkette in Wörter zerlegen möchten, können Sie die Funktion `split` verwenden. Das Standardtrennzeichen ist das Leerzeichen, aber Sie können ein benutzerdefiniertes Trennzeichen als zweites Argument übergeben.
- Schreiben Sie eine Funktion namens `reverse_array(x)`, die als Eingabe ein Array nimmt und ein **neues** Array mit den Elementen in umgekehrter Reihenfolge zurückgibt.
- Schreiben Sie eine Funktion namens `even_numbers(x)`, die als Eingabe ein Array von Ganzzahlen nimmt und ein neues Array zurückgibt, das nur die geraden Elemente enthält.
**Hinweis:** Zur Instantiierung einer Matrix sind keine Kommas zwischen den Elementen erforderlich. Die folgende Zeile wird eine 1x3-Matrix und nicht einen Vektor erzeugen.
Sie können auch explizit überprüfen, dass ein Vektor einfach ein eindimensionales Array ist und dass eine Matrix einfach ein zweidimensionales Array ist.
**Hinweis:**`Array` und `Vector` sind immer konkrete Typen, unabhängig von der Art der Elemente. Daher geben die üblichen Typbeziehungen nicht die erwarteten Ergebnisse:
Die Einheitsmatrix wird als `I` dargestellt. **Hinweis**: Dies ist eigentlich keine Matrix, sondern eher eine `UniformScaling`, die die Wirkung der Identitätsoperation ohne die Notwendigkeit von alloziertem Speicher bringt. Die einheitlichen Skalierungen passen sich automatisch an die Größe der Matrizen an, auf die sie wirken.
- Implementieren Sie einen Solver für lineare Systeme, der die [Jacobi-Methode](https://de.wikipedia.org/wiki/Jacobi-Verfahren) verwendet. Vergleichen Sie dann das Ergebnis mit der Standardlösung unter Verwendung der Matrixinversion.