Se aspetto troppo a metterlo in rete rischio di ... non completarlo comunque e neppure di divulgarlo... dunque comincio a mettere in rete questo abbozzo, magari pieno di insidiosi errori...
Il mio obbiettivo è di SEMPLIFICARE L'USO DEL CALCOLO TENSORIALE adattandolo alle esigenze dell' HTML e dei linguaggi di programmazione più noti ed usati ( ma solo quelli di cui ho un po' pratica non perduta per il mio decadimento cerebrale ovvero rimbecillimento senile... e benvenga chi volesse tradurre queste funzioni scritte in Javascript in altri linguaggi più professionali ed usati nel calcolo intensivo ovvero nel supercalcolo fattibile, per esempio con le macchine del http://www.cilea.it )
Io stesso ho in programma di tradurre le regole e le funzioni in Maximese ( vedere http://www.elegio.it/max ) ed in Mathematichese ( vedere http://www.elegio.it/cdf/ ) anche se parecchie funzioni di calcolo tensoriale sono già disponibili. In quel caso mi limiterei soltanto a fare interfacce tra le mie funzioni ( quelle che piacciono a me ) e quelle disponibili nei vari ambienti di calcolo in modo che sia facile tradurre funzioni di calcolo tensoriale complicate molto più di queste che vorrei che fossero quelle assolutamente preliminari.
Naturalmente il primo utilizzatore delle mie funzioni di calcolo tensoriale sono io_me e SOGNO di fare o rifare grandi cose e dimostrazioni almeno numeriche.
Il primo e più facile obbiettivo è difendere il calunniato Albert Einstein che, anche se varie cose le ha scopiazzate senza dire da chi, come è tradizione anche in Fisica e Matematica... ha proposto un modello ROBUSTISSIMO anche se ovviamente parziale della realtà fisica. Mi ha fatto piacere leggere le pagine dedicate alle verifiche sperimentali della Relatività Generale ( http://it.wikipedia.org/wiki/Prove_della_relativit%E0_generale ) anche se, prima o poi, spero che saltino fuori vistosi difetti, magari solo computazionali, che permettano di sostenere come migliori altri modelli, magari operativamente simili ma più facili da usare in pratica...
Altri obbiettivi più ambiziosi ma, a mio parere, proporzionati alle mie, pur modeste, capacità sono il dimostrare CHE I BUCHI NERI NON ESISTONO o che, almeno, esistono dall'inizio della CREAZIONE DELL'UNIVERSO e, quelli che esistono, non possono che agire come singolarità catalizzatrici di quegli ammassi enormi di materia considerati buchi neri ma in realtà COAGULI ( http://it.wikipedia.org/wiki/Buco_nero_supermassiccio ) di materia fermionica attorno a buchi neri nati contemporaneamente con la nascita dell'Universo
Ecco cosa ha scritto P.A.M.Dirac quando doveva passare il tempo spiegando anche la R.G.
Senza tirare in ballo nessuna formula ma appoggiandomi a quello che Dirac ( 1902-1984) ridotto, forse in MISERIA, a fare il professore probabilmente sottopagato, mise in evidenza nel febbraio 1975 a Tallahassee, Florida e ripubblicato nel 1996 da pup.princeton.edu suggerisco questo problema.
Ma se Dirac l'ha detta giusta, ogni particella di massa trascurabile impiega un tempo infinito ( misurato da un osservatore non disturbato dai buchi neri in movimento ) QUINDI QUANTO TEMPO BISOGNEREBBE ASPETTARE LA FUSIONE DEI DUE ORIZZONTI GRAVITAZIONALI ? INFINITO SE DIRAC NON MENTE PER LA GOLA ! E dunque, per me noi possiamo vedere solo COAGULI DI MATERIA SEMPRE PIU' DENSA CHE SI SFORZA DI PENETRARE, DOPO PIU' DI MILIONI DI MILIONI DI ANNI NEL BUCO NERO NATO QUANDO LA LUCE FU' COME E' DETTO poeticamente NELLA GENESI http://www.vatican.va/archive/bible/genesis/documents/bible_genesis_it.html...
Se SBAGLIO CORRIGGETEMI ma, dato che ho solo SPERANZA e POCA FEDE, fatemi credere con belle formule che io riesca un po' a capire... Forse sono un San Tommaso Reincarnato !
Qualche indirizzo forse interessante
http://www.elegio.it/doc/tn/lumodulare.html ( esempi di funzioni di soluzione di sistemi lineari )http://www.elegio.it/doc/tridia/sorgenti/alin-20130106.html Libreria di algebra lineare del 2008 con file leggermente ristrutturato nel gennaio 2013http://www.elegio.it/calcolatrice/quarto-grado+.html per promemoria radici di terzo e quarto gradohttp://www.elegio.it/doc/tn/lumodulare.html Contiene la funzione per risolvere sistemi sia in virgola mobile che in algebra modulare ( sfruttando l'algoritmo di Euclide per il calcolo dell'inverso modulare di un numero intero )Per esempio: Scrivere qualcosa e cliccarci sopra . Qui ho definito prima la funzione potenza(a,b) che dunque posso usare...
...Come dedurre una permutazione da una stringa di caratteri qualsiasi.
Innanzi tutto va scelto quale è il primo dei simboli usati mentre i seguenti sono i consecutivi nella tabella Unicode e quanti sono i caratteri che rappresentano simboli diversi. Ad esempio il primo simbolo usato potrebbe essere "1" oppure "A" oppure "a" ma nulla vieta di usare simboli greci partendo dal carattere alfa "α" o partendo dall'alef ebraica, in Unicode il carattere 64289 ossia "ﬡ" ( http://it.wikipedia.org/wiki/Alfabeto_ebraico ) o quello arabo partendo dal carattere 1575 "ا" , "ب", "ة", "ت", "ت" che scopro che il browser scrive in ordine inverso e strano ☺.
...
...Notare che la funzione usata fornisce anche il segno della permutazione ossia il segno del corrispondente elemento del simbolo di Levi Civita ( http://it.wikipedia.org/wiki/Simbolo_di_Levi-Civita ) e, in sintesi, ricordo che il simbolo di Levi-Civita è un vero tensore se il valore assoluto del determiante del tensore metrico ( una matrice di funzioni delle coordinate ) a cui si riferisce, vale 1 e ricordo che il rango di questo tensore è uguale al numero di dimensioni dello spazio a cui si riferisce per cui in Relatività Speciale e in Relatività Generale, dove l'ordine del tensore metrico è 4, il rango del simbolo di Levi Civita, vero tensore se il tensore metrico ha valore assoluto del suo determinante uguale ad 1, ha rango 4 ossia possiede 256 elementi, molti dei quali di valore zero.
In Javascript uso questa funzione:
var inipermuta="1"; //quindi usa le cifre decimali. function ossiapermuta(sv,diversi){ var j,k,kk,n,nn,ss=sv,vs=[],vp=[]; n=inipermuta.charCodeAt(0); vp[0]="( carattere iniziale '"+ String.fromCharCode(n)+"' )"; nn=diversi-n%diversi; for(j=0;diversi>j;j++){ss+=inipermuta; vs[j]=true;} for(j=0;diversi>j;j++){ n=(nn+ss.charCodeAt(j))%diversi; if(vs[n]){vp[j+1]=n+1;vs[n]=false;} else{ vp[j+1]=-1; for(k=n+1;diversi+n>k;k++){ kk=k%diversi; if(vs[kk]){vp[j+1]=kk+1; vs[kk]=false;break;}}}} for(j=1;diversi>=j;j++)vs[j]=vp[j]; n=1;for(j=1;diversi>=j;j++){ if(vs[j]!=j)for(k=1;diversi>=k;k++){ if(vs[k]==j){vs[k]=vs[j]; vs[j]=j;n=-n;break;}}} return ["LeviCivita \u03b5 : ",n,vp]; }Caratteristiche del tensore dedotte dalla sua lista di memorizzazione
Definisco qui una regola, un po' sperperosa di memoria, che consente di definire le due fondamentali caratteristiche di un tensore ossia il suo ordine, ovvero la dimensione dello spazio a cui si riferisce, e il suo rango, ovvero l'esponente dell'ordine che permette di esprimere ( ordinerango ) il numero massimo di elementi indipendenti del tensore.
Fino a pochi anni fa era importantissimo economizzare la memoria del calcolatore perché la memoria era poca, espressa addirittura da pochi milioni di byte ovvero ottetti di bit. L'esigenza rimane se si debbono trattare problemi di enorme complessità magari dovendo ricorre a supercalcolatori o se si vuole affrontare un problema impegnativo pur avendo a disposizione poche risorse ossia calcolatori datati o poco costosi. Tuttavia ormai la memoria disponibile è enorme e consente un suo ragionevole sperpero usato per semplificare i programmi di calcolo e/o renderli meno esposti ad errori di programmazione.
In
mindimor
il primo argomento rappresenta la base ovvero l'ordine del tensore e il secondo rappresenta il rango ed il risultato è la lunghezza minima della lista necessaria per memorizzare il tensore....In sintesi considerando le basi di uso più frequente ossia 2,3 e 4 ed i ranghi più usati ossia lo 0 ovvero quello dello scalare, 1 ossia quello dei vettori, 2 ossia quello delle matrici, 3 ossia quello dei simboli di connessione, 4 ossia il tensore di curvatura...
ordine\rango 0 1 2 3 4 5 2 2 3,4 6,8 12,16,20 24,32,40,56 48,60,64.. 3 2 5 10,14 28,36,44,52.. 88,104,.. 272,304,.. 4 2 7 18,22 68,76,84,.. 264,280,.. 1040,1072,.. 5 2 9 26,30,34 132,140,.. 632,648,.. 3152,3184,.. 6 2 11 38,42,46 220,228,.. 1304,1320,.. 7792,7284,.. In pratica si opera in questo modo basandosi sul fatto che ogni intero è fattorizzabile in un unico modo in una sequenza di primi ordinati in ordine crescente ed elevati, ciascuno ad un suo personale esponente. Tra tutti i numeri primi ha un carattere speciale il numero 2 che è il più piccolo dei primi. Attribuisco all'esponente del due un ruolo speciale... :
- La potenza di due intera e positiva per la quale è esattamente divisibile la lunghezza della lista rappresenta il rango del tensore diminuito di una unità.
- Se la lunghezza della lista è esattamente una potenza di 2, l'ordine del tensore è 2 e il rango del tensore è l'esponente di 2 che permette di ottenere mezza lunghezza della lista ossia l'esponente di 2 diminuito di uno. Notare però che una pura potenza di 2 è ammessa come lunghezza di una lista ma non è una lunghezza ottimale ossia minima per quel tensore di dato ordine e rango !
- Se la lunghezza della lista è un numero dispari il rango è 1 ossia il tensore è un vettore e l'ordine è la lunghezza della lista aumentata di 1 e divisa per due.
- Se la lunghezza della lista non è esattamente una potenza di 2, il maggiore intero che elevato al rango approssima per difetto la lunghezza della lista rappresenta l'ordine del tensore ossia il numero di dimensioni del suo spazio di definizione. Notare che l'ordine può essere un potenza di 2, come ad esempio 4, perché, anche se divisibile per due, è determinato dai fattori primi dispari della lunghezza della lista.
Data questa regola ci si potrebbe domandare se l'attribuzione di un ruolo particolare al numero 2 è una scelta arbitraria o se è una scelta obbligata. Si tratta di una scelta resa obbligatoria dalla ultima regola ossia usare come ordine del tensore l'intero che, elevato al rango del tensore, approssima meglio per difetto la lunghezza della lista.
In effetti sarebbe possibile usare 3 come primo usato per memorizzare il rango ma... l'uso di 3 richiede, per tensori di rango maggiore di 1, l'uso di liste più lunghe di quelle necessarie quando si usa 2.
Per primi grossi, poi, ossia da 5 in su, si ha, oltre ad un forte spreco di memoria, anche l'impossibilità di definire la lunghezza di alcuni tipi di tensori e dunque l'uso di primi diversi da 2 e da 3 non è assolutamente possibile.
Insomma, l'uso di 2 rappresenta la scelta ottimale.
Nella
kebaserango
l'unico argomento rappresenta la lunghezza della lista da cui si vuole dedurre la base ossia l'ordine del tensore, ed il rango del tensore. Se la lunghezza della lista non fosse la minima necessaria viene stampata anche la lunghezza minima per memorizzare il tensore di quella stessa base e rango....Ecco una sequenza della traduzione delle lunghezze pari della lista; quelle dispari individuano vettori ossia tensori di rango 1 e dunque il dedurre l'ordine è banale.
Notare che l'unica lista che individua uno scalare è quella lunga 2 per cui, anche nel caso di uno scalare si ha a disposizione un elemento usabile per info sulla natura dello scalare.... ATTENZIONE ! ... Javascript non attivato... Per usare questo documento di studio bisogna farlo funzionare !... La critica a questo metodo è che spreca un po' di memoria soprattutto nel caso di tensori di rango 1 dato che obbliga ad usare una lunghezza dispari quasi doppia del necessario. Ma attualmente, con l'enorme disponibilità di memoria a disposizione, a mio parere dovrebbe prevalere l'apprezzamento della semplicità del metodo di poter caratterizzare un qualsiasi tensore solo in base alla lunghezza della lista dei suoi elementi.
sperimenta la ricerca della lunghezza minima...
...sperimenta l'individuazione della base e del rango...
...altra prova in casi in cui la lunghezza usata non è la minima ammissibile per un dato tipo di tensore...
...In Javascript uso queste due funzioni:
function mindimor(base,rango){ var hh,nt,pb; var ba=Math.round(base), ra=Math.round(rango); if(2>ba || 1>ra) return 2; if(1==ra)return (2*ba-1); pb=Math.pow(2,ra-1); nt=Math.pow(ba,ra); hh=nt-nt%pb; return (hh+pb*(1+(hh/pb)%2)); } // // Non uso questa ma... // Come mindimor ma senza il vincolo di usare // la potenza di 2 per consevare l'info del // rango del tensore. // function tensolungo(base,rango,primo){ var mm; var ba=Math.round(base), ra=Math.round(rango), pr=Math.max(2,Math.round(primo)); if(2>ba || 1>ra) return 2; if(ra==1){mm=ba+1+Math.floor(ba/(pr-1));} else{ mm=Math.pow(pr,ra-1)* Math.ceil(Math.pow(ba,ra)/Math.pow(pr,ra-1)); if(mm%(Math.pow(pr,ra))==0)mm+=Math.pow(pr,ra-1);} return mm; } // function baserango(lungo){ var j,ba=1,pd=1,ra=0,lu=Math.round(lungo); if(3>lu)return [2,ba,ra]; for(j=0;lu>j;j++){ra++; pd=2*pd;if(lu%pd!=0)break;} if(pd==2)ba=(lu+1)/2; else if(pd==2*lu){ba=2;ra=ra-2;} else for(j=0;lu>j;j++){ba++; if(Math.pow(ba+1,ra)>lu)break;} return [lu,ba,ra]; }Effettuare una permutazione specificata da un solo numero intero
Assumo come convenzione che una qualsiasi lista possa essere trattata come un tensore di rango e ordine determinati dalla lunghezza della lista stessa secondo le regole messe a punto qui sopra....
La lista non deve essere tanto lunga o di lunghezza scorretta da produrre errori nel calcolo del rango e dell'ordine.
Ovviamente sarebbe illogico, perché dispendioso, usare liste più lunghe del necessario per cui il rischio di fraintendere il rango e l'ordine del tensore è piccolo...
Altra regola motivata da considerazione di traducibità degli algoritmi è il cercare di non usare mai, se esiste, l'elemento 0 della lista. Si ottiene questo memorizzando i dati del tensore in modo che l'ultimo dato sia anche l'ultimo elemento della lista. Quando si vuole, con questa regola, basta usare per scopi di commento uno degli elementi ridondanti della lista, causato dalla regola assunta per determinare il rango e l'ordine del tensore. Se si vuole, si può usare l'elemento 0 nei linguaggi di programmazione in cui esiste ( Javascript, C++ etc.) ma già questa scelta provoca qualche problema di traduzione delle
function
nei linguaggi in cui la numerazione della lista parte da 1 (Mathematichese, Maximese, Fortran etc..) per cui ... meglio non usare mai l'elemento zero della lista che potrebbe in certi ambienti non esistere.Impostazione orientata agli oggetti: un tensore di rango due è un vettore di vettori, un tensore di rango tre è un vettore di vettori di vettori, un tensore di rango quattro è un vettore di vettori di vettori di vettori ... etc.
Con questa impostazione, possibile praticamente in tutti i linguaggi di programmazione moderni, a partire dal
C++
, ( in informatica è detta impostazione orientata agli oggetti ) ogni tensore diventa una specie di matrioska russa http://en.wikipedia.org/wiki/Matryoshka_doll o, meglio, un insieme di scatole cinesi http://en.wikipedia.org/wiki/Chinese_boxes e le funzioni si possono semplificare rendendole ricorsive ossia una funzione può richiamare se stessa con argomenti dedicati ad una parte degli argomenti della funzione che utilizza se stessa...Inxpermuta
gli argomenti sono: numeropermutazione, base, rango. Normalmente il numero della permutazione ha tante cifre quanto il numero del rango....
I dati del tensore sempre il più in fondo possibile nella lista sovradimensionata che lo contiene
In Javascript uso queste due funzioni:
// Assegnato l'intero ki e nota la base ba e il rango ra // calcola il vettore che esprime il numero ki con ra cifre // usando la base ba. // Se ba==10 e ra==3 allora 573 diventerebbe ["...",5,7,3] // ossia la prima cifra rappresenta la potenza maggiore e // l'ultima la potenza zero. // function indici(ki,ba,ra){ var k,kk=ki; var vj=new Array(ra+1); for(k=0;ra>k;k++){ vj[ra-k]=kk%ba kk=(kk-vj[ra-k])/ba; } vj[0]=" Base "+ba+") "; return vj; } // // Dato il vettore degli indici ind ed il vettore della // permutazione vxp, calcola la nuova posizione come un intero. // function indove(indici,vxp,ba){ var h,ii=0; if(indici.length!=vxp.length)return -1; for(h=1;indici.length>h;h++){ ii=ba*ii+indici[vxp[h]]; } return ii; } // // Calcola la permutazione del tensore di base e rango // assegnati e usando il numero nsv per definire la permutazione. // function xpermuta(nsv,base,rango){ var j,kk,vip,ni,nn=Math.pow(base,rango); // Quanto deve essere lunga la lista. var dove,lungo=mindimor(base,rango); // Trova la vera permutazione indicata da nsv var veraper=ossiapermuta(nsv,rango); vip=new Array(lungo); vip[0]="{"+veraper[2]+"} "; dove=lungo-nn; for(j=1;dove>j;j++)vip[j]=" "; for(j=0;nn>j;j++){ // Esprime le cifre di j come un vettore ni=indici(j,base,rango); // Dove deve prendere il j_esimo dato. kk=indove(ni,veraper[2],base); vip[j+dove]=kk+dove; } return vip; }Avendo calcolato la lista degli indici di un dato tipo di permutazione di un dato tipo di tensore posso permutare qualsiasi tensore dello stesso tipo usando la lista precalcolata.
Basta scrivere, usando la listapermuta(...)
:for(k=0;permuta.length>k;k++)tpermutato[k]=toriginale[permuta[k]];per cui, mano a mano che si alloca memoria per la lista che deve contenere il nuovo tensore, si va a prendere il giusto elemento che deve occupare la j_esima posizione nella lista e il tensore è memorizzato in modo che il suo ultimo elemento sia anche l'ultimo elemento della lista di lunghezza minima per memorizzare il tensore secondo le regole prefissate.
Inindici
gli argomenti sono la posizione della lista partendo da 0, la base usata e il numero di cifre che corrisponde al rango del tensore a cui ci si riferisce....Inindove(...)
gli argomenti sono i seguenti: il primo è la lista degli indici del tensore, il secondo è la lista della permutazione voluta ( enumera le posizioni degli indici da 1 al rango essendo1,2,..,rango
la permutazione identità ossia senza spostamenti dei dati ) e il terzo è la base ossia le dimensioni dello spazio in cui viene usato il tensore. Notare che le due liste dei due primi argomenti debbono avere uguale lunghezza. Notare che il primo indice del tensore è quello che gira più lentamente e l'ultimo indice è quello che varia più velocemente ossia individua elementi contigui nella lista che contiene il tensore....Qui si fa un controllo di come e se si ottiene la posizione originaria nella lista quando si fa la permutazione identica ( 12 o 123 o 1234 etc. a seconda del rango del tensore ossia vettore di vettore, vettore di vettore di vettore etc. )....
...Javascript non attivato !...http://www.elegio.it/omnia/ht/ l'indice dei file dedicati a questi argomenti.Per fare calcoli vari...
...Risultato ►...Risultato ►...Risultato ►...Risultato ►...Risultato ►...Risultato ►La funzioneRisultato ►acasot(base,rango)
genera tensori di ordinebase
e di rangorango
. Dato che la lista che contiene il tensore può essere molto lunga, consiglio di ridefinire la variabilenon_oltre
ma poi di riassegnarle un valore ragionevole, come 25 o poco di più.Qui fare esperimenti sull'uso diRisultato ►xpermuta(sv,base,rango)
che, a sua volta fa uso dimindimor(base,rango)
,ossiapermuta(sv,rango)
,indici(j,base,rango)
,indici(vind,veraper,base)
. Inoltre mette alla prova la permutazione effettuata applicandola ad un tensore creato a caso...Altri esperimenti sull'uso diRisultato ►xpermuta(sv,base,rango)
che mette alla prova la permutazione effettuata applicandola ad un tensore creato a caso...Altri esperimenti sull'uso diRisultato ►xpermuta(sv,base,rango)
facendo permutazioni circolari su tensori di rango tre per cui alla terza permutazione si deve ottenere quella di partenzaAltri esperimenti sull'uso diRisultato ►xpermuta(sv,base,rango)
facendo permutazioni circolari su tensori di rango quattro per cui alla quarta permutazione si deve ottenere quella di partenza