Schleife für Invertieren

Code-Stücke können hier veröffentlicht werden.
linda_96
User
Beiträge: 12
Registriert: Sonntag 14. März 2021, 14:13

Hallo zusammen,

ich möchte für folgendes Problem eine Schleife anlegen:

Code: Alles auswählen

import numpy as np
A = np.array( [ [2,1,-1,0,0], [2,4,0,-1,0], [0,4,0,0,-1] ] )
A = np.delete(A,(2,3), axis=1)
Inverse_von_A = np.linalg.inv(A)
b = np.array( [6,12,4] )
x = np.dot(Inverse_von_A,b)
x
Die Schleife soll nacheinander alle verschiedenen Kombis auf 0 setzen, das sind insg. 10. In dem Beispiel Spalte 3 und 4.
Wie kann ich das umsetzen?
Sirius3
User
Beiträge: 18358
Registriert: Sonntag 21. Oktober 2012, 17:20

Da in dem Beispiel nichts auf 0 gesetzt wird, ist die Frage, wie man "alle verschiedenen Kombis" auf 0 setzen kann, unverständlich.

Wenn Du wissen willst, wie man alle verschiedenen zweier-Kombinationen der Zahlen 0 bis 5 oder besser 0 bis A.shape[1] erzeugt, dann schau Dir itertools.combinations an.
linda_96
User
Beiträge: 12
Registriert: Sonntag 14. März 2021, 14:13

Ich habe das ganze etwas umgeformt:

Code: Alles auswählen

import numpy as np
A = np.array( [ [2,1,-1,0,0], [2,4,0,-1,0], [0,4,0,0,-1] ] )

Code: Alles auswählen

i = 0
j = 1
A = np.delete(A,(i,j), axis=1)
Inverse_von_A = np.linalg.inv(A)
b = np.array( [6,12,4] )
x = np.dot(Inverse_von_A,b)
print("Diese x nehmen den Wert 0 an: ", i+1, ",", j+1, "\n")
if (x>=0).all():
    print("Die übrigen x nehmen folgende Werte an: ", x)
else:
    print("Diese Lösung kommt nicht in Frage, weil x negative Werte annimmt")
i soll zunächst den Wert 0 annehmen und j nach und nach 1,2,3,4.
Danach soll i = 1 sein und j nach und nach 2,3,4
Danach soll i = 2 sein und j nach und nach 3,4
Danach soll i = 3 sein und j 4

-> insg. 10 Kombinationen
Benutzeravatar
__blackjack__
User
Beiträge: 14303
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@linda_96: Du suchst also ``for``-Schleifen und `range()`.
„Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it.“ — Brian W. Kernighan
linda_96
User
Beiträge: 12
Registriert: Sonntag 14. März 2021, 14:13

Genau, ich weiß aber nicht, wie ich das umsetzen kann.
Sirius3
User
Beiträge: 18358
Registriert: Sonntag 21. Oktober 2012, 17:20

Du weißt nicht, wie man eine for-Schleife programmiert? Und wie Du an die Zahlen kommst, hatte ich ja auch schon geschrieben: itertools.combinations
linda_96
User
Beiträge: 12
Registriert: Sonntag 14. März 2021, 14:13

Prinzipiell schon. Aber wie kann ich itertools.combinations in die Schleife einbauen?
Sirius3
User
Beiträge: 18358
Registriert: Sonntag 21. Oktober 2012, 17:20

Code: Alles auswählen

import numpy as np
b = np.array( [6,12,4] )
A = np.array( [ [2,1,-1,0,0], [2,4,0,-1,0], [0,4,0,0,-1] ] )
for i,j in itertools.combinations(range(A.shape[1]), 2):
    teil_von_A = np.delete(A, [i, j], axis=1)
    inverse_von_A = np.linalg.inv(teil_von_A)
    x = inverse_von_A.dot(b)
    print("Diese x nehmen den Wert 0 an: ", i+1, ",", j+1, "\n")
    if (x>=0).all():
        print("Die übrigen x nehmen folgende Werte an: ", x)
    else:
        print("Diese Lösung kommt nicht in Frage, weil x negative Werte annimmt")
Besser als zu löschen, wäre das Positiv zu formulieren, also die Spalten, die erhalten werden sollen:

Code: Alles auswählen

import numpy as np
b = np.array( [6,12,4] )
A = np.array( [ [2,1,-1,0,0], [2,4,0,-1,0], [0,4,0,0,-1] ] )
for columns in itertools.combinations(reversed(range(A.shape[1])), A.shape[0]):
    columns = list(columns)
    inverse = np.linalg.inv(A[:, columns])
    x = np.zeros(A.shape[1])
    x[columns] = inverse.dot(b)
    if (x>=0).all():
        print("x nimmt folgende Werte an: ", x)
    else:
        print("Diese Lösung kommt nicht in Frage, weil x negative Werte annimmt")
linda_96
User
Beiträge: 12
Registriert: Sonntag 14. März 2021, 14:13

Super, ich benötige die erste Variante.
Das funktioniert, bis ich an den Punkt komme, an dem die Spalten mit dem Index 1 und 4 dran kommen.
Da kommt der Error "Singular matrix". Woran könnte das liegen?
Sirius3
User
Beiträge: 18358
Registriert: Sonntag 21. Oktober 2012, 17:20

Die zweite Variante ist identisch zur zweiten Variante, nur dass sie besser ist.

Der Fehler liegt daran, dass Du eine Singuläre Matrix hast.
linda_96
User
Beiträge: 12
Registriert: Sonntag 14. März 2021, 14:13

Wie kann ich denn nun eine dritte Variable "k" zu i und j in die Schleife aufnehmen?

Code: Alles auswählen

