Calcolo del determinante di una matrice

1

Sto lavorando su una libreria (nel mio tempo libero) che spero di aprire presto. Uno degli elementi nella libreria è un metodo per calcolare il determinante di una data matrice di input. Per questo, ho creato un sottoprogetto chiamato "LUDecomposition" perché userò LU Decomposition per calcolare il Determinante.

Ora, il mio approccio migliore era:

  1. Avere una classe "LUDecomposition" che calcola la LU Decomposizione di un segnale di input

  2. Avere un'altra classe "Determinante" che usa LUDecomposition per il calcolo e poi restituisce questo.

Attualmente è contenuto in un file e, "Determinante" sta ereditando da "LUDecompostion" ma non sembra corretto, poiché la relazione non ha senso. LUDecomposition - > CAN BE/IS A Determinant

Ma non vedo altre opzioni se non quella di avere un metodo all'interno della "Decomposizione LU" e di restituirlo da lì. MA l'unico problema è che, se non volessi che gli utenti della libreria / interfaccia conoscessero come viene calcolato il determinante?

#include <iostream>
#include <vector>

typedef std::vector<double> Vector;


namespace LUDecomposition {

    class LUDecompostion {

        public:

            LUDecompostion();


            template<typename Inverse>
            LUDecompostion(Inverse begin, Inverse end)
            : matrix_input(begin, end)
            {
                    const size_t matrix_size = matrix_input.size();

                    this->upper.resize(matrix_size, std::vector<double>(matrix_size));
                    this->lower.resize(matrix_size, std::vector<double>(matrix_size));
                    Solve();

            }

            void Solve();

            std::vector<Vector> getUpper();
            std::vector<Vector> getLower();

        protected:

            std::vector<Vector> matrix_input;
            std::vector<Vector> upper;
            std::vector<Vector> lower;

        };

        /*
                Class Determinant

        */


    class Determinant : public LUDecomposition {

        public:

            Determinant();

            template<typename Inverse>
            Determinant(Inverse begin, Inverse end)
            :   matrix_input(begin, end)
            {
                    /*
                            TO DO
                            TO DO
                            TO DO
                    */

            }


    };
}

EDIT:

namespace LUP
{

    class LUPDecomposition {

        public:

            LUPDecomposition()
            {

            }

            string getLower()
            {
                return "This is the lower matrix";
            }

            string getUpper()
            {
                return "This is the upper matrix";
            }

        protected:

            std::vector<double> data; 


    };

    LUPDecomposition FactorMatrix()
    {
        return LUPDecomposition();

    }
}
    
posta Phorce 17.03.2015 - 10:06
fonte

1 risposta

2

Innanzitutto, non c'è niente di sbagliato nella tua ereditarietà, anche se eviterei di nominare la classe Determinant ; Probabilmente userò LUP::Determinant e se è richiesta la compatibilità con altri oggetti implementa un'interfaccia IDeterminant (ma in questo caso specifico sembra eccessivo). Questo perché il determinante non è un determinante generico ma un'implementazione specifica in base a una fattorizzazione . E non vedo alcun problema dall'avere il tuo oggetto determinante ridotto alla fattorizzazione da cui è stato calcolato. Potrebbero esserci tuttavia problemi di spazio e prestazioni (se ho bisogno solo del determinante perché memorizzare tutto il resto?).

Con lo spazio dei nomi, preferirei avere uno spazio dei nomi Decomposition con la fattorizzazione LUP , la fattorizzazione Cholesky , la fattorizzazione QR e così via. E tieni presente che probabilmente stai pianificando di eseguire la fattorizzazione LUP e LU , in modo che anche ciò si rifletta.

Ora, tornando alle fatture, probabilmente non vuoi avere il solve che è l'algoritmo e il risultato che rappresenta i dati nello stesso oggetto. Per questo puoi:

  • Utilizza funzioni generiche e interrompe l'ereditarietà e le dipendenze degli oggetti

Può essere implementato con funzioni o oggetti functor ma l'API dovrebbe essere qualcosa del tipo:

LUP::Decomposition decomposition = LUP::FactorMatrix(matrix.begin(), matrix.end());
auto determinant = LUP::ComputeDeterminant(decomposition);

dove

LUP::FactorMatrix influenza la matrice e restituisce la decomposizione LU (o LUP); questa potrebbe essere solo una semplice funzione (con i modelli iteratori)

LUP::Decomposition (o LU) contiene la matrice triangolare inferiore e superiore e, se necessario, la matrice di permutazione

LUP::ComputeDeterminant può essere usato su vari input, e in questo caso un overload che funziona con una decomposizione restituirà il determinante della matrice. Puoi averlo in uno spazio dei nomi più generico con un sovraccarico per la decomposizione LUP.

Il vantaggio è che puoi decidere facilmente quali dati memorizzare e puoi anche aggiungere altre operazioni come:

LUP::Decomposition decomposition = LUP::FactorMatrix(matrix.begin(), matrix.end());
if (LUP::ComputeDeterminant(decomposition) > 5) //whatever
    auto matrix = LUP::ComputeMatrixInverse(decomposition);

Pochi altri vantaggi:

  • L'iniezione delle dipendenze è facile purché le interfacce siano compatibili. Puoi avere due metodi di Solve che si comportano in modo diverso (iterativo?) Ma restituisce lo stesso tipo di oggetto in modo che il processo sia lo stesso.
  • Non c'è eredità quindi aggiungere funzionalità è semplice come creare una nuova funzione (functor)
  • Puoi persino combinare in una certa misura diversi algoritmi con metodi diversi
  • Sei tu che controlli ciò che viene chiamato, quando viene chiamato, quali risorse usa ogni passo e così via. Puoi decidere quando rilasciare la decomposizione dalla memoria e cosa fare con quello.
  • Hai una chiara separazione tra i tuoi dati e i tuoi algoritmi che per tali applicazioni è un vantaggio.
risposta data 17.03.2015 - 12:00
fonte

Leggi altre domande sui tag