}// end ~Dtor(). #endregion Ctors #region Rango /// <summary> /// dimensione del massimo minore nonnullo. Ovvero numero di linee della piu' grande sottomatrice quadrata, a determinante nonnullo. /// La matrice analizzata (i.e. sourceMat) puo' essere rettangolare, con dimensioni qualsiasi. Il massimo rango possibile e' la minore /// delle dimensioni della matrice analizzata. /// Il caso di matrice in esame rettangolare, costituisce il caso generale. Da esso vengono prodotti molteplici sottocasi di matrice quadrata. /// Lo entry point del Rango deve quindi essere una funzione che smista dal caso generale, di input rettangolare, al caso semplificato di input quadrato /// Il caso di primo input gia' quadrato, permette soluzione diretta, mediante il medesimo metodo di individuazione delle sottomatrici, utilizzato per i cofattori dell'inversa. /// Il caso di primo input rettangolare, richiede invece un'iterazione, per la produzione di tutti i sottocasi quadrati, fino ad individuazione del primo minore nonnullo. /// Durante tale processo, sara' utilizzata la variabile "curDimension", ad indicare l'ordine delle sottomatrici quadrate in esame. /// Esaurite tutte le sottomatrici quadrate di ordine "curDimension", si passa alla produzione delle quadrate d'ordine "curDimension-1". /// Per ogni valore di "curDimension"=="k", si hanno (n k) (i.e. "n" bionomioNewton "k") quadrate kXk, estratte da una rettangolare nXk, con n>k. /// Nel caso si parta gia' da una quadrata kXk, si deve in primis calcolarne il determinante. Ove esso sia nullo si opera "--curDimension" e cosi' via. /// Le sottofunzioni ad oggi(2015.09.02) individuate sono: /// - selezione di "curDimension": distingue i casi quadrata-rettangolare e imposta "curDimension" /// - "producer" : genera la sottomatrice da analizzare( combinando colonne) /// - "ePermutazioneDi" : valuta se una certa sequenza di indici di colonna sia una permutazione di una gia' valutata; si serve della sottofunzione "appartieneA" /// - "appartieneA" : prende uno scalare, indice di una colonna, e dice se appartiene ad una collezione di indici di colonna, ricevuta a parametro. E' una funzione elementare, con /// schema {1}appartieneA({1,2,3})==true; {7}appartieneA({1,2,3})==false; la precedente funzione "ePermutazioneDi", va implementata considerando il risultato booleano cumulativo /// di "appartieneA", ovvero: {1,3,2}"ePermutazioneDi"({1,2,3})==({1}appartieneA({1,2,3})and{2}appartieneA({1,2,3})and{3}appartieneA({1,2,3}) ). /// </summary> /// <returns></returns> public int Rango() // LinearAlgebra.RealMatrix sourceMat ) { // schema operativo: //NB. il numero antistante la riga, indica la funzione nella quale viene svolto il task. // legenda: // (1)==EntryPoint()( i. e. rango). // (2)==gestioneQuadrata(). // (3)==gestioneRettangolare(). // (4)==producer(). // (5)==selettore(). // (6)==ePermutazioneDi(). // (7)==appartieneA(). //------------------------------------------------------------------------ // 1) distinguere tra sourceMat quadrata e sourceMat rettangolare // 1) individuare la minore fra le cardinalita', di riga e di colonna e valorizzare la variabile "curDimension" // 2) incaso di sourceMat quadrata, ->gestioneQuadrata() e uscita. // 3) incaso di sourceMat rettangolare, ->gestioneRettangolare(), da cui (4)producer->(5)selettore->(6)ePermutazioneDi->appartieneA()->gestioneQuadrata()->rientro a // gestioneRettangolare() per l'estrazione delle quadrate successive. // (4)Osservazioni sul producer(4):comporre le sottomatrici, formando le combinazioni semplici( i.e. senza ripetizione) delle "n" linee, prese "k" per volta. // (4)tali combinazioni semplici hanno cardinalita' (n k), nel senso del binomio di Newton; ovvero "k" elenti, estratti da un insieme di cardinalita' "n", senza possibilita' // (4)di reinserimento del medesimo elemento e con irrilevanza dell'ordine. Oss. k<=n. // int curDimension; bool isSquare = false; int Rango; LinearAlgebra.MatrixRank workCopy = null; // if (this.Get_cols < this.Get_rows) { workCopy = new MatrixRank(this.transpose()); curDimension = this.Get_cols;//---###################### the minimum between the two dimensions, becomes curDimension ############## }// end if ( this.Get_cols < this.Get_rows ) else if (this.Get_cols > this.Get_rows) { // i.e. Get_cols > Get_rows workCopy = new MatrixRank(this); // keep it as is. curDimension = this.Get_rows; //---###################### the minimum between the two dimensions, becomes curDimension ############## }// end if Get_cols >= Get_rows else // this.Get_cols == this.Get_rows { workCopy = new MatrixRank(this); // keep it as is. curDimension = this.Get_rows; //---###################### the minimum between the two dimensions, becomes curDimension ############## isSquare = true; }// end if. // if (isSquare) { Rango = this.gestioneQuadrata(workCopy); //----------###################### NonTailrecursion ########################################################## } else { Rango = this.gestioneRettangolare(workCopy); //--------############# Produzione sottomatrici quadrate ed iterazione su this.gestioneQuadrata() ######## } //ready. return(Rango); }// end Rango()
}// end sottomatriciTelescopiche() /// <summary> /// Tiene costanti tutti gli indici di colonna, tranne uno. Su questo itera, attribuendo tutti gli indici del range(i.e. la dimensione massima fra le due; a valle della /// trasposizione e' l'indice delle colonne>righe). /// Cosi' facendo produce configurazioni, che vanno date in esame a "selettore", per verificare che siano effettivamente nuove. /// Data una rettangolare nXk (con n>k; in caso sia kxn si traspone, senza effetti sui minori), ci sono n_binomio_k combinazioni semplici( i.e. senza ripetizione) /// delle "n" colonne, prese "k" a "k". /// il producer implementa i cicli necessari a combinare gli indici di colonna; ad ogni combinazione prodotta, entra in azione il selettore, per stabilire se tale /// configurazione sia da utilizzare( ovvero calcolarne il determinante) o da scartare. /// Solo nel caso il selettore risponda di utilizzare la configuazione, essa viene restituita sotto forma di LinearAlgebra.RealMatrix; altrimenti si fa "continue" nei /// cicli di produzione. Osservazione: quando viene prodotta una sottomatrice quadrata, essa viene lavorata sino al piu' piccolo dei suoi minori e qundi viene associato /// il rango di tale sottomatrice, al vettore di indici della sua configurazione. Sarebbe problematico esplorare solo la "curDimension" e poi dover tornare sulla medesima /// configurazione, quando fosse intervenuto un "--curDimension". /// </summary> private int gestioneRettangolare(LinearAlgebra.MatrixRank rettangolareAnalizzanda) { // since columns are more than Get_rows( always after translation), the simple combinations are cardinality of sorceMat.Get_cols taken // rettangolareAnalizzanda.Get_rows each time ( i.e. sorceMat.Get_cols Newton binomial rettangolareAnalizzanda.Get_rows ). this.combinationParams = new CombinationParams(rettangolareAnalizzanda); // nullify on exit, for gc. int binomioN = binomioNewton(rettangolareAnalizzanda.Get_cols, rettangolareAnalizzanda.Get_rows); this.RankSequence = new SquareSmallerRank[binomioN]; // // ciclo di lavorazione del vettore di configurazioni. for (int SquareSmallerRank_element = 0; SquareSmallerRank_element < this.RankSequence.Length; SquareSmallerRank_element++) // ciclo di lavorazione del vettore di configurazioni. { // allocazione del singolo record di configurazione: chiama il Ctor() della struttura e imposta il vettore degli indici, al numero effettivo delle colonne. this.RankSequence[SquareSmallerRank_element] = new SquareSmallerRank(rettangolareAnalizzanda.Get_rows); // if (SquareSmallerRank_element == 0) { this.RankSequence[SquareSmallerRank_element].columnIndexes = this.combinationParams.naturalIndexes; } else if (SquareSmallerRank_element > 0) { for (int c = 0; c < rettangolareAnalizzanda.Get_rows; c++) { // NB. e' cruciale assegnare per singolo scalare, in modo da copiare by_value; se si assegna il vettore in un colpo, viene assegnato il puntatore // e i vettori delle diverse strutture puntano alla stessa copia in memoria. this.RankSequence[SquareSmallerRank_element].columnIndexes[c] = this.RankSequence[SquareSmallerRank_element - 1].columnIndexes[c]; // as the preceeding one. } producer(this.RankSequence[SquareSmallerRank_element].columnIndexes); } //bool bocciato = this.selettore( this.RankSequence[SquareSmallerRank_element].columnIndexes ); ex codice TODO eliminare //if ( bocciato ) //{ // throw new System.Exception("configurazione bocciata dal selettore."); //} // #if debug //-----debug output for (int columnIndex = 0; columnIndex < rettangolareAnalizzanda.Get_rows; columnIndex++)// per ciascuna colonna, compresa l'ultima { System.Console.WriteLine(" record # {0} ", this.RankSequence[SquareSmallerRank_element].columnIndexes[columnIndex]); }// end output del vettore di indici di colonna, per debug. System.Console.WriteLine(" fine record nr.{0}\n\n ", SquareSmallerRank_element); #endif // }// end for RankSequence // //----ciclo valorizzazione del campo "Rank" nel vettore RankSequence for (int SquareSmallerRank_element = 0; SquareSmallerRank_element < this.RankSequence.Length; SquareSmallerRank_element++) // ciclo di lavorazione del vettore di configurazioni. { //----ciclo valorizzazione del campo "Rank" nel vettore RankSequence LinearAlgebra.MatrixRank rankBanco = new MatrixRank(this.combinationParams.cardinalitaRighe, this.combinationParams.cardinalitaRighe); for (int c = 0; c < this.combinationParams.cardinalitaRighe; c++) { bool colInserted = rankBanco.putCol(c, rettangolareAnalizzanda.getCol(this.RankSequence[SquareSmallerRank_element].columnIndexes[c])); #if debug System.Console.WriteLine(" record # {0} ", this.RankSequence[SquareSmallerRank_element].columnIndexes[c]); #endif }// end construction by columns #if debug System.Console.WriteLine(" fine record nr.{0}\n\n ", SquareSmallerRank_element); #endif // now compute the rank on such SubMatrix this.RankSequence[SquareSmallerRank_element].Rank = gestioneQuadrata(rankBanco); rankBanco.deallocator_publicProxy(); // gc, to avoid any risk of using old data. rankBanco = null; // gc, to avoid any risk of using old data. }// end --ciclo valorizzazione del campo "Rank" nel vettore RankSequence // //----ciclo di determinazione del massimo, fra i ranghi, nel vettore RankSequence int MaxDeiRanghi = 0; // init and then compare with actual values. int MaxRankConfiguration = 0; for (int SquareSmallerRank_element = 0; SquareSmallerRank_element < this.RankSequence.Length; SquareSmallerRank_element++) // ciclo di lavorazione del vettore di configurazioni. { //----ciclo di determinazione del massimo, fra i ranghi, nel vettore RankSequence if (MaxDeiRanghi < this.RankSequence[SquareSmallerRank_element].Rank) { MaxDeiRanghi = this.RankSequence[SquareSmallerRank_element].Rank; MaxRankConfiguration = SquareSmallerRank_element;// memorize which configuration ha s the maximum rank. }// end rank comparison, on the single scalar. }// end ---ciclo di determinazione del massimo, fra i ranghi( array), nel vettore RankSequence // this.combinationParams = null;// garbage collect. return(MaxDeiRanghi); }// end gestioneRettangolare