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: 17741
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: 13077
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@linda_96: Du suchst also ``for``-Schleifen und `range()`.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
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: 17741
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: 17741
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: 17741
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: 17741
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: 17741
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: 17741
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: 17741
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