Seite 1 von 1

Wörterbuch als Matrix umformulieren

Verfasst: Montag 4. Januar 2021, 08:18
von CaptainNeemo
Hallo liebes Python Forum,
ich suche aktuell eine Möglichkeit um ein Wörterbuch wie dieses:

Code: Alles auswählen

Wörterbuch = {0 : [(1,1.),(2,2.)],
            1 : [(0,1.),(3,3.)],
            2 : [(0,2.),(3,3.),(4,4.)],
            3 : [(1,3.),(2,3.),(5,5.)],
            4 : [(3,4.),(5,5.)],
            5 : [(3,5.),(4,5.)]}
möglichst einfach in eine Quadrat-Matrix umzuschreiben, wobei der key die Reihe in der Matrix und das a im Tupel (a,b) die Spalte und das b soll jeweils in die Matrix eingetragen werden. Die restlichen Felder werden 0
Ich habe es mit Schleifen versucht, dachte mir da gibt es aber bestimmt noch eine einfachere Möglichkeit. Die restlichen Felder werden 0

Vielen Dank schonmal im Vorraus für eure Hilfe

Re: Wörterbuch als Matrix umformulieren

Verfasst: Montag 4. Januar 2021, 08:32
von Sirius3
Nein, einfacher als zwei for-Schleifen geht es nicht. Saß ist ja durch die Datenstruktur so vorgegeben.

Re: Wörterbuch als Matrix umformulieren

Verfasst: Montag 4. Januar 2021, 11:24
von CaptainNeemo
@Sirius3: Okay vielen Dank ich habe es jetzt auch mit den zwei for-Schleifen geschrieben. Ich ätte noch eine Frage, die ich stellen wollte und zwar, habe ich jetzt eine Matrix und will diese jetzt lösen mit linalg.solve. Dort bekomme ich ja meine Matrix x. Allerdings sollen 2 Lösungen schon gegeben sein. Aktuell multipliziere ich dieLösungen in die Werte der ersten und der letzten Reihe der Matrix, jedoch scheint es nicht zu funktionieren.
Weißt du zufällig wie ich diese ander angeben könnte oder wo das Problem liegt? Hier mein Code falls dieser weiterhilft:

Code: Alles auswählen

ResiLink = {0 : [(1,1.),(2,2.)],                            
            1 : [(0,1.),(3,3.)],
            2 : [(0,2.),(3,3.),(4,4.)],
            3 : [(1,3.),(2,3.),(5,5.)],
            4 : [(3,4.),(5,5.)],
            5 : [(3,5.),(,5.)]}

def Kirchhoffmain(ResiLink,sw=0,ew=1):
    """
    Berechnung nach dem Knotenpotentialverfahren, wobei einem Knoten ein Anfangswert und ein Endwert gegeben werden kann. In diesem Falle per default(sw=0,ew=1).  
    """
    Ivec = np.zeros(len(ResiLink)).reshape(len(ResiLink),1) #Den Spaltenvektor der Spannungen
    lgs = np.zeros((len(ResiLink))*(len(ResiLink))).reshape((len(ResiLink)),len(ResiLink)) 
    #Matrix für die Zweigleitwerte

    for i in range(int(len(ResiLink))): #Befüllen der Matrix
        line = ResiLink[i]
        for (j,r) in line: 
            if i == r:
                if i==0:
                    lgs[i,j] = sw/r
                if 0==(len(ResiLink)-1):
                    lgs[i,j] = ew/r
                else:
                    lgs[i,j] = 1/r
            else:
                lgs[i,j] = -1/r      
    solved = np.linalg.solve(lgs,Ivec)
    print(lgs)
    print(Ivec)
    return solved

Re: Wörterbuch als Matrix umformulieren

Verfasst: Montag 4. Januar 2021, 11:58
von Sirius3
Variablennamen werden wie Funktionen komplett klein geschrieben.
np.zeros kann auch gleich mehrdimensionale Arrays erzeugen.
Wenn ResiLink wirklich ein Wörterbuch ist, ist es komisch, dass Du da einen Index i erzeugst, um auf die Schlüssel zuzugreifen. Wenn das wirklich nur aufsteigende Zahlen sind, dann wäre eine Liste die richtige Datenstruktur.
Ansonsten iteriert man in Python auch nicht über einen Index.
Dann verstehe ich nicht, was Du da versuchst zu lösen. Warum ist der zweite Tupelwert zwar irgendwie der Wert eines Matrixelements, aber auch irgendwie ein Zeilenindex, denn r wird mit i verglichen.
Ivec ist immer ein Vektor mit nullen. Und das wird an solve übergeben?

