Lineare Gleichungssysteme lösen

Übersicht BlitzMax, BlitzMax NG Codearchiv & Module

Neue Antwort erstellen

BlitzMoritz

Betreff: Lineare Gleichungssysteme lösen

BeitragMi, Mai 06, 2009 10:53
Antworten mit Zitat
Benutzer-Profile anzeigen
Ich habe mich ein bisschen gewundert, dass es hier dazu noch nichts Gescheites gibt, daher:
Für alle, die ein lineares Gleichungssystem lösen müssen, sei hier folgende benutzerdefinierte Klasse "TGleichungssystem" zur Verfügung gestellt.
Die Lösungen und Koeffizienten sind beliebige rationale Zahlen und auch der Grad des Systems ist theoretisch beliebig. Es ist aber anzuraten, nicht mehr als höchstens 8 Gleichungen mit 8 Variablen zu benutzen. Ich denke, für die meisten hiesigen Problemstellungen ist das genug. Funktionsweise und Beispiel-Demonstration entnehme man bitte demBlitzMax: [AUSKLAPPEN]
SuperStrict
SeedRnd MilliSecs()
Local Time:Int = MilliSecs()
Local Wiederholungsanzahl:Int = 100
For Local wdh:Int = 1 To Wiederholungsanzahl
Local GS:TGleichungssystem = New TGleichungssystem
Local Bsp_Grad:Int = Rand(1, 8)
Local Bsp_Loesung:Float[Bsp_Grad]
Print "--------------------------------------------------------"
Print "Neues (Zufalls-)Gleichungssystem aus " + Bsp_Grad + " Gleichungen mit " + Bsp_Grad + " Variablen:"
Print "Die Zufalls-Loesungen seien:"
Local Info:String
For Local i:Int = 0 To Bsp_Grad-1
Bsp_Loesung[i] = Rnd() * 10 * (-1)^Rand(0,1)
Info = Info + "x[" + (i+1) + "] = " + Bsp_Loesung[i] + " "
Next
Print Info
Print "Die (Zufalls-)Gleichungen seien:"
Local Bsp_Koeffizient:Float[Bsp_Grad+1]
Local Zwischensumme:Double
For Local i:Int = 0 To Bsp_Grad-1
Info = ""
Zwischensumme = 0
For Local j:Int = 1 To Bsp_Grad
Bsp_Koeffizient[j] = Rnd() * 10 * (-1)^Rand(0,1)
Info = Info + " + (" + Bsp_Koeffizient[j] + ") x[" + (j) + "]"
Zwischensumme = Zwischensumme + Bsp_Koeffizient[j] * Bsp_Loesung[j-1]
Next
Bsp_Koeffizient[0] = -Zwischensumme
Info = "0 = (" + Bsp_Koeffizient[0] + ")" + Info
GS.Gleichung_hinzufuegen(Bsp_Koeffizient)
Print Info
Next
Local Ermittelte_Loesung:Double[] = GS.Loesung()
Info = ""
For Local i:Int = 0 To Bsp_Grad-1
Info = Info + "x[" + (i+1) + "] = " + Float(Ermittelte_Loesung[i]) + " "
Next
Print "Die Loesung des Gleichungssystems ergibt:"
Print Info
Next
Print "============================================================="
Print Wiederholungsanzahl + " Gleichungssysteme wurden in " + (MilliSecs()-Time) + " Millisekunden geloest."
'======================================================================================

' Benutzerdefinierte Klasse "TGleichungssystem", © 2009, Udo Kinast Alias "BlitzMoritz"
' =================================================================
' Diese Klasse hat den Zweck, lineare Gleichungssysteme zu lösen.
' Der Grad des Gleichungssystems ist theoretisch beliebig, wurde hier aber auf 8 beschränkt,
' da sich sonst u.U. in seltenen Fällen durch numerische Fehler-Verstärkung falsche Lösungen
' ergeben könnten. Intern rechnet die Klasse daher möglichst genau mit Double-Werten
' Ein neues Gleichungssystem wird ganz simpel wie üblich folgendermaßen erzeugt:
'
' System:TGleichungssystem = New TGleichungssystem
'
' Die Koeffizienten k werden als Array für jede Gleichung bzw. Zeile einzeln hinzugefügt:
'
' System.Gleichung_hinzufuegen( Alle_Koeffizienten_der_ersten_Gleichung:Float[] )
' System.Gleichung_hinzufuegen( Alle_Koeffizienten_der_zweiten_Gleichung:Float[] )
' usw. usw. usw.
'
' Auf die korrekte Anzahl hinzugefügter Gleichungen und Variablen muss geachtet werden!
' Dabei wird zwingend von folgender Norm der Gleichungen ausgegangen (mit k als Koeffizienten):
'
' 0 = k[0] + k[1] * x + k[2] * y + k[3] * z + . . .
'
' Sobald die korrekte Anzahl von Gleichungen hinzugefügt wurde, wird das Lösungsarray ermittelt:
'
' Loesung:Doueble[] = System.Loesung()
'
' Falls man das Objekt für ein anderes Gleichungssystem nicht jedes Mal neu erstellen will,
' MUSS man unbedingt alles leeren VOR der Hinzufügung einer neuen ersten Gleichung:
'
' System.leeren()