for i,j in comb(range(A.shape[1]), 2):
    teil_von_A = np.delete(A, [i, j], axis=1)
    if np.linalg.det(teil_von_A) != 0:
        inverse_von_A = np.linalg.inv(teil_von_A)
        x = inverse_von_A.dot(b)
        print("Diese x nehmen den Wert 0 an: ", i+1, ",", j+1, "\n")
        if (x>=0).all():
            print("Die übrigen x nehmen folgende Werte an: ", x, "\n\n")
        else:
            print("Diese Lösung kommt nicht in Frage, weil x negative Werte annimmt\n\n")
    else:
        print("Diese x nehmen den Wert 0 an: ", i+1, ",", j+1, "\n")
        print("Diese Lösung kommt nicht in Frage, weil die Matrix nicht invertierbar ist \n\n")
linda_96
User
Beiträge: 12
Registriert: Sonntag 14. März 2021, 14:13

Nachtrag:

Code: Alles auswählen

from itertools import combinations
def comb(arr,r):
    return list(combinations(arr,r))
arr = np.array( [0,1,2,3,4,5,6] )
r = 3
print(comb(arr,r))
Sirius3
User
Beiträge: 18358
Registriert: Sonntag 21. Oktober 2012, 17:20

Wo ist denn konkret das Problem? Das sollte doch offensichtlich sein, wie man i,j in i,j,k umschreibt.
linda_96
User
Beiträge: 12
Registriert: Sonntag 14. März 2021, 14:13

Code: Alles auswählen

for i,j,k in comb(range(A.shape[2]), 2):
    teil_von_A = np.delete(A, [i, j, k], axis=1)
    if np.linalg.det(teil_von_A) != 0:
        inverse_von_A = np.linalg.inv(teil_von_A)
        x = inverse_von_A.dot(b)
        print("Diese x nehmen den Wert 0 an: ", i+1, ",", j+1, ",", k+1, "\n")
        if (x>=0).all():
            print("Die übrigen x nehmen folgende Werte an: ", x, "\n\n")
        else:
            print("Diese Lösung kommt nicht in Frage, weil x negative Werte annimmt\n\n")
    else:
        print("Diese x nehmen den Wert 0 an: ", i+1, ",", j+1, ",", k+1, "\n")
        print("Diese Lösung kommt nicht in Frage, weil die Matrix nicht invertierbar ist \n\n")
Da kommt jedoch der IndexError: tuple index out of range
Sirius3
User
Beiträge: 18358
Registriert: Sonntag 21. Oktober 2012, 17:20

In Deinem "Nachtrag" hast Du es doch richtig gemacht.
linda_96
User
Beiträge: 12
Registriert: Sonntag 14. März 2021, 14:13

Deswegen verstehe ich es nicht.
Mit meinem "Nachtrag" werden 35 Kombinationsmöglichkeiten generiert, die jeweils aus 3 Elementen bestehen. Soweit richtig.
In meiner for Schleife habe ich dann i,j und k als Variablen gesetzt und den Index angepasst.
Trotzdem erscheint der Error 'tuple index out of range' mit Verweis auf die erste Zeile der for Schleife.
Sirius3
User
Beiträge: 18358
Registriert: Sonntag 21. Oktober 2012, 17:20

Naja, wie sieht denn Dein A jetzt aus? Und wie willst Du aus einer 3D-Matrix die Inverse bilden?
linda_96
User
Beiträge: 12
Registriert: Sonntag 14. März 2021, 14:13

Code: Alles auswählen

import numpy as np
A = np.array( [ [2,4,0,1,1,0,0], [1,1,5,1,0,1,0], [0,1,1,1,0,0,1] ] )
b = np.array( [20,30,10] )
A
natürlich...
Sirius3
User
Beiträge: 18358
Registriert: Sonntag 21. Oktober 2012, 17:20

Bei einer 7x3-Matrix brauchst Du aber 4 Spalten, die Du löschen mußt, und nicht 3.
Außerdem hast Du nur eine 2D-Matrix, ein shape[2] existiert daher nicht, daher der IndexError.

Um nochmal zum Anfang zurückzukommen: meine zweite Variante des Codes ist der bessere, weil er mit beliebigen Matrizen arbeiten kann.
linda_96
User
Beiträge: 12
Registriert: Sonntag 14. März 2021, 14:13

Die Löschvorgabe habe ich leider.

Code: Alles auswählen

import numpy as np
A = np.array( [ [2,4,0,1,1,0,0], [1,1,5,1,0,1,0], [0,1,1,1,0,0,1] ] )
b = np.array( [20,30,10] )
A

Code: Alles auswählen

from itertools import combinations
def comb(arr,r):
    return list(combinations(arr,r))
arr = np.array( [0,1,2,3,4,5,6] )
r = 4
print(comb(arr,r))

Code: Alles auswählen

for i,j,k,l in comb(range(A.shape[4]), 2):
    teil_von_A = np.delete(A, [i, j, k, l], axis=1)
    if np.linalg.det(teil_von_A) != 0:
        inverse_von_A = np.linalg.inv(teil_von_A)
        x = inverse_von_A.dot(b)
        print("Diese x nehmen den Wert 0 an: ", i+1, ",", j+1, ",", k+1, ",", l+1, "\n")
        if (x>=0).all():
            print("Die übrigen x nehmen folgende Werte an: ", x, "\n\n")
        else:
            print("Diese Lösung kommt nicht in Frage, weil x negative Werte annimmt\n\n")
    else:
        print("Diese x nehmen den Wert 0 an: ", i+1, ",", j+1, ",", k+1, ",", l+1, "\n")
        print("Diese Lösung kommt nicht in Frage, weil die Matrix nicht invertierbar ist \n\n")
...und immer noch ist "tupel index out of range"
Antworten