20.6.1 Task-Project 2
Project 2 is based on the following task: calculating the adjoints of a (square) matrix via Laplace's evolution theorem.
This solution idea was developed: When calculating the adjoints of a matrix - as transpose of the co-factor matrix - a large number of sub-determinants (minors) must be calculated, which generally have nothing to do with each other. The task is broken down into n subtasks for calculating sub-determinants.
This proposal for implementation arose from the solution idea:
- List itemIn the task class, a Main() function is declared where the same algorithm can be used for all calculations of the sub-determinants:
Public Function Main() As Variant
'-- Calculate array of sub-determinants...
Return aFloatArray
End
- In the (main) programme, a separate task is started in each case in a FOR-NEXT control structure, in which n sub-determinants are calculated. The processing of the n sub-tasks is delegated to one task each! The individual tasks are started sequentially, but then all run in parallel. Unfortunately, this will hardly be noticed in practice because the calculations - even for a matrix of dimension 30 - are so short on modern computers.
- If all n sub-determinants are calculated, then the adjoints are calculated from the n partial solutions and output.
The following specifications apply:
- 2 arguments are passed to each of the tasks.
- The tasks are passed both the matrix on which they are to work and the specific row in which all co-factors are to be determined as arguments when they are created (_new() in the task class).
- Only the function value of the main method (data type Variant) in the Task_Kill() event is read out with LAST.Value after the automatic termination of the tasks and temporarily stored in a matrix.
The source texts for the task class and the main programme are given in full. The above solution idea is implemented in them. First, the content of the task class is presented - stored in the file TaskMinors.class:
' Gambas class file '-- This class calculates the minors of the specified matrix when the specified row has been deleted. '-- The function value is an appropriately sized float array of the individual determinants. 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 '-- The function value is of the data type float array End Private Function Tag_Read() As Variant Return $vTag End Private Sub Tag_Write(Value As Variant) $vTag = Value End
File MMain.module:
' Gambas module file ' -- Dimension of a random square 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 '-- Create matrix of the given dimension with random elements $hMatrix = RandomMatrix() Print "Matrix:";; $hMatrix.ToString() $hAdjugate = New Matrix($hMatrix.Width, $hMatrix.Height) $iTasks = 0 For iRow = 0 To $hMatrix.Height – 1 '-- k task are created For iCol = 0 To $hMatrix.Width - 1 '-- Calculate all minors when deleting row iRow hDet = New TaskMinors($hMatrix, iRow) As "TaskMinors" hDet.Tag = iRow Inc $iTasks '-- Counts the started tasks Next '-- The tasks are started after their instantiation at the next call of the event loop. So that '-- not to start them all at once, let each individual task start via WAIT. Wait Next '-- Wait for the calculation of the adjoints (-->> Minor_Kill()) While $iTasks '-- As long as calculations are still being made ... Wait 0.001 '-- ...wait 0.001 seconds Wend Print "Adjunkte adj(A):";; $hAdjugate.ToString() '-- Display adjuncts End Public Sub TaskMinors_Kill() Dim iRow, iCol As Integer Dim aDet As Float[] = Last.Value iRow = Last.Tag For iCol = 0 To aDet.Max '-- The adjoints is the transpose of the co-factor matrix. $hAdjugate[iCol, iRow] = IIf(Even(iRow + iCol), 1, -1) * aDet[iCol] Next Dec $iTasks '-- Decrease the number of tasks by 1 End 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 '-- Provide matrix with random elements End
This was output to the IDE console for a calculation with dimension 3:
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]]
Note that with matrices of higher dimension (>10) rounding errors already have a very strong effect on the result. The identity adj(A) = det(A)∙A^(-1) provides a more precise calculation of the adjoints.
