Versione 20080828
Libreria: http://www.elegio.it/doc/tridia/sorgenti/alin_libesterna(operativa).txt
Riesumazione: http://www.elegio.it/doc/tridia/sorgenti/alin-20130106.html
http://www.elegio.it/calcolatrice/

Fattorizzazione LU, soluzione di sistema ed
autovalori di matrice simmetrica e non

Ovvero micro libreria di algebra lineare in JavaScript fatta in modo che la traduzione da Fortran ed in Fortran http://www.g95.org/ ( e da Mathematica in Mathematica http://www.wolfram.com/ ) sia semplice e naturale. In particolare la numerazione dei vettori non parte da 0 ma da 1, anche se l'elemento 0 in Javascript esiste ma serve come memoria ausiliaria (ed avere a disposizione qualche vettore di servizio facilita la vita).

In ho stabilito la convenzione che, se l'oggetto è un vettore, l'elemento 0 deve valere 0 mentre se è una matrice deve rappresentare l'ordine della matrice.

Qui non si è curata molto la veste grafica ma solo l'aspetto computazionale. La possibilità di effettuare operazioni matriciali di larga applicazione consente di realizzare delle specie di calcolatrici capaci di calcoli difficilmente effettuabili a mano (provare a risolvere a mano un sistema di quattro incognite). Naturalmente qui, in mancanza di appositi form, per lavorare occorre editare il sorgente HTML e modificarlo.... cosa che non è assolutamente difficile per chi è abituato a programmare calcoli scientifici in Fortran.

In effetti JavaScript non si pone come un linguaggio in competizione con linguaggi di alto livello come il Fortran o Mathematica o Maxima ma come un linguaggio che in simbiosi col Fortran lo potenzia sul versante della grafica e della interattività.

Come è definito l'oggetto fondamentale ARMA
function ARMA(ld,n){
    var j,k,i;
    // Questo tipo derivato serve per definire sia vettori che matrici.
    //
    // Commento a questo dato:
    this.commento="\u003cbr/\u003e"
    // Risultato dell'ultima operazione (0 == riuscita bene).
    this.error=0;
    // Ordine della matrice rettangolare, conservato per sicurezza.
    // Se la matrice e' un vettore deve valere 0.
    this.ordine=parseInt(n);
    // Lunghezza di ogni colonna meno 1 (ossia quante righe stanno
    // in una colonna). 
    this.ld=parseInt(ld);
    if(this.ordine>this.ld) this.ld=this.ordine;
    // Dati della matrice e della soluzione.
    this.a= new Array();
    //
    // In 0 ci sta l'ordine del sistema ossia n
    // Tra 1 e n ci sta, a volte, il vettore soluzione.
    // Ogni colonna e' lunga ld >=n e l'elemento 0
    // di ogni colonna serve per gestire i dati ed e' 
    // un intero mentre gli altri sono float.
    //
    i=-1;
    for (j=0;this.ordine>=j;j++){
        i++;
        this.a[i]=j;
        for(k=1;this.ld>=k;k++){
            i++;
            this.a[i]=Math.PI;       
            }
        }
    this.a[0]=this.ordine;
    // Eventuale risultato scalare di un calcolo algebrico.
    this.scalare=Math.PI;
    // Dati per definire la sottomatrice di lavoro.
    // Primo elemento della sottomatrice (start riga,colonna).
    this.clip_sr=1;
    this.clip_srold=this.clip_sr;
    this.clip_sc=1;
    this.clip_scold=this.clip_sc;
    // Ultimo elemento della sottomatrice (end riga,colonna).
    // this.clip_er=this.ordine;
    if(this.ordine>0) { this.clip_er=this.ordine; }
    else { this.clip_er=this.ld;}
    this.clip_erold=this.clip_er;
    this.clip_ec=this.ordine;
    this.clip_ecold=this.clip_ec;
    // Limite del vettore ed ordine delle matrici di servizio
    this.ndim=this.ordine;
    if(this.ordine==0) this.ndim=this.ld;
    return this;
    }

Funzioni della libreria

Quella che segue è una spiegazione non sempre completa. Guardare il sorgente JavaScript di questa libreria per capire i dettagli. Anche gli esempi applicativi messi al termine di questa pagina danno indicazioni su come usare questa libreria.

function ARMA(ld,n)

Crea un oggetto di tipo ARMA ossia una matrice corredata di vari componenti utili per la sua gestione. In essa ld rappresenta il numero massimo di righe ed n rappresenta il numero massimo di colonne. Si noti che esiste anche la riga zero e la colonna zero ma sono nascoste.
La numerazione inizia da 1 e la colonna zero contiene un vettore ausiliario usato in certe situazioni, quali il prodotto di matrice per vettore.
Per attivare questa funzione occorre usare l'operatore new; se ad esempio si vuole una matrice di 4 righe e 3 colonne occorre scrivere:

miamat = new ARMA(4,3);

