Lineares Gleichungssystem lösen

Code-Stücke können hier veröffentlicht werden.
Antworten
Üpsilon
User
Beiträge: 222
Registriert: Samstag 15. September 2012, 19:23

Hallöchen.
Heute in der Schule habe ich versucht, ein LGS zu lösen. Was immer ich auch tat, ich kam immer zu falschen Ergebnissen. Nach einer Stunde Quälerei mit Einsetzungs-, Gleichsetzungs- und Additionsverfahren fiel mir auf, dass ich die Aufgabe falsch abgeschrieben hatte :roll: . Dann wollte ich eigentlich wutentbrannt Amok laufen, aber stattdessen hab ich dieses Programm geschrieben:

Code: Alles auswählen

from __future__ import division, print_function

def liste_mal(zahl, liste):
    return [zahl*i for i in liste]
def liste_plus(a, b):
    return [sum(paar) for paar in zip(a,b)]

def var_eliminieren(lgs):
    erste_zeile = lgs[0]
    lgs_neu = []
    for zeile in lgs[1:]:
        faktor = - zeile[0] / erste_zeile[0]
        erste_zeile_malgenommen = liste_mal(faktor, erste_zeile)
        zeile_neu = liste_plus(erste_zeile_malgenommen, zeile)[1:]
        lgs_neu.append(zeile_neu)
    return lgs_neu
    
def errechne_stufenform(lgs):
    if len(lgs) == 1: return lgs
    return [lgs[0]] + errechne_stufenform(var_eliminieren(lgs))
    
def auffuellen(lgs):
    maxlen = max(len(zeile) for zeile in lgs)
    return [[0]* (maxlen-len(zeile)) + zeile for zeile in lgs]
    
def loese_stufenform(lgs):
    verdreht = [list(reversed(zeile[:-1])) + [zeile[-1]] for zeile in reversed(lgs)]
    rueckeingesetzt = errechne_stufenform(verdreht)
    aufgeloest = [liste_mal(1/zeile[0], zeile) for zeile in rueckeingesetzt]
    loesungen = list(reversed([zeile[-1] for zeile in aufgeloest]))
    return loesungen
    
def loese_lgs(lgs):
    stufenform = errechne_stufenform(lgs)
    return loese_stufenform(auffuellen(stufenform))
    
print(loese_lgs([[-1,1,-2,-5], [0,3,-1,3], [2,0,1,5]]))
Kritik ist wie immer erwünscht. Lg Y.

PS/Edit: Dies ist mein hundertölfter Beitrag hier. Helau!
PS: Die angebotene Summe ist beachtlich.
Benutzeravatar
MagBen
User
Beiträge: 799
Registriert: Freitag 6. Juni 2014, 05:56
Wohnort: Bremen
Kontaktdaten:

Sehr schön, Dein Gleichungslöser rechnet richtig.
So kannst Du das testen

Code: Alles auswählen

import numpy as np
A = [[-1,1,-2], [0,3,-1], [2,0,1]]
b = [-5, 3, 5]
print(np.linalg.solve(A, b)) # [ 1.  2.  3.]
Ich hab's auch mal mit einem anderen Gleichungssystem probiert

Code: Alles auswählen

print(loese_lgs([[-0.1,1,-2,-6,-5], [0,0.3,-1,1.2,3], [0.2,0,1,-2,5], [1,0,-1,0,3.5]])) 
#[11.083916083916066, 25.678321678321687, 7.583916083916087, 2.4003496503496513]
und es stimmt auch da

Code: Alles auswählen

import numpy as np
A = [[-0.1,1,-2,-6], [0,0.3,-1,1.2], [0.2,0,1,-2], [1,0,-1,0]]
b = [-5, 3, 5, 3.5]
print(np.linalg.solve(A, b)) 
# [ 11.08391608  25.67832168   7.58391608   2.40034965]
Üblicherweise wird ein Gleichungssystem in zwei Variablen an einen Löser übergeben:
A: Koeffizientenmatrix
b: rechte Seite