'##############################################
Type TGleichungssystem
'==========================================
'Objekt-eigene Variablen:
'-------------------------------------------------------------------------------
'Zutaten für das Lösen linearer Gleichungssysteme
Const GradMax:Int = 8
Field Grad:Int, Anzahl:Int = 0, Loe:Double[], Koef:Double[GradMax,GradMax+1]
'==========================================
Method Gleichung_hinzufuegen(koe:Float[])
Local j:Int
If Len(koe) =< GradMax+1 Then
Anzahl = Anzahl + 1
If Grad < Len(koe) - 1 Then Grad = Len(koe) - 1 Grad = Min(Grad , GradMax)
For j = 0 To GradMax
If j < Grad+1 Then
Koef[Anzahl-1, j] = Double(koe[j])
Else
Koef[Anzahl-1, j] = 0
End If
Next
Else
Notify "Der Grad des linearen Gleichungssystems ist auf " + GradMax + " beschränkt!~nEs wird KEINE Gleichung hinzugefuegt!"
End If
End Method 'Gleichung_hinzufuegen
'==========================================
Method Loesung:Double[]()
Local i:Int , j:Int , h:Int 'Indizes für allerei Gebrauch ...
If Anzahl = 0 Or Grad <> Anzahl Then
Return Null
Else
'------------------------------------------------------------------
Loe = New Double[GradMax]
'Gleichungen ggf. so präparieren, dass alle Koef[i,i] <> 0 sind:
For i = 0 To Grad-1
If Koef[i , i+1] = 0 Then
'Irgendeine Gleichung suchen, bei der Koef[j,i+1] <> 0 ist:
j = 0
While Koef[j,i+1] = 0
If j < Grad-1 Then
j = j + 1
Else
Notify "Das Gleichungssystem ist NICHT eindeutig lösbar!"
Return Null
End If
Wend
'Lückenhafte i-te Gleichung durch Addition mit j-ter Gleichung korrigieren:
For h = 0 To Grad
Koef[i,h] = Koef[i,h] + Koef[j,h]
Next
End If
Next
'------------------------------------------------------
Local MinKoef:Double = 1
Local MaxKoef:Double = 1
'Bestimmte Koeffizienten gezielt auf 0 bringen:
For h = Grad-1 To 1 Step -1
For i = 0 To h - 1
MinKoef = 1
MaxKoef = 1
For j = 0 To h+1
Koef[i,j] = Koef[i,j] * Koef[h,h+1] - Koef[h,j] * Koef[i,h+1]
'If Abs(Koef[i , j]) < 0.0000000001 Then Koef[i , j] = 0
If Koef[i , j] <> 0 And Abs(Koef[i , j]) < MinKoef Then MinKoef = Koef[i , j]
If Abs(Koef[i , j]) > MaxKoef Then MaxKoef = Koef[i , j]
Next
'Damit die Koeefizienten nicht zu groß oder zu klein werden und an die Grenzen der Variablen-Belastbarkeit des Computers stoßen:
If MaxKoef > 1 / MinKoef Then
If MaxKoef > 10000 Then
For j = 0 To Grad
Koef[i , j] = Koef[i , j] / MaxKoef * 10000
Next
End If
Else
If MinKoef < 0.0001 Then
For j = 0 To Grad
Koef[i , j] = Koef[i , j] / MinKoef / 10000
Next
End If
End If
Next
Next
'--------------------------------------------------------------
'Sukzessiv einsetzen und auflösen:
For i = 0 To Grad-1
Loe[i] = - Koef[i,0]
For j = 1 To i
Loe[i] = Loe[i] - Koef[i,j] * Loe[j-1]
Next
If Koef[i,i+1] <> 0 Then
Loe[i] = Loe[i] / Koef[i,i+1]
Else
Notify "Das Gleichungssystem ist NICHT eindeutig lösbar!~nDer Koeffizient Koef[" + i + "," + i+1 + "] = " + Koef[i , i+1] + " ist gleich Null!"
Return Null
End If
Next
Return Loe
'------------------------------------------------------------------
End If
End Method 'GW_Loesung
'==========================================
Method leeren()
Koef = New Double[GradMax,GradMax+1]
Grad = Null Anzahl = 0
End Method 'leeren
'==========================================
End Type 'TGleichungssystem
'##############################################

Neue Antwort erstellen


Übersicht BlitzMax, BlitzMax NG Codearchiv & Module

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group