示例#1
0
  void SetCases()
  {
    std::string error;
    Dynamic table = TABLE;
    nkit::TableIndex::Ptr index;
    nkit::TableIndex::ConstIterator it;

    DynamicVector vargs;
    vargs.push_back(Dynamic("NEW"));
    vargs.push_back(Dynamic(0));
    vargs.push_back(Dynamic(true));
    vargs.push_back(Dynamic(0));
    vargs.push_back(Dynamic(0.0));

    COMMON_TABLE_INIT(table);

    index = table.CreateIndex("name,name1", &error);
    NKIT_TEST_ASSERT_WITH_TEXT(index, error);

    NKIT_TEST_ASSERT(table.SetRow(table.height() / 2, vargs));
    DynamicVector::iterator vit = vargs.begin();
    for (size_t col = 0; vit != vargs.end(); ++vit, ++col)
    {
  #if defined(MY_TRACE_)
    print(*vit, "", false);
    std::cout << " <> ";
    print(table.GetCellValue(table.height() / 2, col));
  #endif // MY_TRACE_
      NKIT_TEST_ASSERT(*vit == table.GetCellValue(table.height() / 2, col));
    } // for
    NKIT_TEST_ASSERT(index->GetEqual(Dynamic("NEW"),Dynamic(0)) != index->end());
  }
