Calculate the determinant of an array : Matrix « Data Type « VB.Net Tutorial

Home
VB.Net Tutorial
1.Language Basics
2.Data Type
3.Operator
4.Statements
5.Date Time
6.Class Module
7.Development
8.Collections
9.Generics
10.Attributes
11.Event
12.LINQ
13.Stream File
14.GUI
15.GUI Applications
16.Windows Presentation Foundation
17.2D Graphics
18.I18N Internationlization
19.Reflection
20.Regular Expressions
21.Security
22.Socket Network
23.Thread
24.Windows
25.XML
26.Database ADO.net
27.Design Patterns
VB.Net
VB.Net by API
VB.Net Tutorial » Data Type » Matrix 
2.46.3.Calculate the determinant of an array
' Quote from
'Visual Basic 2005 Cookbook Solutions for VB 2005 Programmers
'by Tim Patrick (Author), John Craig (Author)
'# Publisher: O'Reilly Media, Inc. (September 212006)
'# Language: English
'# ISBN-100596101775
'# ISBN-13978-0596101770

Public Class Tester
    Public Shared Sub Main
        Dim matrixA(,As Double = _
            {123}, _
            {546}, _
            {978}}
        Dim determinant As Double = MatrixHelper.Determinant(matrixA)

        Console.WriteLine(MatrixHelper.MakeDisplayable(matrixA& _
            vbNewLine & vbNewLine & "Determinant: " & _
            determinant.ToString)
     End Sub
End Class



Module MatrixHelper
    Public Function MakeDisplayable(ByVal sourceMatrix(,As DoubleAs String
        ' ----- Prepare a multi-line string that shows the contents
        '       of a matrix, a 2D array.
        Dim rows As Integer
        Dim cols As Integer
        Dim eachRow As Integer
        Dim eachCol As Integer
        Dim result As New System.Text.StringBuilder

        ' ----- Process all rows of the matrix, generating one
        '       output line per row.
        rows = UBound(sourceMatrix, 11
        cols = UBound(sourceMatrix, 21
        For eachRow = To rows - 1
            ' ----- Process each column of the matrix on a single
            '       row, separating values by commas.
            If (eachRow > 0Then result.AppendLine()
            For eachCol = To cols - 1
                ' ----- Add a single matrix element to the output.
                If (eachCol > 0Then result.Append(",")
                result.Append(sourceMatrix(eachRow, eachCol).ToString)
            Next eachCol
        Next eachRow

        ' ----- Finished.
        Return result.ToString
    End Function

    Public Function MakeDisplayable(ByVal sourceArray() As DoubleAs String
        ' ----- Present an array as multiple lines of output.
        Dim result As New System.Text.StringBuilder
        Dim scanValue As Double

        For Each scanValue In sourceArray
            result.AppendLine(scanValue.ToString)
        Next scanValue

        Return result.ToString
    End Function

    Public Function Inverse(ByVal sourceMatrix(,As DoubleAs Double(,)
        ' ----- Build a new matrix that is the mathematical inverse
        '       of the supplied matrix. Multiplying a matrix and its
        '       inverse together will give the identity matrix.
        Dim eachCol As Integer
        Dim eachRow As Integer
        Dim rowsAndCols As Integer

        ' ----- Determine the size of each dimension of the matrix.
        '       Only square matrices can be inverted.
        If (UBound(sourceMatrix, 1<> UBound(sourceMatrix, 2)) Then
            Throw New Exception("Matrix must be square.")
        End If
        Dim rank As Integer = UBound(sourceMatrix, 1)

        ' ----- Clone a copy of the matrix (not just a new reference).
        Dim workMatrix(,As Double = _
            CType(sourceMatrix.Clone, Double(,))

        ' ----- Variables used for backsolving.
        Dim destMatrix(rank, rankAs Double
        Dim rightHandSide(rankAs Double
        Dim solutions(rankAs Double
        Dim rowPivots(rankAs Integer
        Dim colPivots(rankAs Integer

        ' ----- Use LU decomposition to form a triangular matrix.
        workMatrix = FormLU(workMatrix, rowPivots, colPivots, rowsAndCols)

        ' ----- Backsolve the triangular matrix to get the inverted
        '       value for each position in the final matrix.
        For eachCol = To rank
            rightHandSide(eachCol1
            BackSolve(workMatrix, rightHandSide, solutions, rowPivots, colPivots)
            For eachRow = To rank
                destMatrix(eachRow, eachCol= solutions(eachRow)
                rightHandSide(eachRow0
            Next eachRow
        Next eachCol

        ' ----- Return the inverted matrix result.
        Return destMatrix
    End Function

    Public Function Determinant(ByVal sourceMatrix(,As DoubleAs Double
        ' ----- Calculate the determinant of a matrix.
        Dim result As Double
        Dim pivots As Integer
        Dim count As Integer

        ' ----- Only calculate the determinants of square matrices.
        If (UBound(sourceMatrix, 1<> UBound(sourceMatrix, 2)) Then
            Throw New Exception_
                "Determinant only calculated for square matrices.")
        End If
        Dim rank As Integer = UBound(sourceMatrix, 1)

        ' ----- Make a copy of the matrix so we can work inside of it.
        Dim workMatrix(rank, rankAs Double
        Array.Copy(sourceMatrix, workMatrix, sourceMatrix.Length)

        ' ----- Use LU decomposition to form a triangular matrix.
        Dim rowPivots(rankAs Integer
        Dim colPivots(rankAs Integer
        workMatrix = FormLU(workMatrix, rowPivots, colPivots, count)

        ' ----- Get the product at each of the pivot points.
        result = 1
        For pivots = To rank
            result *= workMatrix(rowPivots(pivots), colPivots(pivots))
        Next pivots

        ' ----- Determine the sign of the result using LaPlace's formula.
        result = (-1^ count * result
        Return result
    End Function

    Public Function SimultEq(ByVal sourceEquations(,As Double, _
            ByVal sourceRHS() As DoubleAs Double()
        ' ----- Use matrices to solve simultaneous equations.
        Dim rowsAndCols As Integer

        ' ----- The matrix must be square and the array size must match.
        Dim rank As Integer = UBound(sourceEquations, 1)
        If (UBound(sourceEquations, 2<> rankOr _
                (UBound(sourceRHS, 1<> rankThen
            Throw New Exception("Size problem for simultaneous equations.")
        End If

        ' ----- Create some arrays for doing all of the work.
        Dim coefficientMatrix(rank, rankAs Double
        Dim rightHandSide(rankAs Double
        Dim solutions(rankAs Double
        Dim rowPivots(rankAs Integer
        Dim colPivots(rankAs Integer

        ' ----- Make copies of the original matrices so we don't
        '       mess them up.
        Array.Copy(sourceEquations, coefficientMatrix, sourceEquations.Length)
        Array.Copy(sourceRHS, rightHandSide, sourceRHS.Length)

        ' ----- Use LU decomposition to form a triangular matrix.
        coefficientMatrix = FormLU(coefficientMatrix, rowPivots, _
            colPivots, rowsAndCols)

        ' ----- Find the unique solution for the upper-triangle.
        BackSolve(coefficientMatrix, rightHandSide, solutions, _
            rowPivots, colPivots)

        ' ----- Return the simultaneous equations result in an array.
        Return solutions
    End Function

    Private Function FormLU(ByVal sourceMatrix(,As Double, _
            ByRef rowPivots() As Integer, ByRef colPivots() As Integer, _
            ByRef rowsAndCols As IntegerAs Double(,)
        ' ----- Perform an LU (lower and upperdecomposition of a matrix,
        '       a modified form of Gaussian elimination.
        Dim eachRow As Integer
        Dim eachCol As Integer
        Dim pivot As Integer
        Dim rowIndex As Integer
        Dim colIndex As Integer
        Dim bestRow As Integer
        Dim bestCol As Integer
        Dim rowToPivot As Integer
        Dim colToPivot As Integer
        Dim maxValue As Double
        Dim testValue As Double
        Dim oldMax As Double
        Const Deps As Double = 0.0000000000000001

        ' ----- Determine the size of the array.
        Dim rank As Integer = UBound(sourceMatrix, 1)
        Dim destMatrix(rank, rankAs Double
        Dim rowNorm(rankAs Double
        ReDim rowPivots(rank)
        ReDim colPivots(rank)

        ' ----- Make a copy of the array so we don't mess it up.
        Array.Copy(sourceMatrix, destMatrix, sourceMatrix.Length)

        ' ----- Initialize row and column pivot arrays.
        For eachRow = To rank
            rowPivots(eachRow= eachRow
            colPivots(eachRow= eachRow
            For eachCol = To rank
                rowNorm(eachRow+= Math.Abs(destMatrix(eachRow, eachCol))
            Next eachCol
            If (rowNorm(eachRow0Then
                Throw New Exception("Cannot invert a singular matrix.")
            End If
        Next eachRow

        ' ----- Use Gauss-Jordan elimination on the matrix rows.
        For pivot = To rank - 1
            maxValue = 0
            For eachRow = pivot To rank
                rowIndex = rowPivots(eachRow)
                For eachCol = pivot To rank
                    colIndex = colPivots(eachCol)
                    testValue = Math.Abs(destMatrix(rowIndex, colIndex)) _
                        / rowNorm(rowIndex)
                    If (testValue > maxValueThen
                        maxValue = testValue
                        bestRow = eachRow
                        bestCol = eachCol
                    End If
                Next eachCol
            Next eachRow

            ' ----- Detect a singular, or very nearly singular, matrix.
            If (maxValue = 0Then
                Throw New Exception("Singular matrix used for LU.")
            ElseIf (pivot > 1Then
                If (maxValue < (Deps * oldMax)) Then
                    Throw New Exception("Non-invertible matrix used for LU.")
                End If
            End If
            oldMax = maxValue

            ' ----- Swap row pivot values for the best row.
            If (rowPivots(pivot<> rowPivots(bestRow)) Then
                rowsAndCols += 1
                Swap(rowPivots(pivot), rowPivots(bestRow))
            End If

            ' ----- Swap column pivot values for the best column.
            If (colPivots(pivot<> colPivots(bestCol)) Then
                rowsAndCols += 1
                Swap(colPivots(pivot), colPivots(bestCol))
            End If

            ' ----- Work with the current pivot points.
            rowToPivot = rowPivots(pivot)
            colToPivot = colPivots(pivot)

            ' ----- Modify the remaining rows from the pivot points.
            For eachRow = (pivot + 1To rank
                rowIndex = rowPivots(eachRow)
                destMatrix(rowIndex, colToPivot= _
                    -destMatrix(rowIndex, colToPivot/ _
                    destMatrix(rowToPivot, colToPivot)
                For eachCol = (pivot + 1To rank
                    colIndex = colPivots(eachCol)
                    destMatrix(rowIndex, colIndex+= _
                        destMatrix(rowIndex, colToPivot* _
                        destMatrix(rowToPivot, colIndex)
                Next eachCol
            Next eachRow
        Next pivot

        ' ----- Detect a non-invertible matrix.
        If (destMatrix(rowPivots(rank), colPivots(rank)) 0Then
            Throw New Exception("Non-invertible matrix used for LU.")
        ElseIf (Math.Abs(destMatrix(rowPivots(rank), colPivots(rank))) / _
                rowNorm(rowPivots(rank))) (Deps * oldMaxThen
            Throw New Exception("Non-invertible matrix used for LU.")
        End If

        ' ----- Success. Return the LU triangular matrix.
        Return destMatrix
    End Function

    Private Sub Swap(ByRef firstValue As Integer, ByRef secondValue As Integer)
        ' ----- Reverse the values of two reference integers.
        Dim holdValue As Integer
        holdValue = firstValue
        firstValue = secondValue
        secondValue = holdValue
    End Sub

    Private Sub BackSolve(ByVal sourceMatrix(,As Double, _
            ByVal rightHandSide() As Double, ByVal solutions() As Double, _
            ByRef rowPivots() As Integer, ByRef colPivots() As Integer)
        ' ----- Solve an upper-right-triangle matrix.
        Dim pivot As Integer
        Dim rowToPivot As Integer
        Dim colToPivot As Integer
        Dim eachRow As Integer
        Dim eachCol As Integer
        Dim rank As Integer = UBound(sourceMatrix, 1)

        ' ----- Work through all pivot points. This section builds
        '       the "B" in the AX=B formula.
        For pivot = To (rank - 1)
            colToPivot = colPivots(pivot)
            For eachRow = (pivot + 1To rank
                rowToPivot = rowPivots(eachRow)
                rightHandSide(rowToPivot+= _
                    sourceMatrix(rowToPivot, colToPivot_
                    * rightHandSide(rowPivots(pivot))
            Next eachRow
        Next pivot

        ' ----- Now solve for each X using the general formula
        '       x(i(b(i- summation(a(i,j)x(j)))/a(i,i)
        For eachRow = rank To Step -1
            colToPivot = colPivots(eachRow)
            rowToPivot = rowPivots(eachRow)
            solutions(colToPivot= rightHandSide(rowToPivot)
            For eachCol = (eachRow + 1To rank
                solutions(colToPivot-= _
                    sourceMatrix(rowToPivot, colPivots(eachCol)) _
                    * solutions(colPivots(eachCol))
            Next eachCol
            solutions(colToPivot/= sourceMatrix(rowToPivot, colToPivot)
        Next eachRow
    End Sub
End Module
1,2,3
5,4,6
9,7,8

Determinant: 15
2.46.Matrix
2.46.1.Display a Matrix
2.46.2.Invert a matrix
2.46.3.Calculate the determinant of an array
2.46.4.Solve equations using matrices
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.