Einen Unterschied zwischen Deinem Löser und dem von Numpy wirst Du sehen, wenn Du das Gleichungssystem größer machst. Probier mal ein Gleichungssystem mit 10 oder mehr Unbekannten.
a fool with a tool is still a fool, www.magben.de, YouTube
Üpsilon
User
Beiträge: 222
Registriert: Samstag 15. September 2012, 19:23

Hat zwar nichts mit dem eigentlichen Thema zu tun, aber ich hab heute noch ein Programm hingerotzt, was mir bei der Klausurvorbereitung hilft, indem es Gleichungssysteme mit "netten" Zahlen auswürfelt. Vielleicht hilft es ja noch jemandem.

Code: Alles auswählen

from random import randint, shuffle
loesungen = [randint(-10,10) for _ in range(3)]
koeffs = list(range(-4,5))
shuffle(koeffs)
for i in range(3):
    zeile = koeffs[3*i:3*i+3]
    erg = sum(a*x for a,x in zip(zeile, loesungen))
    print(zeile, erg)
PS: Die angebotene Summe ist beachtlich.
Üpsilon
User
Beiträge: 222
Registriert: Samstag 15. September 2012, 19:23

Hier mein neuer Lieblings-LGS-Algorithmus. Am Computer zwar nicht wirklich besser, aber egal.

Code: Alles auswählen

from __future__ import division, print_function

def liste_mal(zahl, liste):
    return [zahl*i for i in liste]
def liste_plus(a, b):
    return [sum(paar) for paar in zip(a,b)]

def var_eliminieren(lgs):
    erste_zeile = lgs[0]
    lgs_neu = []
    for zeile in lgs[1:]:
        faktor = - zeile[0] / erste_zeile[0]
        erste_zeile_malgenommen = liste_mal(faktor, erste_zeile)
        zeile_neu = liste_plus(erste_zeile_malgenommen, zeile)[1:]
        lgs_neu.append(zeile_neu)
    return lgs_neu
    
def loese_2er(lgs):
    # Doppelkreuz-Formel, Herleitung trivial
    [[a,b,c],[d,e,f]] = lgs
    y = (a*f - c*d) / (a*e - b*d)
    x = (c - b*y) / a
    return y
    
def errechne_2er(lgs):
    if len(lgs) == 2: return lgs
    return errechne_2er(var_eliminieren(lgs))
    
def einsetzen(lgs, spalte, wert):
    return [zeile[:spalte] + zeile[spalte+1:-1] + [zeile[-1] - zeile[spalte]*wert] for zeile in lgs]
    
def loese_lgs(lgs):
    loesungen = []
    while len(lgs) != 1:
        z = loese_2er(errechne_2er(lgs))
        loesungen = [z] + loesungen
        lgs = einsetzen(lgs, len(lgs)-1, z)[:-1]
    return [lgs[0][1]/lgs[0][0]] + loesungen
    
lgs = [[-1,1,-2,-5], [0,3,-1,3], [2,0,1,5]]
print(loese_lgs(lgs))
lgs = [[1,1,1,1,5],[8,4,2,1,16],[-1,1,-1,1,1],[3,-2,1,0,8]]
print(loese_lgs(lgs))
lgs = [[8,4,2,1,0],[1,1,1,1,-3],[3,2,1,0,0],[6,2,0,0,0]]
print(loese_lgs(lgs))
PS: Die angebotene Summe ist beachtlich.
Benutzeravatar
pixewakb
User
Beiträge: 1405
Registriert: Sonntag 24. April 2011, 19:43

Ihr kennt??? http://docs.sympy.org/dev/modules/solvers/solvers.html

Übrigens finde ich den ersten Post mit der A***-Redewendung und dem Benutzer, der seinen Wohnort angibt (Mainz?), schwierig. Möglicherweise möchtest Du Deinen Beitrag überarbeiten.

BTW: Die Code auswählen-Box müsste mal überarbeitet werden. Es ist sonst Glückssache, die richtige Option zu finden.
Antworten