Re: Wörterbuch als Matrix umformulieren

Verfasst: Montag 4. Januar 2021, 12:15
von pillmuncher
Was Sirius3 gesagt hat. Ich hab es mal etwas pythonischer umgeschrieben, unter Beibehaltung der Logik (hoffentlich):

Code: Alles auswählen

import numpy as np


def kirchhoff(resi_link, begin=0, end=1):
    """
    Berechnung nach dem Knotenpotentialverfahren, wobei einem Knoten ein
    Anfangswert und ein Endwert gegeben werden kann. In diesem Falle per
    default(begin=0, end=1).
    """
    # Spaltenvektor der Spannungen:
    Ivec = np.zeros(len(resi_link)).reshape(len(resi_link), 1)
    lgs = np.zeros((len(resi_link), len(resi_link)))
    # Matrix für die Zweigleitwerte:
    for i, line in enumerate(resi_link):
        for n, r in line:
            if i != r:
                lgs[i, n] = -1 / r
            elif len(resi_link) == 1:
                lgs[i, n] = end / r
            elif i == 0:
                lgs[i, n] = begin / r
            else:
                lgs[i, n] = 1 / r
    print(lgs)
    print(Ivec)
    return np.linalg.solve(lgs, Ivec)


def main():
    print(kirchhoff([
        [(1, 1.), (2, 2.)],
        [(0, 1.), (3, 3.)],
        [(0, 2.), (3, 3.), (4, 4.)],
        [(1, 3.), (2, 3.), (5, 5.)],
        [(3, 4.), (5, 5.)],
        [(3, 5.), (4, 5.)]
    ]))



if __name__ == '__main__':
    main()
Ergebnis:

Code: Alles auswählen

[[ 0.         -1.         -0.5         0.          0.          0.        ]
 [ 1.          0.          0.         -0.33333333  0.          0.        ]
 [ 0.5         0.          0.         -0.33333333 -0.25        0.        ]
 [ 0.          0.33333333  0.33333333  0.          0.         -0.2       ]
 [ 0.          0.          0.          0.25        0.         -0.2       ]
 [ 0.          0.          0.          0.2         0.2         0.        ]]
[[0.]
 [0.]
 [0.]
 [0.]
 [0.]
 [0.]]
[[ 0.]
 [-0.]
 [ 0.]
 [ 0.]
 [-0.]
 [ 0.]]
Was soll anderes rauskommen? Wie unterscheidet sich das von der tatsächlichen Ausgabe?

Re: Wörterbuch als Matrix umformulieren

Verfasst: Montag 4. Januar 2021, 14:34
von CaptainNeemo
@Sirius3 und @pillmuncher:
Wir haben in dem Wörterbuch von unserem Dozenten {Knotenpunkt: (Verbindungspunkt, Widerstand)} gegeben. Das alles versuche ich nun so zu schreiben, dass man der Funktion eine Spannung geben kann, welche am ersten und am letztem Knotenpunkt anliegt und diese dann im Sinne des Knotenpotentialverfahrens, die restlichen Spannungen berechnet. Das i mit r verglichen wird war ein Fehler meinerseits. i muss mit j verglichen werden, damit auf der Diagonale der Matrix die positive Summe steht und beim Rest die negative. Und dort wo keine Verbindung zwischen zwei Knoten besteht ist eine 0.
Und eigentlich wollte ich somit die Spannungen, an jedem Knotenpunkt berechnen.
Hier die überarbeitete Version:

Code: Alles auswählen

ResiLink = {0 : [(1,1.),(2,2.)],
            1 : [(0,1.),(3,3.)],
            2 : [(0,2.),(3,3.),(4,4.)],
            3 : [(1,3.),(2,3.),(5,5.)],
            4 : [(3,4.),(5,5.0)],
            5 : [(3,5.),(4,5.0)]}