e da qui in poi miamat.ld vale 4 e miamat.ordine vale 3. l'ultimo elemento del vettore di servizio vale miamat.ndim che non può superare il valore di miamat.ld ed inizialmente vale miamat.ordine. Per definire un oggetto che contiene solo il vettore di servizio (e pertanto si potrà usare solo come vettore) bisogna scrivere:
miovet = new ARMA(4,0);
ossia fare in modo che miovet.ordine valga 0. In tal caso miovet.ndim viene inizializzato al suo massimo valore ossia vale miovet.ld ossia, nell'esempio, 4.

function clip(a,sr,sc,er,ec)

Definisce i limiti di clip ossia della selezione della parte della matrice che interessa, e verifica che siano corretti. Bisogna specificare il primo elemento e l'ultimo elemento della sottomatrice su cui si intende operare nei calcoli seguenti.
La numerazione parte da 1 e dunque per considerare l'intera matrice disponibile bisogna usare sr=1, sc=1, er=a.ld e ec=a.ordine.
Per clippare l'intero vettore memorizzato in colonna zero basta scrivere clip(a,1,0,a.ld,0).
Quando viene chiamata questa function, vengono salvati i vecchi limiti di clip che dunque possono essere ripristinati usando la clip_old.

function clip_coerenza(a)

I dati di clip devono individuare sempre almeno un elemento realmente contenuto nella matrice. Questa funzione controlla che i dati di a siano coerenti con le dimensioni di a.
E' ammesso usare la colonna 0 ma non la riga zero che è destinata a contenere dati di servizio.

function clip_copymat(a,b)

Copiatura tra sottomatrici. La sottomatrice a, ricevente stabilisce dei limiti che non possono venire superati. Se la sottomatrice b di prelievo è più piccola della sottomatrice a, vengono prelevati solo i dati disponibili. Il primo elemento della sottomatrice b viene sempre copiato nel primo elemento della sottomatrice a e così via...
La copiatura con trasposizione di b si fa con la clip_trasposta(a,b).

function clip_diade(a,b,c)

La prima colonna della sottomatrice b moltiplicata per la prima riga della sottomatrice c formano una diade che viene aggiunta alla sottomatrice a. I confini della sottomatrice a sono invalicabili ma, a parte questo la diade aggiunta dipende dall'effettivo numero di righe della sottomatrice b e del numero di colonne della sottomatrice c.

function clip_diagomat(a,diago,nondiago)

La diagonale della sottomatrice vale diago, il resto vale nondiago.

clip_formato=7

Variabile usata per controllare il numero di cifre da visualizzare. Usare almeno 5 (cinque cifre utili)

function clip_format(v)

Serve per tagliare le cifre al numero v di tipo float.

function clip_get(a)

Restituisce un vettore con i dati dell'oggetto ARMA passato in argomento.

function clip_getmat(v,sinfo)

Preleva valori dalla sottomatrice "clippata" tramite una stringa contenente dati float separati tra loro dal carattere identico all' ultimo carattere della stringa. L'inizio della stringa deve essere un intero che specifica quanti dati vengono prelevati al massimo.

function clip_inversa(a,usemat)

Fa l'inversa sostituendola alla matrice originaria. Come ordine usa la differenza delle colonne piu' uno. Usa una matrice di servizio (usemat) che deve essere di dimensioni adeguate.

function clip_matmul(a,b,c)

Prodotto matriciale tra le sottomatrici b e c che viene aggiunto alla sottomatrice a.

function clip_matpluseq(a,scala,b)

Alla sottomatrice a aggiunge la sottomatrice b scalata.

function clip_matscala(a,scala)

Moltiplica ogni elemento della sottomatrice di a per il fattore di scala.

var clip_maxcol=10

Variabile di controllo del numero di colonne nella stampa di una sottomatrice. Non stampa più di queste colonne. Serve nella function clip_vedomat(a).

function clip_old(a)

Ristabilisce i vecchi limiti di clip. riprendendo i valori messi in salvo dall'ultima clip o clip_save.

function clip_save(a)

Salva i limiti di clip per poter usare le componenti di clip per altri scopi. I vecchi limiti sono recuperabili con la clip_old.

function clip_setmat(v,s)

Assegna valori alla sottomatrice "clippata" tramite una stringa contenente dati float separati tra loro dal carattere identico all' ultimo carattere della stringa.

function clip_trasposta(a,b)

Copiatura tra sottomatrici In a viene copiata la trasposta di b. La copiatura senza trasposizione si fa con la clip_copymat(a,b).

function clip_vedomat(a)

Fa la parte interna di una tabella ossia usa solo i tag <tr> e <td>. Permette di visualizzare anche il vettore di colonna zero, purchè si usi il clippaggio opportuno.

function clip_vedovet(a)

Fa la parte interna di una tabella ossia usa solo i tag <tr> e <td>. Visualizza il solo vettore di colonna zero senza dovere cambiare il clippaggio. Analoga alla clip_vedomat.

Vere funzioni matematiche, non dedicate alla gestione dei dati

