Dem Projekt 2 liegt die folgende Aufgabe zugrunde: Berechnung der Adjunkte einer (quadratischen) Matrix über den Laplace'schen Entwicklungssatz.
Diese Lösungsidee wurde entwickelt: Bei der Berechnung der Adjunkte einer Matrix – als Transponierte der Co-Faktor-Matrix – müssen sehr viele Unter-Determinanten (Minoren) berechnet werden, die i.A. nichts mit einander zu tun haben. Die Aufgabe wird in n Teilaufgaben zur Berechnung von Unter-Determinanten zerlegt.
Aus der Lösungsidee entstand dieser Vorschlag zur Umsetzung:
Public Function Main() As Variant ' Array von Unter-Determinanten berechnen... Return aFloatArray End
Es gelten folgende Spezifikationen:
Die Quelltexte für die Task-Klasse und das Haupt-Programm werden vollständig angegeben. In ihnen wird die o.a. Lösungsidee umgesetzt. Zuerst wird der Inhalt der Task-Klasse vorgestellt – gespeichert in der Datei TaskMinors.class:
' Gambas class file ' Diese Klasse berechnet die Minoren der angegebenen Matrix, wenn die angegebene Zeile gestrichen wurde. ' Der Funktionswert ist ein entsprechend dimensioniertes Float-Array der einzelnen Determinanten. Inherits Task Property Tag As Variant Private $hMatrix As Matrix Private $vTag As Variant Private $iRow As Integer Public Sub _new({Matrix} As Matrix, Row As Integer) $hMatrix = {Matrix} $iRow = Row End ' _new(..) Public Function Main() As Variant Dim hMinor As New Matrix($hMatrix.Width - 1, $hMatrix.Width - 1) Dim iRemCol, iSrcRow, iSrcCol, iDstRow, iDstCol As Integer Dim aFloatArray As New Float[] For iRemCol = 0 To hMinor.Width ' Untermatrix aufbauen iDstRow = 0 For iSrcRow = 0 To hMinor.Height If iSrcRow = $iRow Then Continue iDstCol = 0 For iSrcCol = 0 To hMinor.Width If iSrcCol = iRemCol Then Continue hMinor[iDstRow, iDstCol] = $hMatrix[iSrcRow, iSrcCol] Inc iDstCol Next Inc iDstRow Next aFloatArray.Add(hMinor.Det()) Next Return aFloatArray ' Funktionswert vom Datentyp Float-Array End ' Function Main() As Variant Private Function Tag_Read() As Variant Return $vTag End ' Function Tag_Read() Private Sub Tag_Write(Value As Variant) $vTag = Value End ' Tag_Write(Value As Variant)
Datei MMain.module:
' Gambas module file ' Dimension einer zufälligen quadratischen Matrix (d > 1) Const Dimension As Integer = 15 ' Maximum 30 Private $hMatrix As Matrix Private $hAdjugate As Matrix Private $iTasks As Integer Public Sub Main() Dim iRow, iCol As Integer Dim hDet As TaskMinors Dim hOther As Matrix ' Matrix der vorgegebenen Dimension mit zufälligen Elementen erzeugen $hMatrix = RandomMatrix() Print "Matrix:";; $hMatrix.ToString() $hAdjugate = New Matrix($hMatrix.Width, $hMatrix.Height) $iTasks = 0 For iRow = 0 To $hMatrix.Height – 1 ' k Task werden erzeugt For iCol = 0 To $hMatrix.Width - 1 ' Alle Minoren beim Streichen von Zeile iRow berechnen hDet = New TaskMinors($hMatrix, iRow) As "TaskMinors" hDet.Tag = iRow Inc $iTasks ' Zählt die gestarteten Tasks Next ' Die Tasks werden nach ihrer Instantiierung beim nächsten Aufruf der Event-Schleife gestartet. Damit ' nicht alle auf einmal starten hier jeden einzelnen Task über WAIT anlaufen lassen. Wait Next ' Auf die Berechnung der Adjunkte warten (-->> Minor_Kill()) While $iTasks ' So lange noch gerechnet wird ... Wait 0.001 ' ...0.001 Sekunden warten Wend Print "Adjunkte adj(A):";; $hAdjugate.ToString() ' Anzeige Adjunkte End ' Main() Public Sub TaskMinors_Kill() Dim iRow, iCol As Integer Dim aDet As Float[] = Last.Value iRow = Last.Tag For iCol = 0 To aDet.Max ' Die Adjunkte ist die Transponierte der Co-Faktor-Matrix. $hAdjugate[iCol, iRow] = IIf(Even(iRow + iCol), 1, -1) * aDet[iCol] Next Dec $iTasks ' Task-Anzahl um 1 verringern End ' TaskMinors_Kill() Public Function RandomMatrix() As Matrix Dim hMatrix As New Matrix(Dimension, Dimension, False) Dim iRow, iCol As Integer For iRow = 0 To hMatrix.Height - 2 hMatrix[iRow, 0] = Rnd(0, hMatrix.Height + 1) For iCol = 1 To hMatrix.Width - 1 hMatrix[iRow, iCol] = IIf(iRow = iCol, iRow + 1, hMatrix.Height) Next Next For iCol = 0 To hMatrix.Width - 1 hMatrix[hMatrix.Height - 1, iCol] = Rnd(0, hMatrix.Width + 1) Next Return hMatrix ' → Matrix mit zufälligen Elementen bereitstellen End ' RandomMatrix() As Matrix
Das wurde in der Konsole der IDE für eine Berechnung mit der Dimension 3 ausgegeben:
Matrix:
[[0.13973 | 3 | 3] ; [0.60071 | 2 | 3] ; [2.73226 | 0.28943 | 2.89609]]
Adjunkte adj(A):
[[4.92387 | -7.81996 | 3] ; [6.45708 | -7.79211 | 1.38293] ; [-5.29066 | 8.15636 | -1.52266]]
Beachten Sie, dass sich bei Matrizen höherer Dimension (>10) Rundungsfehler bereits sehr stark auf das Ergebnis auswirken. Die Identität adj(A) = det(A)∙A^(-1) liefert eine präzisere Berechnung der Adjunkten.