LR Zerlegung , Arrays , Zeiger



  • Hey,

    ich habe hier eine LR Zerlegung programmiert. Es läuft aber nicht durch, also es zeigt mir mein Ergebnis nicht an sondern landet irgendwie in einer Endlosschleife.
    Ich weiß nicht wo genau das Problem liegt, aber ich denke dass es in der Methode lrZerlegung irgendein Problem mit den Zeigern und den Arrays geben könnte.
    vielleicht kann mir ja jemand hier weiter helfen 🙂

    Hier der Code:

    #include <iostream>
    #include <vector>
    
    using namespace std;
    
    //Klassendefinitionen ----------------------------------------------------------
    class Matrix
    {
    public:
            vector<vector<double> > a;
            int laenge;
    
            Matrix(int n)
            {
                    laenge = n;
                    a.resize(n);
                    for (int i = 0; i < n; i++) {
                            a[i].resize(n);
                            for (int j = 0; j < n; j++)
                                    a[i][j] = 0;
                    };
            };
    
            void print()
            {
                    for (int i = 0; i < laenge; i++)
                    {
                            cout << "| ";
                            for (int j = 0; j < laenge; j++)
                                    cout << a[i][j] << " ";
                            cout << "|" << endl;
                    }
            }
    };
    
    class Vektor
    {
    public:
            vector<double> a;
            int laenge;
    
            Vektor(int n)
            {
                    laenge = n;
                    a.resize(n);
                    for (int i = 0; i<n; i++)
                            a[i] = 0;
            }
            void print()
            {
                    for (int i = 0; i < laenge; i++)
                    {
                            cout << "| " << a[i] << " |" << endl;
                    }
            }
    };
    
    //Matrix über die Eingabe hinzufügen -------------------------------------------
    Matrix newMatrixcin()
    {
            int n;
            cout << "Länge der nxn Matrix: n = ";
            cin >> n;
            Matrix a(n);
            cout << "Werte der Matrix eingeben:" << endl;
            for (int i = 0; i < n; i++)
                    for (int j = 0; j < n; j++)
                    {
                            cout << "a[" << i << "][" << j << "] = ";
                            cin >> a.a[i][j];
                    };
            return a;
    }
    
    //Beispielmatrix zur Überprüfung -----------------------------------------------
    Matrix newMatrixA()
    {
            Matrix a(4);
            for (int i = 0; i < 4; i++)
                    for (int j = 0; j < 4; j++)
                    {
                            a.a[i][j] = i*j + 1;
                    };
    
            return a;
    }
    
    //Matrixmultiplikation (m*n)----------------------------------------------------
    Matrix matrixMult(Matrix m, Matrix n)
    {
            if (m.laenge != n.laenge)
                    cout << "Matrizen haben eine unterschiedliche Laenge und koennen daher nicht multipliziert werden!" << endl;
            Matrix x(m.laenge);
            for (int i = 0; i < x.laenge; i++)
                    for (int j = 0; j < x.laenge; j++)
                    {
                            for (int k = 0; k < x.laenge; k++)
                                    x.a[i][j] += m.a[i][k] * n.a[k][j];
                    };
    
            return x;
    }
    
    //LR-Zerlegung -----------------------------------------------------------------
    void lrZerlegung(Matrix m, Matrix &l, Matrix &r)
    {
            Matrix* LM[5];
            for (int i = 0; i < m.laenge - 1; i++)
            {
                    Matrix lMatrizen(m.laenge);
                    for (int j = 0; j < m.laenge; j++)
                    {
                            (lMatrizen).a[j][j] = 1;
                            if (j > i)
                                    (lMatrizen).a[j][i] = m.a[j][i];
    
                    };
                    m = matrixMult((lMatrizen), m);
                    LM[i] = &lMatrizen;
            }
            r = m;
            for (int i = 1; i<l.laenge - 1; i++)
                    for (int j = i + 1; j<l.laenge; j++)
                            l.a[i][j] = -1 * LM[i]->a[i][j];
    
    }
    
    //Vorwaertseinsetzen (Ly=b lösen) ----------------------------------------------
    Vektor vwEinsetzen(Matrix l, Vektor b)
    {
            for (int i = 0; i < l.laenge; i++)
                    if (l.a[i][i] == 0) {
                            cout << "Verfahren kann nicht angewendet werden !" << endl;
                            return NULL;
                    };
            Vektor x(b.laenge);
            x.a[0] = b.a[0] / l.a[0][0];
            for (int i = 1; i < b.laenge; i++)
            {
                    double sum = 0;
                    for (int j = 0; j < i - 1; j++)
                            sum += l.a[i][j] * x.a[j];
                    x.a[i] = (b.a[i] - sum) / l.a[i][i];
    
            }
            return x;
    }
    
    //Rueckwaertseinsetzen (Rx=b lösen) ----------------------------------------------
    Vektor rwEinsetzen(Matrix r, Vektor b)
    {
            for (int i = 0; i < r.laenge; i++)
                    if (r.a[i][i] == 0) {
                            cout << "Verfahren kann nicht angewendet werden !" << endl;
                            return NULL;
                    };
            Vektor x(b.laenge);
            x.a[b.laenge - 1] = b.a[b.laenge - 1] / r.a[b.laenge - 1][b.laenge - 1];
            for (int i = b.laenge - 1; i >= 0; i--)
            {
                    double sum = 0;
                    for (int j = i; j < b.laenge; j++)
                            sum += r.a[i][j] * x.a[j];
                    x.a[i] = (b.a[i] - sum) / r.a[i][i];
    
            }
            return x;
    }
    
    //Hauptmethode -----------------------------------------------------------------
    int main()
    {
            Matrix a = newMatrixA();
            a.print();
            cout << endl << "Finde LR Zerlegung von A:" << endl;
            Matrix l(a.laenge);
            Matrix r(a.laenge);
            lrZerlegung(a, l, r);
            cout << "L:" << endl;
            l.print();
            cout << endl << "R:" << endl;
            r.print();
    
            int s;
            cout << "Um das Programm zu schließen bitte Eingabe bestätigen";
            cin >> s;
            return 0;
    }
    


  • Das ist doch eine prima Gelegenheit, sich mal intensiver mit 'nem Debugger zu beschäftigen. 🙂

    Was mir eben gerade noch aufgefallen ist:

    Matrix matrixMult(Matrix m, Matrix n) {
        ...
    }
    

    Diese Funktion bekommt ihre eigenen Matrizen m und n. Das sind Kopien von den Matritzen, die Du auf der Aufrufseite benutzt. Das Kopieren von so einem Objekt kostet auch etwas Zeit und Speicher. Diese Funktion braucht aber gar keine eigenen Kopien der Parameter. Du kannst das ändern, ohne dabei die Stellen, wo die die Funktion aufrufst ändern zu müssen:

    Matrix matrixMult(Matrix const& m, Matrix const& n) {
        ...
    }
    

    Jetzt sind m und n als Referenzen deklariert. Es sine keine eigenen Kopien. Sie beziehen sich auf dieselben Matrix-Objekte, die Du auf der Aufruferseite hast. Mit dem "const" da drinnen verspricht die Funktion, die Matrix-Objekte des Aufrufers nicht zu verändern.

    Nochwas:

    Matrix(int n)
    

    Da sollte

    explicit Matrix(int n)
    

    stehen. Damit vermeidest Du, dass ein int implizit in eine Matrix umwandelbar ist, was Dir sonst ein Bein stellen könnte, da so ein int wenig mit einer Matrix zu tun hat. Dasselbe gilt für deine Vektor-Klasse.

    Matrix* LM[5]; 
      for (int i = 0; i < m.laenge - 1; i++) 
      { 
          Matrix lMatrizen(m.laenge); 
          ...
          LM[i] = &lMatrizen;
      }
    

    Was soll das denn?! Die 5 sieht hier sehr willkürlich aus und dann legst Du lokale Matrix-Objekte innerhalb der Schleife an, die beim nächsten Durchlauf bzw nach Beendingung der Schleife schon wieder zerstört sind. Und zwischendurch speicherst Du dir die Adresse dieser kurzlebigen Matrix-Objekte in dem Array da oben. Die Adressen sind hinterher natürlich wertlos. Du benutzt sie aber danach!

    BTW: Du kannst eine LR-Zerlegung auch in-place berechnen, also komplett in derselben Matrix. Man muss dann hinterher nur wissen, wie man diese Matrix dann zu benutzen hat. Sowas sollte man dann entsprechend kapseln. Z.B so:

    class LRFaktorisierung
    {
    public:
        explicit LRFaktorisierung(Matrix mat);
    
        // berechnet A^-1 vec und überschreibt mit dem Ergebnis vec
        void loesen(Vektor& vec);
    
    private:
        Matrix mat;
    };
    
    LRFaktorisierung::LRFaktorisierung(Matrix max)
    : mat(std::move(mat))
    {
       ... Zerlegung hier berechnen oder eine
           entsprechende Funktion aufrufen ...
    }
    


  • Bei der main() anfangen.
    Verdächtigen Code von unten nach oben auskommentieren, bis die Funktion gefubnden ist, die hängt.
    Dann in der Funktion so weitermachen.
    Wenn die böse Funktion gefunden ist, uns die Funktion sagen.


Log in to reply