Gauß-Algorithmus

  • VB.NET

Es gibt 14 Antworten in diesem Thema. Der letzte Beitrag () ist von faxe1008.

    Gauß-Algorithmus

    Hi,

    da wir zur Zeit in der Schule viel mit Matrizen rumrechnen wollte ich mir ne Klasse schreiben um Einiges zu vereinfachen. Da wir das in der Schule sehr nach Gefühl machen, welche Reihen mit einander verrechnet werden, möchte ich hier fragen, wie ich dabei beim Programmieren vorzugehen habe.

    Zum Verrechnen der Reihen habe ich schon mal folgende Extension geschrieben:

    VB.NET-Quellcode

    1. Dim ma(1, 1) As Double
    2. ma(0, 0) = 4
    3. ma(1, 0) = 8
    4. ma(0, 1) = 8
    5. ma(1, 1) = 16
    6. ma.EvaluateRows([Operator].Subtract, 1, 1, 0, 1)
    7. Public Enum [Operator]
    8. Add
    9. Subtract
    10. End Enum
    11. Module ExtensionModule
    12. <Extension()>
    13. Public Function EvaluateRows(ByVal Matrix As Double(,), ByVal op As [Operator], ByVal operandrow1 As Integer, ByVal operandrow1_multiplicator As Double, ByVal operandrow2 As Integer, ByVal operandrow2_multiplicator As Double) As Double(,)
    14. For u As Integer = 0 To Matrix.GetLength(0) - 1
    15. Select Case op
    16. Case [Operator].Add
    17. Matrix(u, operandrow1) = Matrix(u, operandrow1) * operandrow1_multiplicator + Matrix(u, operandrow2) * operandrow2_multiplicator
    18. Case [Operator].Subtract
    19. Matrix(u, operandrow1) = Matrix(u, operandrow1) * operandrow1_multiplicator - Matrix(u, operandrow2) * operandrow2_multiplicator
    20. End Select
    21. Next
    22. Return Matrix
    23. End Function
    24. End Module


    Bewirkt folgendes:
    Zeile1: 4 , 8
    Zeile2: 8 , 16

    Zeile2*1 - Zeile1 *1

    Somit wäre die Grundlage für den Algorithmus schon einmal gelegt. Die Frage ist nur wie ich ihn aufbauen kann, um ein Gleichungssystem unbestimmter Größe zu lösen. Die Klasse soll am Ende 5*6 oder auch 3*4 berechnen können. Wie wäre die Vorgehensweise?

    8-) faxe1008 8-)
    Ich hoffe einfach mal, Code ist aussagekräftiger, als der Roman, den ich ansonsten hier reinschreiben müsste:
    github.com/Artentus/MathUtils/…MathUtils/SquareMatrix.cs
    In Zeile 139 beginnt der Algorithmus und in Zeile 195 wird er für das Lösen von linearen Systemen verwendet.
    Deine

    faxe1008 schrieb:

    Vorgehensweise
    ist möglicherweise falsch.
    Wenn Du Gauss implementieren willst, musst Du ihn zunächst verstanden haben, das setze ich mal voraus.
    Dann musst Du formulieren, was für Gleichungssysteme Du lösen willst, deren Ordnung.
    Ich halte es nicht für sinnvoll, alle möglichen Ordnungen in einen Algo zu packen.
    Mach den 2. und 3. Ordnung separat, die höheren brauchen deutlich mehr Aufwand.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Ok danke erstmal. :)

    @Artentus
    Du bestimmst also zunächst den Faktor des Koeffizienten und Subtrahierst dann mit Hilfe des Faktors, so dass in einer Spalte eine Variable nur noch einmal vorkommt.
    Die Frage die sich mir stellt ist, nach welche Kreterien sortierst du die Reihen davor?

    @Rod: Den Algo habe ich verstanden, man verrechnet die Reihen durch Subtraktion oder Addition solange bis man die Stufen form erhält:
    2 , 4 , 6 , 18
    4 , 7 , 8 , 22
    1 , 2 , 3 , 23

    =>
    2 , 4 , 6 | 18
    0 , 4 , 3 | 13
    0 , 0 , 1 | 6

    Und dann kann man das Ganze reversiv aufziehen so, dass sich die Variablen über die Diagonale ablesen lassen. Hinweiß: Das GS oben ist frei erdacht und die Lösung ist auch Unsinn, hatte gerade kein passendes Beispiel zur Hand.

    8-) faxe1008 8-)

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „faxe1008“ ()

    @faxe1008

    Artentus schrieb:

    Die Reihen müssen so sortiert sein
    dass die Hauptdiagonale aus nur 1 besteht, dann ist der Vektor rechts die Lösung.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    faxe1008 schrieb:

    ordnen
    ist da egal, Du musst derartige Rechenoperationen machen, dass hinterher die Einhaitsmatrix übrig bleibt.
    Sortiert wird dann hinterher, wenn zwar in jeder Zeile und jeder Spalte eine 1 drin steht, diese aber nicht die Hauptdiagonale bilden.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Man kann es auch anders rum machen und erst so sortieren, dass nachher beim Verrechnen sofort die EInhatismatrix rauskommt, ohne dann nochmal sortieren zu müssen. Das ist imo einfacher, weil dann das Verrechnen aufgrund fixer Positionen für die 1en leichter wird.
    Wenn das das Programm macht, sollte das schön egal sein.
    Auf dem Papier mach ich das bloß bis zur Ordnung 4. ;)
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Ist zwar hier nicht der Fall, trotzdem wollt ich mal kurz anmerken, dass man bei festen Matrixgrößen (sprich immer 3x3 z.B.) auch über feste Berechnung gehen sollte.
    Das sind ein paar Berechnungen und geht doch deutlich schneller.

    Gonger96 schrieb:

    über feste Berechnung gehen sollte.
    Jou,

    RodFromGermany schrieb:

    Mach den 2. und 3. Ordnung separat
    das reicht normalerweise.
    Ich hatte mal ein 6-dimensionales Problem und dafür hab ich zumindest die Matrizen-Berechnungen optimiert.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Wie gehe ich bei der Sortierung vor? Momentan tausche ich die Reihen zufällig solange aus, bis die Diagonalen ungleich 0 sind. Dass das nicht wirklich efffizient ist, ist mir durchaus bewusst. Wie könnte man das verbessern?

    8-) faxe1008 8-)
    Nur wenn die Reihe an der Stelle ne 0 hat, muss sie überhaupt getauscht werden. Wenn du tauschen musst, suchst du einfach nach einer Zeile, die gültig wäre. Wenn du dabei immer erst eine Zeile darunter mit der Suche anfängst, werden die bereits gefundenen Zeilen automatisch aus der Suche ausgeschlossen.
    Danke :D . Habe das nun so gelöst:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Public Class Form1
    2. Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    3. Dim mam(2, 2) As Double
    4. mam(0, 0) = 0
    5. mam(0, 1) = 4
    6. mam(0, 2) = 5
    7. mam(1, 0) = 3
    8. mam(1, 1) = 0
    9. mam(1, 2) = 2
    10. mam(2, 0) = 6
    11. mam(2, 1) = 6
    12. mam(2, 2) = 0
    13. Dim ma As New Matrix(mam)
    14. ma.SortMatrix()
    15. End Sub
    16. End Class
    17. Public Class Matrix
    18. Private _Matrix As Double(,)
    19. Public Property Matrix As Double(,)
    20. Get
    21. Return _Matrix
    22. End Get
    23. Set(value As Double(,))
    24. _Matrix = value
    25. End Set
    26. End Property
    27. Public Sub New(ByVal matrix As Double(,))
    28. _Matrix = matrix
    29. End Sub
    30. Public Sub SortMatrix()
    31. For index As Integer = 0 To Math.Min(Matrix.GetLength(0), Matrix.GetLength(1)) - 1
    32. If Matrix(index, index) = 0 Then
    33. Dim rownumber As Integer
    34. If AnyRowHasNoZero(index, rownumber) Then
    35. SwapRows(index, rownumber)
    36. End If
    37. End If
    38. Next
    39. End Sub
    40. Public Function AnyRowHasNoZero(ByVal x As Integer, ByRef rownumber As Integer) As Boolean
    41. For width As Integer = 0 To Matrix.GetLength(0) - 1
    42. For height As Integer = 0 To Matrix.GetLength(1) - 1
    43. If width = x AndAlso Not Matrix(x, height) = 0 Then
    44. rownumber = height
    45. Return True
    46. End If
    47. Next
    48. Next
    49. Return False
    50. End Function
    51. Public Sub SwapRows(ByVal row1 As Integer, ByVal row2 As Integer)
    52. Dim saverow(Matrix.GetLength(0) - 1) As Double
    53. ' Reihe zwischenspeichern
    54. For width As Integer = 0 To Matrix.GetLength(0) - 1
    55. saverow(width) = Matrix(row1, width)
    56. Next
    57. 'Reihe1 = Reihe2
    58. For width As Integer = 0 To Matrix.GetLength(0) - 1
    59. Matrix(row1, width) = Matrix(row2, width)
    60. Next
    61. 'Reihe2=saverow
    62. For width As Integer = 0 To Matrix.GetLength(0) - 1
    63. Matrix(row2, width) = saverow(width)
    64. Next
    65. End Sub
    66. End Class


    8-) faxe1008 8-)

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „faxe1008“ ()