def main(ResiLink,sw=0,ew=1):
    """
    Berechnung nach dem Knotenpotentialverfahren, wobei einem Knoten ein Anfangswert und ein Endwert gegeben werden kann. In diesem Falle per default(sw=0,ew=1).  
    """
    size = len(ResiLink)
    ivec = np.zeros((size,1)) #Den Spaltenvektor der Spannungen
    lgs = np.zeros((size,size)) #Die Matrix der Leitwerte  

    for i in range(size): #Befüllen der Matrix
        line = ResiLink[i]
        for (j,r) in line: 
            if i == j:
                lgs[i,j] = 1/r
            else:
                lgs[i,j] = -1/r      
    solved = np.linalg.solve(lgs,ivec)
    return solved

if __name__ == '__main__':
    main(ResiLink)

Re: Wörterbuch als Matrix umformulieren

Verfasst: Montag 4. Januar 2021, 15:00
von pillmuncher
Das Ergebnis ist immer noch

Code: Alles auswählen

[[-0.]
 [-0.]
 [-0.]
 [-0.]
 [-0.]
 [ 0.]]
Was soll ivec denn sein?

Re: Wörterbuch als Matrix umformulieren

Verfasst: Montag 4. Januar 2021, 15:07
von __blackjack__
@CaptainNeemo: Namen werden in Python klein_mit_unterstrichen geschrieben. Ausnahmen sind Konstanten (KOMPLETT_GROSS) und Klassen (MixedCase).

Man sollte keine kryptischen Abkürzungen verwenden. Das wird auch noch mal schlimmer wenn man Deutsch und Englisch mischt, denn dann weiss man im Zweifelsfall nicht mal in welcher Sprache eigentlich abgekürzt wurde.

`line` würde eher `row` heissen. Man muss aber auch nicht jedes kleine Zwischenergebnis an einen Namen binden.

Überarbeitet (ungetestet):

Code: Alles auswählen

#!/usr/bin/env python3
import numpy as np

RESI_LINK = {
    0: [(1, 1), (2, 2)],
    1: [(0, 1), (3, 3)],
    2: [(0, 2), (3, 3), (4, 4)],
    3: [(1, 3), (2, 3), (5, 5)],
    4: [(3, 4), (5, 5)],
    5: [(3, 5), (4, 5)],
}


def main(resi_link, start_value=0, end_value=1):
    """
    Berechnung nach dem Knotenpotentialverfahren, wobei einem Knoten ein
    Anfangswert und ein Endwert gegeben werden kann. In diesem Falle per
    default (start_value=0, end_value=1).
    """
    size = len(resi_link)
    linear_equation_system = np.zeros((size, size))
    for i in range(size):
        for j, resistance in resi_link[i]:
            linear_equation_system[i, j] = (1 if i == j else -1) / resistance

    return np.linalg.solve(linear_equation_system, np.zeros((size, 1)))


if __name__ == "__main__":
    print(main(RESI_LINK))

Re: Wörterbuch als Matrix umformulieren

Verfasst: Montag 4. Januar 2021, 15:44
von CaptainNeemo
@Sirius3 :
Danke für die Tipps, gerade den Variablen Tipp versuche ich mir mal besser einzuprägen. Und deine Lösung funktioniert sehr gut ich habe sie getestet und ist zudem kompakt. Finde es immer beeindurckend, wie kompakt man diese Dinge doch schreiben kann.

@pillmuncher
Und Ivec ist das Ergebnis der Gleichung aus (Matrix der Leitwerte) x (Spannungen der einzelnen Knoten) = Ivec. Und als Ergebnis möchte ich die Spannung der einzelnen Knoten erhalten wobei ich schon zwei Spannungen kenne, nämlich die Spannung des ersten sowie des letzten Knotens. Sprich wenn linalg.solve Matrizen nach folgendem Schema löst Ax= b, dann versuche ich b herauszufinden, und habe schon zwei Lösungen gegeben und versuche die gerade "einzubauen"

Re: Wörterbuch als Matrix umformulieren

Verfasst: Montag 4. Januar 2021, 15:54
von pillmuncher
@CaptainNeemo: Warum stehen dann in ivec lauter Nullen?

Re: Wörterbuch als Matrix umformulieren

Verfasst: Mittwoch 6. Januar 2021, 10:04
von CaptainNeemo
@pillmuncher:
Ja da gab es eine Verwirrung meinerseits, konnte das pysikalische Problem jedoch mit einem Studenten höheren Semesters lösen.