示例#2
0
inline void eliminationOperators(SpMat& A, DynamicVector<size_t>& Cset, size_t fnode,
        DynamicVector<double>& q, SpMat& P, size_t& P_col, size_t P_row) {
    /* Inizializziamo la riga P_row con A.nonZeros(fnode) - 1 non nulli*/
    double scalingFactor = 1.0;
    /* Riserviamo spazio in ciascuna colonna di P per un adeguato numero
     * di elementi. Il -1 c'è perché (il reciproco del)l'elemento in
     * diagonale lo mettiamo in q
     */
    P.reserve(P_row, A.nonZeros(fnode) - 1);
    /* Per ciascuna f-riga prendo gli elementi in ogni c-colonna */
    DynamicVector<size_t>::Iterator ccol = Cset.begin();
    for (SpMat::Iterator frow = A.begin(fnode); frow != A.end(fnode); ++frow) {
        if (frow->index() == fnode) { //Elemento della diagonale
            q[P_row] = (1.0 / frow->value()); //Q ha elementi pari al numero di righe di R
            scalingFactor = -(q[P_row]);
        } else if (ccol != Cset.end()) {
            break; //Non ha senso andare avanti se abbiamo finito i ccol
        } else if (frow->index() == (*ccol)) {
            /* Elemento fuori della diagonale ed è anche un c-colonna */
            P.append(P_row, P_col, frow->value());
            P_col++;
            ccol++;
        }
    }

    P.finalize(P_row); //Finalizziamo la riga P_row

    /* Non dimentichiamo di scalare gli elementi della riga corrente
     * per  -scalingFactor */
    for (SpMat::Iterator it = P.begin(P_row); it != P.end(P_row); it++)
        it->value() *= -scalingFactor;
}
示例#3
0
inline void eliminationOperators(DMat& A, DynamicVector<size_t>& Cset, size_t fnode,
        DynamicVector<double>& q, SpMat& P, size_t& P_col, size_t P_row) {
    double scalingFactor = 1.0;
    P.reserve(P_row, A.nonZeros(fnode) - 1);
    DynamicVector<size_t>::Iterator ccol = Cset.begin();
    for (size_t frow = 0; frow < A.rows(); ++frow) {
        if (frow == fnode) { //Elemento sulla diagonale
            q[P_row] = (1.0 / A(frow, fnode));
            scalingFactor = -(q[P_row]);
        } else if (ccol != Cset.end()) {
            break; //Non ha senso andare avanti se abbiamo finito i ccol
        } else if (frow == (*ccol)) {
            P.append(P_row, P_col, A(frow, fnode));
            P_col++;
            ccol++;
        }
    }
    P.finalize(P_row);

    for (SpMat::Iterator it = P.begin(P_row); it != P.end(P_row); it++)
        it->value() *= -scalingFactor;
}
示例#4
0
LevelElimination * LAMGLSSolver::coarsenElimination(const Matrix & finerMatrix) {
cout << "coarsenElimination()" << endl;
    //Per salvare i P ed i q
    std::vector<qPStage*> cStages;
    /* Prealloco spazio per al più SETUP_ELIMINATION_MAX_STAGES così evito
     * possibili riallocazioni */
    cStages.reserve(SETUP_ELIMINATION_MAX_STAGES);

    //Copio la matrice così posso modificarla senza modificare quella del finerLevel
    Matrix A(finerMatrix);
    Matrix Acc; //Per lo Schur Complement System
    Matrix Acf; //Per lo Schur Complement System
    // Il numero di stage di eliminazione eseguiti sulla matrice A
    size_t stageNum = 0;

    /* Vector che vengono riusati*/
    DynamicVector<size_t> Cset; //Insieme dei nodi da non eliminare
    DynamicVector<size_t> Fset; //Insieme dei nodi da eliminare
    DynamicVector<size_t> degree; //Grado di ciascun nodo
    DynamicVector<size_t> candidate; //Nodi candidati all'eliminazione
    DynamicVector<NodeEliminationStatus> status; //Stato dei nodi
    /* P è sempre sparsa anche quando A è densa */
    SpMat P;
    DynamicVector<double> q;

    while (stageNum < SETUP_ELIMINATION_MAX_STAGES) {

        size_t A_rows = A.rows();
        if (A_rows <= MAX_DIRECT_SOLVE_SIZE)
            break;
        /* (1) Calcola il vettore degree della matrice. */
        degree.resize(A_rows);

        for (size_t i = 0; i < A_rows; ++i) {
            degree[i] = A.nonZeros(i);
            if (A(i, i) != 0)//Tolgo l'elemento sulla diagonale
                degree[i]--;
            else
                cerr << "La diagionale i-esima c'ha lelemento a zero!!! ERRORE MORTALE!!!" << endl;
        }

        /* (2) [f c ] = lowDegreeNodes(A,degree,MaxDegree)  */
        candidate.resize(A_rows);
        candidate = 0;
        /* Individuo i nodi candidati (degree[i] <= MAX_DEGREE) */
        size_t cnnZ = 0; //Devo usare questa variabili perché i valori "settati" di candidate comprendono il valore "0" cioè il nodo 0
        for (size_t i = 0; i < A_rows; ++i) {
            if (degree[i] <= SETUP_ELIMINATION_MAX_DEGREE) {
                candidate[cnnZ++] = i;
            }
        }
        /* I primi cnnZ elementi sono stati inizializzati */
        candidate.resize(cnnZ, true);

        status.resize(A_rows);
        status = HIGH_DEGREE; //Tutti gli elementi prendono HIGH_DEGREE
        //    status(candidate)  = 0; % Reset all relevant nodes to "not visited"
        for (size_t i = 0; i < candidate.size(); ++i) {
            status[candidate[i]] = NOT_DECIDED;
        }

        for (size_t k = 0; k < candidate.size(); ++k) {
            lowdegreesweep(A, candidate[k], status); //Template call
        }

        /* Adesso devo creare i vettori F e C, inserendovi i nodi che verranno
         * o meno eliminati */
        size_t nf = 0; //|Fset|
        size_t nc = 0; //|Cset|
        Cset.resize(A_rows, false);
        Fset.resize(A_rows, false);
        for (size_t i = 0; i < A_rows; ++i) {
            if (status[i] == LOW_DEGREE)
                Fset[nf++] = i; //Inserisco il nodo i nell'insieme F
            else
                Cset[nc++] = i; //Lo inserisco invece in C
        }

        /* L'insieme C non può mai essere vuoto, dobbiamo lasciargli almeno
         * un elemento
         */
        if (nc == 0) {
            Cset[nc++] = Fset[--nf];
            Fset[nf] = 0;

        }
        Cset.resize(nc, true); //nc non è mai 0
        Fset.resize(nf, true);

        /* FINE di (2) [f c ] = lowDegreeNodes(A,degree,MaxDegree) */


        if ((nf <= SETUP_ELIMINATION_MIN_ELIM_FRACTION * A_rows)) {
            /* Il coarsening non è abbastanza efficace perché andiamo ad eliminare
             * un numero, nf, di nodi che è inferiore alla minima soglia accettabile
             * di eliminazione. Ci fermiamo senza eliminare.*/
            break;
        }


        /* (3) Una volta individuati i nodi da eliminare devo calcolare gli
         * operatori P e q che mi consentono di eliminare tutti questi nodi
         *      [R, q] = eliminationOperators(A, f, index);
         */


        /* In MEX si crea una matrice columnMajor che poi verrà trasposta perché
         * le matrici di Matlab sono columnMajor e se uno vuole sfruttare la
         * rappresentazione interna deve usarle così.
         * Noi invece possiamo già generare la matrice trasposta costruendo
         * direttamente la matrice rowMajor e "sostituendo" ai termini riga
         * quelli colonna.
         */
        /* P è sempre una matrice sparsa perché il numero dei suoi nonzero
         * e basso anche quando A è densa */
        P.resize(nf, nc, false);
        q.resize(nf, false);

        /* Quanti elemenenti abbiamo salvato in Q (e quante righe di R
         * abbiamo costruito)
         */
        size_t P_row = 0;
        size_t P_col = 0;
        /* Per ogni f-riga di A prendi ciascun c-elemento di questa riga e formaci
         * la i-esima riga di R. L'inverso dell'f-esimo elemento di ciascuna f-riga
         * va messo in q. Inoltre ciascuna riga i di R va scalata di un fattore -q[i]
         */
        for (DynamicVector<size_t>::Iterator dvit = Fset.begin(); dvit != Fset.end(); dvit++) {
            eliminationOperators(A, Cset, (*dvit), q, P, P_col, P_row);
            P_row++; //Passiamo alla prosssima riga
        }
        //Salvo i dati così creati nel cStages
        cStages.push_back(new qPStage(new SpMat(P), new DynamicVector<double>(q),
                new DynamicVector<size_t>(Fset), new DynamicVector<size_t>(Cset), (nf + nc)));
        /* FINE (03) [R, q] = eliminationOperators(A, f, index);*/




        /* (4) Adesso devo calcolare il sistema complementare di Schur dato da
         *  A = Ac,c + Ac,f*R^t         */

        /* Acc è la sottomatrice di A che ha come elementi tutti gli a_ij tali
         * che (ij) appartiene a Cset x Cset. Quindi per ogni riga crow devo
         * prenderci tutti gli elementi che hanno indice pari a ccol */
        MtxOps::submatrix(A, Cset, Cset, Acc);

        /* Acf invece ha nc righe e nf colonne*/
        MtxOps::submatrix(A, Cset, Fset, Acf);
        /* Finalmente posso aggiornare A*/
        A = Acc + Acf * P;
        /* Acc_[nc x nc] + (Acf * P)_[nc x nc].
         * Dunque La matrice A risultante diventa una nc x nc e perdiamo esattamente nf nodi.*/
    }//Fine while(stageNum...)

    /* Usciti dal while dobbiamo creare il livello, se è possibile farlo */
    LevelElimination* ret = NULL;
    if (stageNum != 0) {

        if (useSparse) {
            if (isSparseOK(A)) {
                ret = new LevelElimination(new SpMat(A), cStages, multiGrid.back());
            } else {
                useSparse = false;
                ret = new LevelElimination(new DMat(A), cStages, multiGrid.back());
            }
        } else {

            ret = new LevelElimination(new DMat(A), cStages, multiGrid.back());
        }
    }
cout << "coarsenElimination() finito" << endl;
    return ret;
}