function copyvet(va,vb)

NON usa i limiti di clip ma va da 1 a va.ndim o vb.ndim. Il valore di va.ndim o vb.ndim può essere cambiato con la function setdim(va,n) vn il vincolo che n sia positivo e non superiore a va.ld o vb.ld rispettivamente.

function euclidea(v)

NON usa i limiti di clip. Norma euclidea del vettore v ossia della colonna 0 dell'oggetto v dall'elemento 1 a v.ndim.

function getvet(v,s,primo,ultimo)

NON usa i limiti di clip: estrae dati da v generando una stringa con i valori numerici separati dal carattere s.

function hessenberg(a)

NON usa i limiti di clip: trasforma la matrice considerata quadrata di ordine a.ndim in modo che assuma la forma di Hessenberg ossia con la triangolare inferiore nulla ad eccezione della prima sottodiagonale della diagonale principale. La trasformazione viene fatta in modo che la matrice risultato abbia gli stessi autovalori della matrice di ingresso.

In uscita la triangolare inferiore non è azzerata ma contiene i dati per poter passare dagli autovettori della matrice di Hessenberg a quelli della matrice originaria.

function hqr(a)

NON usa i limiti di clip e considera che l'ordine di a sia a.ndim.

L'algoritmo QR di J.C.F.Francis e V.N.Kublanovskaya.

Considera qualunque matrice come se fosse in forma di Hessenberg e trova gli autovalori che, in genere, possono essere complessi.
In colonna 0 viene fornito il vettore della parte reale mentre il vettore della parte complessa viene estratto usando la function iper che scambia tra loro parte reale e parte complessa e dunque porta in colonna 0 il vettore delle componenti complesse.

function iper(a)

Di servizio alla function hqr serve a scambiare tra loro parte reale e parte complessa portando in colonna 0 della matrice a la parte complessa.

Il vettore della parte complessa diventa dunque accessibile e può essere estratto dall'oggetto a.

Non si considerano operazioni di clip per cui l'ordine dei vettori trattati è a.ndim.

function jacobi_eigen(a,v)

a e v debbono essere oggetti di tipo ARMA. Il risultato è il numero totale di rotazioni di Jacobi effettuate.
a.a in ingresso contiene la matrice considerata simmetrica (come se la triangolare inferiore fosse la trasposta della triangolare superiore ) ed in uscita contiene valori non significativi nella triangolare superiore e resta con la diagonale e la triangolare inferiore immutate.
La colonna zero di a, in uscita contiene gli eigenvalue NON ordinati.
v.a in uscita rappresenta la matrice degli autovettori.
Usa come ordine di a il valore di a.ndim. Non supera il massimo di iterazioni maxitera e usa come limite accettabile di convergenza il valore di precisione.

function lu_fa(a)

NON usa i limiti di clip: Fattorizza a considerata di ordine a.ndim. La function può andare in errore: ci va se la matrice è singolare.

function lu_so(a)

NON usa i limiti di clip: Il vettore termine noto viene sostituito dal vettore solunzione.

function matvet(a,v)

NON usa i limiti di clip ma va da 1 a a.ndim. Prodotto matrice per vettore. Non azzera il vettore ma aggiunge il risultato del prodotto della matrice a per il vettore v al vettore di servizio contenuto in a (il vettore di colonna zero)

function setallmat(a,s)

NON usa i limiti di clip. Legge da s tutta la matrice considerata di ordine a.ndim. Ricordarsi che s è una stringa con i dati in virgola mobile separati dall'ultimo carattere della stringa s.

function setallvet(v,s)

NON usa i limiti di clip. Legge da s tutto il vettore. Ricordarsi che s è una stringa con i dati in virgola mobile separati dall'ultimo carattere della stringa s.

function setdim(a,n)

Imposta o trova la dimensione di servizio usata quando NON usa i limiti di clip. In altre parole assegna il valore di n a a.ndim se n è interpretabile come numero, altrimenti, se n non inizia con cifre, fornisce per risultato il valore di a.ndim in corso.

function setvet(v,s,primo,ultimo)

NON usa i limiti di clip. Legge dalla stringa s i valori che carica in v da primo a ultimo.

function zerovet(v)

NON usa i limiti di clip. Azzera il vettore ossia la colonna 0 della matrice; sono azzerati gli elementi da 1 a v.ndim.

In fondo a questa pagina c'è una serie di test della libreria stassa.

Si consiglia di guardare il testo HTML al termine di questa pagina per vedere alcuni esempi di chiamata della varie function di questa microlibreria di algebra lineare in ECMAscript (ovvero JavaScript).

Esempi applicativi

Per capirli è indispensabile guardare il sorgente HTML. Per farne altri si consiglia di salvare la pagina originaria (per sicurezza) e modificare una copia locale sul proprio PC.

avviso1:

avviso2:
avviso3:
avviso4:
avviso5:
avviso6:
avviso7:
avviso8:
avviso9:
avviso10:
AMEN