Upload
doraemon85
View
309
Download
50
Embed Size (px)
DESCRIPTION
Wolfram Mathematica - Guida all'uso del software di calcolo
Citation preview
Appunti di Mathematica
-100
0
100
-100
0
100
0
5
10
Daniele Lupo
Studente di Ingegneria Elettronica (speriamo ancora per poco...)
Università degli studi di Palermo
[email protected] riguardanti il programma Mathematica. Spero vivamente che possano esservi utili.
Contattatemi se trovate errori di qualsiasi genere, oppure avete commenti o suggerimenti da darmi.
Sommario
Introduzione………………………………………………………………………….1 ⇒ Perché Mathematica?……………………………………………….……....2 ⇒ Suggerimento………………………………………………………………….5
Primi Passi……………………………………………………………...…………….6 ⇒ Cominciamo………………………………………………………...………….6 ⇒ Numeri e Precisione………………………………………………...……….10 ⇒ Liste……………………………………………………………………….…….27
Creazione……………………………………………………………...….27 Ricerca………………………………………………………………...….37 Manipolazione……………………………………………………...…….42
⇒ Vettori e Matrici………………………………………………………….….45 ⇒ Nota sulla Visualizzazione delle formule…………………………...….49
Calcolo Simbolico 1………………………………………………………...…….51 ⇒ Introduzione……………………………………………………………….….51 ⇒ Manipolazioni Algebriche……………………………………………...….53 ⇒ Manipolazioni Avanzate……………………………………………..…….64 ⇒ Altre Manipolazioni……………………………………………………..….70 ⇒ Nota per Dimensioni Fisiche……………………………………………...75
Calcolo Simbolico 2……………………………………………………………...77 ⇒ Introduzione………………………………………………………………….77 ⇒ Funzioni……………………………………………………………………….77 ⇒ Sommatorie e Produttorie………………………………………………...84 ⇒ Equazioni……………………………………………………………………...85
Scrittura di equazioni…………………………………………………….85 Disequazioni……………………………………………………………..86
⇒ Risolvere le Equazioni……………………………………………………..88 Equazioni Semplici…………………………………………………........88 Sistemi di Equazioni……………………………………………………..94 Disequazioni……………………………………………………………..98 Equazioni Differenziali………………………………………………....100
⇒ Serie di Potenze……………………………………………………………..102 ⇒ Limiti………………………………………………………………………….103 ⇒ Trasformate Integrali……………………………………………………..106
Calcolo Numerico………………………………………………………………..107 ⇒ Introduzione…………………………………………………………………107 ⇒ Sommatorie, Produttorie, Integrali……………………………………108 ⇒ Soluzione di Equazioni……………………………………………………109 ⇒ Equazioni Differenziali……………………………………………………111
⇒ Ottimizzazione Numerica………………………………………………113 ⇒ Dati Numerici……………………………………………………………...116 ⇒ Precisione…………………………………………………………………...118
Grafica……………………………………………………………………………..122 ⇒ Introduzione…………………………………………………………….....122 ⇒ Funzione ad una Variabile………………………………….………….122 ⇒ 2D Generale………………………………………………………………..134 ⇒ Funzioni a due Variabili………………………………………………...148 ⇒ Introduzione al 3D………………………………………………………..152 ⇒ Visualizzazione Dati……………………………………………………...162 ⇒ Grafici Parametrici……………………………………………………….166 ⇒ Suoni…………………………………………………………………………177
Importazione ed Esportazione……………………………………………..180 ⇒ Introduzione………………………………………………………………..180 ⇒ Importazione……………………………………………………………….180 ⇒ Esportazione………………………………………………………………..187
Dati…………………………………………………………………….187 Formule………………………………………………………………..189
⇒ Packages…………………………………………………………………….192 Introduzione……………………………………………………………192 Salvataggio e Caricamento…………………………………………….193
Programmazione………………………………………………………………..200 ⇒ Introduzione………………………………………………………………..200 ⇒ Comandi Base……………………………………………………………...200
Inizio…………………………………………………………………...200 Input ed Output………………………………………………………...202 Flusso di Programma…………………………………………………...207 Stringhe………………………………………………………………...217
Formattazione……………………………………………………………………225 ⇒ Introduzione………………………………………………………………..225 ⇒ Celle…………………………………………………………………………..225 ⇒ Sezioni……………………………………………………………………….227
Mathematica Avanzata……………………………………………………….231 ⇒ Introduzione………………………………………………………………..231 ⇒ Espressioni…………………………………………………………………231
Cosa Sono……………………………………………………………..231 Valutazione delle Espressioni……………………………………..….236
⇒ Pattern………………………………………………………………………241 Cosa Sono……………………………………………………………..241 Ricerca di Pattern, e Modifica……………………………………..….246
⇒ Operazioni su Funzioni………………………………………………….262 Introduzione…………………………………………………………...262 Manipolazioni Base…………………………………………………....262 Modifica Strutturale delle Espressioni………………………………...277 Funzioni Pure………………………………………………………….289
Definizioni di Espressioni e Funzioni………………………………………………………………292
Regole di Trasformazione……………………………………………306 ⇒ Programmazione Avanzata…………………………………………...314
Introduzione………………………………………………………….314 Visibilità di Variabili Locali…………………………………………314
Appendice A: Packages……………………………………………………..320 ⇒ Algebra`AlgebraicInequalities`………………………………………320 ⇒ Algebra`ReIm`…………………………………………………………...322 ⇒ Algebra`RootIsolation`…………………………………………………323 ⇒ Calculus`FourierTransform`…………………………………………325 ⇒ Calculus`VectorAnalysis`……………………………………………...333 ⇒ DiscreteMath`Combinatorica`……………………………………….344 ⇒ DiscreteMath`GraphPlot`……………………………………………..363 ⇒ Graphics`Animation`…………………………………………………...370 ⇒ Graphics`ComplexMap`……………………………………………….374 ⇒ Graphics`FilledPlot`…………………………………………………….378 ⇒ Graphics`Graphics`……………………………………………………..384 ⇒ Graphics`Graphics3D`…………………………………………………400 ⇒ Graphics`ImplicitPlot`…………………………………………………416 ⇒ Graphics`InequalityGraphics`……………………………………….419 ⇒ Graphics`Legend`……………………………………………………….426 ⇒ Graphics`PlotField`……………………………………………………..431 ⇒ Graphics`PlotField3D`…………………………………………………440 ⇒ Graphics`SurfaceOfRevolution`……………………………………..444 ⇒ LinearAlgebra`FourierTrig`………………………………………….448 ⇒ LinearAlgebra`MatrixManipulation`………………………………449 ⇒ LinearAlgebra`Orthogonalization`…………………………………463 ⇒ Miscellaneous`Units`……………………………………………………467 ⇒ NumberTheory`Recognize`……………………………………………473
Appendice B: Eq. Differenziali…………………………………………..476 ⇒ Introduzione………………………………………………………………476 ⇒ Tipi di Equazioni………………………………………………………...476 ⇒ Risoluzione Simbolica………………………………………………….477
DSolve……………………………………………………………….477 ⇒ ODE…………………………………………………………………………484 ⇒ Sistemi ODE………………………………………………………………499 ⇒ PDE…………………………………………………………………………505 ⇒ DAE…………………………………………………………………………516 ⇒ Problema del Valore al Contorno……………………………………522 ⇒ NDSolve…………………………………………………………………….536
Appunti diMathematica
Introduzione
Benvenuti a tutti quanti. Questi appunti cercheranno, in qualche modo, di farvi capire qualche
aspetto più approfondito riguardo il programma Mathematica: cercherò di farvelo conoscere ad un
livello un tantinello più avanzato riguardo l'uso come semplice calcolatrice :-)
Purtroppo sono soltanto un semplice studentello, e ci sono un'infinità pazzesca di cose di questo
programma che non conosco neach'io. Dopotutto, il programma è così vasto che credo sia
impossibile comprenderlo tutto appieno se non si usa tutto il giorno, tutti i giorni... Cosa che io,
almeno per il momento, evito di fare, dato che gli studi ancora non mi hanno tolto del tutto la vita
sociale, e riesco ancora ad uscire. Tuttavia, saper usare questo programma semplificherà
notevolmente la vita a tutti quanti, ve lo garantisco.
Daniele Lupo Appunti di Mathematica
1Printed by Mathematica for Students
ü Perchè Mathematica?
Nella mia facoltà ci sono principalmente due scuole di pensiero riguardo il miglior programma di
calcolo attualmente disponibile su computer: la maggioranza degli studenti e dei professori
preferisce Matlab, mentre una minoranza preferisce Mathematica.
Io personalmente sono convinto che un confronto diretto fra i due programmi non si possa fare: sono
entrambi ottimi, sono standard de facto, e le preferenze si devono più che altro a flussi di lavoro
diversi, ed al tipo di risultati che si vogliono ottenere.
Una della cose che può scoraggiare un utente che si trova per la prima volta davanti ad un
programma come Mathematica, è la sua interfaccia spartana: icone, comandi, sono quasi del tutto
assenti, e si lavora scrivendo formule e trasformazioni a mano, come se si usasse il blocco note di
Windows. Anche le formule, normalmente, si sccrivono in questo modo, dando un 'aspetto poco
elegante a tutto quanto. Ci sono comandi ed icone che permettono di ottenere gli stessi risultati di
una formula stampata con LATEX, ma, una volta perse quelle due orette ad abituarsi al programma,
tutto quanto procede molto più velocemente di quanto si riesca a fare che andare a cercare sempre la
giusta icona col mouse.
Matlab, d'altro canto, è pure troppo user-friendly; intendiamoci, lo è quanto può esserlo un
programma di matematrica e tecnica che ti fa utilizzare i più avanzati algoritmi e di creare schemi e
formule fra le più complicate del mondo, ma è sempre dominato da icone e toolbox. All'avvio,
sembra anch'esso abbastanza spartano: ci sono più finestre ed icone, è vero, ma se devi fare una
somma devi sempre scrivere numeretti come se usassi il blocco note. Invece, basta trovare il
pulsantino Start per accedere ad un mondo immenso fatto di finestre e di Toolbox già
preconfezionati per quasi tutto; se ti serve una GUI per poter studiare il luogo delle radici di una
funzione di trasferimento, c'è. Se vuoi pulsantini che ti creino filtri numerici, ci sono anche quelli.
Tool per l'analisi dei segnali preconfezionati: ci sono anche quelli. In Mathematica, invece, queste
cose non ci sono, o meglio, ci sono a livello testuale; deci sempre scrivere i comandi a mano etc. In
realtà, dalla versione 4 sono spuntati comandi per poter creare interfacce grafiche con Java e, dalla
versione 5.1, con il Framework .NET di Microsoft, ma sono aspetti parecchio avanzati che, se
semplificano di molto la vita in fase di esecuzione, la complicano esponenzialmente in fase di
progettazione, se non si sa programmare bene ad oggetti. Se volete qualcosa di aspetto gradevole con
Mathematica, provate a cercare qualcosa di già fatto su Internet.
Da un punto di vista di facilità d'uso, quindi, Matlab è oggettivamente migliore. A mio avviso, però,
è computazionalmente meno potente. Attenzione, però! Non dico che diano risultati diversi, oppure
che sia un programma peggiore, ma che utilizzano delle filosofie completamente diverse. Matlab è
un programma che esegue principalmente calcolo numerico. Dategli una matrice numerica, e vi da
l'inversa numerica. Dategli due liste di valori numerici, e Matlab vi farà la convoluzione numerica in
un attimo.
Daniele Lupo Appunti di Mathematica
2Printed by Mathematica for Students
Mathematica, dal canto suo, ha un motore di calcolo che è prettamente simbolico. Macina calcoli
numerici alla grande e, fra l'altro, permette anche di superare la precisione di macchina, permettendo
di fare qualsiasi calcolo concepibile dalla mente umana ed anche oltre con una precisione arbitraria
che potete decidere da soli. Volete calcolare l'area di un cerchio con una precisione di 31413531531
cifre decimali? Mathematica ve lo fa in un attimo... provate a farlo con Matlab!
Ma non è questo quello che volevo dire, anche se da questo si può intuire la maggior flesibilità del
suo kernel. Parlavamo del calcolo simbolico; se, con matlab, provate a calcolarvi un integrale di
questo tipo
‡1
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄè!!!!!!!!!!!!!!logHxL
‚ x
Matlab vi chiederebbe per forza il valore iniziale e finale, per poi calcolarvi numericamente
l'integrale. Dato in pasto a Mathematica, invece, vi da direttamente la soluzione completa:
è!!!!p erfiIlog
1ÅÅÅÅ2 HxLM
Le possibilità di calcolo già si fanno più interessanti, a questo punto. Senza andare a scomodare
centri di ricerca e scienziati, quello che interessa a noi studenti è la forma simbolica che può essere
usata per verificare (od anche risolvere direttamente), problemi dati per casa, dando risultati che
possono essere facilemente verificati e scritti in bell'aspetto direttamente sul quadernone. Inoltre, i
Toolbox di Matlab, nella loro forza hanno anche il loro limite: sono specifici. Se cominciate a
lavorare su un sistema di controllo, difficilmente l'equazione trovate potete usarle in altri toolbox per
eseguire altri calcoli che vi servono, ammesso che riusciate a farvi dare da Matlab come risultati
formule e non numeri: con Mathematica, invece, potete direttamente utilizzare tutte le formule che
avete in tutti i contesti che volete, fare quello che vi pare. In Mathematica avete il controllo assoluto.
E scusate se è poco! Farete calcoli e risolverete cose che non credevate possibili, senza
approssimazioni od altro.
Per farvi capire in maniera molto grossolana la differenza, con Matlab si fanno solo gli esercizi. Con
Mathematica si fa la teoria, quella pesante e quella importante. Inoltre, si fanno anche gli esercizi
con un'elasticità che ben pochi programmi possono permettersi, fissati nel loro rigido modo di
pensare imposto dai programmatori.
Ma la potenza di Mathematica non si ferma qui. Effettivamente, la potenza del programma è in
qualche modo infinita... Riuscirete a fare cose inimmaginabili, se sapete come usarlo, e se ci perdete
un po' di tempo scoprirete che riuscite a fare qualsiasi cosa vogliate. Mathematica non permette
solamente di fare calcoli. Il frontend, ovvero la parte di Mathematica che vi permette inviare gli
input al kernel, e di ricevere il corrispondente output, permette di creare anche documentazione
dall'aspetto professionale; potrete scrivere tesi, tesine, relazioni, esercitazioni e quant'altro con un
Daniele Lupo Appunti di Mathematica
3Printed by Mathematica for Students
aspetto che l'Equation Writer di Word si può soltanto sognare. Con, oltretutto, il vantaggio che
Mathematica vi permette anche di fare i calcoli al posto vostro!
L'importante è non sottovalutare la potenza di questo programma. Se volete soltanto qualcosa che vi
permetta di fare calcoli, al posto di spendere poco più di 100€ per la versione studenti di
Mathematica, compratevi una calcolatrice HP 49G+, che costa sulle 130 e vi permette di fare cose
che nessun altra calcolatrice vi permette di fare, ma pur sempre nell'eseguire calcoli tutto sommato
semplici, anche se di tutto rispetto. Inoltre, potete anche portarvela per gli esami... Se, invece, volete
un potente strumento di calcolo che, chissà, magari potrà servirvi anche per dopo, allora siete nel
posto giusto e, anche se scalfiremo solamente la superfice, quello che imparerete in questi pochi
appunti vi permetterà di risolvere facilmente la quasi totalità dei problemi che affronterete nel corso
dei vostri studi.
Ovviamente, anche Mathematica ha qualche limite, a mio avviso. Per esempio, mi dispace
veramente che non ci sia qualcosa di analogo al Simulink di Matlab. Sicuramente, avere una
rappresentazione grafica delle funzioni, linkabili a piacimento renderebbe più semplice il lavoro e ne
mostrerebbe una rappesentazione, perchè no, anche più chiara ed elegante. Così come il fatto che
manchi, per esempio, il syntax highlighting, cioè la colorazione del codice, permettendo di
distinguere variabili, funzioni e così via, che, assieme magari ad un editor separato con qualche
funzione in più, semplificherebbe molto la scrittura dei programmi, un poco come l'editor dei file m,
sempre di Matlab (anche Mathematica ha la sua versione di file m, ma vedremo verso la fine a cosa
servono).
Inoltre, all'inizio non sarà semplicissimo da usare, in quanto usa un interfaccia prettamente testuale:
questo ha il vantaggio di non dover andare in giro con il mouse a cercare pulsantini ed amenità
simili, come accade, per esempio, in Mathcad, ma allo stesso tempo, se non si conosce una funzione,
bisogna per forza andare a cercarla nell'help, per vedere se è disponibile, mentre nel caso di
interfacce grafiche, basta esplorare i menù ed i pulsanti fin quando non si trova. Se non c'è, pazienza.
Comunque la scoperta di nuovi comandi è certamente più intuitiva per interfacce grafiche che non
per quelle testuali, anche ammesso che, una volta impratichiti, l'interfaccia di Mathematica è snella e
veloce, permettendovi di fare quello che fanno altri programmi in una frazione di tempo.
Quindi, se proprio Mathematica vi fa antipatia, niente vi impedisce di imparare un altro programma
con cui avete più feeling: di certo, a livello di studenti, non useremo molto le funzioni avanzate, e
quelle base sono comuni a tutti quanti i programmi.
Io personalmente ho scelto Mathematica perchè mi piace un sacco; il mio primo programma di
calcolo scientifico è stato Mathcad 7, che avevo scoperto mentre ero al superiore, giocandoci un
pochino a scuola. Dopo, quando andavo in giro per il Web alla ricerca di un buon programma per la
creazione di frattali, sono venuto a conoscenza di Mathematica, ed le cose per me sono
drasticamente cambiate (anche se per i frattali uso Ultrafractal: http://www.ultrafractal.com ).
Daniele Lupo Appunti di Mathematica
4Printed by Mathematica for Students
Durante i corsi universitari ho anche avuto a che fare con Matlab, e ho capito la differenza fra i due
programmi: sinceramente, ho preferito di gran lunga l'approccio simbolico di Mathematica, che mi
permetteva di trovare soluzioni a problemi teorici, piuttosto che Matlab, per il quale se non ho i dati
da dargli in pancia, è in grado di fare ben poco (anche se all'inizio mi stavo affezionando al suo
comando 'magic'). Certamente è grande e forse migliore per l'elaborazione dei dati (e chi fa
Elaborazione numerica dei segnali ne sa qualcosa, vero Giovanni?), ma sa fare solo questo, oltre ad
avere un'interfaccia che sì, da moltissimi strumenti, ma è anche vero che è molto frammentata, e per
fare cose diverse bisogna aprire altri toolbox etc.
Qua si parla di Mathematica (naturalmente!!!), ma il mio consiglio comunque è di provarli entrambi,
e magari anche qualche altro, come Mathcad oppure Maple. Se, dopo, mi darete ragione, allora sarò
felice di riceve ringraziamenti ed assegni in bianco come ringraziamento per avervi scritto queste
righe!!!
ü Suggerimento
Il mio consiglio spassionato riguardo Mathematica è il seguente: USATE QUANTO PIU' SPESSO
POTETE L'HELP IN LINEA!!! Scusate il tono brusco, ma è una cosa che veramente poche persone
fanno; saper usare Mathematica è questione di poco, ma saperlo usare bene è difficile, per la quantità
di funzioni e di aspetti e caratteristiche nascoste che non si trovano subito. Appena avete un
problema con qualsiasi cosa, come una funzione che non ricordate o di cui non sapete il nome,
andate a vedervi l'help, cercando la parola chiave di quello che state facendo o volete (in inglese,
ovvio): se cercate funzioni per i numeri primi, cercate "prime", e così via. Quello che farò io è farvi
capire il funzionamento di Mathematica, non quello di presentarvi ogni funzione presente: oltre che
perdere trecento anni a descrivere le funzioni, sarebbe inutile, dato che tutto è già scritto nell'aiuto in
linea. Probabilmente alcuni avranno difficoltà a destreggiarsi con la lingua inglese, ma non posso
farci niente: dovete rendervi conto che l'inglese è una lingua fondamentale, specialmente per chi
affronta temi scientifici oppure tecnici come noi. Di documentazione inglese se ne trova a bizzeffe, e
ve la consiglio caldamente. Io non sono in grado di farvi capire fino in fondo Mathematica: Cerco
solamente di darvi uno spunto, ed un punto d'inizio (anche se abbastanza solido) per cominciare ad
usare questo programma. Con quello che imparerete qui saprete fare veramente un sacco di cose...
Figuratevi se poi decidete di imparare il restante 99,9% di quello che il programma vi offre!
Daniele Lupo Appunti di Mathematica
5Printed by Mathematica for Students
Primi passiü Cominciamo
Bene bene: dato che state leggendo, starete sicuramente cercando un modo per capire facilmente (ed
in italiano), qualche base per poter cominciare ad usare questo simpatico programma.
Prima di tutto dovrei dirvi come installarlo, etc etc, ma credo che non abbiate bisogno di sapere
queste banalità, vero? In fondo, siamo nati nell'era del computer!
Comunque, una volta avviato il programma per la prima volta, dovrebbe apparirvi una schermata
simile alla seguente:
Effettivamente, non è che sia così esaltante. Comunque, quello che vedete a sinistra è il 'Notebook',
cioè la finestra dove andrete a scrivere il vostro lavoro, mentre la finestra piccola a destra è una
'palette', ovvero un insieme di pulsanti che contengono comandi per semplificarvi il lavoro e per
evitare di dover scrivere comandi; nel menù File->Palettes potete trovare altre palettes che magari
riescono a semplificarvi il lavoro. Personalmente non la uso molto: trovo più veloce e semplice
scrivere direttamente tutti i comandi a mano, anche se, devo ammetterlo, la uso ancora per inserire le
lettere alcune greche, anche se ci sono opportune combinazioni da tastiera molto semplici per poter
fare la stessa cosa.
Daniele Lupo Appunti di Mathematica
6Printed by Mathematica for Students
Provate ad inserire, adesso, il seguente, complicatissimo comando ed osservate la potenza di
Mathematica nel risolverla in un tempo inferiore alle due ore:
In[1]:= 2 + 2
Out[1]= 4
Magicamente, il risultato Mathematica ve lo da effettivamente in meno di due ore. notate come, per
far eseguire il comando, dovete premere Shift+Invio oppure il tasto Invio del tastierino numerico; il
tasto Invio normale serve solo per andare a capo senza eseguire operazioni, il che può sembrare
strano, ma sicuramente utile non appena faremo qualcosa id più complicato della somma eseguita
sopra. Intanto, si possono notare già da adesso alcune cose caratteristiche di Mathematica; se notate,
alla sinistra delle espressioni potete notare i nomi In/Out, del tipo In[1]:= e Out[1]:=. queste
rappresentano l'ordine con cui vengono eseguite le operazioni dal kernel. Infatti, mentre eseguite
operazioni, potete, con il mouse, selezionare varie parti del Notebook e continuare a scrivere nel
mezzo, come volete. Però eseguirete sempre le operazioni nell'ordine con cui sono state calcolate.
considerate, per esempio, questo piccolo esempio:
Possiamo vedere già una cosa nuova, ma che credo non stupisca nessuna delle persone che leggano
queste righe, ovvero la possibilità di poter dichiarare delle variabili. Le variabili possono essere
qualsiasi cosa possibile, in Mathematica: da numeri, a simboli, formule, funzioni, liste, e chi più ne
ha più ne metta, ma vedremo dopo queste cose. Per adesso vedete come sono combinati i risultati ed
i numeri; dopo l'esempio iniziale, abbiamo dichiarato la variabile m inizializzandola al valore 3, e poi
al valore 7: tuttavia, vedendo i tag a sinistra, si vede che l'inizializzazione al valore 7 viene prima:
dopo viene In[7], che esegue l'espressione dando il risultato giusto. La prossima espressione che
Daniele Lupo Appunti di Mathematica
7Printed by Mathematica for Students
viene eseguita è In[8], che riscrive il valore della variabile m e lo pone uguale a 3. Infine,
rieseguendo l'espressione In[9], si vede che il risultato è esatto (ovviamente) con l'ultima
inizializzazione di m. Inoltre, qualsiasi cosa appaia in un notebook è racchiuso in 'celle', come si
vede alla destra. Le celle permettono di raggruppare il lavoro, e possono essere compresse ed
espanse facendo doppio clic sulla linea corrispondente. Inotre, come si vede, possono essere anche
annidate fra di loro. Comunque, servono solo per dare una particolare organizzazione al file, per cui
non cene occuperemo, dato che Mathematica ha un buon gestore automatico di celle, che fa tutto da
solo.
L'ordine è importante anche per un operatore importante in Mathematica, cioè l'operatore
percentuale (%). In parole povere % rappresenta l'ultimo risultato ottenuto da Mathematica:
Qua possiamo vedere come l'operatore percentuale rappresenti l'ultimo risultato ottenuto. Questo è
importante, perchè permette di usare velocemente un risultato senza riscriverlo e senza dover
utilizzare una variabile per memorizzarla, e bisogna stare attenti ad utilizzarla quando ci si sposta a
scrivere avanti ed indietro nel notebook. A questo si raggiungono altri risultati: per esempio %% si
riferisce al penultimo risultato, %%% al terzultimo e così via; inoltre, %n indica il risultato Out[n].
Inoltre, potete anche vedere un'altra cosa MOLTO IMPORTANTE, che i principianti scordano
facilmente e cadono facilmente in errore: quando si definisce e si usa una funzione in Mathematica,
gli argomenti devono essere racchiusi entro parentesi QUADRE, non tonde. Le parentesi tonde sono
utilizzate esclusivamente per raggruppare i termini di un'espressione, le parentesi quadre per
determinare gli argomenti di una funzione, e (poi vedremo), le parentesi quadre per definire le liste e
le matrici. Questo, sebbene in apparenza strano, ha un ben preciso significato. Infatti Nathematica
permette manipolazioni 'simboliche' molto potenti, e permette quindi di usare variabili e funzioni
non ancora inizializzate, lasciandole incognite; allora, se si scrive qualcosa come varH3 + 5 IL, allora
ci si troverebbe in difficoltà a capire se rappresenta la funzione var con il suo argomento, oppure la
variabile var che moltiplica quello che è racchiuso fra parentesi. Ora capite meglio come mai si
usano le parentesi quadre, vero? Inotre, Mathematica è case-sensitive, vuol dire che distingue fra
maiuscole e minuscole: le funzioni predefinite (e, credetemi, ce ne sono un sacco), cominciano tutte
con la lettera maiuscola, per convenzione, e per questo si scrive Sqrt invece che sqrt. Inoltre, quasi
tutte le funzioni hanno il nome esteso, a parte qualche caso standard: infatti, dato il considerevole
numero di funzioni, dare loro delle abbreviazioni renderebbe molto difficile ricordarsele. Si usano
abbreviazioni sono per funzioni che le hanno standardizzate nel mondo matematico: quindi, il seno
Daniele Lupo Appunti di Mathematica
8Printed by Mathematica for Students
si indicherà con Sin, invece che con Sinus, mentre, per fare un esempio, le funzioni di bessel si
indicheranno con BesselJ@n, qD, invece che con J, per esempio, perchè non è ancora convenzione
internazionale usare soltanto la J. Questo ha anche un vantaggio; se conoscete il nome della funzione
(in inglese), allora basta scriverla per intero, e Mathematica la userà direttamente senza alcun
problema, perchè sicuramente l'avrà già dentro la pancia.
Qua sotto potete vedere una lista di alcune delle funzioni più comuni che si utilizzano di solito:
Sqrt[x] radice quadrata (è!!!x )
Exp[x] esponenziale (ex)
Log[x] logaritmo naturale (loge x)
Log[b, x] logaritmo in base b (logb x)
Sin[x], Cos[x], Tan[x] funzioni trigonomentriche (con argomento in radianti)
ArcSin[x], ArcCos[x],ArcTan[x]
funzioni trigonometriche inverse
n! fattoriale
Abs[x] valore assoluto
Round[x] intero più vicino ad x
Mod[n, m] n modulo m (resto della divisione)
Random[ ] numero pseudocasuale fra 0 ed 1
Max[x, y, … ], Min[x, y, … ] massimo e minimo fra x, y, ...
FactorInteger[n] scomposizione in fattori primi
mentre, qua in basso, sono indicate alcune funzioni che magari vedrete meno spesso, e che sono più
specialistiche:
Beta[a, b] funzione beta di Eulero B Ha,bL Beta[z, a, b] funzione beta incompleta Bz Ha,bL
BetaRegularized[z, a, b] funzione beta incompleta regolarizzata I Hz,a,bL Gamma[z] funzione Gamma di Eulero G HzL
Gamma[a, z] funzione Gamma incompleta G Ha,zL Gamma[a, z0, z1] funzione Gamma incompleta generalizzata G Ha,z0L-G Ha,z1L
GammaRegularized[a, z] funzione Gamma incompleta regolarizzata Q Ha,zL InverseBetaRegularized[s, a, b] funzione beta inversa
InverseGammaRegularized[a, s] funzione Gamma inversa
Pochhammer[a, n] simbolo di Pochhammer HaLn
PolyGamma[z] digamma function y HzL PolyGamma[n, z] nth derivative of the digamma function yHnL HzL
Daniele Lupo Appunti di Mathematica
9Printed by Mathematica for Students
Naturalmente, le funzioni non finiscono certo qua!!! Quello vhe vi consiglio è di andare a cercare, di
volta in volta, quello che vi serve dall'help in linea: per il numero di funzionalità e funzioni, vi posso
assicurare che l'help di Mathematica è più importante di qualsiasi altro programma, credetemi.
ü Numeri e precisione
Quello che ci interessa, naturalmente, è trovare soluzioni a problemi. A volte, avendo a che fare con
la matematica, avremo a che fare con i numeri, quindi... :-)
Mathematica cerca di riconoscere il tipo di numero con cui abbiamo a che fare, di volta in volta,
utilizzando diversi algoritmi per ottimizzare velocità di calcolo e risultato in funzione dei dati
iniziali. Per esempio possiamo distinguere fra numeri interi e complessi. I tipi di numeri predefiniti
in Mathematica sono 4:
Integer numeri interi esatti di lunghezza arbitraria
Rational integer/integer ridotto ai minimi termini
Real numero reale approssimato, con precisione qualsiasi
Complex numero complesso nella forma number + number I
Sebbene sembri strano dover distinguere fra diversi tipi di numeri, dato che un numero è sempre tale,
in realtà non è così; come quelli che fra di voi programmano ben sanno, di solito il computer gestisce
in maniera diversa i diversi tipi di numeri, quando andiamo a scrivere un programma. Per questo,
quando definiamo una variabile, dobbiamo specificare, in C come in Pascal come in Fortran, se il
numero è intero oppure a virgola mobile: in un caso o nell'altro verranno utilizzate diverse istruzioni
per eseguire lo stesso calcolo.
In Mathematica succede qualsosa di simile; sono presenti diversi algoritmi che ci permettono di
ottimizzare il calcolo ed utilizzare la maniere più opportuna di trattare un numero. Inoltre, c'è in più
il vantaggio che Mathematica fa tutto questo automaticamente: a noi basta semplicememte scrivere i
numeri, ed il programma riconoscerà automaticamente il tipo di numero con cui abbiamo a che fare,
utilizzando l'algoritmo opportuno.
Per esempio, possiamo eseguire un calcolo che sarebbe improponibile in precisione macchina:
In[2]:= 130!
Out[2]= 6466855489220473672507304395536485253155359447828049608975952322944781961185526165512707047229268452925683969240398027149120740074042105844737747799459310029635780991774612983803150965145600000000000000000000000000000000
Daniele Lupo Appunti di Mathematica
10Printed by Mathematica for Students
Come potete vedere, Mathematica riconosce il numero come intero esatto, applicando quindi la
precisione arbitraria. Se vogliamo un risultato approssimato, invece, dobbiamo far capire al
programma che il numero usato come input è anch'esso approssimato:
In[3]:= 130.!
Out[3]= 6.46686×10219
Mettendo il punto, Mathematica interpreta il numero non come esatto, ma come approssimato; di
conseguenza effettua il calcolo con un algoritmo alternativo.
Inoltre, possiamo eseguire calcoli avanzati anche con i numeri approssimati. Infatti, un aspetto molto
importante in Mathematica, è che permette di passare sopra uno dei limiti principali del calcolo al
computer, ovvero la precisione di macchina. Quando andate ad eseguire dei calcoli, come degli
integrali numerici, dovrete sempre stare attenti alla precisione. Mathematica permette di ottenere due
tipi di precisione di calcolo:
1) La precisione standard di macchina. Quando scrivete delle espressioni in virgola mobile,
Mathematica le tratta come numeri che hanno insita la precisione di macchina, per cui considera
inutlie utilizzare una precisione maggiore:
In[4]:= [email protected]
Out[4]= 3.4641
Tuttavia, se non si utilizza il punto, Mathematica considera il numero con una precisione assoluta, e
utilizza la sua precisione, che può dare un risultato simbolico, oppure anche numerico, ma con una
precisione impostabile a piacere. se riscriviamo l'espressione di sopra senza il punto otteniamo:
In[5]:= Sqrt@12D
Out[5]= 2 è!!!3
che rappresenta il risultato che scriveremmo nel quaderno. Tuttavia, possiamo anche avere un
risultato numerico con precisione arbitraria, utilizzando la funzione N. questa funzione prende come
argomento un'espressione che da un risultato esprimibile in numero (niente incognite, quindi), e
fornisce il risultato in forma approssimata. Scrivendo
In[6]:= N@Sqrt@12DD
Out[6]= 3.4641
oppure
Daniele Lupo Appunti di Mathematica
11Printed by Mathematica for Students
In[7]:= Sqrt@12D êê N
Out[7]= 3.4641
il risultato che si ottiene è il seguente
3.4641
Il risultato è identico a prima, perchè, se non si specifica nella funzione N anche il numero di cifre
significative che si desidera, allora usa la precisione di macchina (per i calcoli interni, dato che da un
risultato con un minor numero di cifre, considerando solo quelle significative). Se proviamo anche a
scrivere il numero di cifre significative richieste, Mathematica ci accontenta:
In[8]:= N@Sqrt@12D, 30D
Out[8]= 3.46410161513775458705489268301
Come vedete, il risultato da un numero di cifre significative maggiore di quelle raggiungibili con la
precisione di macchina. Possiamo tranquillamente richiedere 10000 cifre significative, se vogliamo...
Mathematica utilizza la precisione arbitraria anche per le costanti. Per esempio, Pi definisce il
pigreco (dato che la lettera greca è difficile da scrivere con la tastiera), E rappresenta il numero di
Nepero. Se vogliamo una precisione di 100 cifre, per dirne una, possiamo scrivere semplicemente
In[9]:= N@Pi, 100D
Out[9]= 3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117068
La precisione arbitraria, abbiamo visto, si applica anche per espressioni non razionali, in quanto
Mathematica tratta l'espressione simbolicamente, fornendo il risultato sotto forma facilmente
leggibile:
In[10]:= Sin@Piê3D Sqrt@5D
Out[10]=è!!!!!!152
Notate che la moltiplicazione può essere indicata anche, oltre al canonico asterisco, lasciando uno
spazio fra i fattori, in questo caso fra le funzioni. Questi sono solo esempi banalissimi. Le cose
possibili sono davvero uno sproposito.
Possiamo anche scegliere la precisione da utilizzare anche durante i calcoli. Se, per esempio
Daniele Lupo Appunti di Mathematica
12Printed by Mathematica for Students
eseguiamo un'operazione con due numeri approssimati, otteniamo un risultato anch'esso
approssimato:
In[11]:= 2.ê3.
Out[11]= 0.666667
Questo specifica la precisione standard utilizzata, pari a quella macchina. Tuttavia, se specifchiamo
numeri approssimati con maggior precisione, Mathematica automaticamente esege il risultato non
più in precisione macchina, ma adeguandola alla precisione dei numeri in ingresso:
In[12]:= 2.0000000000000000000000ê3.00000000000000000000000000
Out[12]= 0.6666666666666666666667
Tuttavia, se la precisione dei numeri non è uguale, Mathematica esegue il calcolo restituendo un
risultato con il giusto numero ci cifre significative:
In[13]:= 2.0000000000000000000000ê3.
Out[13]= 0.666667
Adegua, in questo modo, la precisione per evitare risultati scorretti.
Inoltre, Mathematica tratta anche con estrema naturalezza i numeri complessi:
In[14]:= Sqrt@−4D
Out[14]= 2
In[15]:= [email protected]
Out[15]= 1.57079632679489661923132 − 3.29799076132040785635379
L'unità immaginaria si indica con la lettera maiuscola I, maiuscola mi raccomando: vi ricordi che,
per convenzione, tutte le funzioni e costanti predefinite cominciano con una lettera maiuscola.
Alcune semplici funzioni che riguardano i numeri complessi sono quelle
standard:
Daniele Lupo Appunti di Mathematica
13Printed by Mathematica for Students
x + I y il numero complesso x+i y
Re[z] parte reale
Im[z] parte immaginaria
Conjugate[z] complesso coniugato z* or zê
Abs[z] valore assoluto »z» Arg[z] argomento j in »z»ei j
Se poi abbiamo determinati valori, possiamo testare di che tipo siano:
NumberQ[x] testa se x è una quantità numerica di qualsiasi tipo
IntegerQ[x] testa se x è un numero intero
EvenQ[x] testa se x è un numero pari
OddQ[x] testa se x è un numero dispari
PrimeQ[x] testa se x è un numero primo
Head[x]===type testa il tipo di numero
I primi comandi servono per testare se un numero appartiene ad un determinato tipo; per esempio se
è intero, oppure se è pari:
In[16]:= NumberQ@3D
Out[16]= True
In[17]:= NumberQ@aD
Out[17]= False
In[18]:= EvenQ@4D
Out[18]= True
In[19]:= [email protected]
Out[19]= False
L'ultimo risultato deriva dal fatto che, essendo un numero reale, Mathematica non è in grado di
capire se è pari o dispari, perchè è approssimato. 4. potrebbe anche essere
4.000000000000000000001, che non sarebbe nè pari nè dispari, applicando questi due concetti
solamente a numero interi.
Per verificare se un numero è, invece, razionale o qualt'altro, occorre utilizzare l'ultimo comando:
Daniele Lupo Appunti di Mathematica
14Printed by Mathematica for Students
In[20]:= Head@4ê7D === Rational
Out[20]= True
Head è un comando avanzato, che vedremo meglio più avanti... Qua serve solo per analizzare il tipo
di numero che contiene. In questo caso testiamo se il suo argomento è un numero razionale, dandoci
risposta affermativa. Possiamo anche eliminare il test, ed in questo caso il comando restituisce il tipo
di numero che ha come argomento:
In[21]:= Head@3 + 5 ID
Out[21]= Complex
Vediamo adesso il seguente esempio:
In[22]:= NumberQ@πD
Out[22]= False
Qua qualcosa potrebbe andare per il verso sbagliato, perchè, anche se in forma simbolica, p
rappresenta a tutti gli effetti un numero, mentre non viene riconosciuto come tale. Il fatto è che
NumberQ testa se l'argomento è un numero esplicito, cioè se è scritto in forma di numero come 3.14,
per intenderci. Rigirosamente, p non è un numero, ma rappresenta invece una quantità numerica:
NumberQ[expr] testa se expr rappresenta in maniera esplicita un numero
NumericQ[expr] testa se expr è un valore numerico
Per vedere se l'argomento, pur non essendo scritto sotto forma di numero, rappresenta una quantità
numerica, dobbiamo utilizzare il secondo comando:
In[23]:= NumberQ@Sqrt@2DD
Out[23]= False
In[24]:= NumericQ@Sqrt@2DD
Out[24]= True
In[25]:= NumericQ@Sqrt@xDD
Out[25]= False
Vediamo che adesso il cerchio si chiude, e che possiamo testare effettivamente se un espressione
rappresenta un numero, oppure non è definita.
Daniele Lupo Appunti di Mathematica
15Printed by Mathematica for Students
Dato che la precisione dei risultati assume un ruolo importante, Mathematica pone la giusta
importanza alle cifre significative di un numero; esistono anche delle funzioni che determinano la
precisione oppure l'accuratezza di un numero:
Precision[x] il numero totale di cifre significative di x
Accuracy[x] il numero di cifre decimali significative di x
Quando si parla di precisione di un numero approssimato, bisogna sempre distinguere fra precisione
ed accuratezza. Nel primo caso, infatti, si parla di numero totale delle cifre che compongono un
numero. Nel secondo, invece, si considerano solamente il numero di cifre significative che
compongono la parte decimale di un numero, ignorando le cifre che compongono la parte intera di
un numero. Vediamo, per esempio:
In[26]:= a = N@Sqrt@2D + 1987, 40D
Out[26]= 1988.414213562373095048801688724209698079
Vediamo il numero di cifre significative di questo numero:
In[27]:= Precision@aD
Out[27]= 40.
Questo risultato l'abbiamo ottenuto proprio perchè lo abbiamo imposto dal secondo parametro di N.
Vediamo adesso l'accuratezza di questo stesso numero:
In[28]:= Accuracy@aD
Out[28]= 36.7015
Approssimando, abbiamo 36 cifre significative, il che significa che 36 cifre decimali sono
significative; questo concorda con il risultato precedente, dato che la parte intera è composta da
quattro cifre, e che 36 + 4 = 40.
Questo permette di definire sempre l'incertezza su di un numero. D'altronde, per questo motivo, due
numeri possono anche essere considerati uguali se la loro differenza è inferiore alla precisione
oppure all'accuratezza dei due numeri.
Se un determinato valore numerico x ha un'incertezza pari a d, allora il valore vero di x, cioè non
approssimato, può essere uno qualunque nell'intervallo che va da x - d ê 2 a x+d/2. Se l'accuratezza
di un numero è pari ad a, allora l'incertezza legata a quel numero sarà data da 10-a; mentre, se al
posto dell'accuratezza abbiamo la precisione di un numero, definito come p, allora l'incertezza sarà
Daniele Lupo Appunti di Mathematica
16Printed by Mathematica for Students
pari a » x » 10-p.
Supponiamo di avere un numero con cinque cifre significative:
In[29]:= x = N@Sqrt@2D, 5D
Out[29]= 1.4142
Andiamo a sommarci, adesso, un numero minore della sua incertezza:
In[30]:= b = N@1ê10000000, 7D
Out[30]= 1.000000×10−7
In[31]:= x + b
Out[31]= 1.4142
Come possiamo vedere, il risultato non è variato, perchè sommo ad un numero un altro più piccolo
della precisione del precedente. Se li sommassi, otterrei un risultato senza significato, dato che non
so a cosa sto sommando il secondo numero: potrebbe essere un qualsiasi numeri dell'intervallo di
incertezza. Se non si specifica niente, come precisione Mathematica utilizza quella di macchina del
computer:
MachinePrecision la precisione predefinita per un numero calcolatocon precisione di macchina
$MachinePrecision variabile di sistema che contiene il valore dellaprecisione di macchina
MachineNumberQ[x] testa se x è un numero macchina
Dato che il numero di cifre significatice può variare a seconda del computer e del sistema operativo
(si pensi ai nuovi processori a 64 bit, per esempio), il valore della precisione di macchina può
variare. Per questo Mathematica, invece di restituire la precisione di un numero macchina sotto
forma di numero di cifre significative, lo restituisce con il simbolo MachinePrecision: specifica che
il numero è un numero macchina e basta, restando coerente con la sua logica interna e non con
l'archichettura del computer. La variabile di sistema $MachinePrecision, invece, contiene questo
numero, che può variare da computer a computer:
In[32]:= N@ED
Out[32]= 2.71828
Daniele Lupo Appunti di Mathematica
17Printed by Mathematica for Students
In[33]:= Precision@N@EDD
Out[33]= MachinePrecision
In[34]:= $MachinePrecision
Out[34]= 15.9546
L'esempio di sopra mostra che N, senza argomenti, restituisce il valore approssimato in precisione di
macchina e che su questo computer, in Athlon 64 con WindowsXP Home, la precisione di macchina
è data dal valore riportato. Probabilmente, quando installerò un sistema operativo a 64 bit, questo
valore varierà...
Notate, adesso, questo particolare:
In[35]:= [email protected]
Out[35]= MachinePrecision
In[36]:= [email protected]
Out[36]= 39.6424
Questa è una particolarità interessante; se il numero di cifre significative è superiore a quello di
precisione di macchina, Mathematica lo memorizza come valore con la sua corretta precisione,
mentre se il numero ha una precisione inferiore a quella macchina, il programma, invece di dargli la
precisione che gli spetterebbe, gli assegna invece la precisione macchina.
Così, se andiamo a sommare due numeri con precisione diversa, ma inferiore a quella macchina, il
risultato avrà sempre la stessa precisione:
In[37]:= a = 1.45
Out[37]= 1.45
In[38]:= Precision@aD
Out[38]= MachinePrecision
In[39]:= b = 1.4545
Out[39]= 1.4545
Daniele Lupo Appunti di Mathematica
18Printed by Mathematica for Students
In[40]:= Precision@bD
Out[40]= MachinePrecision
In[41]:= a + b
Out[41]= 2.9045
In[42]:= Precision@a + bD
Out[42]= MachinePrecision
Come vedete, la somma considera tutte le cifre signigficative della macchina, sebbene abbiamo
scritto il valore di a con un numero di cifre significative inferiore...
Vediamo adesso questo esempio:
In[43]:= N@Sqrt@2DD
Out[43]= 1.41421
E' sempre quello, va bene... tuttavia notiamo come sia rappresentato con un numero di cifre
significative inferiore a quelle di macchina. Questo perchè, anche se Mathematica lo calcola con
tutte le cifre, restituisce un risultato con cifre più significative. Se vogliamo vedere tutto il numero,
dobbiamo utilizzare il comando InputForm;
In[44]:= InputForm@N@Sqrt@2DDD
Out[44]//InputForm= 1.4142135623730951
Questo comando visualizza il suo argomento come appare a Mathematica stesso, non come compare
a noi nel notebook. Questo rappresenta un numero macchina. Visualizziamo invece il seguente
esempio:
In[45]:= InputForm@N@Sqrt@2D, 50DD
Out[45]//InputForm= 1.4142135623730950488016887242096980785696718\753769480731766797379907`50.
In questo caso c'è qualcosa di diverso. Non solo viene visualizzato il numero per intero, ma gli viene
pure attaccato un valore, che rappresenta la precisione di quel numero. Questo è il modo che
Mathematica ha di riconoscere la precisione dei numeri. Purtroppo il simbolo ` nella tastiera italiana
non esiste: per stamparlo dovete utiilzzare la combinazione Alt+096 con i numeri del tastierino
numerico oppure, come faccio io quando mi serve parecchie volte, scriverlo solo questo carattere in
Daniele Lupo Appunti di Mathematica
19Printed by Mathematica for Students
un notebook, e copiarlo ed incollarlo ogni volta che serve. Sebbene il primo metodo sia abbastanza
veloce, io personalmente utilizzo il secondo perchè utilizzo il portatile, e non ho tastierino
numerico... Un aiutino per chi come me si sbraitava per capire come fare!!!
In questa maniera possiamo specificare la precisione anche per quei numeri che DEVONO averla
inferiore a quella macchina, perchè magari il risultato dell'esperimento non raggiunge quella
precisione:
In[46]:= a = 1.01`3
Out[46]= 1.01
In[47]:= b = 0.0003`2
Out[47]= 0.00030
In[48]:= a + b
Out[48]= 1.01
Qua potete notare due cose: prima di tutto, che specificando le precisioni inferiori a quelle di
macchina, il calcolo viene eseguito con la precisione apposita. Secondo, che abbiamo specificato b
con una precisione minore delle sue cifre... Questo perchè la cifra, in quel caso, è solamente una,
dato che la mantissa del numero è ad una sola cifra:
In[49]:= Precision@bD
Out[49]= 2.
In[50]:= Accuracy@bD
Out[50]= 5.52288
In questo caso, con Accuracy abbiamo visto il numero di cifre 'decimali' significative, e si ottiene
calcolando il numero per intero, senza lasciarlo nella forma mantissa ed esponente. In questo caso il
numero di cifre significative è 6, perchè è dato dalla cifra 3 più lo zero alla sua destra dato dalla
precisione.
Analigamente a prima, possiamo anche scrivere dei numeri con le ultime cifre pari a 0, tenendo
conto di quest'ultime se sono anch'esse cifre significative:
In[51]:= 3`40
Out[51]= 3.000000000000000000000000000000000000000
Daniele Lupo Appunti di Mathematica
20Printed by Mathematica for Students
Un'altra maniera per definire il numero di cifre significative o di accuratezza di un numero, più
consono alla nostra tastiera, p di usare i comandi opportuni:
SetPrecision[x, n] crea un numeri con n cifre decimali di precisione,completandolo con degli 0 se risultasse necessario
SetAccuracy[x, n] crea un numero con n cifre decimali di accuratezza
Si creano in questa maniera risultati analoghi ai precedenti:
In[52]:= SetPrecision@3, 40D
Out[52]= 3.000000000000000000000000000000000000000
In[53]:= [email protected], 7D
Out[53]= 342321.230000
Dato che abbiamo parlato di mantissa ed esponente, vediamo come possiamo scrivere i numeri in
questa maniera. Possiamo utilizzare, naturalmente, la forma classica:
In[54]:= 2 ∗ 10^5
Out[54]= 200000
Ma Mathematica permette una piccola scorciatoia per scrivere la stessa cosa:
In[55]:= 2*^5
Out[55]= 200000
Vediamo come viene applicata la precisione:
In[56]:= a = 3.1351364265764745873578*^34
Out[56]= 3.1351364265764745873578×1034
In[57]:= InputForm@aD
Out[57]//InputForm= 3.1351364265764745873578`22.496256444056755*^\34
Come possiamo vedere a conferma di quanto detto poco fa, la precisione viene applicata alla
mantissa, non all'esponente del numero.
Daniele Lupo Appunti di Mathematica
21Printed by Mathematica for Students
Notiamo anche come il simbolo ` definisce il numero di cifre di precisione. Se invece vogliamo
definire il numero di cifre di accuratezza, dobbiamo utilizzare ``:
In[58]:= 124.134315`6
Out[58]= 124.134
In[59]:= a = 124.134315``6
Out[59]= 124.13432
In[60]:= InputForm@aD
Out[60]//InputForm= 124.134315`8.09389185204773
Notiamo che le cifre di accuratezza sono sempre quelle, anche se capita che ne vengano visualizzate
di meno per convenzione...
A volte, le piccole quantità sono dati da errori di approssimazione, e si vorrebbero eliminarli. Per
esempio, capita che venga scritto 0.0000000000000000231 quando sappiamo che il risultato
sicuramente sarà pari a 0. Per questo problema Mathematica ha un apposito comando:
Chop[expr] sostituisce tutti i numeri reali in expr con modulominore di 10-10 con 0
Chop[expr, dx] sostituisce i numeri con modulo minore di dx con 0
Questo può essere utile quando cerchiamo, per esempio, numericamente delle radici di equazioni; in
questo caso ci saranno numeri molto piccoli che possono essere eliminati:
In[61]:= Chop@2 + [email protected]
Out[61]= 2.
Mathematica, quando esegue un'operazione, cerca di ottenere sempre il maggior numero di cifre
significative, però compatibilmente con il calcolo da eseguire. Possono esserci calcoli che fanno
perdere precisione ad un valore numerico per proprietà intrinseche, come sa chi ha fatto calcolo
numerico:
In[62]:= a = x = N@1 − 10^−30, 40D
Out[62]= 0.9999999999999999999999999999990000000000
Daniele Lupo Appunti di Mathematica
22Printed by Mathematica for Students
In[63]:= 1 + a
Out[63]= 1.999999999999999999999999999999000000000
In[64]:= 1. + a
Out[64]= 2.
In[65]:= b = Ha^2 − 1LêH3 a − 1L
Out[65]= −1.000000000×10−30
In[66]:= Precision@bD
Out[66]= 10.
Come possiamo vedere, il valore dell'espressione ha una precisione minore, dovuto alla differenza
a2 - 1, che è quasi nulla, portando ad un grande errore di cancellazione.
Per poter ottenere risultati con la precisione massima possibile, Mathematica a volte deve aumentare
forzatamente la precisione durante il processo dei suoi algoritmi interni. La variabile di sistema
$MaxExtraPrecision rappresenta il limite massimo di aumento di precisione. A volte, però, può non
bastare per ottenere un risultato con la precisione voluta:
In[67]:= N@Tan@10^1000D, 50D
— N::meprec : Internal precision limit$MaxExtraPrecision = 49.99999999999999` reached while evaluatingTan@1000000000000000000000000000 945 0000000000000000000000000000D. More…
Out[67]= ComplexInfinity
In questo caso, bisogna provare ad aumentare il valore della variabile, per ottenere il risultato voluto:
In[68]:= $MaxExtraPrecision = 2000
Out[68]= 2000
In[69]:= N@Tan@10^1000D, 50D
Out[69]= −0.86303668636289036146207322773061805888611871314800
In questo modo, durante il calcolo, abbiamo approssimato l'argomento della funzione con un numero
di cifre significative sufficiente per ottenere il risultato con il numero di cifre significative richiesto,
e questo è utile quando si vogliono molte cifre significative per un risultato che invoca operazioni
Daniele Lupo Appunti di Mathematica
23Printed by Mathematica for Students
che diminuiscono la precisione del numero approssimato.
Per quanto riguarda l'utilizzo dell'estensione della precisione dei calcoli, va fatta con la dovuta
accortezza. Il fatto che, quando definiamo numeri con precisione inferiore a quella macchina,
vengano definiti con una precisione uguale a quella macchina, ha un suo perchè: infatti, con
precisione standard Mathematica può utilizzare direttamente i comandi per il calcolo in virgola
mobile del processore, aumentando l'efficienza del calcolo. Introducendo precisioni maggiori,
Mathematica usa altri algoritmi che rallentano il calcolo, tenendo conto del fatto che, per fare una
stessa operazione, occorrono più passaggi e cicli del processore per tenere in considerazione la
precisione maggiore, dato che il processore calcola sempre numeri in precisione macchina.
L'implementazione è software, con i rallentamenti del caso.
Per tener conto della precisione del computer su cui gira, Mathematica ha delle variabili di sistema
che tengono conto di queste caratteristiche:
$MachinePrecision il numero di cifre significative di precisione
$MachineEpsilon il numero macchina più piccolo possibile che,sommato ad 1.0, restituisce un numero diverso da 1.0
$MaxMachineNumber il numero macchina più grande rappresentabile
$MinMachineNumber il numero macchina più piccolo rappresentabile
$MaxNumber il modulo più grande di un numeromacchina rappresentabile
$MinNumber il modulo più piccolo di un numeromacchina rappresentabile
Questi valori sono importanti se si vuole tenere in considerazione la precisione di macchina nei
propri calcoli:
In[70]:= $MachinePrecision
Out[70]= 15.9546
In[71]:= $MaxNumber
Out[71]= 1.920224672692357×10646456887
In[72]:= $MachineEpsilon
Out[72]= 2.22045×10−16
In[73]:= a = 1 + $MachineEpsilon
Out[73]= 1.
Daniele Lupo Appunti di Mathematica
24Printed by Mathematica for Students
In[74]:= InputForm@aD
Out[74]//InputForm= 1.0000000000000002
In[75]:= b = 1 + 1.2*^-17
Out[75]= 1.
In[76]:= InputForm@bD
Out[76]//InputForm= 1.
Come potete vedere, in quest'ultimo caso ho sommato ad 1 un valore minore del più piccolo
rappresentabile in precisione macchina, quindi il risultato non è variato.
Mathematica è anche in grado di gestire i numeri in base diversa da quella decimale:
b^^nnnn un numero rappresentato in base b
BaseForm[x, b] stampa x in base b
Questo ci permette di utilizzare altre basi utilizzate in vari ambiti, per esempio quello informatico:
In[77]:= 2^^11010010001 + 2^^10010001111
Out[77]= 2848
Come potete vedere, il risultato viene sempre restituito in forma decimale. Se vogliamo invece
otterere anche quest'ultimo, nella stessa base, occorre utilizzare BaseForm:
In[78]:= BaseForm@2848, 2D
Out[78]//BaseForm= 1011001000002
Con Mathematica possiamo anche trattare, nelle diverse basi, anche numeri reali, oltre che interi:
In[79]:= 16^^ffa39.c5
Out[79]= 1.0471×106
Possiamo anche eseguire delle operazioni con numeri di base diversa fra di loro:
Daniele Lupo Appunti di Mathematica
25Printed by Mathematica for Students
In[80]:= 16^^aa34 ∗ 8^^3143
Out[80]= 71240220
Un ultimo appunto per i numeri riguarda i risultati indeterminati ed infiniti. Infatti, non c'è precisione
che tenga per un risultato di questo tipo:
In[81]:= 0ê0
— Power::infy : Infinite expression10
encountered. More…
— ∞::indet : Indeterminate expression 0 ComplexInfinity encountered. More…
Out[81]= Indeterminate
In[82]:= 0 ∞
— ∞::indet : Indeterminate expression 0 ∞ encountered. More…
Out[82]= Indeterminate
In questo caso non possiamo calcolare il risultato, che non ha nessun significato. Pur non potendo
restituire nessun numero, Mathematica capisce che è dovuto non ad un'approssimazione di calcolo,
ma ad una regola matematica, e restituisce Indeterminate come risultato, ovvero un risultato
indeterminato.
Analogamente Mathematica riconosce un risultato matematicamente infinito:
In[83]:= Tan@π ê2D
Out[83]= ComplexInfinity
Dato che il programma tratta il calcolo simbolico alla pari di quello numerico, il risultato è restituito
non come numero, ma come simbolo corrispondente all'equazione, mentre Matlab avrebbe restituito
un errore.
Oltre al simbolo per il risultato indeterminato, ce ne sono diversi per l'infinito:
Daniele Lupo Appunti di Mathematica
26Printed by Mathematica for Students
Indeterminate un risultato numerico indeterminato
Infinity una quantità infinita positiva
-Infinity una quantità infinita negativa (DirectedInfinity[-1])
DirectedInfinity[r] una quantità infinita con direzione complessa r
ComplexInfinity una quantità infinita di direzione indeterminata
DirectedInfinity[ ] equivalente a ComplexInfinity
I simboli di infinito possono essere usati nei calcoli che li comprendono:
In[84]:= Sum@1êHx^3L, 8x, Infinity<D
Out[84]= Zeta@3D
In[85]:= 4êInfinity
Out[85]= 0
In[86]:= −3 ∗ Infinity
Out[86]= −∞
In[87]:= Indeterminate ∗ 4
Out[87]= Indeterminate
Come vedete, la potenza di questo programma supera già in questo quella di molti altri... E siamo
solamente all'inizio dell'inizio...
ü Liste
Creazione
Uno degli aspetti più importanti in Mathematica è rappresentato dalle liste. Definirle è semplice; una
serie di elementi raggruppati in parentesi graffe:
In[88]:= 81, 5, 6, Sin@E^xD, 81, 4, 5<, variabile<;
Quello che si nota dall'esempio è che le liste possono contenere di tutto, come se fossero semplici
contenitori. Mathematica usa le liste per poter rappresentare una quantità differente di dati, come
vettori, matrici, tavole, ecc.
Le operazioni sulle matrici sono molto potenti e sofisticate, e ne permettono una gestione molto
avanzata. Facciamo un esempio, e creiamo una lista:
Daniele Lupo Appunti di Mathematica
27Printed by Mathematica for Students
In[89]:= lista = 8a, b, c, d, e, f, g<;
Quando applichiamo una funzione ad una lista, la funzione in generale viene applicata ad ogni
elemento della lista, come in questo caso:
In[90]:= Log@listaD
Out[90]= 82.22045×10−16, 0., Log@cD, Log@dD, Log@eD, Log@fD, Log@gD<
In[91]:= 2^lista
Out[91]= 82., 2., 2c, 2d, 2e, 2f, 2g<
In[92]:= % + 2
Out[92]= 84., 4., 2 + 2c, 2 + 2d, 2 + 2e, 2 + 2f, 2 + 2g<
Come potete vedere, abbiamo anche utilizzato l'operatore percento, per considerare l'ultimo risultato:
tanto per tenervi fresca la memoria...
Mathematica usa le liste per la maggior parte dei suoi calcoli. Sono importanti per diversi punti di
vista, e si troveranno quaso ovunque. Non bisogna pensarli, in effetti, come semplici contenitori. Si
può, per esempio, anche modificare la struttura delle stesse e molto altro. In effetti, dalla
manipolazione delle strutture di questo tipo dipende buona parte della potenza del calcolo simbolico
di Mathematica.
Possiamo anche effettuare delle operazioni sulle liste: partendo da quelle più semplici, è possibile
estrarre dalla lista un valore che si trova in una posizione specifica, indicando la posizione entro
doppie parentesi quadre:
In[93]:= lista@@3DD
Out[93]= c
In[94]:= lista@@−3DD
Out[94]= e
In[95]:= lista@@81, 4<DD
Out[95]= 81., d<
Daniele Lupo Appunti di Mathematica
28Printed by Mathematica for Students
Le doppie parentesi quadre sono, a tutti gli effetti, un modo alternativo di scrivere una funzione
(effettivamente, tutto in Mathematica è equivalente a scrivere funzioni, e proprio in questo sta la sua
potenza). La funzione equivalente è Part:
In[96]:= Part@lista, 3D
Out[96]= c
Come potete vedere, se indichiamo il numero (che potrebbe essere anche una variabile) entro le
DOPPIE parentesi quadre (sempre per evitare le ambiguità di scrittura), andiamo a ricavarci il valore
corrispondente a quel valore: se l'indice è positivo, Mathematica restituisce l'elemento della lista
contando a partire dall'inizio mentre, se lo indichiamo con un numero negativo, il programma
conterà l'indice a partire dall'ultimo elemento della lista restituendo, nell'esempio, il terzultimo
elemento. Inoltre, come indice possiamo anche inserire una lista (possiamo inserire liste quasi
ovunque, ed è uno degli aspetti che rende Mathematica così potente), in modo da poter selezionare
gli elementi che ci servono.
Possiamo anche creare delle liste di liste, cioè delle liste nidificate:
In[97]:= nid = 883, 4, 5<, 821, 3, 643<<;
In questo caso, per specificare un elemento avremo bisogno di più indici: uno per la posizione nella
lista esterna, ed uno per quella corrispondente interna. In questo caso particolare, se volessimo per
esempio estrarre il numero 21, dobbiamo considerare che si trova nella seconda 'sottolista', ed in
quest'ultima, nella prima posizione, per cui per estrarre questo elemento dovremo scrivere:
In[98]:= nid@@2, 1DD
Out[98]= 21
Visto? Questo ragionamento si può fare per un qualsiasi livello di nidificazione; oltretutto, non è
neanche necessario che le sottoliste abbiano lo stesso numero di elementi:
In[99]:= nid2 = 8882, 4, 5, 2, 4<, 8824, 542, 843, 13<<, 3<, 4, 6, 85, 2, 22<<<;
Vediamo che, se vogliamo prendere il 43:
In[100]:= nid2@@1, 2, 1, 3, 1DD
Out[100]= 43
Naturalmente, non dobbiamo scervellarci per scegliere un elemento!!! Mathematica ha delle potenti
funzioni di ricerca di elementi, che vedremo più avanti, oltre al fatto che naturalmente non avremo
Daniele Lupo Appunti di Mathematica
29Printed by Mathematica for Students
mai a che fare con liste casuali, ma avranno una struttura fortemente organizzata e dipendente dal
nostro problema...
Un modo veloce ed efficiente per creare liste è usare la funzione Table:
Table[f, {imax}] restituisce una lista di imax elementi tutti pari ad f
Table[f, {i, imax}] restituisce una lista di valori della funzione f[i], con iche varia da 1 a imax
Table[f, {i, imin, imax}] girestituisce una lista di valori della funzione f[i], coni che varia imin to imax
Table[f, {i, imin, imax, di}] specifica il passo di
Table[f, {i, imin, imax}, {j,jmin, jmax}, … ]
genera una lista multidimensionale
Per esempio, se vogliamo una lista di 7 elementi tutti pari ad 1, possiamo semplicemente scrivere
In[101]:= Table@1, 87<D
Out[101]= 81, 1, 1, 1, 1, 1, 1<
Se, invece, voglio usare una lista dal 3° al 10° numero primo, posso utilizzare la funzione Prime:
In[102]:= Table@Prime@nD, 8n, 3, 10<D
Out[102]= 85, 7, 11, 13, 17, 19, 23, 29<
Facile come bere un bicchier d'acqua, vero? Possiamo anche darle una rappresentazione un tantinello
più leggibile, usando la notazione postfissa del comando TableForm:
In[103]:= lista êê TableForm
Out[103]//TableForm=1.1.cdefg
Possiamo anche creare con tranquillità liste di centinaia di migliaia di elementi. In questo caso, però,
l'output sarebbe leggermente meno gestibile, no? Se concludiamo il comando di Mathematica con il
punto e virgola, eviteremo di avere l'output del comando. Questo è particolarmente utile quando
dovrete definire liste, vettori e matrici molto lunghi:
Daniele Lupo Appunti di Mathematica
30Printed by Mathematica for Students
In[104]:= listalunga = Table@Sin@xD, 8x, 0, 1000, 0.01<D;
con il comando Lenght possiamo velutare il numero di elementi di una lista:
In[105]:= Length@listalungaD
Out[105]= 100001
Avete intenzione di visualizzare a schermo una lista così lunga? Io spero di no, e comunque avete
appena visto come fare. Questo non vale soltanto per le liste, ma in generale per tutti i comandi di
cui non desiderate per un motivo o per un altro l'output.
Un'altra funzione utilissima per creare velocemente delle liste è Range, che permette di creare
velocemente liste numerice che contengono un determinato intervallo: con un solo argomento si crea
una lista da 1 a n, con due argomenti da n ad m, e con tre argomenti da m ad n con passo d:
Range[n] restituisce la lista {1, 2, 3, … , n} Range@n,mD restituisce la lista 8n,…, m<
Range@n,m,dD restituisce la lista 8n,…, m< con passo d
Questo permette di creare dei determinati intervalli di valori molto velocemente, anche di grande
dimensioni, senza andare a scomodare Table
In[106]:= Range@6D
Out[106]= 81, 2, 3, 4, 5, 6<
In[107]:= Range@3, 10D
Out[107]= 83, 4, 5, 6, 7, 8, 9, 10<
In[108]:= Range@5, 7, .3D
Out[108]= 85, 5.3, 5.6, 5.9, 6.2, 6.5, 6.8<
Ovviamente, niente ci vieta di andare a creare liste lunghe decine di migliaia di elementi, ma in
questo caso di solito non è conveniente visualizzare il risultato:
In[109]:= a = Range@4, 40000, .01D;
In questa maniera possiamo utilizzare la lista appena ottenuta nella maniera che più ci piace e,
soprattutto, che più ci serve...
Un altro comando utile nella creazione delle liste è il seguente:
Daniele Lupo Appunti di Mathematica
31Printed by Mathematica for Students
Array[f, n] crea una lista di lunghezza n, i cui elementi sono datida f @iD
Array@ f , 8n1, n2, … <D crea una lista di dimensione n1än2ä... ,con gli elementi formati da f @i1,i2...D
Array@ f ,8n1, n2, … <, 8r1, r2, … <D
genera una lista come nel caso precedente,ma con gli indici che cominciano da 8r1, r2, … <,invece che da 1 come avviene di default
Array@ f , dims, origin, hD usa l' head h invece che List per ogni livello dell' array
Questa funzione ci permette di creare, quindi, facilmente delle liste che hanno gli elementi che sono
dati in funzione dei loro indici
In[110]:= Array@f, 10D
Out[110]= 8f@1D, f@2D, f@3D, f@4D, f@5D, f@6D, f@7D, f@8D, f@9D, f@10D<
Potrei utilizzare anche più indici, se necessario:
In[111]:= Array@g, 83, 4<D
Out[111]= 88g@1, 1D, g@1, 2D, g@1, 3D, g@1, 4D<,8g@2, 1D, g@2, 2D, g@2, 3D, g@2, 4D<,8g@3, 1D, g@3, 2D, g@3, 3D, g@3, 4D<<
Posso creare, per esempio una lista dove compaiano i seni degli indici:
In[112]:= Array@Sin, 7D êê N
Out[112]= 80.841471, 0.909297, 0.14112,−0.756802, −0.958924, −0.279415, 0.656987<
Possiamo anche utilizzare delle funzioni personalizzate, se lo vogliamo: vedremo più avanti come
fare per poter creare delle funzioni personalizzate. Bisogna solamente stare attendi ad utilizzare un
numero di indici pari al numero di argomenti della funzione; nel caso seguente, ci sono due indici,
quindi chiama la funzione coseno con due indici, mentre tutti noi sappiamo che in realtà ne richiede
soltanto uno. In questo caso Mathematica capisce che c'è qualcosa che non va e ci avverte:
Daniele Lupo Appunti di Mathematica
32Printed by Mathematica for Students
In[113]:= Array@Cos, 84, 4<D
— Cos::argx : Cos called with 2 arguments; 1 argument is expected. More…
— Cos::argx : Cos called with 2 arguments; 1 argument is expected. More…
— Cos::argx : Cos called with 2 arguments; 1 argument is expected. More…
— General::stop : Further output of Cos::argx will be suppressed during this calculation. More…
Out[113]= 88Cos@1, 1D, Cos@1, 2D, Cos@1, 3D, Cos@1, 4D<,8Cos@2, 1D, Cos@2, 2D, Cos@2, 3D, Cos@2, 4D<,8Cos@3, 1D, Cos@3, 2D, Cos@3, 3D, Cos@3, 4D<,8Cos@4, 1D, Cos@4, 2D, Cos@4, 3D, Cos@4, 4D<<
I messaggi di errore indicano che Mathematica non è in grado di valutare la funzione, perchè ci sono
due argomenti, mentre la funzione ne richiede uno solo. Notate, tuttavia, come in ogni caso viene
restituito il risultato del comando, anche se non in forma valutata. Questo è particolarmente utile
quando andiamo ad utilizzare particolari funzioni personalizzate che non sono state pienamente
definite, o lo saranno in seguito.
Inoltre, al posto delle liste, possiamo utilizzare delle funzioni personalizzate. Per esempio, notate
quello che restituisce il seguente comando:
In[114]:= Array@f, 83, 3<, 80, 0<, gD
Out[114]= g@g@f@0, 0D, f@0, 1D, f@0, 2DD,g@f@1, 0D, f@1, 1D, f@1, 2DD, g@f@2, 0D, f@2, 1D, f@2, 2DDD
In questo caso abbiamo utilizzato la funzione nella sua forma più completa: abbiamo specificato la
funzione da applicare agli indici, che sarebbe la f; poi abbiamo specificato il valore massimo degli
indici, ed anche quello minimo. Inoltre, al posto di creare delle liste abbiamo utilizzato la funzione g,
mettendo g[...] ogni volta che compariva una lista. Questo è un metodo veloce ed efficace per
costruire espressioni complesse, invece che delle liste.
Un altro modo interessante di creare delle liste, utile in casi particolari, è il seguente:
NestList[f, x, n] {x, f[x], f[f[x]], … } con livelli di annidamenteche arriva ad n
Questo consente di creare una lista dove gli elementi sono dati dalla ricorsione di una funzione:
Daniele Lupo Appunti di Mathematica
33Printed by Mathematica for Students
In[115]:= NestList@Sqrt, y, 6D
Out[115]= 8y, è!!!y , y1ê4, y1ê8, y1ê16, y1ê32, y1ê64<
Questo permette di creare delle radici quadrate annidate.
In[116]:= NestList@Exp, 3, 9D
Out[116]= 93, 3,3,
3
,3
,3
,3
,3
,
3
,
3
=
Qua viene visto come la funzione esponenziale viene annidata, e come un elemento della lista sia
dato dall'elemento che lo precede a cui sia applicata la funzione selezionata, come da definzione di
ricorsione.
A volte è necessario costruire una lista a partire da un'altra. Per esempio, quando vogliamo applicare
una funzione ad ogni elemento della lista; in questo caso molte volte basta applicare la lista come
argomento della funzione, ma questo non è vero per tutte le funzioni. Oppure bisogna creare una
lista come sottolista di una originale, i cui elementi soddisfino determinati criteri. Ci sono
determinati comandi che permettono di creare liste siffatte:
Map[f, list] applica f a qualsiasi elemento di list
MapIndexed[f, list] restituisce la funzione f[elem, {i}] per l'elemento i-simo
Select[list, test] selezione gli elementi per la quale test[elem]restituisce True
Supponiamo di avere la seguente lista:
In[117]:= lista = 83, 5, 6, 2, 4, 5, 6, 4, 3, 1<;
Se vogliamo applicare una funzione, possiamo creare per esempio:
In[118]:= Map@f, listaD
Out[118]= 8f@3D, f@5D, f@6D, f@2D, f@4D, f@5D, f@6D, f@4D, f@3D, f@1D<
Se la funzione è particolare, e necessita di due argomenti, di cui uno è l'indice:
In[119]:= MapIndexed@g, listaD
Out[119]= 8g@3, 81<D, g@5, 82<D, g@6, 83<D, g@2, 84<D, g@4, 85<D,g@5, 86<D, g@6, 87<D, g@4, 88<D, g@3, 89<D, g@1, 810<D<
Daniele Lupo Appunti di Mathematica
34Printed by Mathematica for Students
Come possiamo vedere, in questa maniera possiamo creare una lista con delle funzioni in maniera
più paricolare rispetto a Map
Certe volte le liste devono essere estremamente lunghe, ma soli una piccola parte dei loro elementi
deve essere diversa da zero. Di solito questo non è un problema, ma ci possono essere casi un cui, in
una lista di centinaia di migliaia di elementi, solamente un centinaio devono essere diversi da zero;
oppure la lista è piena di valori tutti uguali e diversi da zero, e solamente alcuni sono diversi da
questo valore. In questo caso, la gestione normale delle liste crea un inutile spreco di memoria,
considerando anche che, se in un problema ci serve una lista del genere, probabilmente ce ne
serviranno anche altre. Per ovviare a questo problema Mathematica fornisce dei comandi che
permettono di creare liste sparse di questo tipo con un notevole guadagno di memoria, andando a
memorizzare solamente i valori che servono, e non la lista intera:
SparseArray[{i1->v1, … }] crea una lista sparsa, dove l'elemento ik assume ilvalore vk
SparseArray@8pos1, pos2, … <−>
8val1, val2, … <D
restituisce la stessa lista ottenuta con il comando di sopra
SparseArray@listD crea una lista sparsacorrispondente a quella normale data da list
SparseArray@data, 8d1, d2, … < Crea una lista sparsa nidificata,con gli elementi specificati, di dimensione 8d1, d2, … <
SparseArray@data, dims, valD Crea una lista di dimensioni specificate,in cui l' elemento che non viene specificato,al posto di assumere valore nullo assume valore val
In questo caso, nella creazione delle matrici Mathematica crea una rappresentazione interna fatta di
puntatori ed altro, una struttura che crea un notevole guadagno di memoria quando si creano appunto
matrici con molti elementi, mentre, se la lista è densa, cioè con molti elementi non nulli, questo
metodo di memorizzazione diventa inefficiente, dato che per ogni elemento deve esplicitarne la
posizione, mentre nel caso normale vengono semplicemente accodate fra di loro. Le matrici sparse
sono utilizzate in molti programmi tecnici dove è solito risolvere sistemi lineari con matrici sparse ad
elevata dimensione, come ad esempio i CAD di elettronica.
Come abbiamo visto, ci sono diversi modi di creare una matrice sparsa; vediamo questo semplice
esempio:
In[120]:= listasparsa = SparseArray@82 → 5, 30 → 3<D
Out[120]= SparseArray@<2>, 830<D
Abbiamo creato in questo modo una matrice sparsa. Viene visualizzata in maniera diversa,
specificando che ha dimensione 30, e che ci sono 2 elementi non nulli. Mathematica non la
Daniele Lupo Appunti di Mathematica
35Printed by Mathematica for Students
rappresenta perchè appunto questa rappresentaizione viene usata per liste di dimensioni elevate,
quindi praticamente inutili da visualizzare. Tuttavia possiamo eseguire le stesse operazioni si du una
lista:
In[121]:= listasparsa@@4DD
Out[121]= 0
In[122]:= listasparsa@@30DD
Out[122]= 3
Abbiamo visto come possiamo estrarne facilmente gli elementi, esattamente come se si trattasse di
una lista normale.
In[123]:= 2 + listasparsa
Out[123]= SparseArray@<2>, 830<, 2D
Anche se tutti gli elementi adesso sono diversi da zero, Mathematica continua a mantenere la
struttura sparsa, perchè è questa la maniera più conveniente. L'unica differenza è che adesso il
risultato contiene pure il valore di tutti gli elementi non specificati, che in questo caso è pari a 2, dato
che è stato sommato a tutti gli elementi nulli.
Però, possiamo vedere che in questa maniera, quando definiamo la lista, la dimensione è la minima
necessaria a contenere l'ultimo elemento non nullo. Nel nostro caso ha dimensione 30, esattamente la
posizione del nostro ultimo elemento. Se vogliamo creare una lista di dimensioni definite, il cui
ultimo elemento può anche essere zero, dobbiamo specificarlo nel comando. Il modo grezzo è quello
di definire un elemento pari a zero come ultimo elemento. Per esempio, in una matrice di settecento
elementi, in cui l'ultimo elemento non nullo è nella centesima posizione, posso scrivere:
In[124]:= listasparsa2 = SparseArray@81 → s, 34 → f, 100 → r, 700 → 0<D
Out[124]= SparseArray@<4>, 8700<D
Tuttavia, questo metodo ve lo sconsiglio. Invece, vi conviene direttamente esplicitare le dimensioni
all'interno del comando, come secondo argomento:
In[125]:= listasparsa3 = SparseArray@81 → s, 34 → f, 100 → r<, 700D
Out[125]= SparseArray@<3>, 8700<D
Questo metodo è di certo più intuitivo e chiaro, oltre a evitare errori e dimenticanze. Usate sempre
questo, mi raccomando.
Daniele Lupo Appunti di Mathematica
36Printed by Mathematica for Students
Nel caso poi ce ne fosse bisogno, possiamo trasformare una lista sparsa in una lista normale, tramite
il comando Normal:
In[126]:= Normal@listasparsaD
Out[126]= 80, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3<
Come possiamo vedere, tutti gli elementi specificati sono nulli. Se invece vogliamo specificare un
altro valore, dobbiamo scriverlo nella funzione, esattamente come accade per le dimensioni:
In[127]:= nonnullo = SparseArray@83 → 5, 24 → 7<, 25, 3D
Out[127]= SparseArray@<2>, 825<, 3D
In questo caso, abbiamo specificato una lista sparsa con gil elementi specificati, di dimensione pari a
25, e in cui gli elementi non specificati sono tutti uguali a 3. Possiamo vederlo meglio andando a
scrivere la lista in forma normale:
In[128]:= Normal@nonnulloD
Out[128]= 83, 3, 5, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 7, 3<
Non sembra esserci tutto questo vantaggio, effettivamente, ma considerate che il vantaggio aumenta
all'aumentare delle dimensioni della matrice sparsa, specialmente se è dell'ordine delle migliaio di
elementi per dimensione (matrici di centinaia di elementi sono ancora facilmente gestibili da
Mathematica su di un computer attuale).
Ricerca
Una volta create le liste, è opportuno conoscere qualche basilare funzione e metodo per poterle
manipolare; raramente una lista nel corso di uno studio dovrà rimanere costante: spesso sarà
necessario aggiungere elementi, toglierli, cambiarli, estrarre dei dati e così via.
Abbiamo già visto l'operazione forse più semplice e quella usata più spesso: cioè l'estrazione di un
elemento dalla lista, usando le doppie parentesi quadre:
In[129]:= 86, 2, 3, a, 67, 2<@@5DD
Out[129]= 67
Le funzioni per estrarre direttamente elementi di una lista sono poche e semplici, e sono qua sotto
riassunte:
Daniele Lupo Appunti di Mathematica
37Printed by Mathematica for Students
Take[list, n] restituisce l' n-simo elemento in list
Take[list, -n] restituisce l' n-simo elemento contando dalla coda
Take[list, {m, n}] restituisce la lista di elementi dalla posizione malla posizione n (incluse)
Rest[list] list con il primo elemento scartato
Drop[list, n] list con i primi n elementi scartati
Most[list] list l'ultimo elemento scartato
Drop[list, -n] list con gli ultimi n elementi scartati
Drop[list, {m, n}] list con gli elementi da m a n scartati
First[list] il primo elemento in list
Last[list] l'ultimo elemento
Part[list, n] or list[[n]] l'elemento n-simo della lista
Part[list, -n] or list[[-n]] l'elemento n-simo della lista contando dalla fine
Part[list, {n1, n2, … }]or list[[{n1, n2, … }]]
la lista degli elementi in posizione n1, n2, …
Creiamoci una lista, e vediamo come possiamo estrarre elementi da essa:
In[130]:= Clear@a, b, c, d, e, f, g, hD
In[131]:= lista = 8a, b, c, d, e, f, g, h<;
Non lasciatevi ingannare dalla semplicità dell'esempio; le lettere possono essere in realtà qualsiasi
cosa, da numeri a variabili a funzioni, ad altre liste e così via. Voi sperimentate e poi ditemi se non
ho ragione. Comunque, una volta creata la lista, è semplice, per esempio, andare a vedere il primo
oppure l'ultimo elemento della lista:
In[132]:= First@listaD
Out[132]= a
In[133]:= Last@listaD
Out[133]= h
Invece, per prendere, per esempio, i primi tre elementi della lista, possiamo scriverli direttamente fra
le doppie parentesi quadre, oppure usare la funzione Take:
In[134]:= lista@@81, 2, 3<DD
Out[134]= 8a, b, c<
Daniele Lupo Appunti di Mathematica
38Printed by Mathematica for Students
In[135]:= Take@lista, 3D
Out[135]= 8a, b, c<
Insomma, avete capito come funzionano le cose, vero?
Tuttavia, a volte desideriamo non tanto estrarre gli elementi, ma solo testare e sapere se qualcosa è
presente nella matrice, dopo che abbiamo eseguito un determinato numero di calcoli; per esempio, ci
piacerebbe sapere se un elemento è presente nella lista. Certo, potremmo semplicemente visualizzare
la lista e cercare, ma se la lista contiene, per esempio, 10000 elementi, come facciamo? E se
vogliamo scoprire la posizione di un elemento? Sarebbe scomodo, ed oltretutto, queste funzioni
hanno anche l'immenso vantaggio di automatizzare la ricerca che è una cosa utile, per esempio,
quando andiamo a scrivere dei programmi in Mathematica. A volte non possiamo proprio farne a
meno. Ecco quindi alcune utili funzioni per la ricerca di elementi in una lista:
Position[list, form] la posizione in cui form compare in list
Count[list, form] il numero di volte che form compare come elemento in list
MemberQ[list, form] verifica se form è un elemento di list
FreeQ[list, form] verifica se form non compare da nessuna parte in list
Al solito, creiamo una lista, e vediamo come possiamo estrarre e vedere elementi in essa:
In[136]:= lista = 8a, bb, c, a, d, f, d<;
Supponiamo, adesso, di voler contare il numero di volte che a compare nella lista:
In[137]:= Count@lista, aD
Out[137]= 2
Adesso, vogliamo sapere se, per esempio, z è un elemento della lista:
In[138]:= MemberQ@lista, zD
Out[138]= False
Il che ci fa capire che z non è un elemento della nostra lista
Inoltre, se la nostra lista è composta da numeri, a volte ci piacerebbe sapere dove si trova, per
esempio, l'elemento più grande, e sapere qual'è: in questo caso ci torneranno utili le seguenti
funzioni di ricerca nelle liste:
Daniele Lupo Appunti di Mathematica
39Printed by Mathematica for Students
Sort[list] ordina gli elementi di list
Min[list] l'elemento più piccolo che si trova in list
Ordering[list, n] la posizione degli n elementi più piccoli in list
Max[list] l'elemento più grande in list
Ordering[list, -n] la posizione degli n elementi più grandi in list
Ordering[list] visualizza l'ordine degli elementi in list
Permutations[list] tutte le possibili permutazioni di list
Costruiamoci una lista numerica:
In[139]:= lista = 83, 5, 4, 8, 1, 3, 6<
Out[139]= 83, 5, 4, 8, 1, 3, 6<
Supponiamo di vole conoscere l'elemento più piccolo che si trova nella lista:
In[140]:= Min@listaD
Out[140]= 1
Adesso, supponiamo di voler conoscere i tre elementi più grandi della lista. Effettivamente non
esiste una funzione che permette di ricavarceli direttamente, ma possiamo fare così: prima di tutto,
con Ordering calcoliamo la posizione dove si trovano i tre elementi più grandi della lista:
In[141]:= Ordering@lista, −3D
Out[141]= 82, 7, 4<
Adesso, possiamo usare il risultato come indici per trovare gli elementi:
In[142]:= lista@@%DD
Out[142]= 85, 6, 8<
Avete capito cos'ho hatto, vero? con Ordering ho trovato gli indici della lista che corrispondono ai
tre valori più grandi, e dopo ho usato le doppie parentesi per visualizzare gli elementi corrispondenti
ad ogni singolo indice trovato con il comando precedente. Ed, essendo il risultato precedente, perchè
riscriverlo quando posso usare l'operatore percento?
Un'altra interessante funzione è Permutations, che permette di osservare tutte le combinazioni degli
elementi della lista.
Daniele Lupo Appunti di Mathematica
40Printed by Mathematica for Students
In[143]:= Permutations@8a, b, c, d<D
Out[143]= 88a, b, c, d<, 8a, b, d, c<, 8a, c, b, d<, 8a, c, d, b<,8a, d, b, c<, 8a, d, c, b<, 8b, a, c, d<, 8b, a, d, c<, 8b, c, a, d<,8b, c, d, a<, 8b, d, a, c<, 8b, d, c, a<, 8c, a, b, d<, 8c, a, d, b<,8c, b, a, d<, 8c, b, d, a<, 8c, d, a, b<, 8c, d, b, a<, 8d, a, b, c<,8d, a, c, b<, 8d, b, a, c<, 8d, b, c, a<, 8d, c, a, b<, 8d, c, b, a<<
Chi si occupa di statistica apprezzerà particolarmente questa funzione, assieme ad un altro centinaio
di funzioni implementate in Mathematica...
Sebbene questi tipi di ricerca siano molto veloci e completi, tuttavia sono ancora abbastanza limitate,
perchè non abbiamo affrontato l'argomento dei pattern, cosa che faremo più avanti. Per adesso faccio
soltanto un esempio riguardante le strutture. Possiamo specificare di cercare non dei valori, ma delle
espressioni con delle determinate strutture; per esempio, possiamo cercare i casi in cui gli elementi
siano degli esponenziali:
In[144]:= lista =
8a, b, c^e, Ha x^2 + vL^H3 + tL, Sin@vD, Cos@bD^Sin@bD, x + y, nm ∗ er<;
In[145]:= Cases@lista, _ ^ _D
Out[145]= 8ce, H0.9999999999999999999999999999980000000000 a + vL3+t, Cos@bDSin@bD<
In questo modo ho estratto tutti gli elementi della lista che sono stati scritti in forma di esponenziale,
identificandio gli elementi con _^_, che significa: 'qualsiasi espressione elevata a qualsiasi altra
espressione'. Vedremo molto più avanti come trattare meglio i pattern, anche perchè è con questo
metodo che si possono fare profonde ed avanzate ricerche di specifici elementi in liste di milioni di
elementi....
Daniele Lupo Appunti di Mathematica
41Printed by Mathematica for Students
Manipolazione
Una volta creata la lista, può essere utile eseguire delle manipolazioni su di essa, come per esempio
inserire oppure eliminare qualche specifico elemento. Le funzioni base per poter eseguire queste
operazioni sono le seguenti:
Prepend[list, element] aggiungi element all'inizio di list
Append[list, element] aggiungi element alla fine di list
Insert[list, element, i] inserisci element nella posizione i in list
Insert[list, element, -i] inserisci element nella posizione i contando a dalla finedi list
Delete[list, i] elimina l'elemento in posizione i in list
ReplacePart[list, new, i] sostituisci l'elemento in posizione i in list con new
ReplacePart[list, new, {i, j}] sostituisci list[[i, j]] con new
Possiamo usare come lista di esempio la stessa che abbiamo usato prima:
In[146]:= lista = 8a, b, c, d, e, f, g, h<;
e vedere come possiamo modificarla. Supponiamo, per esempio, di voler inserire l'elemento x prima
all'inizio, e poi alla fine della lista; la sintassi per poter eseguire queste due operazioni sono
elementari, come potete intuire:
In[147]:= Prepend@lista, xD
Out[147]= 80.9999999999999999999999999999990000000000, a, b, c, d, e, f, g, h<
In[148]:= Append@lista, xD
Out[148]= 8a, b, c, d, e, f, g, h, 0.9999999999999999999999999999990000000000<
Invece, se vogliamo sostituire un elemento della lista, possiamo usare ReplacePart:
In[149]:= ReplacePart@lista, ciao, 3D
Out[149]= 8a, b, ciao, d, e, f, g, h<
Effettivamente, al posto di usare ReplacePart, possiamo semplicemente utilizzare le doppie parentesi
per ottenere lo stesso risultato:
In[150]:= lista@@3DD = ciao
Out[150]= ciao
Daniele Lupo Appunti di Mathematica
42Printed by Mathematica for Students
In[151]:= lista
Out[151]= 8a, b, ciao, d, e, f, g, h<
Sembrano la stessa cosa, ma ad un esame un attimino più attento si nota una fondamentale
importanza: nel primo caso, infatti, con la funzione noi creiamo semplicemente una lista dove viene
sostituito un elemento con un altro, ma la lista originale rimane invariata; nel secondo caso, invece,
andiamo a modificare l'elemento della lista in esame, che risulta quindi permanentemente modificata:
una volta modificato l'elemento, l'elemento sovrascritto viene definitvamente perso, a meno che
ovviamente non sia stato salvato prima in un'altra variabile. State attenti, quindi, a decidere quale
metodo di sostituzione vorrete utilizzare ogni volta, e dipende principalmente da cosa volete: se vi
serve modificare il valore di un elemento della lista, usate le doppie parentesi; se vi serve una lista
con l'elemento modificato, ma non volete modificare la lista originale perchè vi servirà in seguito,
per esempio, per eseguire dei test, usate ReplacePart, magari memorizzando la nuova lista con un
altro nome.
Inoltre, le liste possono anche essere unite assieme: in questo caso, ci sono due funzioni per unire le
liste, apparentemente simili, ma con un'importante differenza:
Join[list1, list2, … ] concatena assieme le liste
Union[list1, list2, … ]
Intersection [list1, list2, … ]Complement[universal, list1, … ]
Subsets[list]
combina le liste, rimuovendo gli elementi duplicati eriordinando i restanti elementicrea una lista contenente elementi comuni a tutte le listecrea una lista con tutti gli elementi presenti in universal,ma che non sono contenuti in nessuna delle altre listeelencateCrea una lista contenente tutte le possibili sottoliste di list
Quando vogliamo semplicemente unire due liste, conviene usare il comando Join, mentre, se invece
occorre prendere tutti gli elementi delle liste, per unirle in un'unica lista dove compaiono soltanto gli
elementi distinti, allora occorre usare il comando Union. Prestate attenzione al differente modo di
operare di queste due funzioni, mi raccomando. Le altre funzioni non credo che abbiano bisogno di
particolari commenti o delucidazioni. comunque, il mio consiglio è quello di sperimantare quanto
più potete, per vedere quello che potete fare, quello che avete capito e quello che invece vi manca. A
proposito, vi ho già suggerito di leggervi l'help on line ogni volta che ne avete bisogno, vero? :-)
Un altro modo per elaborare le liste consiste nel poterle riordinare come meglio ci aggrada, in ordine
crescente oppure decrescente, e implementando anche lo scorrimento della lista:
Daniele Lupo Appunti di Mathematica
43Printed by Mathematica for Students
Sort[list] ordina gli elementi di list in maniera standard
Union[list] sort riordina gli elementi, eliminando i duplicati
Reverse[list] inverte l'ordine degli elementi in list
RotateLeft[list, n] scorre gli elementi di list di n posizioni verso sinistra
RotateRight[list, n] non riuscirete mai ad indovinare cosa fa questa funzione...
Notate il riutilizzo del comando Union : prima l'avevamo utilizzato per unire le liste scartando gli
elementi duplicati, ma aveva anche l'effetto di riordinarli. Qua fa effettivamente la stessa cosa, ma
limitandosi ad una lista soltanto. Vediamo con il solito esempiuccio come funzionano queste
funzioni:
In[152]:= lista = 8a, b, g, r, t, s, w, r, x, v, a, b<;
Come potete vedere, la lista questa volta è formata da elementi casuali e disordinati.
In[153]:= Sort@listaD
Out[153]= 80.9999999999999999999999999999990000000000,a, a, b, b, g, r, r, s, t, v, w<
In[154]:= Union@listaD
Out[154]= 80.9999999999999999999999999999990000000000, a, b, g, r, s, t, v, w<
Qua potete vedere la differenza fra le due funzioni, e come il secondo comando permetta, oltre
all'ordinamento, anche l'eliminazione degli elementi duplicati. Bisogna fare, invece, un attimino più
di attenzione al comando Reverse:
In[155]:= Reverse@listaD
Out[155]= 8b, a, v, 0.9999999999999999999999999999990000000000,r, w, s, t, r, g, b, a<
Come possiamo vedere, non esegue l'ordinamento degli elementi di una lista, come potrebbe ad
alcuni sembrare, dato che qua parliamo di ordinamento: semplicemente, inverte gli elementi della
lista; se vogliamo avere un'ordinamento inverso, però, niente paura: basta invertire la lista
precedentemente ordinata, no?
In[156]:= Reverse@Sort@listaDD
Out[156]= 8w, v, t, s, r, r, g, b, b, a, a,0.9999999999999999999999999999990000000000<
Daniele Lupo Appunti di Mathematica
44Printed by Mathematica for Students
Tanto semplice quanto efficace. Ricordate solo che quando effettuate operazioni di questo tipo, la
lista originale rimane invariata, dato che i comandi forniscono solamente un risultato: se volete che
la lista cambi effettivamente, dovete scrivere qualcosa del tipo:
In[157]:= lista = Union@listaD
Out[157]= 80.9999999999999999999999999999990000000000, a, b, g, r, s, t, v, w<
e, andando a vedere il contenuto della lista, si vede che ora è effettivamente cambiato:
In[158]:= lista
Out[158]= 80.9999999999999999999999999999990000000000, a, b, g, r, s, t, v, w<
Comunque, sono sicuro che non avrete difficoltà a capire questo, se avete, almeno una volta nella
vostra vita, messo mano ad un qualsiasi linguaggio di programmazione. Fatevi qualche esercizietto e
sperimentate, dato che le liste sono elementi molto importanti, in Mathematica, specialmente quando
si devono, per esempio, eseguire operazioni su dei dati sperimentali di un esperimento oppure di una
simulazione.
ü Vettori e Matrici
Le liste sono anche il modo che ha Mathematica per poter scrivere vettori e matrici: il vettore si
scrive come una lista semplice, mentre la matrice si scrive come una lista di liste, dove le liste
elementi della lista principale rappresentano le righe della matrice in esame:
In[159]:= vet = 8a, b, c<;
In[160]:= mat = 88a, b<, 8c, d<<;
Per estrapolare gli elementi, si usano pure in questo caso, dato che in fondo di tratta di liste, le
doppie parentesi quadre per indicare gli indici.
In[161]:= vet@@1DD
Out[161]= a
In[162]:= mat@@1DD
Out[162]= 8a, b<
Questo perchè, dal punto di vista del programma, una matrice è una lista di liste, e il primo elemento
di una lista è proprio la prima sotto-lista, che rappresenta la prima riga. Tutto regolare, quindi. Per
poter estrapolare un singolo elemento, bisogna usare due indici
Daniele Lupo Appunti di Mathematica
45Printed by Mathematica for Students
In[163]:= mat@@1, 2DD
Out[163]= b
Semplice, no?
Le operazioni con i vettori sono molto semplici; possiamo sommare i vettori:
In[164]:= vet + 8e, r, t<
Out[164]= 8a + e, b + r, c + t<
Tuttavia, se proviamo a moltiplicare gli elementi dei vettori, non utilizziamo il risultato voluto:
In[165]:= vet 8e, r, t<
Out[165]= 8a e, b r, c t<
Questo perchè la moltiplicazione viene eseguita fra elementi delle liste aventi lo stesso indice. per
poter effettuare il prodotto scalare o, più in generale, il prodotto righe per colonne, dobbiamo
utilizzare il comando del prodotto vettoriale, che è semplicemente il punto:
In[166]:= vet.8e, r, t<
Out[166]= a e + b r + c t
In[167]:= Sin@8x, y, z<D.82, 3, 4<
Out[167]= 1.682941969615793013305004643259517394633+ 3 Sin@yD + 4 Sin@zD
In[168]:= mat.81, 2<
Out[168]= 8a + 2 b, c + 2 d<
Un modo utile di definire i vettori (ma anche liste: ricordate che in fondo in Mathematica sono la
stessa cosa...) è usare il comando Array: richiere cone primo argomento il nome della funzione, e
come secondo argomento un numero, od una lista di numeri, che andranno a rappresentare
l'argomento: in pratica, avendo gli indici i,j, costruisce la matrice A dove aij=funz[i,j]
In[169]:= Array@funz, 5D
Out[169]= 8funz@1D, funz@2D, funz@3D, funz@4D, funz@5D<
Daniele Lupo Appunti di Mathematica
46Printed by Mathematica for Students
In[170]:= Array@funz, 83, 2<D
Out[170]= 88funz@1, 1D, funz@1, 2D<,8funz@2, 1D, funz@2, 2D<, 8funz@3, 1D, funz@3, 2D<<
Per le matrici, due funzioni utili sono quelle che permettono di creare matrici identità oppure
diagonali: nel primo caso occorre come argomento la dimensione n della matrice (ne basta una, è
quadrata...), nel secondo caso occorre la lista di elementi diagonali. Vedremo la scrittura anche per
poter ottenere un'output più consono a quello delle matrici:
In[171]:= IdentityMatrix@3D êê MatrixForm
Out[171]//MatrixForm=
i
k
jjjjjj1 0 00 1 00 0 1
y
{
zzzzzz
In[172]:= DiagonalMatrix@81, 2, r, 4<D êê MatrixForm
Out[172]//MatrixForm=
i
k
jjjjjjjjjjj
1 0 0 00 2 0 00 0 r 00 0 0 4
y
{
zzzzzzzzzzz
E possiamo anche calcolarci le dimensioni di una matrice o di un vettore:
In[173]:= Dimensions@%D
Out[173]= 84, 4<
Qua sotto sono riportate pochissime ma indispensabili formule per poter operare con le
matrici:
c m moltiplicazione per uno scalare
a . b prodotto matriciale
Inverse[m] inversa di una matrice
MatrixPower[m, n] potenza nth di una matrice
Det[m] determinante
Tr[m] traccia
Transpose[m] trasposta
Eigenvalues[m] autovalori di una matrice
Eigenvectors[m] autovettori di una matrice
Sempre considerando la matrice mat creata in precedenza, possiamo scrivere, per fare qualche veloce
esempio:
Daniele Lupo Appunti di Mathematica
47Printed by Mathematica for Students
In[174]:= Det@matD
Out[174]= −b c + a d
In[175]:= Eigenvalues@matD
Out[175]= 9 12Ia + d −
è!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!a2 + 4 b c − 2 a d + d2 M, 12Ia + d +
è!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!a2 + 4 b c − 2 a d + d2 M=
In[176]:= Inverse@matD
Out[176]= 99 d−b c + a d
, −b
−b c + a d=, 9−
c−b c + a d
, a−b c + a d
==
In questi semplici esempi potete vedere come Mathematica tratta con la stessa semplicità sia calcoli
numerici che calcoli simbolici. Vi risparmo la scrittura degli autovettori, ma potete provarla da soli
per vedere come facilmente si possono ottenere risultati di tutto rispetto. Sono pochi i programmi
che permettono un calcolo simbolico così sofisticato...
Adesso, dopo aver visto qualche nozione di base di Mathematica, andiamo a scalfire un poco più a
fondo le sue capacità, andando a vedere un pochino di calcolo simbolico. Non allarmatevi, ma siate
rilassati e contemplate la potenza di questo programma. D'altra parte, prima di scrivere il resto mi
prenderò una pausa ed andrò a farmi un bagno al mare. Non dispiace a nessuno, vero? A presto,
allora!!!
Daniele Lupo Appunti di Mathematica
48Printed by Mathematica for Students
ü Nota sulla visualizzazione delle formule
In Mathematica, si scrivono le equazioni e tutto il resto sotto forma si testo: L'integrale si scriverà,
per esempio, con il comando Integral: potete effettivamente usare la palette che compare di default
per poter scrivere direttamante in forma tradizionale, ma io personalmente ve lo sconsiglio. Anche se
le prime ore sarete tentati a farlo, dopo che vi sarete scritti una decina di integrali scoprirete che è
molto più veloce battere Integral sulla tastiera che dover andare a cliccare col mouse prima nel
simbolo d'integrale e dopo in ogni quadratino per poter scrivere tutto quanto.
Tuttavia, se dovete, per esempio, stampare qualche lavoro, una forma tradizionale di presentazione
delle equazioni è certamente preferibile. In questo caso, la soluzione esiste ed è anche
particolarmente semplice. Una volta finito il lavoro, potete cliccare col mouse sulla linea a destra del
Notebook che definisce la formula, ed a questo punto selezionare la voce di menù Cell->Convert
To->Traditional Form (o, più velocemente, premendo Shift+CTRL+T). In questo modo, la formula
sarà convertita in una scrittura standard, di certo più comprensibile a chi non usa Mathematica. Però,
in questo caso, la formula non sarà più univocamente definita, per esempio per il problema delle
parentesi di cui vi ho accennato. In questo caso Mathematica lo segnala evidenziando in modo
particolare la cella. Se volete di nuovo convertire la formula in formato di Mathematica, potete
andarci sempre dal menù Cell->Convert To->Input Form, ma in questo caso Mathematica userà
metodi euristici per convertitre di nuovo il risultato, con una piccola probabilità di errore:
Per esempio, vediamo come si scrive una formula per l'integrale:
In[177]:= Integrate@Hx + 1L^Sin@xD, 8x, 0, 3 Pi<D
— Integrate::ilim : Invalid integration variable or limitHsL in 80.9999999999999999999999999999990000000000, 0, 3 π<. More…
Out[177]= ‡0
3 π
1.791876223827922019268189315426164890819
0.9999999999999999999999999999990000000000
Sebbene sia una formula semplice, non è certo questa la forma di più facile comprensione per il
profano, e si vorrà certamente avere una scrittura più da libro: in questo caso, basta convertire la
formula con il metodo che vi ho appena spiegato, per ottenere:
‡0
3 p
Hx + 1LsinHxL ‚ x
E di certo, in questo modo è di più facile comprensione per tutti (notate come la cella è segnata
diversamente). Dato che, però, occorrerà a volte ritornare sul lavoro per ulteriori elaborazioni, io
personalmente, quando devo stampare qualcosa, salvo il file con un altro nome e uso la copia per
convertire la scrittura delle formule. Se poi dovessi riutilizzare il file, vado a modificare di nuovo
Daniele Lupo Appunti di Mathematica
49Printed by Mathematica for Students
l'originale, in modo che non ci siano problemi di mancato riconoscimento di formule.
Vedremo, comunque, melgio questo aspetto nel capitolo riguardante il front-end e la formattazione.
Daniele Lupo Appunti di Mathematica
50Printed by Mathematica for Students
Calcolo Simbolico 1ü Introduzione
Ahhh!!! Ci voleva proprio questo bel bagnetto!!! Magari riuscirò pure a far sparire l'effetto
mozzarella della mia pelle, prima che finiscano le lezioni!!!
...Ehm....
...Dicevamo... Come vi avevo già accennato, uno degli aspetti più importanti di Mathematica è il
fatto che permette di eseguire con la stessa straordinaria facilità e velocità sia calcoli numerici che,
sopratutto, calcoli simbolici. Possiamo scrivere qualcosa del tipo
In[1]:= 3 + 5 ∗H3 + 7L
Out[1]= 53
ma possiamo anche, se vogliamo, eseguire calcoli che includano elementi simbolici
In[2]:= x + 5 x + 2
Out[2]= 2 + 6 x
Mathematica riordina automaticamente gli elementi:
In[3]:= x^2 + 2 + 4 x
Out[3]= 2 + 4 x + x2
E applica, automaticamente, alcune semplici semplificazioni:
In[4]:= Sqrt@1 + xD^4
Out[4]= H1 + xL2
Come potete vedere, la radice quadrata è magicamente scomparsa
A volte, facciamo delle elaborazioni algebriche, ottenendo una particolare espressione, e poi ci
piacerebbe sapere il valore che assumerebbe quell'espressione se andiamo a sostituire dei valori
determinati alle varie incognite. Possiamo fare questo tramite l'operatore di sostituzione:
Daniele Lupo Appunti di Mathematica
51Printed by Mathematica for Students
In[5]:= 3 + x + 24 x^4 + Sqrt@xD ê. x → 4
Out[5]= 6153
L'operatore di sostituzione è dato dalla combinazione /. dopo l'espressione, e dalle regole di
sostituzione: la regola di sostituzione è data scrivendo l'incognita da sostituire, dopo -> ed infine il
valore che vogliamo al posto dell'incognita. Ovviamente, dato che conoscete le liste, a questo punto
(vero?), potete intuire che possiamo andare a sostituire più incognite in una sola volta usando una
lista per le regole di sostituzione, come in quest'esempio:
In[6]:= x^2 + y^2 − 3 x y ê. 8x → 1, y → 5<
Out[6]= 11
Se vogliamo che la sostituzione sia invece permanente, conviene andare a definire una variabile che
abbia il nome dell'incognita:
In[7]:= x = 1; y = 5;
Notate, fra l'altro, un altra caratteristica di Mathematica: possiamo eseguire più comandi in una volta
sola, concatenandoli tramite il punto e virgola, e premendo solo alla fine Shift+Invio. Una volta
eseguita questa operazione, ogni volta che il programma incontrerà la variabile, andrà sempre a
sostituire il valore corrispondente:
In[8]:= x^2 + y^2 − 3 x y
Out[8]= 11
Per cancellare il valore di una variabile, e renderla ancora incognita, possiamo usare l'assegnamento
del punto oppure il comando Clear:
In[9]:= x =.
In[10]:= Clear@yD
Andando a ricalcolarci l'espressione, vediamo come alle due incognite non è associato più nessun
valore:
In[11]:= x^2 + y^2 − 3 x y
Out[11]= x2 − 3 x y + y2
Daniele Lupo Appunti di Mathematica
52Printed by Mathematica for Students
Inoltre, dato che possiamo associare alle variabili sia espressioni numeriche che simboliche, lo stesso
possiamo fare per le sostituzioni, che quindi non sono limitate solo a valori numerici:
In[12]:= x^2 + 3 y + z ê. z → 4 y
Out[12]= x2 + 7 y
ü Manipolazioni Algebriche
Una volta ottenute e scritte le nostre espressioni, può risultare molto utile effettuare delle determinate
manipolazioni per scriverle nella forma che più ci aggrada. Andiamo, per esempio, a definire la
seguente equazione algebrica:
In[13]:= eq = H1 + xL^4
Out[13]= H1 + xL4
Ci sono due funzioni basilari, che ci permettono di espandere e contrarre i termini di un'espressione
algebrica:
Expand[expr] moltiplica tuti i prodotti e potenze, dando il risultatocome somma di prodotti
Factor[expr] scrive expr come prodotto di fattori minimali
Se volessimo utilizzare le funzioni per l'espressione che abbiamo appena scritto, possiamo avere:
In[14]:= Expand@eqD
Out[14]= 1 + 4 x + 6 x2 + 4 x3 + x4
Mentre, Factor lo riporta nella forma originale
In[15]:= Factor@%D
Out[15]= H1 + xL4
Anche se in genere non abbiamo problemi, bisogna prestare comunque, un attimino di attenzione
nell'usare queste due funzioni. Se, per esempio, volessimo usare Expand per l'espressione
H1 + xL100000, possiamo subito notare che avremo sullo schermo (sempre che la memoria del
computer non ci tradisca prima), qualcosa che non avremmo mai voluto avere. Ma questo capita nel
99,9999% dei casi se effettuiamo qualche malaugurato errore di battitura. In questi tre anni che
conosco Mathematica non mi è mai capitato di dover scrivere apposta formule così lunghe...
Se, invece, ci preme poter scrivere la forma più semplice di un espressione, non sempre usare i due
Daniele Lupo Appunti di Mathematica
53Printed by Mathematica for Students
comandi appena citati è utile. Infatti non è sempre verificabile subito se la forma più semplice è data
dall'una oppure dall'altra formula, e possiamo solo provare, come in questo caso:
In[16]:= eq = x^10 − 1
Out[16]= −1 + x10
In[17]:= Expand@eqD
Out[17]= −1 + x10
In[18]:= Factor@eqD
Out[18]= H−1 + xL H1 + xL H1 − x + x2 − x3 + x4L H1 + x + x2 + x3 + x4L
In questo caso la forma più semplice, al contrario del caso precedente, si ottiene con il comando
Factor. Expand lavora in maniera diversa quando abbiamo a che fare con delle funzioni razionali
fratte:
In[19]:= expr = HHx − 2L Hx + 5L Hx − 4LLêHHx − 1L Hx − 1L Hx − 8L Hx + 1LL
Out[19]=H−4 + xL H−2 + xL H5 + xLH−8 + xL H−1 + xL2 H1 + xL
In[20]:= Expand@exprD
Out[20]=40
H−8 + xL H−1 + xL2 H1 + xL −22 x
H−8 + xL H−1 + xL2 H1 + xL −
x2
H−8 + xL H−1 + xL2 H1 + xL +x3
H−8 + xL H−1 + xL2 H1 + xL
Possiamo vedere che il denominatore non viene intaccato dal comando, ed anche che abbiamo in
questo caso separato l'espressione in più espressioni razionali fratte. Questo a volte non è
conveniente. Per espandere questo tipo di espressioni ci sono altri comandi più specifici:
ExpandNumerator[expr] espande solamente il numeratore
ExpandDenominator[expr] espande solamente il denominatore
Expand[expr] espande il numeratore, distribuendo il denominatoresu ogni termine
ExpandAll[expr] espande sia il numeratore che il denominatore
Come possiamo vedere, quindi, se vogliamo espandere per esempio il numeratore, ma non vogliamo
che sia espanso compretamente come prima, dobbiamo usare il comando appropriato:
Daniele Lupo Appunti di Mathematica
54Printed by Mathematica for Students
In[21]:= ExpandNumerator@exprD
Out[21]=40 − 22 x − x2 + x3
H−8 + xL H−1 + xL2 H1 + xL
In questa maniera, espandiamo il numeratore, ma la scrittura è più compatta. Possiamo anche
espandere il denominatore, oppure entrambe le cose, tramite gli altri comandi:
In[22]:= ExpandDenominator@exprD
Out[22]=H−4 + xL H−2 + xL H5 + xL−8 + 9 x + 7 x2 − 9 x3 + x4
In[23]:= ExpandAll@exprD
Out[23]=40
−8 + 9 x + 7 x2 − 9 x3 + x4 −22 x
−8 + 9 x + 7 x2 − 9 x3 + x4 −
x2
−8 + 9 x + 7 x2 − 9 x3 + x4 +x3
−8 + 9 x + 7 x2 − 9 x3 + x4
Se vogliamo una riscrittura più compatta, possiamo combinare per esempio due dei comandi
precedenti:
In[24]:= ExpandNumerator@ExpandDenominator@exprDD
Out[24]=40 − 22 x − x2 + x3
−8 + 9 x + 7 x2 − 9 x3 + x4
In questa maniera abbiamo espanso tutto, ma avitando di scrivere un'espressione fratta per ogni
termine del numeratore...
ExpandAll, pur espandendo tutto quanto, ha un'opzione molto interessante:
ExpandAll[expr, patt], etc. espande quelle parti dell'espressione che contengono patt
Supponiamo di avere un'espressione con più incognite:
In[25]:= expr = Hx − yL^4 + Hx − 3L^2
Out[25]= H−3 + xL2 + Hx − yL4
Proviamo, adesso, ad espanderlo completamente:
In[26]:= ExpandAll@exprD
Out[26]= 9 − 6 x + x2 + x4 − 4 x3 y + 6 x2 y2 − 4 x y3 + y4
Daniele Lupo Appunti di Mathematica
55Printed by Mathematica for Students
Quello che ci aspettavamo, in fondo; supponiamo, adesso, di voler espandere la parte
dell'espressione che contiene la y: in questo caso basta specificarla nel comando ExpandAll:
In[27]:= ExpandAll@expr, yD
Out[27]= H−3 + xL2 + x4 − 4 x3 y + 6 x2 y2 − 4 x y3 + y4
In questa maniera abbiamo lasciato inalterata la parte che non contiene la y; questo è un metodo
abbastanza potente per poter espandere solo le porzioni che ci interessano.
Tuttavia Mathematica ci viene incontro con due comandi molto potenti per la semplificazione delle
espressioni:
Simplify[expr] cerca la forma più semplice utilizzando un setdi semplificazioni algebriche standard
FullSimplify[expr] cerca la forma più semplice applicando un
set di regole di semplificazione molto più ampio
Questi due comandi permettono di trovare la forma più compatta di scrivere un'equazione:
In[28]:= Simplify@x^2 + 4 x + 4D
Out[28]= H2 + xL2
In[29]:= Simplify@x^10 − 1D
Out[29]= −1 + x10
Si può notare che nel primo caso la forma più compatta è quella ottenuta con Factor, mentre nel
secondo caso quella ottenuta con Expand, e che in entrambi i casi Simplify restituisce il risultato
corretto. Tuttavia questo comando va ben oltre le semplici equazioni algebriche; permette infatti di
semplificare una vasta gamma di espressioni.
In[30]:= SimplifyA 1
4 H−1 + xL−
1
4 H1 + xL−
1
2 H1 + x2LE
Out[30]=1
−1 + x4
Quando, tuttavia, le espressioni sono complicate e usano funzioni avanzate, Simplify potrebbe non
farcela da solo, e qua entra in gioco il comando FullSimplify, che utilizza un numero di regole molto
più vasto, includendo anche equazioni trascendentali e semplificazioni di funzioni avanzate, come la
funzione Gamma:
Daniele Lupo Appunti di Mathematica
56Printed by Mathematica for Students
In[31]:= eq = Gamma@xD Gamma@1 − xD
Out[31]= Gamma@1 − xD Gamma@xD
In[32]:= Simplify@eqD
Out[32]= Gamma@1 − xD Gamma@xD
In[33]:= FullSimplify@eqD
Out[33]= π Csc@π xD
A questo punto, si sarebbe tentati di utilizzare sempre il secondo comando, ma io lo sconsiglio: è
vero che è più potente, ma è anche vero che lo è a prezzo di un costo computazionale
esponenzialmente più elevato; questo potrebbe fare la differenza per espressioni grandi, per cui
potrebbe impiegare un tempo esagerato per portare a termine l'operazione. Usatelo, quindi, solo se
ne vale la pena, e se Simplify da solo non vi soddisfa. Anche se, per i calcoli che siamo soliti fare,
non si perde in fondo tutto questo tempo...
Inoltre, ci sono anche altre funzioni che permettono di manipolare ulteriormente le espressioni, in
modo da poter, magari, visualizzarle nel modo che preferiamo:
Expand[expr] moltiplica tutti i prodotti e potenze
ExpandAll[expr] applica Expand ovunque
Factor[expr] scrive sottoforma di prodotto di fattori
Together[expr] scrive tutti i termini con un comun denominatore
Apart[expr] separa l'espressione in termini con semplici denominatri
Cancel[expr]
Collect[expr, x]FactorTerms[expr, x]
cancella i fattori comuni fra numeratore e denominatore Scrive l'equazione raggruppando le potenze di xScompone in due fattori, dove in uno non compare iltermine x
Supponiamo, di avere per esempio
In[34]:= espr = Hx − 1L^2 H2 + xLêHH1 + xL Hx − 3L^2L
Out[34]=H−1 + xL2 H2 + xLH−3 + xL2 H1 + xL
In[35]:= Expand@esprD
Out[35]=2
H−3 + xL2 H1 + xL −3 x
H−3 + xL2 H1 + xL +x3
H−3 + xL2 H1 + xL
Daniele Lupo Appunti di Mathematica
57Printed by Mathematica for Students
Come possiamo vedere, Expand espande solamente i termini presenti al numeratore; se vogliamo
fare la stessa cosa anche per il denominatore, dobbiamo utilizzare la funzione ExpandAll:
In[36]:= ExpandAll@esprD
Out[36]=2
9 + 3 x − 5 x2 + x3 −3 x
9 + 3 x − 5 x2 + x3 +x3
9 + 3 x − 5 x2 + x3
Riscriviamo tutto sotto comun denominatore: come facciamo? Con Together, naturalmente, dato che
fa proprio questo:
In[37]:= Together@%D
Out[37]=2 − 3 x + x3
H−3 + xL2 H1 + xL
Aggiungiamo Factor, e riotteniamo quello che avevamo in partenza:
In[38]:= Factor@%D
Out[38]=H−1 + xL2 H2 + xLH−3 + xL2 H1 + xL
Adesso, supponiamo di avere un'espressione in due variabili:
In[39]:= espr2 = H1 + xL^2 + Hx − yL^3
Out[39]= H1 + xL2 + Hx − yL3
Vediamo di raggruppare tuti i termini in x:
In[40]:= Collect@espr2, xD
Out[40]= 1 + x3 + x2 H1 − 3 yL − y3 + x H2 + 3 y2L
Come si può vedere, abbiamo ottenuto termini dove xn moltiplica vari termini, più un eventuale
termine noto... un'espressione in x, insomma... Se, invece, vogliamo ottenere la stessa espressione,
ma evidenziando l'incognita y:
In[41]:= Collect@espr2, yD
Out[41]= x3 + H1 + xL2 − 3 x2 y + 3 x y2 − y3
Il comando Apart permette di scrivere un rapporto di polinomi come somma di frazioni semplici:
Daniele Lupo Appunti di Mathematica
58Printed by Mathematica for Students
In[42]:= ApartA x^2 − 5 x + 3
Hx − 5L Hx − 3L Hx + 4LE
Out[42]=1
6 H−5 + xL +3
14 H−3 + xL +13
21 H4 + xL
Il comando Cancel fa quello che si farebbe utilizzando una frazione numerica; riduce la frazione ai
minimi termini, elidendo tutti i fattor comuni:
In[43]:= Expand@Hx + 1L Hx + 3LDêExpand@Hx + 1L Hx + 5L Hx − 6LD
Out[43]=3 + 4 x + x2
−30 − 31 x + x3
A questo punto, si potrebbe pensare che è ridotto ai minimi termini, ma non è vero. Mathematica in
questo caso ha prima creato le espressioni, e poi ha fatto il rapporto. In questo caso, se non lo
comunichiamo con il comando Cancel, Mathematica non controlla automaticamente se ci sono dei
fattori comuni, cosa che invece sappiamo per costruzione: per poterli cancellare, basta utilizzare il
comando...
In[44]:= Cancel@%D
Out[44]=3 + x
−30 − x + x2
Vediamo come, prima di tutto abbiamo eliminato il fattor comune, e come il risultato sia sempre dato
sotto forma non di prodotto di binomi, ma come polinomi completi. Se avessimo creato l'espressione
razionale fratta senza Expand, Mathematica non avrebbe espanso i termini, cancellando
automaticamente (perchè sono presenti in maniera esplicita) i fattori comuni:
In[45]:= Hx + 1L Hx + 3LêHHx + 1L Hx + 5L Hx − 6LL
Out[45]=3 + x
H−6 + xL H5 + xL
In questa maniera, però, non otteniamo automaticamente il denominatore in forma polinomiale,
come nel caso precedente.
Il comando seguente che andiamo ad esaminare è Collect: esso permette di raccogliere i termini di
un'espressione, e di scriverla sotto forma di prodotto di potenze di una determinata variabile.
Supponiamo di avere il seguente polinomio:
Daniele Lupo Appunti di Mathematica
59Printed by Mathematica for Students
In[46]:= xyz = Expand@Hx + yL Hx + 3 zL Hz − 5 yL Hz − 2 xLD
Out[46]= 10 x3 y + 10 x2 y2 − 2 x3 z + 23 x2 y z +
25 x y2 z − 5 x2 z2 − 20 x y z2 − 15 y2 z2 + 3 x z3 + 3 y z3
A questo punto, possiamo decidere se scrivere questa espressione come polinomio in x, y, oppure z,
specificando la variabile con cui vogliamo raccogliere i termini. Per esempio, se li volessimo
raccogliere in x:
In[47]:= Collect@xyz, xD
Out[47]= x3 H10 y − 2 zL − 15 y2 z2 + 3 y z3 +
x2 H10 y2 + 23 y z − 5 z2L + x H25 y2 z − 20 y z2 + 3 z3L
Si può notare che in questo caso abbiamo raccolto, appunto, i termini in x, con i rispettivi
coefficienti. Analogamente possiamo fare per gli altri due casi:
In[48]:= Collect@xyz, yD
Out[48]= −2 x3 z − 5 x2 z2 + 3 x z3 +
y2 H10 x2 + 25 x z − 15 z2L + y H10 x3 + 23 x2 z − 20 x z2 + 3 z3L
In[49]:= Collect@xyz, zD
Out[49]= 10 x3 y + 10 x2 y2 + H−2 x3 + 23 x2 y + 25 x y2L z +
H−5 x2 − 20 x y − 15 y2L z2 + H3 x + 3 yL z3
Naturalmente la maniera più conveniente dipende dal nostro problema, e da cosa dobbiamo mettere
in evidenza...
Possiamo considerare l'ultimo comando del gruppo, FactorTerms, come il duale di quello che
abbiamo appena visto; infatti, il suo scopo consiste nel dividere l'espressione come prodotto di altre
due espressioni, in cui però in una non compare l'ingognita specificata:
In[50]:= expr = x^2 y^2 + 3 x y − x z^3
Out[50]= 3 x y + x2 y2 − x z3
Possiamo adesso dividere l'espressione in due termini, in cui in uno non compare, per esempio, la z:
In[51]:= FactorTerms@expr, zD
Out[51]= −x H−3 y − x y2 + z3L
Analogamente, se volessimo che in uno dei due termini non compaia la x:
Daniele Lupo Appunti di Mathematica
60Printed by Mathematica for Students
In[52]:= FactorTerms@expr, xD
Out[52]= 3 x y + x2 y2 − x z3
In questo caso, evidentemente, la cosa non si può fare... Non si può pretendere l'impossibile!!! Tanto
per dovere di cronaca, vediamo se si può fare nell'ultima variabile rimasta:
In[53]:= FactorTerms@expr, yD
Out[53]= x H3 y + x y2 − z3L
Effettivamente, c'è tutto un insieme di comandi Factor che permettono di fattorizzare il polinomio in
maniera diversa a seconda dei casi:
Factor[poly] fattorizza un polinomio
FactorSquareFree[poly] estrapola i fattori quadrati dal polinomio
FactorTerms[poly, x] fattorizza i termini che non contengono x
FactorList[poly], FactorSquareFreeList[poly], FactorTermsList[poly]
restituiscono il risultato come lista di fattori, inveceche come prodotto
Costruiamoci il nostro polinomio:
In[54]:= t = Expand@3 Hx − 4L Hx^2 − x + 2L Hx + 3L^4D
Out[54]= −1944 − 1134 x − 567 x2 − 693 x3 − 294 x4 + 21 x6 + 3 x7
Factor e FactorTerms abbiamo giàò visto come funzionano:
In[55]:= Factor@tD
Out[55]= 3 H−4 + xL H3 + xL4 H2 − x + x2L
In[56]:= FactorTerms@t, xD
Out[56]= 3 H−648 − 378 x − 189 x2 − 231 x3 − 98 x4 + 7 x6 + x7L
Quello che non avevamo visto è FactorSquareFree:
In[57]:= FactorSquareFree@tD
Out[57]= 3 H3 + xL4 H−8 + 6 x − 5 x2 + x3L
Daniele Lupo Appunti di Mathematica
61Printed by Mathematica for Students
Come abbiamo visto, non è stato fattorizzato completamente: sono stati estratti soltanto il fattore
costante, e il fattore che è un quadrato (possiamo considerare 4 come quadrato del quadrato...),
moltiplicando questi per il restante polinomio.
Gli altri comandi, invece, servono nel caso che, per qualche motivo, abbiamo bisogno della lista dei
fattori, invece che del loro prodotto. Questo può essere utile quando dobbiamo estrarre particolari
fattori per andare ad utilizzarli da qualche altra parte:
In[58]:= FactorList@tD
Out[58]= 883, 1<, 8−4 + x, 1<, 83 + x, 4<, 82 − x + x2, 1<<
In[59]:= FactorTermsList@t, xD
Out[59]= 83, 1, −648 − 378 x − 189 x2 − 231 x3 − 98 x4 + 7 x6 + x7<
In[60]:= FactorSquareFreeList@tD
Out[60]= 883, 1<, 83 + x, 4<, 8−8 + 6 x − 5 x2 + x3, 1<<
Inoltre, questi comandi hanno anche delle opzioni che permettono di manipolare il risultato che
otteniamo. Le opzioni sono, per i comandi di Mathematica, degli argomenti, che si scrivono nella
seguente forma:
f@argomenti, opzione1 → val1, opzione2 → opz2 ...D
Permettono di gestire meglio il comportamento di varie funzioni. Comunque lo vedremo meglio più
avanti. Qua vediamo soltanto come funzionano per Factor. Questo comando ha quattro opzioni:
Extension, GaussianIntegers, Modulus, Trig. Il primo serve per poter utilizzare particolari numeri
nella scomposizione, che di default non verrebbero considerati. Il secondo permette, in particolare,
di utilizzare nella scomposizione gli interi di Gauss. La terza opzione permette di effettuare la
scomposizione con un modulo specificato, mentre la quarta permette di scomporre tramite
coefficienti trigonometrici. creiamoci un altro polinomio per l'occasione:
In[61]:= tt = Expand@5 H4 x^2 + 1L Hx^3 − 1L Hx^2 − 2LD
Out[61]= 10 + 35 x2 − 10 x3 − 20 x4 − 35 x5 + 20 x7
In[62]:= Factor@ttD
Out[62]= 5 H−1 + xL H−2 + x2L H1 + x + x2L H1 + 4 x2L
Daniele Lupo Appunti di Mathematica
62Printed by Mathematica for Students
Come vedete, tutto rientra nella norma. Tuttavia proviamo ad utilizzare l'opzione GaussianIntegers,
impostandola su True, mentre di default è False:
In[63]:= Factor@tt, GaussianIntegers → TrueD
Out[63]= 5 H−1 + xL H− + 2 xL H + 2 xL H−2 + x2L H1 + x + x2L
Come possiamo vedere, abbiamo ottenuto una ulteriore scomposizione del fattore H1 + 4 x2L,facendolo diventare H2 x - ÂL H2 x + ÂL, scomponendo parte reale e parte immaginaria, cosa che di
default Factor non fa.
Con Modulus, invece, possiamo specificare il modulo della scomposizione:
In[64]:= Factor@tt, Modulus → 3D
Out[64]= 2 H2 + xL3 H1 + x2L2
Il risultato è scomposto tenendo conto del modulo dei polinomi.
Extension, dal canto suo, permette di utilizzare altri valori per la scomposizione, introducendo dei
numeri voluti da noi:
In[65]:= Factor@tt, Extension → Sqrt@2DD
Out[65]= −5 Hè!!!2 − xL H−1 + xL Hè!!!2 + xL H1 + x + x2L H1 + 4 x2L
Come abbiamo potuto vedere, dicendo a Factor che poteva utilizzare anche è!!!2 nelle sue operazioni,
ha correttamente scomposto in questo modo anche il fattore Hx2 - 2L.
Inoltre, potete anche dire a Mathematica di provare da solo ad ampliare il numero di valori possibili
di fattorizzazione, aggiungendo altri tipi di numeri oltre a quello interi, ponento Extension->-
Automatic.
Invece, se impostiamo Trig su True, possiamo trattare anche coefficienti trigonometrici:
In[66]:= tr = x^4 − Sin@π ê7D x^2 + 3
Out[66]= 3 + x4 − x2 SinA π7E
In[67]:= Factor@trD
Out[67]= 3 + x4 − x2 SinA π7E
Daniele Lupo Appunti di Mathematica
63Printed by Mathematica for Students
In[68]:= Factor@tr, Trig → TrueD
Out[68]= −12H−1L6ê7 H6 H−1L1ê7 − x2 + H−1L11ê14 x2 + 2 H−1L1ê7 x4L
ü Manipolazioni avanzate
A volte è necessario creare delle manipolaizoni più avanzate di quelle che abbiamo visto prima, ed
effettuare operazioni particolari, come trovare il massimo comun divisore fra due polinomi, per
esempio. Alcuni comandi avanzati sono mostrati di seguito:
PolynomialQuotient[ poly1,poly2, x]
trova il quoziente ottenuto dividendo poly1 nellavariabile x con poly2, trascurando l'eventuale resto
PolynomialRemainder[ poly1,poly2, x]
trova il resto della divisione fra il polinomio poly1 in xed il polinomio poly2
PolynomialGCD[poly1, poly2] trova il massimo comun divisore fra i due polinomi
PolynomialLCM[poly1, poly2] trova il minimo comune multiplo fra i due polinomi
PolynomialMod[poly, m] riduce il polinomio poly utilizzando il modulo m
Resultant[poly1, poly2, x] trova la risultante fra i die polinomi
S u b r e s u l t a n t s [poly1 ,poly2, x]
trova i principali valori delle sottorisultanti fra idue polinomi
G r o e b n e r B a s i s [ {poly1 ,poly2, … }, {x1, x2, … }]
trova la base di Gröbner per i polinomi polyi
G r o e b n e r B a s i s [ {poly1 ,poly2, … }, {x1, x2, … }, {y1, y2,
trova la base di Gröbner ottenuta eliminando le yi
PolynomialReduce[p o l y,{poly1, poly2, … }, {x1, x2, … }]
trova la rappresentazione minima di poly nei termini polyi
Come potete vedere, questi comandi permettono di risolvere parecchi problemi che hanno a che fare
con polinomi. Danno il meglio di sè, però, quando i polinomi sono ordinari, cioè con esponenti interi
e con numeri razionali come coefficienti. Niente vieta però di vedere come va a finire utilizzandoli
con altri tipi, naturalmente.
Il primo comando, Polynomial quotient, restituisce il risultato della divisione fra due polinomi.
Infatti, come ben sapete, possiamo scrivere il rapporto di due polinomi in questa maniera:
pHxLÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄqHxL
aHxL +bHxLÄÄÄÄÄÄÄÄÄÄÄÄÄÄqHxL
Il comando restrituisce proprio aHxL che sarebbe il risultato della divisione, mentre bHxL è il risultato
restituito da PolynomialRemainder, che restituisce il resto. Vediamo di definire i due polinomi:
In[69]:= p = x^7 − 5 x^2 + 4 x − 10; q = −2 x^5 − x^4 + 7 x^3 − 2 x^2 + 9 x − 4;
Daniele Lupo Appunti di Mathematica
64Printed by Mathematica for Students
Vediamo di vedere il quoziente di questo rapporto:
In[70]:= a = PolynomialQuotient@p, q, xD
Out[70]= −158
+x4−
x2
2
Vediamo, adesso, di trovare bHxL, cioè il resto:
In[71]:= b = PolynomialRemainder@p, q, xD
Out[71]= −352
+175 x
8− 13 x2 +
145 x3
8−
37 x4
8
Come potete vedere, il polinomio ha un grado inferiore a quello di q, cosa che fra l'altro era scontata,
dato che nel resto l'ordine del muneratore è per forza di cose inferiore a quello del denominatore:
vediamo adesso se effettivamente quoziente e resto sono quelli che abbiamo trovato:
In[72]:= pêq
Out[72]=−10 + 4 x − 5 x2 + x7
−4 + 9 x − 2 x2 + 7 x3 − x4 − 2 x5
Applichiamo la definizione:
In[73]:= a + bêq
Out[73]= −158
+x4−
x2
2+− 35
2 + 175 x8 − 13 x2 + 145 x3
8 − 37 x4
8−4 + 9 x − 2 x2 + 7 x3 − x4 − 2 x5
In[74]:= Simplify@%D
Out[74]=10 − 4 x + 5 x2 − x7
4 − 9 x + 2 x2 − 7 x3 + x4 + 2 x5
Come avete potuto vedere, i due rapporti sono uguali, segno che abbiamo trovato realmente il
risultato della divisione con quei due comandi. D'altronde, avevate qualche dubbio in proposito???
Spero proprio di no, altrimenti buttate questi appunti e datevi all'ippica!!!
PolynomialGCD, invece, restituisce il massimo comun divisore, come potete facilmente intuire dal
nome del comando:
In[75]:= PolynomialGCD@p, qD
Out[75]= 1
Daniele Lupo Appunti di Mathematica
65Printed by Mathematica for Students
In questo caso, possiamo dire che i polinomi sono primi fra di loro... non sono stato fortunatissimo
nella scelta, per l'esempio. Pazienza, vorrà dire che mi farò altri due polinomi ad hoc:
In[76]:= pp = 2 − x − 3 x2 + x3 + x4; qq = 6 − x − 4 x2 − x3;
In[77]:= PolynomialGCD@pp, qqD
Out[77]= −2 + x + x2
Questa volta l'ho azzeccata... Possiamo vedere come, in questo caso, non ci sia bisogno di specificare
una variabile per la creazione del massimo comun divisore.
PolynoialLCM restituisce il minimo comune multiplo (che in italiano è MCM, ma in inglese è Least
Common Multiple) fra due polinomi:
In[78]:= PolynomialLCM@pp, qqD
Out[78]= H−1 + x2L H6 − x − 4 x2 − x3L
Niente di particolarmente complicato. Penso che capiate tutti come usare questo comando.
PolynomialMod è un comando che praticamente non ho usato mai, perchè non mi è mai servito. E'
l'equivalente di Mod per i numeri, e permette la riduzione in modulo M di un polinomio, sia esso un
numero oppure un altro polinomio (in quest'ultimo caso, però, le cose si complicano).
In[79]:= pol = 4 x^3 + 7 x − 2;
In[80]:= PolynomialMod@pol, 3D
Out[80]= 1 + x + x3
In questo caso, abbiamo applicato semplicemente Mod ai coefficienti numerici, mediante un fattore
anch'esso intero. Naturalmente possiamo fare anche cose più complicate...
In[81]:= PolynomialMod@x^5 − x^4 + 5 y x^2 − x, x^2D
Out[81]= −x
Come possiamo vedere, abbiamo ottenuto una riduzione più elaborata, di cui fra l'altro non conosco
molto bene la teoria, perchè non ne ho mai avuto niente a che fare con questo tipo di operazioni. Per
chi ci bazzica, probabilmente ci ha trovato qualcosa con cui divertirsi parecchio.
Un altro comando che non ho mai utilizzato, ma che qualcuno di voi può trovare interessante, è
Daniele Lupo Appunti di Mathematica
66Printed by Mathematica for Students
Resultant, che restituisce la risultante fra due polinomi, che è dato dal prodotti dei termini ai - b j che
sono le radici dei polinomi. Riprendiamo quelle che avevamo prima:
In[82]:= p
Out[82]= −10 + 4 x − 5 x2 + x7
In[83]:= q
Out[83]= −4 + 9 x − 2 x2 + 7 x3 − x4 − 2 x5
In[84]:= Resultant@p, q, xD
Out[84]= 962920402
Naturalmente questo funziona anche se abbiamo dei coefficienti letterali:
In[85]:= Resultant@p, x^3 + r x^2 − l x + 1, xD êê Simplify
Out[85]= 500 + 4 l6 − 10 l7 + 575 r + 495 r2 − 462 r3 + 680 r4 − 15 r5 − 84 r6 + 100 r7 +
l5 H−5 + 70 rL + 2 l4 H−5 + 113 rL + l3 H258 + 625 r − 500 r2 + 250 r3L +5 l2 H167 − 153 r − 14 r2 + 260 r3 − 48 r4 + 10 r5L +l H475 − 610 r + 1895 r2 − 245 r3 − 404 r4 + 680 r5 − 40 r6L
come possiamo vedere, il concetto è identico anche se, in forma letterale, le cose possono cominciare
a diventare complicate. Le sottorisultanti si posso avere tramite Subresultants, che contiene gli stessi
argomenti:
In[86]:= Subresultants@p, q, xD
Out[86]= 8962920402, −324201, 133564, 3767, −37, 4<
Se il coefficiente del termine di grado più elevato di entrambi i polinomi è pari ad uno, allora il
numero delle radici in comune fra i due polinomi è pari al numeri dei primi elementi della lista pari a
0. Supponiamo di avere questi polinomi:
In[87]:= p = −3 x + 2 x2 + x3 + 6 z − 4 x z − 2 x2 z;q = 48 − 2 x − 57 x2 + x3 + 9 x4 + x5;
A questo punto, possiamo calcolarci le sottorisultanti dei polinomi:
In[89]:= Subresultants@p, q, xD
Out[89]= 80, 0, −16 − 20 z + 28 z2 + 8 z3, 1<
Daniele Lupo Appunti di Mathematica
67Printed by Mathematica for Students
Come possiamo vedere, abbiamo due elementi nulli, il che ci suggerisce che i due polinomi hanno
due radici in comune. Infatti possiamo vederlo direttamente:
In[90]:= Factor@pD
Out[90]= H−1 + xL H3 + xL Hx − 2 zL
In[91]:= Factor@qD
Out[91]= H−2 + xL H−1 + xL H1 + xL H3 + xL H8 + xL
Come possiamo vedere, le radici che hanno in comune sono 1 e -3, che sono soluzione di entrambe:
In[92]:= 8p, q< ê. 88x → 1<, 8x → −3<<
Out[92]= 880, 0<, 80, 0<<
Come possiamo vedere, sostituendo ai due polinomi le radici, in entrambi i casi sono nulli, come
d'altronde era ovvio... La matematica non è un'opinione.
La base di Gröbner ha assunto particolare rilevanza specialmente negli ultimi anni, avendo avuto
applicazione in molti campo. In parole povere, trovando la base di Gröbner di un insieme di
polinomi, ne ricaviamo altri polinomi, che hanno particolari caratteristiche dipendenti dai polinomi
presi in esame. Per esempio, hanno lo stesso numero di radici in comune del set originale, assieme
ad altre proprietà che vi conviene andarvi a studiare; qua non si fanno giochini e cosette varie, e
Mathematica è fatto per chi sa quello che fa, altrimenti che ce li spendete a fare i soldi per
comprarlo, dico io?!?!?!?
In[93]:= GroebnerBasis@8x + y + 3 z, x^2 − y<, 8x, y<D
Out[93]= 8−y + y2 + 6 y z + 9 z2, x + y + 3 z<
Come possiamo vedere, abbiamo ottenuto la stessa soluzione di quella del libro dove è riportato
questo esempio (quale libro?!?!? Andate ed esplorate, cari miei adepti....).
Vediamo questo altro esempio:
In[94]:= p1 = x^3 − y^2 x^2 + y ;p2 = 2 x^3 − 4 y^3;p3 = −4 x3 + 2 y − 2 x2 y2 + 12 y3;
Andiamo a trovarci la base di questi tre:
Daniele Lupo Appunti di Mathematica
68Printed by Mathematica for Students
In[97]:= GroebnerBasis@8p1, p2, p3<, 8x<D êê FullSimplify
Out[97]= 8y H−1 − 6 y2 − 12 y4 − 8 y6 + 4 y9L,y Hx + 2 y H2 + y2 H8 + y H−1 + 2 y H4 + y − 2 y3LLLLL, x3 − 2 y3<
Possiamo anche trovare la base ottenuta eliminando le variabili che non sono di nostro interesse,
mettendole come terzo argomento della funzione:
In[98]:= GroebnerBasis@8p1, p2, p3<, 8x<, 8y<D
Out[98]= 8−2 x3 − 6 x8 − 4 x9 + x12<
L'ultimo comando di questo gruppo che ci rimane da vedere è PolynomialReduce, che restituisce una
lista, il cui primo elemento è dato da una lista di una serie di polinomi, ed il secondo elemento da un
polinomio minimo, che hanno una particolarità: vedendo l'esempio si chiarisce meglio:
In[99]:= p
Out[99]= −3 x + 2 x2 + x3 + 6 z − 4 x z − 2 x2 z
In[100]:= PolynomialReduce@p, 8x − 4, x^2 + 5<, 8x, z<D
Out[100]= 8821 + 6 x + x2 − 12 z − 2 x z, 0<, 84 − 42 z<
Il risultato è la lista che abbiamo specificato. Se adesso moltiplichiamo ogni elemento della lista che
compare nel risultato, ognuno per il corrispettivo polinomio nella lista che abbiamo scritto come
secondo argomento della funzione, ed a questo ci sommiamo il secondo elemento della lista ottenuta
come risultato, riotteniamo il polinomio originale:
In[101]:= %@@1, 1DD Hx − 4L + %@@1, 2DD Hx^2 − 5L + %@@2DD
Out[101]= 84 − 42 z + H−4 + xL H21 + 6 x + x2 − 12 z − 2 x zL
In[102]:= Expand@%D
Out[102]= −3 x + 2 x2 + x3 + 6 z − 4 x z − 2 x2 z
Come potete vedere, abbiamo riottenuto il polinomio originale.
Analoghe considerazioni possiamo fare per gli altri, considerando che FactorTerms accetta solo le
opzioni Modulus e Trig, mentre FactorSquareFree, oltre a questi due, accetta anche Extension, ma
non GaussianIntegers. Comunque credo che raramente andrete ad usare queste opzioni...
Daniele Lupo Appunti di Mathematica
69Printed by Mathematica for Students
ü Altre Manipolazioni
Questi comandi che abbiamo analizzato, tuttavia, sono specifici per espressioni razionali fratte. In
genere, invece, ci sono altri tipi di espressioni, come quelle trigonometriche. Naturalmente
Mathematica include anche comandi per trattare questo tipo di espressioni, che possono essere
considerate equivalenti a quelle per le espressioni fratte:
TrigExpand[expr] espande i prodotti
TrigFactor[expr] fattorizza in prodotti di fattori
TrigReduce[expr] riduce le espressioni che utilizzano angoli multipli
TrigToExp[expr] converte forme trigonometriche in esponenziali
ExpToTrig[expr] converte forme esponenziali in trigonomentriche
FunctionExpand[expr] espande funzioni speciali
ComplexExpand[expr] effettua espansioni considerando le incognite reali
PowerExpand[expr] trasforma Hx yLp in xp yp, etc.
Sono tutte molto utili ma, ultimamente, ho usato spesso (e la uso come esempio), la funzione
ComplexExpand. Permette, una volta che si ha l'espressione, di dividerla in parte reale e parte
immaginaria. Risulta particolarmente utile, tanto per fare un esempio, per calcolare le interstezioni
con gli assi dei diagrammi di Nyquist. Supponiamo di avere la seguente espressione:
In[103]:= W = H1 + I ω ZLêHH1 + I ω P1L H1 + I ω P2LL
Out[103]=1 + Z ω
H1 + P1 ωL H1 + P2 ωL
Se, adesso, mi piacerebbe per esempio trovare la parte reale di questa espressione, mi verrebbe
naturale scrivere:
In[104]:= Re@WD
Out[104]= ReA 1 + Z ωH1 + P1 ωL H1 + P2 ωL E
Tuttavia, come possiamo vedere, non ci dà il risultato sperato. Perchè? Abbiamo già detto che
Mathematica ha uno dei sui punti di forza nel calcolo simbolico, per cui, dato che non abbiamo
definito le varie incognite come P1, P2, per il programma potrebbero essere numeri reali, complessi,
funzioni, espressioni e così via. Con il comando ComplexExpand, invece, forziamo Mathematica a
trattarli come se fossero numeri reali, permettendodi di avere il risultato desiderato:
Daniele Lupo Appunti di Mathematica
70Printed by Mathematica for Students
In[105]:= ComplexExpand@Re@WDD
Out[105]=1
H1 + P12 ω2L H1 + P22 ω2L −P1 P2 ω2
H1 + P12 ω2L H1 + P22 ω2L +
P1 Z ω2
H1 + P12 ω2L H1 + P22 ω2L +P2 Z ω2
H1 + P12 ω2L H1 + P22 ω2L
Vediamo che il risultato è quello desiderato. Ma è troppo lungo, vero? Basta usare la magica
funzione, allora:
In[106]:= Simplify@%D
Out[106]=1 + P2 Z ω2 + P1 H−P2 + ZL ω2
H1 + P12 ω2L H1 + P22 ω2L
Automaticamente, possiamo calcolarci la parte immaginaria:
In[107]:= Simplify@ComplexExpand@Im@WDDD
Out[107]= −ω HP1 + P2 − Z + P1 P2 Z ω2LH1 + P12 ω2L H1 + P22 ω2L
Ah, ora sì che posso fare tranquillamente i grafici delle esercitazioni di Controlli Automatici e di
Elettronica!!!
Anche le altre funzioni sono, naturalmente, molto utili, e permettono di semplificare parecchio le
espressioni, oppure di scriverle in particolari forme
In[108]:= TrigReduce@Tan@xD Cos@2 xDD
Out[108]= −12
Sec@xD HSin@xD − Sin@3 xDL
In[109]:= TrigFactor@%D
Out[109]= HCos@xD − Sin@xDL HCos@xD + Sin@xDL Tan@xD
Come possiamo vedere, possiamo facilmente manipolare anche espressioni algebriche. Possiamo
anche semplificare i casi in cui compaiono angoli multipli, riducendo opportunamente l'angolo per
restituire lo stesso risultato. Inoltre permette anche di poter effettuare trasformazioni che invocano
gli argomenti
In[110]:= TrigReduce@Sin@5 x πD^2 + Cos@5 x πD^2D
Out[110]= 1
Daniele Lupo Appunti di Mathematica
71Printed by Mathematica for Students
Con il comando seguente, TrigExpand, possiamo espandere le espressioni trigonometriche
utilizzando le regole che ben conosciamo, come quelle di prostaferesi e le altre
In[111]:= Clear@a, b, cD;
In[112]:= TrigExpand@Cos@a + b + cDD
Out[112]= Cos@aD Cos@bD Cos@cD − Cos@cD Sin@aD Sin@bD −Cos@bD Sin@aD Sin@cD − Cos@aD Sin@bD Sin@cD
In[113]:= TrigExpand@Cos@2 xDD
Out[113]= Cos@xD2 − Sin@xD2
In[114]:= TrigExpand@Sin@2 xDD
Out[114]= 2 Cos@xD Sin@xD
Possiamo anche convertire le espressioni da trigonometriche ad esponenziali e viceversa, tramite i
due comandi appositi.
In[115]:= tr = Tan@xD Sin@xD
Out[115]= Sin@xD Tan@xD
In[116]:= TrigToExp@trD
Out[116]= −H − x − xL2
2 H − x + xL
E da questa passare di nuovo alla corrispondente trigonometrica:
In[117]:= ExpToTrig@%D
Out[117]= Sin@xD Tan@xD
Possiamo anche effettuare semplici conversioni avendo soltanto dati numerici, cosa che comunque
risulta essere parecchio utile in molti casi:
In[118]:= ExpToTrig@H−2L^H1ê13LD
Out[118]= 21ê13 CosA π13
E + 21ê13 SinA π13
E
Un modo potente per poter eseguire le semplificazioni in casi particolari sono le supposizioni:
permettono di definire delle caratteristiche particolari alle variabili, in modo da rendere univoco il
Daniele Lupo Appunti di Mathematica
72Printed by Mathematica for Students
significato delle espressioni, in modo da poter effettuare le opportune semplificazioni. Prendiamo il
seguente esempio, per capirci meglio:
In[119]:= a = Sqrt@x^2D
Out[119]=è!!!!!!x2
In[120]:= Simplify@%D
Out[120]=è!!!!!!x2
Vediamo che non viene semplificato in x: questo è normale, perchè il valore x potrebbe essere, sia
positivo che negativo, e quindi potrebbe essere semplificato sia in x che in -x. Per evitare queste
ambiguità, possiamo definire il le caratteristiche della incognita x, come argomento del comando
Simplify:
In[121]:= Simplify@a, x > 0D
Out[121]= x
In questo caso abbiamo detto a Mathematica che ci interessa solamente il caso in cui x è un valore
positivo: anche se non abbiamo assegnato un valore specifico, la condizione che abbiamo imposto
basta a Mathematica per non aver dubbi sul tipo di semplificazione da effettuare; potevamo anche
considerare l'altro caso, naturalmente, in cui ci interessavano soltanto i valori negativi:
In[122]:= Simplify@a, x < 0D
Out[122]= −x
Possiamo anche identificare il tipo di dominio dell'incognita: per esempio, se deve essere un numero
reale oppure intero, usando il comando Element all'interno di Simplify, come nel seguente esempio:
In[123]:= Simplify@Sqrt@x^2D, Element@x, RealsDD
Out[123]= Abs@xD
In questo caso, abbiamo detto a Mathematica di semplificare l'espressione considerando x un
numero reale. Facciamo un altro esempio:
In[124]:= Simplify@Sin@x + 2 n PiD, Element@n, IntegersDD
Out[124]= Sin@xD
In quest'altro esempio abbiamo detto al programma di considerare n un numero intero. In questo
modo abbiamo potuto effetutare la giusta semplificazione, dato che il valore è lo stesso a meno di
Daniele Lupo Appunti di Mathematica
73Printed by Mathematica for Students
valori di n uguali, come sappiamo praticamente da sempre.
Elements può anche essere scritto mediante il suo simbolo corrispondente œ:
In[125]:= Simplify@a, 8x ∈ Integers, x > 0<D
Out[125]= x
I due comandi citati, Simplify e FullSimplify, tentano sempre di semplificare al massimo
l'espressione ottenuta, con varie manipolazioni ed applicando varie regole. Con le assunzioni
possiamo anche semplificare i casi, per così dire, ambigui. Tuttavia, a volte in realtà non vogliamo
modificare la struttura, e semplificare l'espressione; potremmo, invece, voler soltanto vedere il valore
che assume l'espressione quando vengono definiti certe imposizioni, tramite le assunzioni. Per
questo compito c'è il comando seguente:
Refine[expr, assum] riscrive expr usando le assunzioni
Supponiamo di avere la seguente espressione:
In[126]:= expr = Cos@x + π yD Log@xD;
Vediamo di semplificarla:
In[127]:= Simplify@exprD
Out[127]= Cos@x + π yD Log@xD
In[128]:= FullSimplify @exprD
Out[128]= Cos@x + π yD Log@xD
Come potete vedere, non cambia niente. Usiamo delle assunzioni. Per esempio, ipotizziamo che y sia
un numero intero:
In[129]:= Simplify@expr, y ∈ IntegersD
Out[129]= H−1Ly Cos@xD Log@xD
In[130]:= FullSimplify@expr, y ∈ IntegersD
Out[130]= H−1Ly Cos@xD Log@xD
Daniele Lupo Appunti di Mathematica
74Printed by Mathematica for Students
In[131]:= Refine@expr, y ∈ IntegersD
Out[131]= H−1Ly Cos@xD Log@xD
Come possiamo vedere, tutti e tre i comandi danno la stessa definizione, perchè non si può
semplificare altrimenti. Imponiamo adesso una condizione sulla x:
In[132]:= Simplify@expr, x < 0D
Out[132]= Cos@x + π yD Log@xD
In[133]:= FullSimplify@expr, x < 0D
Out[133]= Cos@x + π yD Log@xD
In[134]:= Refine@expr, x < 0D
Out[134]= Cos@x + π yD H π + Log@−xDL
Questa volta qualcosa è cambiato; è stato imposto un logaritmo di un numero negativo e, mentre
Simplify e FullSimplify semplificavano automaticamente il risultato, con Refine questo viene scritto
in maniera esplicita, senza ulteriori semplificazioni.
ü Nota per dimensioni fisiche
Un aspetto interessante di Mathematica, che viene spesso sottovalutato, è il fatto che, per la sua
stessa natura di calcolo simbolico, ci permette di poter effettuare operazioni con quantità fisiche
mantenendo la consistenza delle unità di misura. Per esempio, se vogliamo scrivere una quantità in
metri, possiamo semplicemente scrivere:
In[135]:= a = 13 m;
Se vogliamo una velocità, basta scrivere, per esempio:
In[136]:= %êH7 sL
Out[136]=13 m7 s
E possiamo anche effettuare velocemente delle conversioni, per esempio scrivendo:
In[137]:= 15 m ê. m → 3.2808 feet
Out[137]= 49.212 feet
Daniele Lupo Appunti di Mathematica
75Printed by Mathematica for Students
Si deve notare che questa possibilità non è dovuta al fatto che Mathematica implementa un qualche
metodo per tener conto delle unità di misura, ma viene come naturale conseguenza del calcolo
simbolico; a tutti gli effetti, quelle che per noi sono unità di misura, per Mathematica sono solo
variabili, e sono trattate come tali. Tuttavia, può essere utile usare questo trucchetto quando si vuole
lavorare con le unità di misura, anche se bisogna magari scriversi prima da qualche parte le varie
conversioni. Tuttavia, una volta fatto la prima volta, dopo semplifica notevolmente i conti.
Consideriamo anche che c'è un pacchetto di Mathematica che tratta le unità di misura. I pacchetto
sono dei file che contengono nuove definizioni e nuovi comandi per avere funzionalità in più, che
Mathematica non offre. Con l'installazione standard ce ne sono parecchi, specializzati in calcolo
statistico etc, e ce n'è anche uno per le unità di misura, richiamabile con
In[138]:= << Miscellaneous`Units`
Tuttavia, in queste pagine non tratterò dei pacchetti, perchè per apprezzarli bisogna conoscere prima
quello che si può avere da Mathematica, e usarlo sono in caso che ce ne sia bisogno. Anche in
questo caso, leggere la documentazione del programma è sempre la cosa migliore. Vi ho già detto
che per noi l'inglese è importante (nel bene e nel male)...
Daniele Lupo Appunti di Mathematica
76Printed by Mathematica for Students
Calcolo Simbolico 2ü Introduzione
Abbiamo visto, finora, come elaborare in modo banale alcune espressioni. In fondo, però, fino ad
adesso non abbiamo veramente eseguito calcoli utili, e non abbiamo risolto un bel niente. Mi
dispiace, ma era doveroso scrivere tutto quanto, perchè a mio avviso prima di camminare bisogna
cominciare col saper stare in piedi. Non si può apprezzare la potenzialità di un programma come
Mathematica se prima non se ne conoscono le basi. Andare subito a risolvere un'equazione
differenziale del 10° ordine serve a ben poco, se non si sa dove andare a parare, con il risultato che si
pensa che non si può usare il programma e che non riesce a fare quello che vogliamo, e quindi lo
cestiniamo.
Adesso, però, ne sappiamo abbastanza, e soprattutto si è fatta quel poco di pratica che serve per non
spaventarci a scrivere cose nuove, e per essere sicuri che, quando si scriverà una formula complicata,
in fondo si saprà scrivere nel modo giusto.
Occhio, però!!!! Non abbiamo mica finito di imparare! Per esempio, non abbiamo ancora visto come
si definiscono le funzioni, ma lo faremo fra poco e, soprattutto, le useremo per poterci finalmente
lavorare sopra. Cominceremo a fare elaborazioni banali, come le derivazioni, ma pian piano le cose
si faranno più complesse, più complete e più utili. Dato che questo è un capitolo che mostra le
funzionalità base di Mathematica, sarà, credo uno dei più lunghi. Comunque, niente paura. E' niente
rispetto a quello che potrete sapere, e i concetti matematici che useremo saranno sicuramente digeriti
da molto tempo, per voi.
Ma adesso bando alle ciance, o miei discepoli e diletti sottoposti per la mia futura conquista del
mondo!!! Costruiremo la verità che più ci piace!!!
ü Funzioni
Abbiamo visto alcune delle funzioni tipiche di Mathematica. Per lo più, si tratta di funzioni per
manipolare dati, ma ha anche un numero incredibile di funzioni matematiche, naturalmente:
In[1]:= BesselJ@4, 8D êê N
Out[1]= −0.105357
In[2]:= Binomial@5, 3D
Out[2]= 10
Daniele Lupo Appunti di Mathematica
77Printed by Mathematica for Students
In[3]:= RiemannSiegelTheta@5D
Out[3]= RiemannSiegelTheta@5D
In[4]:= N@%D
Out[4]= −3.45962
E così via nei secoli dei secoli... Ma che succede se vogliamo una funzione personalizzata fatta da
noi? Semplice, ce la facciamo!!! Il modo normale per poter definire delle funzioni è il seguente;
funzione@x_D := espressione
Notate due cose importanti: quando defininiamo la funzione, l'argomento (o gli argomenti) devono
essere obbligatoriamente accompagnati dal segno di underscore, il che indica un pattern: senza
addentrarci troppo, l'underscore indica a Mathematica che x può essere una qualsiasi espressione
(reale, complesso, incognita etc). Per ora ci basta sapere che è così che si definiscono le funzioni.
L'altra cosa da notare è che il segno = è sostituito dal segno := con i due punti che precedono
l'uguale: questo significa che Mathematica deve valutare l'espressione non subito, ma solo quando
viene invocata; per ora ci basti sapere che si definisce così anche questo. Più avanti capiremo meglio
tutte queste precisazioni...
Allora, definiamo la nostra funzione d'esempio:
In[5]:= f@x_D := x^3 + Sin@Cos@xDD
Se vogliamo calcolare la funzione in un punto, basta utilizzarla come qualsiasi altra espressione:
In[6]:= f@2D
Out[6]= 8 + Sin@Cos@2DD
In[7]:= [email protected]
Out[7]= 216.819
In[8]:= f@a + bD
Out[8]= Ha + bL3 + Sin@Cos@a + bDD
Inoltre, è possibile naturalmente definire funzioni a più variabili:
In[9]:= g@x_, y_, z_D := x^2 + y^3 + z^4
Daniele Lupo Appunti di Mathematica
78Printed by Mathematica for Students
Il simbolo di underscore serve ad indicare a Mathematica che l'argomento della funzione può essere
un argomento qualsiasi. A volte, invece, non vogliamo che sia così: per esempio, potremmo voler
definire delle funzioni ricorsive, e quindi ci piacerebbe far sapere a Mathematica che gli argomenti
della funzione possono essere solamente numeri interi. Possiamo naturalmente fare anche questo:
vediamo l'esempio più classico possibile ed immaginabile di funzione ricorsiva, considerando
(guardacaso) i numeri di Fibonacci; F1,F2 sono posti uguali ad 1, e un generico Fn è definito come la
somma dei due precedenti. Per poter definire questa funzione, dobbiamo prima definire i primi due
numeri:
In[10]:= fibo@1D = fibo@2D = 1;
Adesso definiamo la funzione di Fibonacci:
In[11]:= fibo@x_IntegerD := fibo@x − 1D + fibo@x − 2D
Proviamo a vedere se funziona...
In[12]:= fibo@10D
Out[12]= 55
mentre, se vogliamo calcolarci la funzione per un valore non intero, Mathematica non calcola la
funzione, perchè l'argomento non corrisponde con quello che si aspetta:
In[13]:= [email protected]
Out[13]= [email protected]
Effettivamente, funziona. Vediamo di spiegare in modo semplice quello che ho fatto. prima di tutto,
per definire la funzione, ho definito la funzione in punti particolari. In questa maniera eseguo una
specie di overloading: infatti, quando prima si definisce la funzione in un punto generico x, e poi la
si definisce in generale, se poi la calcolo proprio in x Mathematica, che è un programma furbo, evita
di calcolarsi la funzione, dato che ha già il risultato bello e pronto. Logico no? In questo modo,
abbiamo evitato di mettere i valori iniziali nella pancia della funzione, che ne avrebbe complicato la
definizione, tramite comandi If e così via. In realtà, si dovrebbe pure considerare il caso dei numeri
interi negativi, ma si dovrebbe considerare il costrutto If, che considereremo più avanti.
Inoltre, abbiamo anche visto l'uso di Integer: in questo modo abbiamo detto a Mathematica che
quell'argomento poteva essere soltanto intero. Naturalmente, abbiamo anche altri tipi di insiemi di
numeri: Reals, Rationals, Algebraics, Complex e così via. In questa maniera possiamo imporre delle
condizioni specifiche, evitando dei messaggi di errore che possono capitare quando abbiamo delle
funzioni che accettano determinati tipi di argomenti.
Daniele Lupo Appunti di Mathematica
79Printed by Mathematica for Students
Derivazione
Le funzioni, ovviamente, possono essere derivate: la funzione di derivazione in Mathematica è
indicata con la lettera D:
D[f, x] derivata (parziale) ∑ÅÅÅÅÅÅÅ∑x f
D[f, x1, x2, … ] derivata multipla ∑ÅÅÅÅÅÅÅÅÅ∑x1 ∑ÅÅÅÅÅÅÅÅÅ∑x2
... f
D[f, {x, n}] derivata di ordine superiore ∑n fÅÅÅÅÅÅÅÅÅÅ∑xn
Dt[f] differenziale totale d f
Dt[f, x] derivata totale dÅÅÅÅÅÅÅÅd x f
Data la natura simbolica di Mathematica, siamo in grado di effettuare derivazioni anche su funzioni
non definite:
In[14]:= D@r@qD, qD
Out[14]= r @qD
In[15]:= D@q@tD p@tD, tD
Out[15]= q@tD p @tD + p@tD q @tD
Tuttavia, riprendiamo le funzioni che avevamo scritto poco sopra
In[16]:= f@x_D := x^3 + Sin@Cos@xDD
In[17]:= g@x_, y_, z_D := x^2 + y^3 + z^4
e proviamo a derivarle:
In[18]:= D@f@xD, xD
Out[18]= 3 x2 − Cos@Cos@xDD Sin@xD
In[19]:= D@g@x, 5, zD, zD
Out[19]= 4 z3
Potete vedere come sia facile effettuare le derivazioni di funzioni che possono essere anche molto
complesse. Ovviamente possiamo effettuare anche derivate di ordine superiore:
Daniele Lupo Appunti di Mathematica
80Printed by Mathematica for Students
In[20]:= D@x^n, 8x, 10<D
Out[20]= H−9 + nL H−8 + nL H−7 + nL H−6 + nLH−5 + nL H−4 + nL H−3 + nL H−2 + nL H−1 + nL n x−10+n
In aggiunta a questo, possiamo definire derivate miste di ordine superiore. Vediamo l'esempio,
definendo la seguente funzione:
In[21]:= par@x_, y_, z_D := Sin@x Cos@yDDêLog@x^2 yêxD
Una volta definita, possiamo calcolarci, per esempio ∑Hx,yL par@x, y, zD possiamo elencare
semplicemente nel giusto ordine le variabili nel comando D:
In[22]:= D@par@x, y, zD, x, yD êê FullSimplify
Out[22]=1
x y Log@x yD3 H−x Cos@x Cos@yDD Log@x yD HCos@yD + y H−1 + Log@x yDL Sin@yDL +
H2 + x2 y Cos@yD Log@x yD2 Sin@yDL Sin@x Cos@yDDL
Possiamo anche definire la derivata totale con Dt
In[23]:= Dt@x^n, xD
Out[23]= xn I nx
+ Dt@n, xD Log@xDM
La derivata totale è la derivata della funzione quando ogni parametro dipende dall'argomento, quindi
non esistono costanti. Sono importanti, per esempio, quando si effettua il calcolo delle sensibilità di
un sistema.
Possiamo anche specificare, se non ci interessa la derivata totale, quali parametri devono essere
costanti nel calcolo della derivata, e quali, invece, devono essere considerati in funzione della
variabile di derivazione. Questo può essere fatto mediante l'opzione NonConstants, che specifica la
lista di parametri della funzione che NON devono essere considerati costanti. Per esempio,
definendo la funzione come segue:
In[24]:= nc@x_, y_D := c d f@c x, yD y
Proviamo a fare la derivata in x:
In[25]:= D@nc@x, yD, xD
Out[25]= c2 d y fH1,0L@c x, yD
Daniele Lupo Appunti di Mathematica
81Printed by Mathematica for Students
Tutti i parametri sono considerati costanti, come possiamo vedere dal risultato; adesso, invece
imponiamo che il parametro c dipenda da x:
In[26]:= D@nc@x, yD, x, NonConstants → 8c<D
Out[26]= d y D@c, x, NonConstants → 8c<D f@c x, yD +
c d y Hc + x D@c, x, NonConstants → 8c<DL fH1,0L@c x, yD
In questo caso si vede che dove compariva la c elaborata dalla derivata, adesso compare la derivata
di questo parametro, permettendo di vedere come cambia il risultato...
Comunque, se le conoscete sarete ben lieti di poterle utilizzare, scommetto. Per quanto riguarda la
derivazione, non c'è molto altro da dire, data la semplicità del comando.
Integrazione
Dopo aver definito l'integrale, il passo successivo è quello di vedere come si fa l'integrale, che di
solito è più difficile da calcolare a mano, specie se si va oltre il semplice polinomio o prodotto di
seni e coseni: possiamo definire l'integrale definito, indefinito, multiplo:
Integrate[f, x] integrale indefinito Ÿ f d x
Integrate[f, x, y] integrale multiplo indefinito Ÿ d x d y f
Integrate[f, {x, xmin, xmax}] integrale definito Ÿxmin
xmax f d x
Integrate[f, {x, xmin,xmax}, {y, ymin, ymax}]
integrale multiplo definito Ÿxmin
xmaxd x Ÿymin
ymaxd y f
Vediamo subito alcuni esempi di utilizzo dell'integrazione:
In[27]:= Integrate@Cos@xD^2, xD
Out[27]=x2
+14
Sin@2 xD
In[28]:= Integrate@Exp@−x^2D, 8x, 0, Infinity<D
Out[28]=è!!!π2
Notate come potete facilmente, grazie al calcolo simbolico, calcolare risultati anche con intervallo di
integrazione infinito, e come il risultato non sia approssimato, ma preciso. Naturalmente, se vi
piacciono i risultati approssimati potete sempre farlo:
In[29]:= N@%D
Out[29]= 0.886227
Daniele Lupo Appunti di Mathematica
82Printed by Mathematica for Students
Ma questo era solo per rinfrescarvi la memoria. Questo in quanto ci sono casi che non sono
risolvibili, e che quindi Mathematica lascia come sono:
In[30]:= Integrate@x^x, 8x, 1, 6<D
Out[30]= ‡1
6
xx x
In questo caso Mathematica non è in grado di risolvere analiticamente l'integrale (e se non ci riesce
lui dubito che qualche altra cosa nell'universo ci riesca), comunque potete sempre, in questi casi,
avere un'approssimazione del risultato, con la precisione che vi serve di più:
In[31]:= N@%, 60D
Out[31]= 17128.1112747406400791140548362465275891008756059805763169174
Mathematica riesce anche ad integrare funzioni che richiedono l'uso di altre funzioni speciali, e che
quindi è tremendamente difficile tentare di risolvere a mano:
In[32]:= Integrate@Log@1 − x^2Dêx, xD
Out[32]= −12
PolyLog@2, x2D
In[33]:= Integrate@Sin@x^2D, xD
Out[33]= $%%%%%%π2
FresnelSA$%%%%%%2π
xE
Possiamo anche integrare in regioni di spazio. Se imponiamo limiti solo per le variabili, integreremo
in regioni rettangolari; in questo caso la regione è triangolare:
In[34]:= Integrate@x^2 + y^2, 8x, 0, 1<, 8y, 0, x<D
Out[34]=13
Bisogna fare attenzione al fatto che il raggio d'integrazione che scriviamo per ultimo è quello che
viene calcolato prima. Infatti, se vogliamo scrivere la formula in forma tradizionale, possiamo usare
l'opzione TraditionalForm selezionando l'espressione ed utilizzando con CTRL+SHIFT+T:
‡0
1
‡0
xHx2 + y2L ‚ y ‚ x
Daniele Lupo Appunti di Mathematica
83Printed by Mathematica for Students
Inoltre, con il comando Boole possiamo anche definire altri tipi di regioni di integrazione che con gli
indici normali non si possono indicare. Per esempio, questo è un modo per calcolare un integrale in
un intervallo di integrazione circolare:
In[35]:= Integrate@Sin@xD^2 Boole@x^2 + y^2 ≤ 1D, 8x, −1, 1<, 8y, −1, 1<D
Out[35]=12Hπ − π BesselJ@1, 2DL
Come potete vedere, il comando di integrale permettere di risolvere casi anche abbastanza
complicati. Tuttavia, come vedremo più avanti, dove non riesce il calcolo simbolico, riesce quello
numerico.
ü Sommatorie e produttorie
Con Mathematica possiamo risolvere facilmente anche produttorie e sommatorie particolarmente
ostiche; il programma è in grado, nella maggior parte dei casi in cui qualsiasi sommatoria o
produttoria converge, di dare il risultato esatto, anche quando ci sono espressioni particolarmente
complicate e, anche in questo caso, dove non ce la fa il calcolo simbolico ce la fa quello numerico.
Le funzioni per eseguire sommatorie e produttorie sono se seguenti:
Sum[f, {i, imin, imax}] la sommatoria ⁄i=iminimax f
Sum[f, {i, imin, imax, di}] sommatoria con i crescente con passo di
Sum[f, {i, imin, imax}, {j,jmin, jmax}]
sommatoria nididicata ⁄i=iminimax ⁄ j= jmin
jmax f
Product[f, {i, imin, imax}] produttoria ¤i=iminimax f
Ci sono casi banali, dove il valore iniziale e finale sono finiti, ed in questo caso Mathematica calcola
semplicemente la somma normale:
In[36]:= Sum@x^iêi, 8i, 1, 7<D
Out[36]= x +x2
2+
x3
3+
x4
4+
x5
5+
x6
6+
x7
7
Possiamo anche specificare il passo, se vogliamo
In[37]:= Sum@Sin@xD, 8x, 0, Piê2, Piê6<D
Out[37]=32
+è!!!32
Una cosuccia interessante è che Mathematica è in grado i calcolare anche la sommatoria nel caso che
i limiti dell'indice siano incognite:
Daniele Lupo Appunti di Mathematica
84Printed by Mathematica for Students
In[38]:= Sum@x^3 + x, 8x, n<D
Out[38]=14
n H1 + nL H2 + n + n2L
E, soprattutto, il programma è in grado di calcolare esattamente anche le sommatorie con indici che
vanno ad infinito:
In[39]:= Sum@H1ê3L^x, 8x, 3, Infinity<D
Out[39]=1
18
Possiamo definire in maniera analoga le produttorie, dato che richiedono gli stessi argomenti
In[40]:= Product@Log@xD, 8x, 2, 10<D
Out[40]= Log@2D Log@3D Log@4D Log@5D Log@6D Log@7D Log@8D Log@9D Log@10D
Naturalmente potremmo preferire, in questo caso, un risultato numerico
In[41]:= N@%D
Out[41]= 62.3216
In fondo, non c'è molto altro da dire su questo argomento; probabilmente perchè non ne ho mai
avuto un bisogno spropositato per andare avanti con l'università. Ad ogni modo, credo che quanto
detto basti per cominciare a lavorarci sopra.
ü Equazioni
Scrittura di equazioni
Le equazioni sono probabilmente uno degli aspetti più importanti di Mathematica, forse perchè lo
sono anche nello studio... Per scrivere le equazioni è necessario usare il simbolo del doppio uguale
==
In[42]:= 2 + 2 == 4
Out[42]= True
In questo caso Mathematica verifica se l'espressione a sinistra è uguale a quella destra, ed in caso
affermativo restituisce True, altrimenti, e qua la fantasia dilaga, restituisce False.
Si usa l'operatore == per non confonderlo con l'operatore = che invece ha il compito di assegnare
valori alle variabili. Questo sempre per evitare ambiguità nella scrittura delle varie espressioni
Daniele Lupo Appunti di Mathematica
85Printed by Mathematica for Students
Possiamo anche associare nomi alle equazioni, creando quindi variabili che le rappresentano:
In[43]:= eq = x^2 + xêSin @xD 0
Out[43]= x2 + x Csc@xD 0
In questo caso non si restituisce nè il valore True, e neanche False, perchè Mathematica non è in
grado di definire univocamente se l'equazione è verificata oppure no. Dipende dal valore di x, e
prima dobbiamo andare a sostituirlo.
Ovviamente ci sono eccezioni definite dalle identità:
In[44]:= x + x^2 x^2 + x
Out[44]= True
In questo caso, qualsiasi sia il valore di x, l'equazione è sempre la stessa, e il programma riconosce
l'identità.
Disequazioni
Mathematica non riconosce solo le equazioni, ma anche le disequazioni, naturalmente... Gli
operatori relazionali sono in questo caso quelli classici:
x == y uguaglianza
x != y diseguaglianza ( x ∫ y)
x > y maggiore di
x >= y maggiore o uguale a (x ¥ y)
x < y minore di
x <= y minore o uguale a (x § y)
x == y == z uguaglianza globale
x != y != z elementi distinti
x > y > z, etc. strettamente decrescente, etc.
Le relazioni fra due numeri sono abbastanza ovvie:
In[45]:= 1 > 3
Out[45]= False
In[46]:= 1 < 3
Out[46]= True
Daniele Lupo Appunti di Mathematica
86Printed by Mathematica for Students
In[47]:= 34 ≠ 3 ≠ 34
Out[47]= False
Notate una piccola cosa: nelle versioni più recenti di Mathematica capita che alcuni simboli, come
-> oppure != siano poi automaticamente convertiti nella forma tipograficamente corretta, com'è
capitato qua sopra scrivendo le diseguaglianze. Naturalmente i casi in cui non è univocamente
determinata la diseguaglianza non possono essere verificati da Mathematica, e questo è il caso delle
incognite:
In[48]:= 3 x + y < z
Out[48]= 3 x + y < z
In questo caso il programma restituisce semplicemente la disequazione. Ovviamente ci sono metodi
per risolverli, altrimenti che ci stiamo a fare qua?
Operatori logici
Mathematica, com'è facile intuire, dispone anche degli operatori
logici:
!p not (Ÿp)
p && q && … and ( p fl q fl … )
p || q || … or ( p fi q fi … )
Xor[p, q, … ] exclusive or (also input as p q … )
Nand[p, q, … ] e Nor[p, q,
… ] nand e nor (also input as and )
If[p, then, else] restituisce thense p è True, ed else se p è False
LogicalExpand[expr] espande espressioni logiche
Ovviamente, i casi ovvi sono risolti immediatamente da Mathematica:
In[49]:= 5 > 2 && H45 < 3 »» 5 ≠ 2L
Out[49]= True
In questo caso, fra parentesi è verificata soltanto una diseguaglianza, ma il risultato delle parentesi è
True, perchè in mezzo c'è l'operatore Or: la prima disequazione è vera, per cui si fa l'And fra due
espressioni True, ed il risultato, ovviamente, è True!!! Insomma, devo spiegarvi io come sono le
relazioni logiche? Anche in questo caso, ovviamente, ci sono le relazioni che Mathematica, a meno
di non avere altre informazioni, non riesce a gestire:
Daniele Lupo Appunti di Mathematica
87Printed by Mathematica for Students
In[50]:= w »» p && c
Out[50]= w »» Hp && cL
Si vede che, in questo caso, Mathematica lascia l'espressione così com'è, dato che non è in grado di
capire se alle tre incognite corrispondono valori True o False. Possiamo anche vedere, dal risultato,
che il programma riconosce le precedenze fra gli operatori logici: infatti, viene evidenziata sotto il
segno di parentesi l'And logico, che quindi viene valutato prima dell'Or logico. Esattamente come
faremmo noi nella stessa situazione. Possiamo anche effettuare le espansioni logiche delle
espressioni logiche, esattamente come quelle, per dire, algebriche:
In[51]:= LogicalExpand@Ha »» bL && Hc »» dL »» ! Hv »» tLD
Out[51]= Ha && cL »» Ha && dL »» Hb && cL »» Hb && dL »» H! t && ! vL
Tanto semplice quanto efficace. E, adesso che abbiamo capito come si scrivono le equazioni,
vediamo di risolverle. In fondo, siamo qui principalmente per questo, no?
ü Risolvere le equazioni
Equazioni semplici
Adesso, andiamo a vedere un poco più approfonditamente, quello che Mathematica ci può offrire: in
fondo, non abbiamo fatto poi molto, fino ad adesso. A parte qualche caso, ci siamo limitati a capire
come scrivere le nostre formulette delicate ed affascinanti (?!?) dentro il pancino di Mathematica.
Vediamo ora di fargliele digerire e poi di restituirci il risultato dal suo pancino... MMMmmmmm...
Forse il paragone non è stato dei più felici... mi sa che le cose che escono dal pancino non piacciano
proprio a tutti....
Comunque, vediamo di cominciare. Il comando principale che si usa per risolvere le equazioni in
Mathematica è il seguente:
Solve[lhs == rhs, x] risolve l'equazione, dando i valori di x
x /. solution usa la lista di regole per trovare il valore x
expr /. solution usa la lista di regole per trovare il valore dell'espressione
Il comando Solve applica tutta una serie di regole per poter cercare di risolvere le equazioni e trovare
i valori di x. Questo permette di ottenere soluzioni anche simboliche, invece di dover utilizzare
algoritmi numerici per poter trovare un singolo valore numerico. Ovviamente ci sono casi in cui
un'espressione analitica della soluzione non è possibile, ed in questo caso il comando Solve non è in
grado di restituire l'espressione corretta. In questo caso occorre ricorrere alle soluzioni numeriche,
per il semplice fatto che per quella particolare equazione non c'è altra alternativa. Supponiamo, per
esempio, di avere la seguente equazione:
Daniele Lupo Appunti di Mathematica
88Printed by Mathematica for Students
In[52]:= eq = x^2 + a x + a 0;
Vi siete ricordati che = significa assegnamento, mentre == serve per l'uguaglianza relazionale, e che
si usa quest'ultima nelle equazioni, vero?
Ora che so che siete discepoli fedeli, possiamo andare avanti, andando ad usare il comando Solve per
andare a risolvere l'equazione:
In[53]:= Solve@eq, xD
Out[53]= 99x →12H−è!!!!!!!!!!!!!!−4 + a è!!!a − aL=, 9x →
12Hè!!!!!!!!!!!!!!−4 + a è!!!a − aL==
Possiamo anche andarci a trovare il valore a, se ci serve quello:
In[54]:= Solve@eq, aD
Out[54]= 99a → −x2
1 + x==
Mathematica gestisce con altrettanta facilità equazioni in cui sono invocate soluzioni con numeri
complessi:
In[55]:= Solve@x^4 + 3 x^2 + 2 0, xD
Out[55]= 88x → − <, 8x → <, 8x → − è!!!2 <, 8x → è!!!2 <<
In generale, Mathematica è in grado di risolvere esattamente equazioni algebriche fino al quarto
grado:
In[56]:= Solve@a x^4 + b x^3 + c x^2 + d x + e 0, xD
Out[56]= 99x → −b
4 a−
12-J b2
4 a2 −2 c3 a
+ H21ê3 Hc2 − 3 b d + 12 a eLL í J3 a I2 c3 − 9 b c d + 27
a d2 + 27 b2 e − 72 a c e + ,I−4 Hc2 − 3 b d + 12 a eL3+
H2 c3 − 9 b c d + 27 a d2 + 27 b2 e − 72 a c eL2MM1ê3
N +1
3 21ê3 a
JI2 c3 − 9 b c d + 27 a d2 + 27 b2 e − 72 a c e + ,I−4 Hc2 − 3 b d + 12 a eL3+
H2 c3 − 9 b c d + 27 a d2 + 27 b2 e − 72 a c eL2MM1ê3
NN −
12-J b2
2 a2 −4 c3 a
− H21ê3 Hc2 − 3 b d + 12 a eLL í J3 a I2 c3 − 9 b c
d + 27 a d2 + 27 b2 e − 72 a c e + ,I−4 Hc2 − 3 b d + 12 a eL3+
H2 c3 − 9 b c d + 27 a d2 + 27 b2 e − 72 a c eL2MM1ê3
N −
13 21ê3 a
JI2 c3 − 9 b c d + 27 a d2 + 27 b2 e − 72 a c e +
Daniele Lupo Appunti di Mathematica
89Printed by Mathematica for Students
,I−4 Hc2 − 3 b d + 12 a eL3+ H2 c3 − 9 b c d + 27 a d2 +
27 b2 e − 72 a c eL2MM1ê3
N − J−b3
a3 +4 b c
a2 −8 da
N í
J4 -J b2
4 a2 −2 c3 a
+ H21ê3 Hc2 − 3 b d + 12 a eLL í J3 a I2 c3 − 9 b c d +
27 a d2 + 27 b2 e − 72 a c e + ,I−4 Hc2 − 3 b d + 12 a eL3+
H2 c3 − 9 b c d + 27 a d2 + 27 b2 e − 72 a c eL2MM1ê3
N +
13 21ê3 a
JI2 c3 − 9 b c d + 27 a d2 + 27 b2 e − 72 a c e +
,I−4 Hc2 − 3 b d + 12 a eL3+
H2 c3 − 9 b c d + 27 a d2 + 27 b2 e − 72 a c eL2MM1ê3
NNNN=,
9x → −b
4 a−
12-J b2
4 a2 −2 c3 a
+ H21ê3 Hc2 − 3 b d + 12 a eLL í
J3 a I2 c3 − 9 b c d + 27 a d2 + 27 b2 e − 72
a c e + ,I−4 Hc2 − 3 b d + 12 a eL3+
H2 c3 − 9 b c d + 27 a d2 + 27 b2 e − 72 a c eL2MM1ê3
N +1
3 21ê3 a
JI2 c3 − 9 b c d + 27 a d2 + 27 b2 e − 72 a c e + ,I−4 Hc2 − 3 b d + 12 a eL3+
H2 c3 − 9 b c d + 27 a d2 + 27 b2 e − 72 a c eL2MM1ê3
NN +
12-J b2
2 a2 −4 c3 a
− H21ê3 Hc2 − 3 b d + 12 a eLL í J3 a I2 c3 − 9 b c
d + 27 a d2 + 27 b2 e − 72 a c e + ,I−4 Hc2 − 3 b d + 12 a eL3+
H2 c3 − 9 b c d + 27 a d2 + 27 b2 e − 72 a c eL2MM1ê3
N −
13 21ê3 a
JI2 c3 − 9 b c d + 27 a d2 + 27 b2 e − 72 a c e +
,I−4 Hc2 − 3 b d + 12 a eL3+ H2 c3 − 9 b c d + 27 a d2 +
27 b2 e − 72 a c eL2MM1ê3
N − J−b3
a3 +4 b c
a2 −8 da
N í
J4 -J b2
4 a2 −2 c3 a
+ H21ê3 Hc2 − 3 b d + 12 a eLL í J3 a I2 c3 − 9 b c d +
27 a d2 + 27 b2 e − 72 a c e + ,I−4 Hc2 − 3 b d + 12 a eL3+
H2 c3 − 9 b c d + 27 a d2 + 27 b2 e − 72 a c eL2MM1ê3
N +
13 21ê3 a
JI2 c3 − 9 b c d + 27 a d2 + 27 b2 e − 72 a c e +
,I−4 Hc2 − 3 b d + 12 a eL3+
H2 c3 − 9 b c d + 27 a d2 + 27 b2 e − 72 a c eL2MM1ê3
NNNN=,
9x → −b
4 a+
12-J b2
4 a2 −2 c3 a
+ H21ê3 Hc2 − 3 b d + 12 a eLL í
J3 a I2 c3 − 9 b c d + 27 a d2 + 27 b2 e − 72
a c e + ,I−4 Hc2 − 3 b d + 12 a eL3+
H2 c3 − 9 b c d + 27 a d2 + 27 b2 e − 72 a c eL2MM1ê3
N +1
3 21ê3 a
JI2 c3 − 9 b c d + 27 a d2 + 27 b2 e − 72 a c e + ,I−4 Hc2 − 3 b d + 12 a eL3+
H2 c3 − 9 b c d + 27 a d2 + 27 b2 e − 72 a c eL2MM1ê3
NN −
12-J b2
2 a2 −4 c3 a
− H21ê3 Hc2 − 3 b d + 12 a eLL í J3 a I2 c3 − 9 b c
Daniele Lupo Appunti di Mathematica
90Printed by Mathematica for Students
d + 27 a d2 + 27 b2 e − 72 a c e + ,I−4 Hc2 − 3 b d + 12 a eL3+
H2 c3 − 9 b c d + 27 a d2 + 27 b2 e − 72 a c eL2MM1ê3
N −
13 21ê3 a
JI2 c3 − 9 b c d + 27 a d2 + 27 b2 e − 72 a c e +
,I−4 Hc2 − 3 b d + 12 a eL3+ H2 c3 − 9 b c d + 27 a d2 +
27 b2 e − 72 a c eL2MM1ê3
N + J−b3
a3 +4 b c
a2 −8 da
N í
J4 -J b2
4 a2 −2 c3 a
+ H21ê3 Hc2 − 3 b d + 12 a eLL í J3 a I2 c3 − 9 b c d +
27 a d2 + 27 b2 e − 72 a c e + ,I−4 Hc2 − 3 b d + 12 a eL3+
H2 c3 − 9 b c d + 27 a d2 + 27 b2 e − 72 a c eL2MM1ê3
N +
13 21ê3 a
JI2 c3 − 9 b c d + 27 a d2 + 27 b2 e − 72 a c e +
,I−4 Hc2 − 3 b d + 12 a eL3+
H2 c3 − 9 b c d + 27 a d2 + 27 b2 e − 72 a c eL2MM1ê3
NNNN=,
9x → −b
4 a+
12-J b2
4 a2 −2 c3 a
+ H21ê3 Hc2 − 3 b d + 12 a eLL í
J3 a I2 c3 − 9 b c d + 27 a d2 + 27 b2 e − 72
a c e + ,I−4 Hc2 − 3 b d + 12 a eL3+
H2 c3 − 9 b c d + 27 a d2 + 27 b2 e − 72 a c eL2MM1ê3
N +1
3 21ê3 a
JI2 c3 − 9 b c d + 27 a d2 + 27 b2 e − 72 a c e + ,I−4 Hc2 − 3 b d + 12 a eL3+
H2 c3 − 9 b c d + 27 a d2 + 27 b2 e − 72 a c eL2MM1ê3
NN +
12-J b2
2 a2 −4 c3 a
− H21ê3 Hc2 − 3 b d + 12 a eLL í J3 a I2 c3 − 9 b c
d + 27 a d2 + 27 b2 e − 72 a c e + ,I−4 Hc2 − 3 b d + 12 a eL3+
H2 c3 − 9 b c d + 27 a d2 + 27 b2 e − 72 a c eL2MM1ê3
N −
13 21ê3 a
JI2 c3 − 9 b c d + 27 a d2 + 27 b2 e − 72 a c e +
,I−4 Hc2 − 3 b d + 12 a eL3+ H2 c3 − 9 b c d + 27 a d2 +
27 b2 e − 72 a c eL2MM1ê3
N + J−b3
a3 +4 b c
a2 −8 da
N í
J4 -J b2
4 a2 −2 c3 a
+ H21ê3 Hc2 − 3 b d + 12 a eLL í J3 a I2 c3 − 9 b c d +
27 a d2 + 27 b2 e − 72 a c e + ,I−4 Hc2 − 3 b d + 12 a eL3+
H2 c3 − 9 b c d + 27 a d2 + 27 b2 e − 72 a c eL2MM1ê3
N +
13 21ê3 a
JI2 c3 − 9 b c d + 27 a d2 + 27 b2 e − 72 a c e +
,I−4 Hc2 − 3 b d + 12 a eL3+
H2 c3 − 9 b c d + 27 a d2 + 27 b2 e − 72 a c eL2MM1ê3
NNNN==
Non vi mostro il risultato perchè è troppo lungo, ma la soluzione in questo caso è pure esatta.
Andando a sostituire i valori a quello opportuni numerici, Mathematica restituisce il risultato
corretto. Per equazioni algebriche con ordine massimo superiore al 4°, può capitare che il
programmino non trovi le esatte soluzioni. In alcuni casi ci può anche riuscire:
Daniele Lupo Appunti di Mathematica
91Printed by Mathematica for Students
In[57]:= Solve@x^7 5, xD
Out[57]= 88x → −H−5L1ê7<, 8x → 51ê7<, 8x → H−1L2ê7 51ê7<, 8x → −H−1L3ê7 51ê7<,8x → H−1L4ê7 51ê7<, 8x → −H−1L5ê7 51ê7<, 8x → H−1L6ê7 51ê7<<
Ma, in generale, non ci riesce, per il fatto che non esistono funzioni analitiche che permettano di
trovare le soluzioni richieste;
In[58]:= Solve@x^6 + x^5 + x^2 −6 x − 1, xD
Out[58]= 88x → Root@1 + 6 #1 + #12 + #15 + #16 &, 1D<,
8x → Root@1 + 6 #1 + #12 + #15 + #16 &, 2D<,
8x → Root@1 + 6 #1 + #12 + #15 + #16 &, 3D<,
8x → Root@1 + 6 #1 + #12 + #15 + #16 &, 4D<,
8x → Root@1 + 6 #1 + #12 + #15 + #16 &, 5D<,
8x → Root@1 + 6 #1 + #12 + #15 + #16 &, 6D<<
In questo caso, la soluzione restituita non è di facile comprensione, ed è di forma anche abbastanza
criptica. Tuttavia, anche se le soluzioni non sono esprimibili in forma normale, Mathematica è
riuscita a trovarle, per cui possiamo averne un'approssimazione numerica:
In[59]:= N@%D
Out[59]= 88x → −1.59062<, 8x → −0.171551<,8x → −0.661785 − 1.24153 <, 8x → −0.661785 + 1.24153 <,8x → 1.04287 − 0.874004 <, 8x → 1.04287 + 0.874004 <<
Per il comando Solve valgono pure le considerazioni di precisione numerica: se utilizziamo valori
con il punto, allora Mathematica passerà al calcolo numerico invece che quello simbolico:
riprendendo l'equazione che avevamo scritto prima, possiamo aggiungere un punto
In[60]:= Solve@x^4 + 3 x^2 + 2. 0, xD
Out[60]= 88x → 0. − 1. <, 8x → 0. + 1. <, 8x → 0. − 1.41421 <, 8x → 0. + 1.41421 <<
Otteniamo soluzioni numeriche. Per cui, se nel vostro caso, per esempio, 1.64 non è un numero
approssimato, ma è esattamente il vostro valore, se volete soluzioni esatte dovete scrivere questo
numero sotto forma di frazione, in modo da comunicare a Mathematica che il coefficiente, se pure
con la virgola, è esatto:
In[61]:= [email protected] x^2 − 3 x + 5 2, xD
Out[61]= 88x → 0.914634 − 0.99635 <, 8x → 0.914634 + 0.99635 <<
Daniele Lupo Appunti di Mathematica
92Printed by Mathematica for Students
In[62]:= Solve@H164ê100L x^2 − 3 x + 5 2, xD
Out[62]= 99x →5
82H15 − è!!!!!!!!!267 L=, 9x →
582
H15 + è!!!!!!!!!267 L==
Come vedete, un punto può fare la differenza...
Notate un attimo il modo con cui Mathematica restituisce le soluzioni. Riuscite a capire in che forma
le da? Dai che lo sapete... Uff, va bene, ve lo dico io!!! Le soluzioni non sono date in forma di
semplice lista di soluzioni, ma vengono date in forma di regole di sostituzione: Infatti, ponendo per
esempio:
In[63]:= eq = s x^2 + 6 x − 2 0
Out[63]= −2 + 6 x + s x2 0
In[64]:= Solve@eq, xD
Out[64]= 99x →−3 − è!!!!!!!!!!!!!!9 + 2 s
s=, 9x →
−3 + è!!!!!!!!!!!!!!9 + 2 ss
==
Possiamo, ad esempio,andarle a sostituire all'equazione originale:
In[65]:= eq ê. %
Out[65]= 9−2 +6 H−3 − è!!!!!!!!!!!!!!9 + 2 s L
s+H−3 − è!!!!!!!!!!!!!!9 + 2 s L2
s0,
−2 +6 H−3 + è!!!!!!!!!!!!!!9 + 2 s L
s+H−3 + è!!!!!!!!!!!!!!9 + 2 s L2
s0=
In[66]:= Simplify@%D
Out[66]= 8True, True<
Avete seguito i calcoli? Dopo aver trovato le soluzioni, sono andato a sostituirle all'equazione. Al
posto di risriverle, è bastato utilizzare l'operatore percento, per andare a sostituire al suo posto il
risultato precedente, che era proprio la lista di regole. Dopo, andando a semplificare il risultato,
abbiamo verificato che le equazioni sono effettivamente verificate. Questo, ovviamente, non è fine a
se stesso! Che ci frega, con tutto il rispetto, andare a sostiruire le soluzioni all'equazione per vedere
se viene verificata, se intanto sappiamo già che lo saranno? Potrebbe, al massimo, avere un qualche
significato per soluzioni numeriche, ma questo lo vedremo in seguito.
In realtà, la scrittura di soluzioni come regole ha un suo significato. A parte il fatto che, se volessimo
semplicemente la lista delle soluzioni, potremmo lasciarlo sempre così com'è e ricopiarlo sul
Daniele Lupo Appunti di Mathematica
93Printed by Mathematica for Students
quaderno (...), oppure, se proprio vogliamo, definire velocemente una lista ti soluzioni in questo
modo
In[67]:= Solve@eq, xD
Out[67]= 99x →−3 − è!!!!!!!!!!!!!!9 + 2 s
s=, 9x →
−3 + è!!!!!!!!!!!!!!9 + 2 ss
==
In[68]:= lista = x ê. %
Out[68]= 9 −3 − è!!!!!!!!!!!!!!9 + 2 ss
, −3 + è!!!!!!!!!!!!!!9 + 2 ss
=
In questo modo abbiamo ottenuto la lista di soluzioni che volevamo. In realtà, nei problemi reali, se
ci servono le soluzioni per andare a verificare altre equazioni, oppure per andarle a sostituire da
qualche altra parte, effettivamente è meglio utilizzare le regole, invece che direttamente le
sostituzioni. In questo modo le soluzioni sono sempre pronte per essere sostituite dove vogliamo.
Mathematica usa questo approccio perchè, data la sua potenza, molto difficilmente verrà usato per
risolvere soltanto un'equazione, ma le sue soluzioni faranno parte di un sistema ben più complesso:
calcolo con il metodo delle perturbazioni per trovare orbitali, stress di strutture complesse, e chi più
ne ha più ne metta. Ripeto: se vi serve soltanto per risolvere calcolucci da strapazzo, compratevi una
HP 49G+, che ha lo stesso prezzo della versione studenti di Mathematica e che vi potete portare pure
agli esami!!!
Sistemi di equazioni
Mathematica è in grado di risolvere in modo rapido ed indolore anche sistemi di equazioni. Il
comando principale che permette di farlo è sempre Solve, andando a sostituire all'equazioni ed alle
incognite da trovare, le corrispetive liste che contengono tutte le equazioni e incognite che
cerchiamo. Per esempio, possiamo definire le due equazioni:
In[69]:= eq1 = a x^2 − 2 x y + 5 0; eq2 = x − y 0;
E adesso, possiamo risolvere per le incognite che cerchiamo:
In[70]:= Solve@8eq1, eq2<, 8x, y<D
Out[70]= 99y → −è!!!5
è!!!!!!!!!!!2 − a, x → −
è!!!5è!!!!!!!!!!!2 − a
=, 9y →è!!!5
è!!!!!!!!!!!2 − a, x →
è!!!5è!!!!!!!!!!!2 − a
==
Un altro modo alternativo di risolvere il sistema, è concatenare le equazioni in un'espressione logica:
Daniele Lupo Appunti di Mathematica
94Printed by Mathematica for Students
In[71]:= Solve@eq1 && eq2, 8x, y<D
Out[71]= 99y → −è!!!5
è!!!!!!!!!!!2 − a, x → −
è!!!5è!!!!!!!!!!!2 − a
=, 9y →è!!!5
è!!!!!!!!!!!2 − a, x →
è!!!5è!!!!!!!!!!!2 − a
==
Possiamo vedere come le soluzioni siano le stesse, anche se in questo caso possiamo avere soluzioni
più generali, combinando opportunamente le equazioni, Tuttavia, al posto di Solve, può essere utile
in questo caso quest'altro comando:
R e d u c e [ {lhs1 = =rhs1 ,lhs2==rhs2, … }, {x, y, … }]
restituisce un set di equazioni semplificate,includendo tutte le possibili soluzioni
Per esempio, considerando le equazioni di prima:
In[72]:= Reduce@eq1 »» eq2, 8x, y<D
Out[72]= Jx ≠ 0 && y 5 + a x2
2 xN »» y x
Possiamo vedere che il comando Reduce tratta soluzioni più generali di Solve, e possiamo vedere
anche che restituisce le soluzioni in modo diverso. Tuttavia, se ci servono le regole di sostituzione,
possiamo utilizzare il seguente comando ToRules, che prende le soluzioni date da Reduce e le
trasforma in regole:
In[73]:= ToRules@%D
Out[73]= SequenceA9y →5 + a x2
2 x=, 8y → x<E
Reduce può anche essere utilizzato per poter ottenere soluzioni più generali rispetto a Solve. Per
esempio, la classica equazione di secondo grado:
In[74]:= eq = a x^2 + b x + c 0;
Risolta con Solve restituisce il seguente risultato;
In[75]:= Solve@eq, xD
Out[75]= 99x →−b −
è!!!!!!!!!!!!!!!!!!!!b2 − 4 a c2 a
=, 9x →−b +
è!!!!!!!!!!!!!!!!!!!!b2 − 4 a c2 a
==
Tuttavia, non contempla i casi particolari: per esempio, come facciamo a sapere a priori se a ∫ 0 a
priori? Le soluzioni di Solve sono date solo ammettendo che i calcoli necessari per trovare la
soluzione non abbiano eccezzioni. Risolviamo la stessa equazione con Reduce, invece:
Daniele Lupo Appunti di Mathematica
95Printed by Mathematica for Students
In[76]:= Reduce@eq, xD
Out[76]=ikjjjja ≠ 0 &&
ikjjjjx −b −
è!!!!!!!!!!!!!!!!!!!!b2 − 4 a c2 a
»» x −b +è!!!!!!!!!!!!!!!!!!!!b2 − 4 a c
2 ay{zzzzy{zzzz »»
Ia 0 && b ≠ 0 && x −cbM »» Hc 0 && b 0 && a 0L
Come posiamo vedere, questo comando permette di trattare anche i casi particolari delle soluzioni,
scritti sotto forma di espressioni logiche che risultano vere. Infatti Reduce è nato proprio per
risolvere espressioni logiche, e le equazioni, effettivamente, possono anche essere viste come tali,
considerando == come un operatore logico. Quindi, il risultato si legge: "L'espressione logica
(equazione) è vera quando a ∫ 0flx è dato da quelle soluzioni, oppure dagli altri casi. Possiamo
anche in questo caso trasformare l'espressione logica in regole che saranno più facilmente gestibili
In[77]:= ToRules@%D
Out[77]= SequenceA9x →−b −
è!!!!!!!!!!!!!!!!!!!!b2 − 4 a c2 a
=,
9x →−b +
è!!!!!!!!!!!!!!!!!!!!b2 − 4 a c2 a
=, 9a → 0, x → −cb=, 8c → 0, b → 0, a → 0<E
Un altro comando utile in ambito di sistemi di equazioni è il
seguente:
Eliminate[{lhs1==rhs1,lhs2==rhs2, … }, {x, … }]
elimina x, … in un sistema di equazioni
Consideriamo, per esempio, il seguente sistema di equazioni:
In[78]:= sis = 8y m x + m + 4, y 2 x − 3<;
Proviamo a risolverlo:
In[79]:= Solve@sis, 8x, y<D
Out[79]= 99x → −7 + m
−2 + m, y → −
8 + 5 m−2 + m
==
Possiamo provare ad eliminare, invece, la variabile y, e vedere l'equazione risultante:
In[80]:= Eliminate@sis, yD
Out[80]= H−2 + mL x −7 − m
Vediamo che otteniamo l'equazione di una retta, di cui, adesso, possiamo andare a trovare la
soluzione:
Daniele Lupo Appunti di Mathematica
96Printed by Mathematica for Students
In[81]:= Solve@%, xD
Out[81]= 99x →−7 − m−2 + m
==
In alternativa, si poteva utilizzare direttamente la seguente formulazione di Solve:
In[82]:= Solve@sis, x, yD
Out[82]= 99x → −7 + m
−2 + m==
In questo caso, si è detto a Mathematica di risolvere il sistema sis nella variabile x. Inoltre, si è detto,
mediante il terzo argomento, di risolverla eliminando la variabile y. Potevamo, per esempio,
eliminare m, invece di y:
In[83]:= Solve@sis, x, mD
Out[83]= 99x →3 + y
2==
Ed otteniamo il risultato di x in funzione di y. Si utilizza questo metodo perchè abbiamo due
equazioni in tre incognite, e dobbiamo decidere di volta in volta rispetto a quali vogliamo risolvere il
sistema, mantenendo l'altra incognita come parametro.
In generale, Mathematica ha qualche problema a trovare la soluzione di equazioni trigonometriche;
questo è dovuto al fatto che di solito il programma inverte le funzioni, ma in questo modo le
soluzioni dell'inverso delle funzioni trigonometriche non sonon univocamente determinate.
Mathematica segnala questo problema con un Warning, anche s restituisce il risultato del valore
principale dell'argomento della funzione trigonomentrica:
In[84]:= Solve@Sin@xD 2êSqrt@6D, xD
— Solve::ifun : Inverse functions are being used by Solve, so some solutions may not
be found; use Reduce for complete solution information. More…
Out[84]= 99x → ArcSinA$%%%%%%23E==
Possiamo vedere che viene data la soluzione, anche se il Warning ci avverte del fatto che stiamo
usando una funzione inversa, e che non possiamo trovare tutte le soluzioni.
Daniele Lupo Appunti di Mathematica
97Printed by Mathematica for Students
Disequazioni
Mathematica è anche in grado di risolvere disequazioni, oltre che trovare soluzioni di equazioni e
sistemi: i comandi principali sono due, e credo che uno già sapete qual'è, vero?
Reduce[ineqs, {x, y, … }] riduce un set di disequazioni
FindInstance[ineqs, {x, y,… }]
trova delle istanze che soddisfano ineqs
Il metodo più semplice è quello di utilizzare il comando Reduce: abbiamo detto prima che serve per
risolvere espressioni logiche, ed è quello che fa anche in questo caso:
In[85]:= Reduce@x^2 − 5 < 0, xD
Out[85]= −è!!!5 < x < è!!!5
In[86]:= Reduce@x + y > z && z^2 > 5, 8x, y<D
Out[86]= x ∈ Reals && HHz < −è!!!5 && y > −x + zL »» Hz > è!!!5 && y > −x + zLL
Notiamo come, per poter risolvere le disequazioni, Mathematica in questo caso particolare dica che
x deve appartenere ai numeri reali, anche se di solito evita di scrivere queste avvertenze quando è
possibile. Cominquq, non rende di certo meno valida la soluzione...
Con il comando FindInstance, invece, si trova un particolare valore della soluzione che soddisfino le
disequazioni:
In[87]:= FindInstance@Sqrt@xD > y && x + y^5 < 3, 8x, y<D
Out[87]= 99x →12
, y → −1==
Vediamo se effettivamente sono verificate le diseguaglianze:
In[88]:= Sqrt@xD > y && x + y^5 < 3 ê. %
Out[88]= 8True<
Come possiamo vedere, tutto procede secondo i piani...
A volte è necessario, invece, trovare dei casi particolari di FindInstance. Potremmo, per esempio,
trovare i valori che rendano massima e minima una funzione, entro determinati vincoli: per questo ci
sono due funzioni apposite:
Daniele Lupo Appunti di Mathematica
98Printed by Mathematica for Students
Minimize[{expr, ineq}, {x,y, … }]
minimizza expr sotto i vincoli imposti da ineqs
Maximize[{expr, ineq}, {x,y, … }]
se non lo capite da soli, è inutile che andate avanti...
Vediamo un attimino come funzionano:
In[89]:= Minimize@8x^2 + y^2<, 8x, y<D
Out[89]= 80, 8x → 0, y → 0<<
In questo caso, la funzione è stata minimizzata, e, dato che si tratta di un paraboloide, si vede che
avrà un minimo all'origine. Il comando ha restituito una lista contenente sia il punto (x,y) in cui la
funzione è minima, sia il valore della funzione assunta un quel punto.
-2
-1
0
1
2-2
-1
0
1
2
0
2
4
6
8
-2
-1
0
1
Supponiamo, adesso, di dover invece calcolarci il valore minimo della funzione, ma solamente nei
punti in cui il paraboloide interseca il piano x + 3 y - 2:
In[90]:= Minimize@8x^2 + y^2, x + 3 y − 2 0<, 8x, y<D
Out[90]= 9 25
, 9x →15
, y →35==
Come potete vedere, questa volta il minimo è stato vincolato nella curva di interstezione fra
paraboloide e piano...
Daniele Lupo Appunti di Mathematica
99Printed by Mathematica for Students
Vedremo che, quando non è possibile trovare soluzioni simboliche, Mathematica dispone di
potentissimi comandi per poter trovare soluzioni numeriche anche dei sistemi di equazioni più
improbabili che esistano.
Equazioni differenziali
Le equazioni differenziali sono, a mio avviso, uno dei punti forti di Mathematica. Qua affronteremo
le soluzioni ed il calcolo simbolico, ma il comando per poter risolverle è uno dei più potenti, sia per
il calcolo simbolico che per quello, come vedremo più avanti, numerico.
Quello che vediamo qua sotto è un semplice esempio di definizione di equazione differenziale:
In[91]:= diffeq = y''@xD + y@xD a;
Come possiamo vedere, è abbastanza semplice poterle scrivere; si definisce la derivata di una
funzione ponendo l'apice subito dopo il nome, prima delle parentesi che racchiudono l'argomento (o
gli argomenti). Una volta definita, si tratta di risolverla, e possiamo usare il comando dedicato:
DSolve[eqns, y[x], x] calcola la funzione y[x], considerando x comevariabile indipendente
DSolve[eqns, y, x] restituisce la soluzione in forma di funzione pura
Proviamo a risolvele l'equazione differenziale di sopra:
In[92]:= DSolve@diffeq, y@xD, xD
Out[92]= 88y@xD → a + C@1D Cos@xD + C@2D Sin@xD<<
Possiamo vedere come sia risolta velocemente: possiamo anche vedere come, dato che non abbiamo
imposto nessuna condizione al contorno, che la soluzione è data in forma generale, con gli appositi
coefficienti indeterminati, scritti sotto forma di C@nD. Volendo, possiamo anche imporre le condizioni
al contorno, se le abbiamo:
In[93]:= DSolve@8y@xD + y @xD a, y'@0D 4, y@2D 0<, y@xD, xD
Out[93]= 88y@xD → a − a Cos@xD Sec@2D + 4 Sin@xD − 4 Cos@xD Tan@2D<<
In questo modo, possiamo trovare la soluzione per il nostro problema specifico. Notate come, anche
in questo caso, la soluzione è data sottoforma di regole.
Ovviamente Mathematica è anche in grado di risolvere equazioni differenziali semplici, che però
danno soluzioni molto complicate. Consideriamo, per esempio, questo esempio:
Daniele Lupo Appunti di Mathematica
100Printed by Mathematica for Students
In[94]:= diffeq = y''@xD + x y@xD a;
E risolviamola:
In[95]:= DSolve@diffeq, y@xD, xD
Out[95]= 99y@xD → AiryAi@H−1L1ê3 xD C@1D + AiryBi@H−1L1ê3 xD C@2D +
ikjjj3 H−1L2ê3 35ê6 a π x AiryAi@H−1L1ê3 xD GammaA 1
3E
GammaA 53E HypergeometricPFQA9 1
3=, 9 2
3, 4
3=, −
x3
9E −
3 H−1L2ê3 31ê3 a π x AiryBi@H−1L1ê3 xD GammaA 13E GammaA 5
3E
HypergeometricPFQA9 13=, 9 2
3, 4
3=, −
x3
9E −
3 31ê6 a π x2 AiryAi@H−1L1ê3 xD GammaA 23E
2HypergeometricPFQA
9 23=, 9 4
3, 5
3=, −
x3
9E − 32ê3 a π x2 AiryBi@H−1L1ê3 xD
GammaA 23E
2HypergeometricPFQA9 2
3=, 9 4
3, 5
3=, −
x3
9Ey{zzz ì
J27 GammaA 23E GammaA 4
3E GammaA 5
3EN==
Proviamo a semplificarla:
In[96]:= FullSimplify@%D
Out[96]= 99y@xD → AiryAi@H−1L1ê3 xD C@1D +
AiryBi@H−1L1ê3 xD C@2D + a x2 Hypergeometric0F1A 43
, −x3
9E
HypergeometricPFQA9 13=, 9 2
3, 4
3=, −
x3
9E −
12
a x2 Hypergeometric0F1A23
, −x3
9E HypergeometricPFQA9 2
3=, 9 4
3, 5
3=, −
x3
9E==
Come potete vedere, in questo caso la soluzione non è proprio semplice come al solito. Provate a
farlo a mano, se ci riuscite...
Possiamo anche utilizzare le funzioni 'pure':
In[97]:= DSolve@y'@xD x + y@xD, y, xD
Out[97]= 88y → Function@8x<, −1 − x + x C@1DD<<
In questo caso, si vede che il risultato è leggermente diverso. Tuttavia, le funzioni pure sono un
aspetto abbastanza avanzato per noi, per cui vi basti sapere che esistano per adesso, anche se
andremo a vederle meglio più avanti. Se volete studiarvele, al solito, andatevi a leggere l'aiuto in
linea, oppure proseguite spediti verso le vie tortuose che vi sto indicando.
Daniele Lupo Appunti di Mathematica
101Printed by Mathematica for Students
ü Serie di potenze
Fino ad adesso abbiamo considerato sempre funzione e soluzioni esatte. Tuttavia, come molti di voi
sicuramente sapranno, molte volte è più utile utilizzare delle approssimazioni delle funzioni,
scrivendole come serie di potenze. Sicuramente avrete sentito parlare, a magari pure usato, le
formule di Taylor e di MacLaurin. Ricordo che in Analisi 1 era una delle cose che avevo odiato di
più, ma effettivamente mi rendo conto che sono delle cose estremamente utili per noi... Un esempio
semplice semplice? Come studiate i circuiti elettronici a piccolo segnale, senza linearizzazione? E da
cosa viene la teoria della linearizzazione? Bravi, non lo avete detto ad alta voce (almeno spero di
no), ma lo avete pensato.
Mathematica offre comandi (ma và?) anche per questo tipo di problema:
Series[expr, {x, x0, n}] trova l'espansione in serie di expr intorno al punto x =x0 fino all'ordine n
Normal[series] tronca l'espressione in serie in una espressione normale
Magari vi starete chiedendo a cosa serve Normal, vero? No? Pazienza, ve lo spiego comunque...
Consideriamo, per cominciare, l'esempio classico dell'espansione in serie, cioè l'esponenziale:
In[98]:= Series@Exp@xD, 8x, 0, 7<D
Out[98]= 1 + x +x2
2+
x3
6+
x4
24+
x5
120+
x6
720+
x7
5040+ O@xD8
Come potete vedere, Mathematica ha effettuato l'espanzione, nel punto 0, troncando al 6° termine,
che corrisponde alla derivata di ordine 7, come certamente saprete. Tuttavia, compara anche un altro
termine, O@xD. Questo è un infinitesimo. In pratica, dice a Mathematica che l'espressione che
abbiamo trovato non è esatta, ma è troncata e ha un infinitesimo di ordine specificato (nel nostro
caso, 6° ordine). Questo ha una conseguenza molto importante: dato che il programma sa, in questo
caso, che l'espressione trovata è approssimata, quando andremo ad effettuare operazioni su di essa,
darà sempre risultati con la giusta precisione di infinitesimi. E' come se voi avete un numero con due
cifre decimali, ne fate un'operazione e vi spunta un numero con 15 cifre decimali. Se il numero
iniziale era approssimato, è normale che delle 15 cifre, 13 sicuramente non avranno significato... Lo
stesso concetto si può applicare agli infinitesimi. Questo si può notare specialmente quando
compaiono nelle operazioni termini che avrebbero come risultato espressioni di grado superiore.
Supponiamo, per esempio, di prendere il nostro risultato precedente e di elevarlo al quadrato:
In[99]:= %^2
Out[99]= 1 + 2 x + 2 x2 +4 x3
3+
2 x4
3+
4 x5
15+
4 x6
45+
8 x7
315+ O@xD8
Daniele Lupo Appunti di Mathematica
102Printed by Mathematica for Students
In questo caso, vediamo quanto detto poc'anzi: se non avessimo considerato l'infinitesimo, avremmo
avuto un'espressione di quattordicesimo grado. Ciò non era giustificabile, in quanto il grado
massimo della nostra approssimazione era il settimo, e tutti gli altri erano soggetti ad un errore
eccessivo. Se, invece, vi serve l'espressione che avete ottenuto con l'espansione in serie completa,
cioè se non volete, per qualche motivo, considerare l'infinitesimo, allora con il comando Normal lo
potete eliminare (anche un copia ed incolla solo della parte dell'espressione che volete funziona, per
dircela tutta, ma non va se volete automatizzare i calcoli):
In[100]:= Normal@%%D
Out[100]= 1 + x +x2
2+
x3
6+
x4
24+
x5
120+
x6
720+
x7
5040
Come vedete l'espressione (notate che ho preso in considerazione il penultimo risultato con %%), è
senza infinitesimo, e possiamo quindi elevarla al quadrato per ottenere tutti i termini:
In[101]:= %^2
Out[101]= J1 + x +x2
2+
x3
6+
x4
24+
x5
120+
x6
720+
x7
5040N
2
Compare così perchè è la forma più semplice; per averla in forma espansa basta usare il comando
che già conoscete:
In[102]:= Expand@%D
Out[102]= 1 + 2 x + 2 x2 +4 x3
3+
2 x4
3+
4 x5
15+
4 x6
45+
8 x7
315+
127 x8
20160+
41 x9
30240+
19 x10
75600+
x11
25200+
19 x12
3628800+
x13
1814400+
x14
25401600
Et voilà! Pronta per essere cotta a vapore!!!
ü Limiti
Non c'è bisogno che vi spiega cosa sono i limiti, vero? Risparmiatemi tutta la parte sulle differenze
finite e sul rapporto incrementale e su tutto il resto.
Il comando più importante (credo l'unico) che Mathematica ha per calcolarsi i limiti è il seguente:
Limit[expr, x->x0] limite expr quando x tende a x0
Cosa c'è di meglio per un classico esempio di limite della Sinc?
Daniele Lupo Appunti di Mathematica
103Printed by Mathematica for Students
In[103]:= sinc = Sin@xDêx
Out[103]=Sin@xD
x
Come potete intuire, se cerchiamo di calcolarci la funzione in 0, Mathematica ci prende per scemi, ci
riderà in faccia e creerà un virus che ci distruggerà il computer e ci farà venire l'orticaria:
In[104]:= sinc ê. x → 0
— Power::infy : Infinite expression10
encountered. More…
— ∞::indet : Indeterminate expression 0 ComplexInfinity encountered. More…
Out[104]= Indeterminate
Come potete vedere, tutto quello che avevo predetto si è realizzato. Meno male che avevo comprato
un computer di riserva prima di eseguire questo comando...
Comunque, abbiamo visto che non è definito, ma sappiamo anche che esiste il limite:
In[105]:= sinc ê. x → 0.02
Out[105]= 0.999933
Proviamo, quindi, a calcolarci il limite di questa espressione (non è una funzione, vi ricordo, perchè
non l'abbiamo definita come tale. Tuttavia Limit funziona, naturalmente, anche con le funzioni...):
In[106]:= Limit@sinc, x → 0D
Out[106]= 1
Non ve lo sareste mai aspettati, vero?
Comunque, i limiti non finiscono certo qua, come purtroppo sappiamo tutti... Consideriamo, per
esempio, questa funzione:
In[107]:= f@x_D := Sqrt@x^2 − 6 x + 9DêHx − 3L
Come possiamo vedere, la funzione presenta una discontinuità nel punto 3. Proviamo a calcolarci il
limite in questo punto:
Daniele Lupo Appunti di Mathematica
104Printed by Mathematica for Students
In[108]:= Limit@f@xD, x → 3D
Out[108]= 1
Il risultato è esatto solamente a metà. In questi casi, possiamo utilizzare l'opzione Direction:
In[109]:= Limit@f@xD, x → 3, Direction → −1D
Out[109]= 1
In[110]:= Limit@f@xD, x → 3, Direction → 1D
Out[110]= −1
Se scriviamo Direction Ø -1, il limite sarà calcolato a partire da valori più grandi, dando quindi il
limite destro, mentre se poniamo Direction Ø 1, allora calcoleremo il limite a partire da valori più
piccoli, cioè il limite sinistro.
Possiamo naturalmente, nidificando i limiti, trovare limiti per più variabili. Tuttavia bisogna stare
attenti alla direzione da cui si ci arriva. Consideriamo quest'altra funzione classica, che tutti avete
fatto in analisi:
In[111]:= g@x_, y_D := x^2 yêHx^2 + y^2L
Vediamo che, a seconda della direzione con cui la funzione tende ad infinito, la funzione tenderà a 0
oppure a ¶. Si può vedere questo considerando l'ordine dei limite
In[112]:= Limit@Limit@g@x, yD, y → InfinityD, x → InfinityD
Out[112]= 0
In[113]:= Limit@Limit@g@x, yD, x → InfinityD, y → InfinityD
Out[113]= ∞
Come potete vedere, le cose cambiano. Tutavia questi sono problemi propri dell'analisi e della
funzione che prendiamo in considerazione, non del calcolo di Mathematica.
Daniele Lupo Appunti di Mathematica
105Printed by Mathematica for Students
ü Trasformate integrali
Vediamo un altro aspetto di Mathematica, adesso: quello di saper lavorare velocemente e con buoni
risultati con le trasformate integrali, quali quella di Fourier e quella di Laplace:
LaplaceTransform[expr, t, s] trasformata di Laplace di expr
InverseLaplaceTransform[expr, s, t]
trasformata inversa di Laplace di expr
FourierTransform[expr, t, w] trasformata di Fourier di expr
InverseFourierTransform[expr, w, t]
trasformata inversa di Fourier di expr
Il funzionamento di queste funzioni è abbastanza semplice: si scrive l'espressione, poi la variabile
dell'espressione che rappresenta quella indipendente, ed infine la nuova variabile:
In[114]:= LaplaceTransform@Sin@xD Cos@xD, x, sD
Out[114]=1
4 + s2
In[115]:= InverseLaplaceTransform@%, s, xD
Out[115]= Cos@xD Sin@xD
In[116]:= LaplaceTransform@3 x Hx − 9L Sin@xD, x, sD
Out[116]= 3 ikjjj−
18 sH1 + s2L2 +
−2 + 6 s2
H1 + s2L3y{zzz
E andiamo via così all'infinito. Lo stesso possiamo fare, naturalmente, anche per le trasformate di
Fourier:
In[117]:= FourierTransform@Sin@xD Cos@xD, x, wD
Out[117]=12 $%%%%%%π
2DiracDelta@−2 + wD −
12 $%%%%%%π
2DiracDelta@2 + wD
Notate come il programma sia anche in grado di gestirsi espressioni con la Delta di Dirac. Questo
perchè Mathematica ha un approccio simbolico (quante volte lo avrò ripetuto?), e non è, in fondo,
nient'altro che una funzione, e quindi viene trattata come tale. In fondo, non c'è veramente molto
altro da dire riguardo questo argomento... Fatevi qualche esempio e vedete da soli la potenza ed i
limiti di questi comandi.
Daniele Lupo Appunti di Mathematica
106Printed by Mathematica for Students
Calcolo Numericoü Introduzione
Quello che abbiamo visto finora riguarda principalmente il calcolo simbolico. Anche se è uno degli
element che contraddistinguono questo programma dalla massa, sia per il numero di funzioni che per
la loro potenza, le caratteristiche del programma non si fermano certo in quest'aspetto, anzi....
Mathematica contiene una quantità spropositata di algorotmi dedicati per poter risolvere la totalità
dei problemi numerici che possono capitare a questo mondo, ed in questo universo. Le caratteristiche
fondamentali sono la scelta automatica dell'algoritmo e la precisione arbitraria. Con il primo punto,
possiamo stare (quasi) sempre tranquilli e lasciare decidere al programma il metodo migliore per la
risoluzione di un problema: per esempio, per un integrale numerico ci sono i metodi di Simpson,
quello dei trapezi e molti altri che neanche io conosco... Mathematica riesce ad analizzare la
funzione, ed è in grado di decidere da solo quale metodo utilizzare per avere la soluzione migliore al
problema. Chi ha usato qualche volta, in elettronica il programma SPICE (quello originale della
Berkley, non uno dei tanti programmi presenti con grafici etc), sa che vengono usati due principali
algoritmi per la risoluzione delle formule integrali: il metodo trapezoidale e quello di Gear. Sono due
differenti metodi per trovare integrali numerici. Di solito le formule di Gear danno risultati più
precisi, ma hanno problemi di stabilità: per sistemi stiff, cioè con poli lontani dall'origine, può
capitare che il metodo diverga anche quando in realtà converge, e, in minor parte, convergere
quando in realtà diverge, dato che il sistema teorico e quello numerico hanno regioni diverse di
stabilità, dando quindi dei risultati errati, mentre il metodo trapezoidale è a volte meno preciso, ma
rispetta rigorosamente il concetto di stabilità di un sistema, divergendo solo quando effettivamente
siamo di fronte a delle instabilità. Questo porta a dover giocare con le opzioni per essere sicuri di
trovare il metodo che più ci aggrada, e quello che serve per farci avvicinare con maggior precisione
al risultato. Mathematica, d'altrone, per ogni funzione numerica è in grado di trovare da sola
l'algoritmo ideale, applicandolo in maniera del tutto trasparente. Quando andremo a risolvere
un'equazione differenziale, dovremo 'solo' preoccuparci di porre il problema nella maniera corretta,
con le giuste condizioni al contorno, e Mathematica farà il resto. Ci concentriamo, insomma, sul
cosa, non sul come. Questo non toglie il fatto che siamo perfettamente in grado di dire al programma
come risolvere un problema, forzando ad esempio un determinato algoritmo, ma non sono cose di
cui ci preoccupiamo, almeno per ora. Personalmente, non ho mai detto a Mathematica quale
algoritmo utilizzare, e non credo che lo farò mai, a meno di curiosità.
In aggiunta a questo, possiamo anche sfruttare la precisiona arbitraria di Mathematica. Non solo il
programma è in grado di decidere quale algoritmo applicare, ma lo fa con una precisione che
possiamo decidere da soli. Non siamo costretti ad accontentarci della risoluzione dovuta alla
precisione macchina, se 32 o 64 bit. Se vogliamo una soluzione con 10000 cifre significative, con
Daniele Lupo Appunti di Mathematica
107Printed by Mathematica for Students
Mathematica possiamo farlo tranquillamente; il programma basa i suoi calcoli su potenti algoritmi a
precisione arbitraria, che penalizzano quasi di niente la velocità di esecuzione degli algoritmi. Questi
ultimi, fra l'altro, sono altamente ottimizzati, dandoci possibilità di eseguire un numero elevato di
operazioni in relativamente poco tempo.
Adesso, andiamo a vedere le funzioni numeriche di Mathematica. Sono per lo più simili a quelle che
abbiamo già visto per quanto riguarda il calcolo simbolico, almeno nel loro funzionamento base, e
quando non andiamo a toccare le opzioni di default. Se poi vogliamo, possiamo spulciarle per
risolvere anche l'impossibile, utilizzando funzioni quali NSolve ed NDSolve che sono sicuramente
fra i comandi matematici più potenti in assoluto non soltanto in Mathematica, ma in qualsiasi altro
software scientifico che possiate concepire.
ü Sommatorie, Produttorie, Integrali
Abbiamo visto come si risolvono le equazioni simboliche: se ci serve un rusiltato numerico, oppure
il programma non è in grado di trovare la soluzione simbolica, possiamo utilizzare delle funzioni che
sono molto simili, in quanto a sintassi:
NSum[f, {i, imin, Infinity}] approssimazione numerica di ⁄imin¶ f
NProduct[f, {i,imin, Infinity}]
approssimazione numerica di ¤imin¶ f
NIntegrate[f, {x, xmin, xmax}] approssimazione numerica di Ÿxmin
xmax f d x
NIntegrate[f, {x, xmin,xmax}, {y, ymin, ymax}]
approssimazione di Ÿxmin
xmaxd x Ÿymin
ymaxd y f
Proviamo a effettuare qualche calcolo:
In[1]:= NSum@Log@xDêx^5, 8x, 2, Infinity<D
Out[1]= 0.0285738 + 0.
In[2]:= NIntegrate@1êSqrt@Gamma@xD H1 − xLD, 8x, 0, 1<D
Out[2]= 1.61784
Gli integrali possono essere anche calcolati in regioni infite, naturalmente:
In[3]:= NIntegrate@Cos@xD Exp@−Abs@x^2DD, 8x, −Infinity, Infinity<D
Out[3]= 1.38039
Il risultato ottenuto è numerico: è anche possibile lavorare sulla precisione, ma ne parlaremo poco
più avanti, dato che bisogna ragionarci un attimino per poter ottenere il risultato voluto.
Daniele Lupo Appunti di Mathematica
108Printed by Mathematica for Students
ü Soluzione di equazioni
Anche in questo caso, le funzioni sono simili, anche se si aggiunge una funzione interessante, fatta
apposta per il calcolo numerico:
NSolve[lhs==rhs, x] risolve un'equazione polinomiale numericamente
N S o l v e [ {lhs1 = =rhs1 ,lhs2==rhs2, … }, {x, y, … }]
risolve un sistema di equazioni polinomiali nuericamente
FindRoot[lhs==rhs, {x, x0}] cerca una soluzione numerica con seme x = x0
F i n d R o o t [ {lhs1 = =rhs1 ,lhs2==rhs2, … }, {{x, x0},{y, y0}, … }]
cerca soluzioni numeriche per un sistema di equazioni
Abbiamo visto che non esistono soluzioni generali per equazioni polinomiali per un grado superiore
a 4. Tuttavia, possiamo ancora, con il comando NSolve, trovare il risultato numerico per tutte le
radici:
In[4]:= eq = x^7 + 5 x^6 − 34 x^5 + 3 x^4 − 18 x^3 − 64 x + 2 0;
In[5]:= NSolve@eq, xD
Out[5]= 88x → −8.88949<, 8x → −0.73661 − 0.860533 <,8x → −0.73661 + 0.860533 <, 8x → 0.0312415<,8x → 0.716525 − 0.962437 <, 8x → 0.716525 + 0.962437 <, 8x → 3.89842<<
Ovviamente, anche in questo caso noi siamo in grado, tramite questo comando, di trovare soluzioni
di un sistema di equazioni algebrico:
In[6]:= sis = 8x^3 − 4 y^2 3 z^5,x − y z^2,x^2 + y^2 + z^1 0<;
In[7]:= NSolve@sis, 8x, y, z<D êê TableForm
Out[7]//TableForm=
x → −43.596 − 36.3488 y → −36.4276 + 43.5925 z → −6.0454 + 6x → −43.596 + 36.3488 y → −36.4276 − 43.5925 z → −6.0454 − 6x → 0.118835 y → −1.028 z → −1.0709x → −0.276836 − 0.943164 y → 1.19596 − 0.727046 z → −0.088803x → −0.276836 + 0.943164 y → 1.19596 + 0.727046 z → −0.088803x → 0.670104 y → 0.346348 z → −0.568996x → −0.607146 + 0.662123 y → 0.000898087 + 0.351493 z → 0.193327 +x → −0.607146 − 0.662123 y → 0.000898087 − 0.351493 z → 0.193327 −x → 0.0855246 − 0.855851 y → −0.428419 − 0.468186 z → 0.760822 −x → 0.0855246 + 0.855851 y → −0.428419 + 0.468186 z → 0.760822 +
x → 3.76926 × 10−12 y → 3.76926 × 10−12 z → 0.x → 0. y → 0. z → 0.
Daniele Lupo Appunti di Mathematica
109Printed by Mathematica for Students
Effettivamente, sono un pochino di soluzioni in più di quanto pensassi... Non devo più fare degli
esempi a caso, mi sa...
Vediamo come possiamo facilmente trovare tutte le soluzioni, e senza bisogno di andare a mettere
punti iniziali per tentare di trovarli ad uno ad uno. Purtroppo, questo però è l'unico metodo se le
equazioni non sono algebriche, ma di tipo generale. Questo significa che abbiamo bisogno di un
punto iniziale per iniziare la ricerca, e che troveremo soltanto una soluzione, anche se ne sono
presenti più di una. Per trovare altre eventuali soluzioni, dobbiamo creare un altro punto iniziale ed
effettuare un'altra ricerca. In questo caso, bisogna usare il comando FindRoot:
In[8]:= eq = 10 Cos@ Cos@xDD Log@x^2D;
In[9]:= FindRoot@eq, 8x, 1<D
Out[9]= 8x → −33.8957<
Tuttavia possiamo vedere come, se usiamo un altro seme, possiamo andare a trovare un altra
soluzione:
In[10]:= FindRoot@eq, 8x, 5<D
Out[10]= 8x → −41.5941<
Si può vedere che le soluzioni, in questo caso, sono parecchie, e occorre un'oculata scelta del punto
iniziale. Fra l'altro, potete anche vedere che non è vero che basta prendere un punto vicino ad una
soluzione, per ottenere proprio quella cercata. Questo perchè nell'algoritmo iterativo che
Mathematica sceglie, può capitare che il punto, durante le iterazioni, si allontani.
E, tanto per cambiare, possiamo usare FindRoot anche per poter trovare soluzioni di un sistema di
equazioni qualsiasi:
In[11]:= sis = 8Cos@xD Log@Sqrt@x yDD, Tan@yD Gamma@xD<;
In[12]:= FindRoot@sis, 88x, 1<, 8y, 3<<D
Out[12]= 8x → 0.889268, y → 3.96425<
Potete vedere come le possibilità di trovare la soluzione numerica sono sempre quasi certe, anzi
praticamente sempre, a parte problemi di convergenza, che comunque capitano davvero raramente,
data la robustezza degli algoritmi impiegati.
Daniele Lupo Appunti di Mathematica
110Printed by Mathematica for Students
ü Equazioni differenziali
Quello che abbiamo visto per le equazioni, possiamo averlo anche per quelle differenziali, anche se
con una piccola differenza. Infatti bisogna considerare che adesso, invece di dover restituire dei
valori, il comando restituisce una funzione interpolata, dato che viene calcolata per punti: inoltre,
dato che la soluzione è numerica, dobbiamo sempre definire completamente le condizioni al
contorno:
NDSolve[eqns, y, {x,xmin, xmax}]
risolve numericamente la funzione y, con lavariabile indipendente x nel raggio da xmin a xmax
NDSolve[eqns, {y1, y2, …}, {x, xmin, xmax}]
risolve numericamente la funzione nelle variabili yi
In questo modo, vediamo come possiamo risolve numericamente equazioni differenziali anche
abbastanza difficili:
In[13]:= diff = y'@xD + Log@y@xDD x;
In[14]:= NDSolve@8diff, y@1D 2<, y, 8x, 2, 7<D
Out[14]= 88y → InterpolatingFunction@882., 7.<<, <>D<<
Vediamo un'importante differenza, cioè che dobbiamo specificare y come funzione pura, dato che
troviamo y e non y@xD: tuttavia per ora non importa molto, se sappiamo come utilizzarla. Una volta
trovata la soluzione, infatti, per poter trovare un valore all'interno dell'intervallo dove l'abbiamo
risolta, dobbiamo usare la regola:
In[15]:= y@4D ê. %
Out[15]= 85.91218<
Viene detto a Mathematica, in pratica, di sostituire al nome della funzione la funzione pura, in modo
che la funzione si trasformi in quella desiderata. Le regole, infatti, oltre che alle variabili, si
applicano anche ai nomi delle funzioni; in effetti, si applicano a qualsiasi cosa...
Se andiamo fuori range, la funzione non è definita, e Mathematica non sa come calcolarla:
In[16]:= y@40D ê. %%
— InterpolatingFunction::dmval : Input value 840< lies outside the range of data in the
interpolating function. Extrapolation will be used. More…
Out[16]= 8723.148<
Daniele Lupo Appunti di Mathematica
111Printed by Mathematica for Students
In questo caso si decide di eseguire una estrapolazione, soluzione che io sconsiglio sempre.
Possiamo vedere di calcolare la funzione anche in quest'ultimo punto:
In[17]:= NDSolve@8diff, y@1D 2<, y, 8x, 2, 40<D
Out[17]= 88y → InterpolatingFunction@882., 40.<<, <>D<<
E vedere di quanto differisce la soluzione estrapolata da quella interpolata all'interno dell'intervallo
in cui abbiamo definito la funzione:
In[18]:= y@40D ê. %
Out[18]= 8623.523<
Possiamo vedere come differiscano di una quantità notevole, molto al di là del semplice errore di
approssimazione numerica.
10 20 30 40
100
200
300
400
500
600
700
Notiamo come non abbiamo dovuto specificare nessun particolare algoritmo per trovare la
soluzione, dato che Mathematica lo sceglie automaticamente tramite dei criteri molto rigorosi. In
effetti, NDSolve è uno dei comandi più potenti che ci siano all'interno di Mathematica, perchè
permette di risolvere problemi che sono veramente complicati, di quelli per cui si utilizzano i
supercomputer; infatti, del programma ne esiste una versione apposita da far girare su quei mostri,
ed utilizza gli stessi algoritmi presenti nella versione standard.
Il motivo principale della potenza di questo comando risiede principalmente nel poter stabilire, nella
quasi totalità dei problemi, automaticamente il tipo di algoritmo da utilizzare, evitando problemi di
stabilità e precisione che derivano dall'utilizzo di un algoritmo non adatto al problema. Un esempio
Daniele Lupo Appunti di Mathematica
112Printed by Mathematica for Students
classico si ha nella scelta fra le formule di Gear e quella trapezoidale; mentre la prima ha una
precisione maggiore, la seconda presenta un diagramma di stabilità che coincide con quello teorico,
per cui, se una soluzione deve mettersi ad oscillare, con il trapezoidale lo farà, anche se magari avrò
uno scarto maggiore fra la soluzione vera e quella approssimata. Invece, con Gear, possiamo
raggiungere una maggior precisione, ma ha un diagramma di stabilità diverso, il che implica che
potrebbe non oscillare la soluzione di un'equazione dofferenziale, cosa che invece accade poi nella
realtà. Capite quindi l'importanza di scegliere il giusto algoritmo, ma chi ha fatto calcolo numerico
oppure materie di progettazione assistita da calcolatore, conosce bene questi problemi. il bello è che
Mathematica li conosce pure, e fa la fatica di scegliere il giusto algoritmo al posto nostro. Come ci
riesce, non lo so... bisognerebbe chiederlo direttamente a Sthepen Wolfram, se qualcuno ne è
capace...
ü Ottimizzazione numerica
Naturalmente, nessun programma che vanti propietà di calcolo numerico si può definire tale senza
delle funzioni specifiche per trovare i massimi ed i minimi delle funzioni. Mathematica offre
comandi specifici nel caso si voglia trovare il massimo oppure il minimo globale di una funzione e,
nel caso non esista o non sia fattibile, anche funzioni per trovare massimi e minimi locali:
NMinimize[f, {x, y, … }] minimizza f
NMaximize[f, {x, y, … }] massimizza f
NMinimize[{f, ineqs}, {x, y,… }]
minimizza f sotto le condizioni di ineqs
NMaximize[{f, ineqs}, {x, y,… }]
massimizza f sotto le condizioni di ineqs
FindMinimum[f, {x, x0}] cerca il minimo locale di f, partndo da x = x0
FindMinimum[f, {{x, x0},
{y, y0}, … }] cerca il minimo locale in più variabili
FindMaximum[f, {x, x0}] cerca per un massimo locale
La funzione NMinimize e NMaximize, oltre che trovare il punto dove la funzione è minima,
restituisce anche il valore della funzione in quel punto:
In[19]:= NMaximize@xêH1 + Exp@xDL, xD
Out[19]= 80.278465, 8x → 1.27846<<
Possiamo imporre anche delle regioni dove trovare il minimo oppure il massimo:
In[20]:= eq = Cos@xD Sin@x yD;
In[21]:= regione = x^2 + y^2 < 2;
Daniele Lupo Appunti di Mathematica
113Printed by Mathematica for Students
In[22]:= NMaximize@8eq, regione<, 8x, y<D
Out[22]= 80.580755, 8x → 0.672134, y → 1.24428<<
Nel caso che non sia possibile trovare direttamente il minimo globale, o se si è interessati a trovarne
uno locale, dobbiamo andare ad utilizzare le altro funzioni che abbiamo visto sopra:
In[23]:= FindMinimum@Log@xD Cos@Sqrt@xDD, 8x, 10<D
Out[23]= 8−2.36686, 8x → 11.4238<<
In[24]:= FindMinimum@Log@xD Cos@Sqrt@xDD, 8x, 130<D
Out[24]= 8−4.49167, 8x → 89.7131<<
Possiamo vedere come la stessa funzione, dati valori iniziali diversi, abbia risultati diversi, segno che
in questo caso ci troviamo di fronte ad una funzione con più minimi, e ne scegliamo alcuni a seconda
del punto iniziale.
20 40 60 80 100 120 140
-4
-2
2
4
CVD... Vedete come siano presenti più minimi (e anche più massimi), e come la funzione diverge e
non sia effettivamente presente un minimo (massimo) globale.
Trovare il minimo (o massimo) assoluto numericamente può diventare difficile... Il problema
principale risiede sempre nel fatto che numericamente si eseguono varie iterazioni che, a seconda
della forma della funzione, possono non trovare esattamente il minimo od il massimo globale, ma
soltanto uno locale. Questo dipende sempre dal metodo di ricerca, e da come viene scelto il punto
Daniele Lupo Appunti di Mathematica
114Printed by Mathematica for Students
iniziale.
I metodi di ricerca del minimo globale si basano quasi tutti sulla ricerca di una direzione verso cui
andare a cercare il minimo, ripetendo il procedimento iterativamente fino a quando il risultato non
rientra nella tolleranza cercata: ovviamente, per funzioni particolarmente 'tortuose', la ricerca del
giusto cammino può diventare qualcosa di veramente difficile per qualsiasi algoritmo.
Supponiamo di avere una funzione di questo tipo:
In[25]:= f@x_, y_D := Exp@Sin@60 xDD + Sin@60 yD +
Sin@70 Sin@xDD + Sin@Sin@80 yDD − Sin@10 Hx + yLD +1
4Hx2 + y2L
Il grafico di questa funzione è il seguente, riportato in maniera bidimenisionale:
-1 -0.5 0 0.5 1-1
-0.5
0
0.5
1
Come potete vedere, di massimi e di minimi ce n'è a iosa, e non è facile andare a trovare il minimo.
Proviamo con Minimize:
In[26]:= Minimize@f@x, yD, 8x, y<D
Out[26]= MinimizeA Sin@60 xD +14Hx2 + y2L + Sin@60 yD −
Sin@10 Hx + yLD + Sin@70 Sin@xDD + Sin@Sin@80 yDD, 8x, y<E
In questo caso, non abbiamo ottenuto un bel niente... Proviamo a risolverlo numericamente:
Daniele Lupo Appunti di Mathematica
115Printed by Mathematica for Students
In[27]:= NMinimize@f@x, yD, 8x, y<D
Out[27]= 8−2.01986, 8x → −1.48893, y → 0.291833<<
Abbiamo sicuramento trovato un minimo, ma non abbiamo la certezza, in questo caso, di aver
trovato proprio quello globale, per il semplice fatto che la funzione è fortemente non quadratica e
lineare, e quindi i metodi numerici hanno notevoli difficoltà a trovarlo. Effettivamente, ci sono punti
che hanno un valore inferiore, segno che le coordinate trovate non corrispondono ad un minimo:
In[28]:= f@−0.024, 0.21D
Out[28]= −3.32725
I metodi numerici devono quindi essere sempre esaminati con attenzione, come d'altronde capita in
tutti gli algoritmi: utilizzarli alla cieca non serve a niente, e crea solo danno. Bisogna saper bene
quello che si sta facendo, e conoscere i limiti ed i vantaggi degli algoritmi che si utilizzano, perchè
possono portare, come in questo caso, a risultati errati che possono essere considerati giusti se non ci
si pone la giusta attenzione. Bisogna anche considerare che funzioni realmente complicate come
questa, nella pratica non saranno incontrate molto spesso; per le funzioni che possiamo definire
'normali' (per esempio senza 4000 minimi nell'intervallo (0,1)), il comando funziona egregiamente.
Soprattutto se abbiamo comunque un'idea di dove si dovrebbe trovare il minimo globale. Tutti i
metodi di ricerca del minimo, infatti, lavorano meglio se il punto iniziale della ricerca si trova
nell'intorno di quest'ultimo. Comunque vedremo meglio questo problema in una delle appendici di
questo tutorial.
ü Dati numerici
Abbiamo visto fino ad adesso come trattare numericamente le funzioni. Tuttavia, ci sono casi in cui
ciò non è possibile. Si pensi, per esempio, ai dati sperimentali di qualche esperienza: in questo caso
non abbiamo delle funzioni, ma solamente una lista di valori, un campionamento, la variazione di un
parametro del transistor a variare della temperatura e così via: dobbiamo poter trattare anche questo
tipo di dati, elaborarli ed in genere fare con loro quello che vogliamo.
Un'operazione che possiamo effetutare su questi valori, è trovare la funzione che li approssima
meglio; per poter ottenere questo risultato Mathematica ci viene in aiuto con i suoi comandi di fitting:
Fit[{y1, y2, … }, { f1, f2, …}, x]
esegue il fitting dei valori yn con unacombinazione lineare delle funzioni fi
Fit[{{x1, y1}, {x2, y2}, …}, { f1, f2, … }, x]
lo stesso di prima, ma per funzioni evalori multidimensionali.
Adesso, creeremo con Table una lista di valori, e poi cerceremo di effettuare il fitting, usando il
metodo dei minimi quadrati:
Daniele Lupo Appunti di Mathematica
116Printed by Mathematica for Students
In[29]:= dati = Table@Exp@xê5.D + Random@D, 8x, 10<D;
Vediamo adesso di sfruttare il comando appena appreso per scrivere il fitting di questi dati usando,
per esempio, una funzione quadratica, quindi combinazione lineare delle funzioni 1, x, x2:
In[30]:= Fit@dati, 81, x, x^2<, xD
Out[30]= 2.21615 − 0.265065 x + 0.08228 x2
Si vede come abbiano effettuato il fitting dei dati. Naturalmente potevamo avere anche 10000000
punti, e Mathematica avrebbe effettuato il fitting con la stessa facilità.
Oltre a questo, possiamo scrivere direttamente un'equazione parametrizzata, specificare i parametri e
il programma, invece di effettuare una combinazione lineare, aggiusta i parametri in modo di
effettuare il fitting dei dati:
FindFit[data, form, {p1, p2,… }, x]
trova il fitting form con i parametri pi
Possiamo fare lo stesso esempio di sopra, scrivendo l'equazione quadratica parametrizzata e
verificando se il risultato è uguale a quello che abbiamo trovato in precedenza:
In[31]:= FindFit@dati, a x^2 + b x + c, 8a, b, c<, xD
Out[31]= 8a → 0.08228, b → −0.265065, c → 2.21615<
In[32]:= a x^2 + b x + c ê. %
Out[32]= 2.21615 − 0.265065 x + 0.08228 x2
Possiamo vedere come l'equazione ottenuta sia effettivamente la stessa della precedente. Tuttavia,
dato che qua si parla di parametri e non di combinazione lineare, possiamo effettuare anche fitting
non lineari:
In[33]:= FindFit@dati, a + b x + Sin@Sqrt@c xDD, 8a, b, c<, xD
Out[33]= 8a → 0.131899, b → 0.757938, c → 3.73583<
Abbiamo quindi visto come è possibile non solo elaborare funzioni con Mathematica, ma anche dati.
Ovviamente non abbiamo neanche scalfito le potenzialità del programma. Le funzionalità vanno ben
oltre, come calcolare in pochi secondi trasformate numeriche di Fourier di milioni di elementi,
oppure effettuare calcoli statistici sui dati, come il valor medio con la funizione Mean, la mediana
con Median, la deviazione standard con (indovinate?) StandardDeviation e così via.
Daniele Lupo Appunti di Mathematica
117Printed by Mathematica for Students
Non ho avuto molto a che fare, sinceramente, con le funzioni riguardanti la statistica...
Probabilmente, appena comincerò la tesi e dovrò elaborare le misure degli esperimenti, vedrò meglio
questo concetto. Comunque posso vedere che le funzioni di Mathematica dedicate alla statistica non
sono numerose come negli altri campi. Per questo, negli Extra packages dell'installazione standard
ve ne sono numerosi riguardanti la statistica. Se vi serve qualcosa di avanzato, è probabile che prima
dobbiate caricare quello che vi interessa. Andate a spulicarli, se vi serve, e decidete quale usare di
volta in volta. Se li usate spesso, però, nelle opzioni del programma potete decidere di caricarli
all'avvio, per cui vedete un po' voi.
ü Precisione
Abbiamo visto come è facile risolvere problemi numerici con funzioni così potenti. Gli esempi che
vi ho fatto vedere non devono trarre in inganno. Ho usato sempre funzioni semplici, ma questo per
farvi capire il contetto, e perchè funzioni troppo complicate potrebbero distrarre da quello che è il
funzionamento del programma. Però vi posso assicurare che Mathematica digerisce veramente di
tutto.
Quello che ancora non avete visto, però, è come possiamo usare la precisione arbitraria. Le funzioni
che abbiamo utilizzato finora, infatti, usano la precisione di macchina. Se vogliamo invece ottenere
un numero superiore di cifre significative, dobbiamo specificare al programma che ne abbiamo
bisogno. In questo modo dobbiamo un pochino giocare con le opzioni delle funzioni, per specificare
come giostrarci la situazione.
WorkingPrecision numero di cifre da usare nel calcolo
PrecisionGoal numero di cifre della precisione che si cercadi raggiungere
AccuracyGoal numero di cifre dell'accuratezza che si cercadi raggiungere
Una delle opzioni che vengono usate in questo caso è WorkingPrecision. Precisamente, se si pone
uguale ad n, si forza il comando ad utilizzare n cifre significative per l'algoritmo:
In[34]:= NIntegrate@Sin@Log@xDD, 8x, 5, 9<, WorkingPrecision → 70D
Out[34]= 3.689003334597008878366246602388423393856254806708080513846498696
Come possiamo vedere in questo caso, abbiamo ottenuto la precisione richiesta. Per default, il
parametro è fissato alla costante MachinePrecision, che dice in pratica di utilizzare la precisione
macchina su cui si lavora. Tuttavia, sappiamo che se effettuiamo un calcolo numerico con una
precisione di n cifre, le ultime di solito non sono significative, per gli errori di troncamento che si
hanno, e che abbiamo sicuramente tutti quanti studiato a calcolo numerico. Per vedere la precisione,
Daniele Lupo Appunti di Mathematica
118Printed by Mathematica for Students
quindi il numero di cifre significative, del risultato che abbiamo ottenuto, possiamo usare il comando
Accuracy:
In[35]:= Accuracy@%D
Out[35]= 63.0291
Tuttavia, una volta specificato questo parametro, possiamo giocare definendo all'interno di questo
range il numero di cifre significative ed il numero di cifre di accuratezza, perchè WorkingPrecision
definisce solamente un limite superiore. Questo perchè, per ragioni teoriche sulla convergenza,
anche poche cifre significative in più possono aumentare in modo notevole il tempo di calcolo.
Tuttavia, in molti casi è necessario sapere con precisione l'accuratezza con cui troviamo la soluzione
numerica
In[36]:= NIntegrate@Sin@Log@xDD, 8x, 5, 9<,WorkingPrecision → 70, PrecisionGoal → 50D
Out[36]= 3.68900333459700887836624660238842339385625480670808
In[37]:= Accuracy@%D
Out[37]= 50.5546
Vediamo che adesso, anche se abbiamo utilizzato una precisione di 70 cifre, la precisione richiesta è
soltanto di 50 cifre, e l'accuratezza è rimasta tale:
In[38]:= NIntegrate@Sin@Log@xDD, 8x, 5, 9<,WorkingPrecision → 70, AccuracyGoal → 68, PrecisionGoal → 30D
Out[38]= 3.689003334597008878366246602388423393856
In[39]:= Accuracy@%D
Out[39]= 39.2759
Possiamo vedere che, settando entrambi i valori, il calcolo si ferma una volta raggiunta la condizione
che restituisce il numero inferiore di cifre, perchè si è raggiunta una condizione. Tuttavia dobbiamo
notare come tutte le considerazioni vadano considerate sempre all'interno di WorkingPrecision:
Daniele Lupo Appunti di Mathematica
119Printed by Mathematica for Students
In[40]:= NIntegrate@Sin@Log@xDD, 8x, 5, 9<,WorkingPrecision → 30, PrecisionGoal → 50D
— NIntegrate::tmap : NIntegrate is unable to achieve the tolerances specified by the
PrecisionGoal and AccuracyGoal options because the working precision isinsufficient. Try increasing the setting of the WorkingPrecision option.
Out[40]= 3.68900333459700887836624660239
In[41]:= Accuracy@%D
Out[41]= 29.1321
In questo caso si vede che abbiamo cercato di raggiungere una precisione con un numero di cifre
superiore rispetto a quelle usate per il calcolo, cosa che ovviamente è senza senso, e Mathematica si
ferma al numero di cifre utilizzate per il calcolo, segnando questa incongruenza con un warning. In
teoria non possiamo dire niente riguardo il risltato ottenuto, perchè si è interrotto prima di verificare
la convergenza, ma possiamo vedere come il risultato ottenuto abbia la massima precisione possibile
per il numero di cifre che abbiamo preso in esame. Tuttavia questa non è una regola, e il consiglio è
di variare le opzioni in modo che nel risultato non compaia nessun warning. AccuracyGoal e
PrecisionGoal sembrano fare la stessa cosa, ma in realtà hanno significato leggermente diverso a
seconda del tipo di comando che si utilizza, cone ad esempio NIntegral piuttosto che NDSolve.
In[42]:= Options@NDSolveD
Out[42]= 9AccuracyGoal → Automatic, Compiled → True,
DependentVariables → Automatic, EvaluationMonitor → None,
MaxStepFraction →1
10, MaxSteps → Automatic,
MaxStepSize → Automatic, Method → Automatic,NormFunction → Automatic, PrecisionGoal → Automatic,SolveDelayed → False, StartingStepSize → Automatic,StepMonitor → None, WorkingPrecision → MachinePrecision=
In[43]:= Options@NIntegrateD
Out[43]= 8AccuracyGoal → ∞, Compiled → True, EvaluationMonitor → None,GaussPoints → Automatic, MaxPoints → Automatic, MaxRecursion → 6,Method → Automatic, MinRecursion → 0, PrecisionGoal → Automatic,SingularityDepth → 4, WorkingPrecision → MachinePrecision<
Options è una funzione che serve per vedere tutte le opzioni di una funzione, in modo da sapere
quali sono. Possiamo vedere come nelle due funzioni prese in considerazione, di default si sceglie
WorkingPrecision proprio uguale a MachinePrecision, ma come, per esempio, abbiano un valore
diverso di AccuracyGoal, perchè la natura interna delle funzioni preferisce lavorare su una opzione
piùttosto che su un altra. In particolare, il valore ¶ indica di considerare solo se sono soddisfatte le
Daniele Lupo Appunti di Mathematica
120Printed by Mathematica for Students
condizioni dell'altra opzione: in NIntegrate accuracyGoal è settata su ¶, per cui le condizioni di
terminazione dell'algoritmo sono date esclusivamente da PrecisionGoal. Tuttavia, nei casi normali,
un semplice cambiamenti di WorkingPrecision può bastare, dato che in questo modo le altre due
sono risettate automaticamente, dato che Automatic significa il loro valore si modifica
automaticamente al variare di WorkingPrecision.
Daniele Lupo Appunti di Mathematica
121Printed by Mathematica for Students
Grafica e suoniü Introduzione
Abbiamo visto, fino ad adesso, come si possono elaborare funzioni, risolvere equazioni e così via.
Tuttavia, molte volte è necessario trovare il modo di poter visualizzare tramite grafici ed immagini i
risultati così ottenuti. Per esempio, se si crea un filtro per un'immagine, viene naturale, invece di
andare a guardare liste interminabili di numeri di cui non capite niente, fare direttamente un
confronto fra l'immagine iniziale e quella finale, oppure rappresentare graficamente l'andamento di
una funzione, o visualizzare un campo vettoriale.
Mathematica in questo campo ha numerose funzioni, che permettono di visualizzare praticamente
ogni cosa voi vogliate. Ci sono comandi specifici per grafici a due e tre dimensioni, ed anche per la
tipologia di grafico.
Come ultima nota, vedrete che questo capitolo sarà uno dei più lunghi (se non il più lungo). Non
spaventatevi di ciò, e dal numero di pagine, perchè il loro elevato numero è dovuto al fatto che
saranno infarcite di numerose immagini. Con ciò, naturalmente, non voglio dire che starete per
leggere un fumetto... Di carne al fuoco ce n'è tanta...
ü Grafica
Funzioni ad una variabile
Il comando principale con cui si disegnano le funzioni (fra cui quasi tutte quelle che avete visto
finora) è Plot:
Plot[f, {x, xmin, xmax}] disegna f nella variabile x da xmin a xmax
Plot[{ f1, f2, … }, {x,xmin, xmax}]
disegna assieme più funzioni
Il comando ha moltissime opzioni che permettono di personalizzare il grafico, ma per ora ci basta
sapere questo. Vediamo subito un esempio di come si disegna una funzione:
Daniele Lupo Appunti di Mathematica
122Printed by Mathematica for Students
In[1]:= Plot@BesselJ@0, xD, 8x, 0, 10<D;
2 4 6 8 10
-0.4
-0.2
0.2
0.4
0.6
0.8
1
Vediamo come il grafico sia automaticamente scalato nell'asse y.
Possiamo anche visualizzare più funzioni nello stesso grafico:
In[2]:= Plot@8BesselJ@0, xD, BesselJ@1, xD, BesselJ@2, xD<, 8x, 0, 10<D;
2 4 6 8 10
-0.4
-0.2
0.2
0.4
0.6
0.8
1
Vediamo come le funzioni appaiano sovrapposte fra di loro. Naturalmente, in questo caso, dobbiamo
specificare lo stesso dominio per ciascuna funzione, e quindi avremo bisogno di una sola variabile x
per tutte e tre le funizioni.
Daniele Lupo Appunti di Mathematica
123Printed by Mathematica for Students
Nel caso si voglia realizzare il grafico di una lista di funzioni definita con Table, le cose cambiano
leggermente: supponiamo, infatti, di avere:
In[3]:= lista = Table@ChebyshevT@n, xD, 8n, 8<D;
In[4]:= Plot@lista, 8x, −1, 1<D
— Plot::plnr : lista is not a machine−size real number at x = −1.. More…
— Plot::plnr : lista is not a machine−size real number at x = −0.918866. More…
— Plot::plnr : lista is not a machine−size real number at x = −0.830382. More…
— General::stop : Further output of Plot::plnr will be suppressed during this calculation. More…
0.2 0.4 0.6 0.8 1
0.2
0.4
0.6
0.8
1
Out[4]= Graphics
In questo caso possiamo vedere che non possiamo visualizzare le funzioni, restituendo degli errori
ed un grafico vuoto. Questo perchè, in questa notazione, prima vengono valutati i valori della x per
generare il grafico, e dopo viene sostituita alle funzioni: in questo caso, invece è necessario prima
valutare la tavola di valori, e poi andare a sostituire i valori di x. Questo si fa con il comando
Evaluate:
Daniele Lupo Appunti di Mathematica
124Printed by Mathematica for Students
Plot[f, {x, xmin, xmax}] prima specifica precisi valori di x, dopo valuta f perogni valore di x
Plot[Evaluate[f], {x,xmin, xmax}]
prima valuta f, sceglie specifici valori numerici x
Plot[Evaluate[Table[f,… ]], {x, xmin, xmax}]
genera una lista di funzioni, e poi li disegna
Plot[Evaluate[y[x]/. solution], {x, xmin,
plotta un'equazione differenziale numericaottenuta tramite NDSolve
Riproviamo ad effettuare, adesso, il plottaggio precedente, ma stavolta con Evaluate:
In[5]:= Plot@Evaluate@listaD, 8x, −1, 1<D
-1 -0.5 0.5 1
-1
-0.5
0.5
1
Out[5]= Graphics
Vediamo come adesso, avendo valutato prima la tavola di funzioni, questa adesso sia correttamente
riconosciuta, permettendoci di disegnare i grafici di tutte le funzioni definite. Nel primo caso si
mantiene la valutazione simbolica di lista, quindi Table non veniva sviluppata, e di conseguenza
Mathematica non riconosceva le funzioni, impedendo di poter disegnare i grafici.
Quello che dovete ricordare, quindi, è che quando create una serie di funzioni con Table, dovete
usare il comando Evaluate. Supponiamo di trovarci la soluzione numerica di un'equazione
differenziale:
In[6]:= eq = y''@xD + Sin@y'@xDD y@xD x y@xD;
Daniele Lupo Appunti di Mathematica
125Printed by Mathematica for Students
In[7]:= NDSolve@8eq, y@0D 1, y'@0D 3<, y, 8x, 0, 4<D
Out[7]= 88y → InterpolatingFunction@880., 4.<<, <>D<<
Abbiamo visto che la soluzione viene data in forma di funzione pura, quindi, per quello che serve a
noi, bisogna prima valutare la funzione sostituita, e poi andare a graficarla:
In[8]:= Plot@Evaluate@y@xD ê. %D, 8x, 0, 3<D
0.5 1 1.5 2 2.5 3
10
20
30
40
50
Out[8]= Graphics
In realtà, avremmo ottenuto lo stesso risultato anche senza Evaluate, ma il tempo impiegato sarebbe
diverso;
In[9]:= eq2 = y'@xDêSqrt@y@xDD Sin@x^2D;
In[10]:= NDSolve@8eq2, y@0D 3<, y, 8x, 0, 50<D
Out[10]= 88y → InterpolatingFunction@880., 50.<<, <>D<<
Daniele Lupo Appunti di Mathematica
126Printed by Mathematica for Students
In[11]:= Timing@Plot@Evaluate@y@xD ê. %D, 8x, 0, 50<DD
10 20 30 40 50
4.05
4.15
4.2
4.25
4.3
Out[11]= 80.016 Second, Graphics <
In[12]:= Timing@Plot@y@xD ê. %%, 8x, 0, 50<DD
10 20 30 40 50
4.05
4.15
4.2
4.25
4.3
Out[12]= 80.015 Second, Graphics <
Come potete vedere, il risultato grafico è lo stesso. Tuttavia il tempo impiegato per eseguire la
funzione è diverso; con Timing, infatti, si calcola il tempo macchina per effettuare l'operazione che
ha come argomento, e nel secondo caso abbiamo impiegato un tempo maggiore (sempre poco,
effettivamente).
Daniele Lupo Appunti di Mathematica
127Printed by Mathematica for Students
La differenza, in questo caso, sta in questo: nel primo grafico, usando Evaluate, prima abbiamo
valutato la funzione, e quindi abbiamo ottenuto la funzione interpolata, e dopo siamo andati a
sostituire i valori di x alla funzione, andando a trovare i valori e quindi a graficarli. Nel secondo
caso, invece, prima andiamo a calcolarci il valore di x in cui valutare la funzione, e poi andiamo a
valutare la funzione in quel punto; allora, dato che nella funzione c'è una regola di sostituzione,
invece di applicarla solamente una volta, come nel primo caso, la applichiamo per ogni punto x che
calcoliamo. andando ad eseguire quindi un tot numero di sostituzioni identiche, una per ogni punto
che Mathematica usa per creare il grafico. Per funzioni complicate e con molti punti, questo può
rallentare notevolmente il processo, specialmente su computer lenti.
Opzioni di disegno
Abbiamo visto come disegnare le funzioni. Tuttavia, a volte è utile poter personalizzare le opzioni di
visualizzazione dei grafici, per modificarne lo stile, oppure per evidenziarne alcune caratteristiche
particolari. Se andiamo a vedere le opzioni disponibili per il comandio Plot, vediamo che ce ne sono
parecchie:
In[13]:= Options@PlotD
Out[13]= 9AspectRatio →1
GoldenRatio, Axes → Automatic, AxesLabel → None,
AxesOrigin → Automatic, AxesStyle → Automatic, Background → Automatic,ColorOutput → Automatic, Compiled → True, DefaultColor → Automatic,DefaultFont $DefaultFont, DisplayFunction $DisplayFunction,Epilog → 8<, FormatType $FormatType, Frame → False, FrameLabel → None,FrameStyle → Automatic, FrameTicks → Automatic, GridLines → None,ImageSize → Automatic, MaxBend → 10., PlotDivision → 30.,PlotLabel → None, PlotPoints → 25, PlotRange → Automatic,PlotRegion → Automatic, PlotStyle → Automatic, Prolog → 8<,RotateLabel → True, TextStyle $TextStyle, Ticks → Automatic=
Alcune sono utili, altre invece non verranno usate quasi mai: vediamo il loro significato:
ø Axes: definisce se dobbiamo disegnare o no gli assi dei grafici. Se lo impostiamo su False gli assi
non verranno disegnati.
ø AxesLabel: imposta il titolo delle etichette da imporre agli assi cartesiani, in modo da visualizzarli
sul grafico; si usa principalmente per evidenziare la grandezza che corrisponde all'ascissa o
all'ordinata.
ø AspectRatio: rappresenta il rapporto fra larghezza ed altezza del grafico: possiamo imporre un
valore numerico
ø AxesOrigin: definisce il centro in cui verranno rappresentati gli assi cartesiani. Di default è
impostato su Automatic, che definisce quindi il centro degli assi (0,0), se questo è visibile nel
Daniele Lupo Appunti di Mathematica
128Printed by Mathematica for Students
grafico, altrimeni viene impostato in modo che gli assi si trovino nei margini del grafico. Possiamo
comunque impostarlo manualmente per avere l'origine, per esempio, nel massimo di una funzione,
conoscendo il punto.
ø AxesStyle: con questa opzione possiamo imporre lo stile degli assi, per esempio modificandone il
colore, oppure lo spessore delle linee.
ø Background: imposta il tipo di sfondo del grafico, impostando il colore, oppure, mediante scrittura
più avanzata, magari un'immagine oppure un gradiente (anche se non ci sono mai riuscito a fare uno
sfondo che non sia uniforme, ancora...).
ø ColorOutput: questa opzione specifica il tipo di output di colore che viene utilizzato per una
funzione. Permette, per esempio, di disegnare un gradico in scals di grigi invece che a colori, oppure
in colori RGB.
ø Compiled: specifica se una funzione deve essere compilata dal motore interno di Mathematica
prima di poter calcolare i valori della funzione per il plottaggio: di solito si imposta di default su
True, ma può essere impostato su False per alcuni tipi di grafico, se per esempio è necessaria un'alta
precisione numerica, il che a volte con le funzioni compilate possono dare problemi. Credo sia
l'opzione che ho usato di meno fra tutte...
ø DefaultColor: possiamo definire, con questa opzione, il colore standard per disegnare tutto quanto il
grafico, nella sua totalità, e non, per esempio, solo il colore della funzione.
ø DefaultFont: definisce il tipo di font che deve essere usato per visualizzare l'eventuale testo presente
nel grafico.
ø DisplayFunction: non è che abbia mai capito cosa faccia esattamente questa opzione: permette di
definire come visualizzare il grafico. Se settato su Identity non è visualizzato... Mah!!!
ø Epilog: definisce una lista do oggetti grafici (quali punti e cerchi, per esempio), che devono essere
aggiunti al grafico dopo che è stata disegnata la funzione principale. Si può usare, per esempio, per
visualizzare ed evidenziale punti e zone del grafico.
ø FormatType: permette di definire lo stile della cella. Per esempio, se scriviamo una formula come
titolo del grafico, possiamo, mediante questa opzione, visualizzarla in notazione standard, invece che
come la visualizza Mathematica sotto forma di testo.
ø Frame: questa opzione, se settata su True, disegna una cornice intorno al grafico. Mediante le
seguenti, opzioni, dopo, possiamo definire lo stile della cornice.
ø FrameLabel: definisce le etichette da applicare alla cornice. se la impostiamo come {titolo1,
titolo2}, appariranno rispettivamente sotto ed a sinistra, mentre se lo impostiamo a {titolo1, titolo2,
titolo3, titolo4}, compariranno a partire dal basso, in senso orario.
Daniele Lupo Appunti di Mathematica
129Printed by Mathematica for Students
ø FrameStyle: personalizza lo stile con cui viene disegnata la cornice, definendo colore, stile e
spessore delle linee che compongono il frame: ogni lato può avere la sua
personalizzazione{{personalizzax},{personalizzay}}.
ø FrameTicks: definisce in questo senso se devono comparire oppure no i marker degli assi nella
cornice, definendo anche quali valori devono essere segnati.
ø GridLines: specifica se e come visualizzare la griglia nel grafico. Impostato su Automatic permette
a Mathematica di creare la griglia automaticamente, altrimenti si possono definire separatamente il
tipo di griglia per i due assi, definendo una lista del tipo {{valori x},{valori y}}, in cui compaiono i
valori dell'asse x e dell'asse y in cui vogliamo che compaiano le linee della griglia. una di queste iste
può essere sostituita da Automatic, se ci interessa solamente un asse e vogliamo che l'altro sia
definito automaticamente.
ø ImageSize: specifica le dimensioni in cui sono deve essere visualizzata l'immagine. Si può
specificare la larghezza, oppure larghezza ed altezza.
ø MaxBend: definise il massimo angolo di piegatura dell'angolo fra due segmenti. Questo perchè il
comando usa un algoritmo adattivo per poter disegnare il grafico, che avvicina i punti a seconda di
quest'angolo, in modo da avere una curva risultante smussata e non con punti spigolosi, entro i limiti
di PlotDivision. Aumentarlo a volte può servire per visualizzare per intero delle funzioni che
Mathematica, senza impostare i limiti degli assi, non visualizza interamente all'interno del grafico.
ø PlotDivision: specifica l'ammontare massino di divisione che devono essere impiegate per
visualizzare una curva. più alto sarà questo valore, più smussata risulterà la curva, anche se
aumenterà il tempo di calcolo. Da aumentare se si vede che la curva è formata da 'spezzate', che
indica una divisione non sufficiente.
ø PlotLabel: aggiunge il titolo specificato al grafico, mettendolo sopra il disegno della funzione.
ø PlotPoints: definisce il numero di punti iniziali da usare per disegnare la funzione. E' solo iniziale,
perchè l'algoritmo è adattivo, andando a modificarlo in funzione della curvatura della funzione.
Come vedremo più avanti, invece, per il grafici a due variabili sarà più importante.
ø PlotRange: definisce l'area di visualizzazione del grafico: settato su All include tutti i punti calcolati,
su Automatic aggiusta eliminando i punti troppo estremi, oppure può essere una lista pari a {minimo,
massimo} se si vuole limitare solo l'asse y, oppure {{minimox, massimox},{minimoy, massimoy}}
se si vuole specificare interamente l'area.
ø PlotRegion: specifica quale area dell'immagine generata dalla funzione plot deve essere riempita
con il grafico, lasciando vuoto il resto.
Daniele Lupo Appunti di Mathematica
130Printed by Mathematica for Students
ø PlotStyle: definisce lo stile con cui disegnare il grafico. Se si disegna una sola funzione, è possibile
definire l'unico stile, mentre, se si disegnano più funzioni, è possibile decidere se definire lo stile per
tutte le funzioni, oppure gestirle separatamente, tramite le liste.
ø Prolog: come Epilog, con la differenza che le forme descritte in Prolog vengono disegnate prima
della funzione, e quindi appariranno sotto, invece che sopra.
ø RotateLabel: definisce se l'etichetta dell'asse y deve essere ruotata in modo da essere parallela
all'asse, con True, oppure, con False, se deve essere mantenuta orizzontale.
ø TextStyle: specifica lo stile e le opzioni del font del testo che verrà visualizzato.
ø Ticks: definisce i marker che devono essere visualizzati negli assi della funzione, se quello usati di
default non ci vanno bene. O si definisce la lista solo per l'asse x, oppure si definisce la doppia lista
se ci interessa definire entrambi gli assi.
Vediamo, adesso, alcuni esempi su come possiamo utilizzare queste opzioni: supponiamo di definire
la seguente funzione:
In[14]:= f@x_D := Sin@xD^2 + Sqrt@xD
Adesso, disegnamola tramite il comando Plot:
In[15]:= Plot@f@xD, 8x, 0, 10<D
2 4 6 8 10
1
2
3
Out[15]= Graphics
Proviamo ad aggiungere un frame:
Daniele Lupo Appunti di Mathematica
131Printed by Mathematica for Students
In[16]:= Plot@f@xD, 8x, 0, 10<, Frame → TrueD
0 2 4 6 8 10
0
1
2
3
Out[16]= Graphics
Visualizziamo, adesso, la griglia, tarata in multipli di p:
In[17]:= Plot@f@xD, 8x, 0, 10<, Frame → True,GridLines → 880, π ê2, π, 3ê2 π, 2 π, 5ê2 π, 3 π<, Automatic<,FrameTicks −> 880, π ê2, π, 3ê2 π, 2 π, 5ê2 π, 3 π<, Automatic<D
0 π2
π 3 π2
2 π 5 π2
3 π
0
1
2
3
0π2 π
3 π2 2 π
5 π2 3 π
Out[17]= Graphics
Daniele Lupo Appunti di Mathematica
132Printed by Mathematica for Students
Decidiamo, adesso, di andarci a calcolare il primo massimo della funzione, e visualizzarlo:
In[18]:= FindMaximum@f@xD, 8x, 1<D
Out[18]= 82.29129, 8x → 1.7638<<
In[19]:= punto = 8x, %@@1DD< ê. %@@2DD
Out[19]= 81.7638, 2.29129<
Notate come ho dovuto giocare un secondo per scrivere il risultato di FindMaximum nella forma che
mi serviva, dato che dava prima l'ordinata, e dopo la regola per la sostituzione dell'ascissa.
Comunque, se avete seguito la lezioncina sulle liste che abbiamo affrontato prima, non dovreste
avere problemi a capire quello che ho fatto.
Avendo adesso trovato questo punto, posso andare a disegnarlo, completando il disegno della
funzione per come me l'ero prefissato, aggiungendo qualche altra cosuccia:
In[20]:= Plot@f@xD, 8x, 0, 10<,Frame → True,GridLines → 880, π ê2, π, 3ê2 π, 2 π, 5ê2 π, 3 π<, Automatic<,FrameTicks −> 880, π ê2, π, 3ê2 π, 2 π, 5ê2 π, 3 π<, Automatic<,Epilog → [email protected], [email protected], Point@puntoD<,PlotLabel →
StyleForm@TraditionalForm@Sin@xD^2 + Sqrt@xDD, FontSize → 12D,Background → [email protected],PlotStyle → [email protected], [email protected]<D
0 π2
π 3 π2
2 π 5 π2
3 π
0
1
2
3
0π2 π
3 π2 2 π
5 π2 3 π
sin2HxL + è!!!x
Out[20]= Graphics
Daniele Lupo Appunti di Mathematica
133Printed by Mathematica for Students
Abbiamo scritto un po' di codice per disegnare questa funzione con questa, chiamiamole,
'formattazione', per cui analizziamola: prima di tutto, abbiamo visualizzato il frame, e dopo le linee
della griglia, definendole dove volevamo noi, cioè per punti notevoli trigonomentrici, per l'asse x;
dopo, abbiamo definito le etichette dell'asse x nel frame, per far coincidere i valori segnati con la
griglia (infatti hanno gli stessi valori). Con Epilog abbiamo aggiunto un punto nelle coordinate che
ci eravamo trovati prima, imponendo la dimensione ed il colore. Abbiamo imposto il titolo,
scrivendolo in forma tradizionale (come le formule dei libri), ed impostando la dimensione del
carattere; per finire, ho imposto un grigio chiaro per lo sfondo, e ho cambiato lo stile della funzione,
cambiandone il colore e lo spessore. Notate anche come, a parità di area occupata, le ultime due
immagini appaiano più piccole, perchè nello stessa area hanno dovuto trovare posto anche il titolo,
per l'ultima, e le etichette, per entrambe. Quindi, dopo aver modificato l'immagine che vi interessava,
magari dovete ingrandirla col mouse. Comunque, se sapete trovare il tasto ciccione per accendere il
computer e conoscete il nome dell'aggeggio pacioccoso che tenete in mano per sentirvi Guglielmo
Tell per puntare la freccia che avete nello schermo, allora sapete anche ridimensionare un'immagine,
vero? Detto questo, andiamo a vedere un poco più a fondo la grafica bidimensionele in Mathematica.
2D Generale
Abbiamo visto come siamo in grado di visualizzare velocemente e personalizzare in maniera repida
ed efficace il layout delle nostre rappresentazioni grafiche. Tuttavia, Mathematica non si ferma al
mero disegno di funzioni. In effetti, è possibile praticamente disegnare ogni cosa, con i comandi
giusti. Per esempio, con quale funzione possiamo andare a disegnare dei grafi di flusso, oppure delle
macchine a stati? La rappresentazione di queste figure matematiche bidimensionali va al di là del
semplice (ma potentissimo, ed uno dei miei preferiti) comando Plot.
Vediamo innanzitutto come viene visualizzata la grafica in Mathematica. Per default, ogni grafico
viene visualizzato come disegno eps. Questo formato molto usato nei programmi professionali di
grafica ed impaginazione, come Acrobat, perchè rappresenta le immagini in formato vettoriale, e
quindi con una qualità indipendente dalla risoluzione. Una volta creata un'immagine, possiamo
tranquillamente stamparla su un francobollo come su un poster formato A0, senza alcun
decadimento di qualità. Tuttavia, se volete creare immagini abbastanza grandi, dovete ricordare che
lo spessore delle linee rimane costante al variare delle dimensioni, quindi magari vi conviene,
mediante le opzioni, creare linee un poco più spesse, se devono poter essere viste anche da lontano.
Tuttavia con solo un paio di prove sarete in grado di fare quello che volete, e comunque, la
personalizzazione è un aspetto specifico, che dovete provare voi.
Adesso, vediamo come sono rappresentate le figure in Mathematica. Il programma dispone di una
quantità di primitive bidimensionali di default. Le funzioni principali di Mathematica sono due, per i
grafici bidimensionali:
Graphics[list] general two-dimensional graphics
Daniele Lupo Appunti di Mathematica
134Printed by Mathematica for Students
Show[g1, g2, … ] display several graphics objects combined
Con il comando Graphics definiamo le curve e le forme che ci interessano, mentre con Show
visualizziamo le figure create: se, per esempio, vogliamo creare una linea, prima dobbiamo definire
la primitiva grafica che la rappresenta, e poi dobbiamo visualizzarla:
In[21]:= linea = Graphics@Line@880, 1<, 82, 4<<DD
Out[21]= Graphics
Come si può vedere, come output si da un oggetto Graphics. Per visualizzarlo, adesso, basta usare il
comando Show:
In[22]:= Show@lineaD
Out[22]= Graphics
Alcune primitive che siamo in grado di disegnare sono le
seguenti:
Daniele Lupo Appunti di Mathematica
135Printed by Mathematica for Students
Point[{x, y}] punto nella posizione x, y
Line[{{x1, y1}, {x2, y2}, … }] segmento avente gli estremi nelle coordinate {x1,y1}, {x2, y2}, …
Rectangle[{xmin, ymin},{xmax, ymax}]
rettangolo pieno, con angolo inferiore sinistro esuperiore destro specificati
Polygon[{{x1, y1}, {x2,y2}, … }]
poligono pieno con le specificate coordinate per i vertici
Circle[{x, y}, r] circonferenza di raggio r centrata in x, y
Disk[{x, y}, r] cerchio di raggio r ccentrato x, y
Raster[{{a11, a12, … },{a21, … }, … }]
array rettangolare con gli elementi ai, j rappresentantiun valore di scala di grigio compreso fra 0 e 1
Text[expr, {x, y}] il testo di expr, centrato in x, y
Circle[{x, y}, {rx, ry}] ellisse con semiassi rx e ry
Circle[{x, y}, r,{theta1, theta2}]
arco circolare con gli angoli specificati
Circle[{x, y}, {rx,ry}, {theta1, theta2}]
arco ellittico
Raster[array, {{xmin,ymin}, {xmax, ymax}}, {zmin,
array di elementi di grigio fra zmin e zmax disegnatonel rettangolo fra {xmin, ymin} e {xmax, ymax}
RasterArray[{{g11, g12, …}, {g21, … }, … }]
array rettangolare in cui ogni cella è colorata usandole direttive grafiche gij
Possiamo, quindi, anche definire più figure assieme, nello stesso comando Show:
In[23]:= cerchio = Graphics@Circle@80, 0<, 0.8DD;arco =
Graphics@Circle@8−0.5, −0.5<, 82, 4<, 830 Degree, 150 Degree<DD;disco = Graphics@Disk@83, 3<, .6DD;
Daniele Lupo Appunti di Mathematica
136Printed by Mathematica for Students
In[26]:= Show@8cerchio, arco, disco<D
Out[26]= Graphics
Possiamo anche impostare le opzioni per il comando Show; per esempio, vediamo che nella figura di
prima non abbiamo le stesse proporzioni per i due assi; possiamo correggere questo con l'apposita
opzione:
Daniele Lupo Appunti di Mathematica
137Printed by Mathematica for Students
In[27]:= Show@%, AspectRatio → AutomaticD
Out[27]= Graphics
In questo modo, abbiamo impostato la stessa scala sia per le ascisse che per le ordinate.
Una volta saputo questo, e vedendo che effettivamente possiamo creare le primitive semplicemente
definendo delle semplici liste di numeri, viene naturale, nelle applicazioni pratiche, usare valori dei
risultati dei nostri calcoli per poter usare efficacemente queste direttive. Per esempio, possiamo
mostrare semplicemente un dente di sega:
In[28]:= dentedisega = Line@Table@8Mod@n, 2D + n, H−1L^n<, 8n, 9<DD
Out[28]= Line@882, −1<, 82, 1<, 84, −1<,84, 1<, 86, −1<, 86, 1<, 88, −1<, 88, 1<, 810, −1<<D
Daniele Lupo Appunti di Mathematica
138Printed by Mathematica for Students
In[29]:= Show@Graphics@dentedisegaD, AspectRatio → AutomaticD
Out[29]= Graphics
In questo esempio, abbiamo prima creato il dente di sega nel seguente modo; abbiamo creato una
lista di coppie di valori con Table, in cui il primo valore, che rappresenta l'ascissa del punto, varia
ogni due valori di n, usando il comando Mod, che restituisce il resto della divisione, sommato ad n.
In questo caso, se per n il resto è 1, per n + 1 il resto è zero, e quindi rappresentano lo stesso valore,
sommati al numero stesso. Per le ordinate, invece, si è posto alternativamente -1 ed 1. Una volta
creata la lista, è stato semplice, poi, andare a visualizzare i valori, dove Line, in questo caso, contiene
più valori estremi, e rappresenta a tutti gli effetti una linea spezzata, invece di invocarla per ogni
segmento.
Anche il comando Plot restituisce un oggetto grafico visualizzabile tramite Show. Si può capire
perchè, oltre all'immagine, entrambi restituiscono il valore Graphics, in modo da far capire che si
tratta, per Mathematica, entrambi di oggetti grafici, e possono essere trattati allo stesso modo.
Supponiamo, per esempio, di utilizzare la seguente funzione:
In[30]:= f@x_D := Sin@2 xD + Sin@3 xD + Sin@4 xD
Possiamo disegnare il grafico, assegnandogli un nome come per qualsiasi altro oggetto in
Mathematica:
Daniele Lupo Appunti di Mathematica
139Printed by Mathematica for Students
In[31]:= grafico = Plot@f@xD, 8x, 0, 10<D
2 4 6 8 10
-2
-1
1
2
Out[31]= Graphics
Adesso, definiamo una primitiva cerchio:
In[32]:= cerchio = Graphics@Disk@84, 0<, 2DD
Out[32]= Graphics
E visualizziamole assieme:
In[33]:= Show@cerchio, graficoD
Out[33]= Graphics
Daniele Lupo Appunti di Mathematica
140Printed by Mathematica for Students
Graphics
Possiamo vedere come, in questo caso, la funzione sia trattata come una primitiva grafica come le
altre, e priva, quindi, di assi cartesiani oppure polari.
Possiamo, tramite le direttive grafiche, cambiare anche il colore delle primitive, definendo all'interno
di Graphics, oltre alla figura da visualizzare, anche anche il colore che deve assumere. Possiamo, per
esempio, definire una spirale di cerchi: prima di tutto definiamo la lista dei centri dei cerchi di questa
spirale:
In[34]:= centri = Table@8Sin@nD, Cos@nD< n, 8n, 1, 20, Piê6<D;
Ho semplicemente creato le coordinate dei centri utilizzando le proprietà trigonometriche del
cerchio, e per ogni punto ho aumentato il raggio moltiplicandolo per n.
Dopo aver definito i centri, definiamo i raggi dei cerchi:
In[35]:= raggi = Table@nê4, 8n, 1, 20, Piê6<D;
Notate come il numero dei valori della lista sia uguale a prima, e questo perchè dobbiamo creare
dopo una relazione biunivoca fra questi elementi.
Allo stesso modo, adesso, creiamo la lista dei colori che deve assumere ogni singolo cerchio:
In[36]:= colori = Table@Hue@nê40D, 8n, 1, 20, Piê6<D;
Daniele Lupo Appunti di Mathematica
141Printed by Mathematica for Students
Abbiamo utilizzato la funzione Hue, ma potevamo, allo stesso modo, utilizzare RGBColor oppure
GrayLevel. Ho usato Hue perchè permette, come RGBColor, di avere un colore e non un grigio ma,
come GrayLevel, permette di crearlo utilizzando un solo argomento, e non tre come RGBColor.
Tuttavia, dovrete poi utilizzare la funzione che meglio serve per rappresentare i vostri dati. Adesso,
dopo aver creato le liste, andiamo a creare la lista di punti che andremo a visualizzare con il
comando Graphics:
In[37]:= punti = Table@88colori@@nDD, Disk@centri@@nDD, raggi@@nDDD<<, 8n, 37<D;
— General::spell1 : Possible spelling error: new symbolname "punti" is similar to existing symbol "punto". More…
In questo modo, ho creato una lista di punti, utilizzando lo stesso indice per ognuno degli elementi,
in modo da associarli nel modo corretto; per ogni elemento di Table, ho usato un elemento Disk ed
un elemento colori. Notate anche come la funzione che definisce il colore, nella lista, debba essere
definito prima del comando che crea la primitiva.
Una volta creati i punti, non ci resta che visualizzarli tramite il comando Show:
Daniele Lupo Appunti di Mathematica
142Printed by Mathematica for Students
In[38]:= Show@Graphics@puntiD, PlotRange → All, AspectRatio → AutomaticD
Out[38]= Graphics
Ah, com'è elegante...
Ammetto, come avete capito, che all'inizio è un poco difficile utilizzare la grafica in modo adeguato
in Mathematica; questo principalmente perchè non esistono pulsanti per le opzioni, e per qualsiasi
cosa vogliamo fare, dobbiamo scrivere un poco di codice. Questo può essere seccante le prime volte,
ma, una volta imparati quei pochi comandi e opzioni essenziali per ognuno di noi, vi rendererete
conto che scrivere permette un livello di personalizzazione molto più elevato rispetto alle opzioni
grafiche di altri programmi, e questo perchè scrivete voi stessi quello che volete, e non siete limitati
a seguire il modo di pensare di chi ha disegnato l'interfaccia grafica di quel particolare programma.
Un altro comando utile, specialmente per visualizzare facilmente in modo grafico il contenuto di
matrici, è il comando Raster. Possiamo, per fare un esempio, definire una matrice nel seguente modo:
Daniele Lupo Appunti di Mathematica
143Printed by Mathematica for Students
In[39]:= matrice =
Table@Sin@xê5D + Sin@yê5D + Random@Dê2, 8x, 0, 80<, 8y, 0, 80<D êê N;
Adesso, visualizziamola con Graphics:
In[40]:= Show@Graphics@Raster@matriceDD, AspectRatio → AutomaticD
Out[40]= Graphics
Vedete come è più facile guardare il contenuto di questa matrice mediante la rappresentazione
grafica, piuttosto che andare a leggerne gli elementi.
Un altro elemento utile per visualizzare la grafica è Rectangle. Abbiamo già visto che può servire per
rappresentare rettangoli, ma è più utile sapere che, all'interno di questo rettangolo, possiamo andare a
metterci un'altra direttiva grafica: in questo modo possiamo, per esempio, andare ad annidare due
grafici. Un possibile utilizzo consiste nel visualizzare un grafico assieme ad un suo ingrandimento:
Consideriamo, per esempio, la seguente funzione:
Daniele Lupo Appunti di Mathematica
144Printed by Mathematica for Students
In[41]:= fun@x_D := Sin@xD Cos@100 xD
Proviamo a disegnarla:
In[42]:= globale = Plot@fun@xD, 8x, 0, 10<, MaxBend → 1D
2 4 6 8 10
-1
-0.5
0.5
1
Out[42]= Graphics
Come possiamo vedere, non è molto chiara; vediamo che c'è un inviluppo, ma non si vede bene che
la funzione modulata è effettivamente un seno. Proviamo adesso a visualizzare un particolare:
Daniele Lupo Appunti di Mathematica
145Printed by Mathematica for Students
In[43]:= particolare = Plot@fun@xD, 8x, 0, 3<, MaxBend → 0,PlotRange → 881.3, 1.7<, 8−1, 1.<<, PlotPoints → 300D
1.35 1.4 1.45 1.5 1.55 1.6 1.65
-1
-0.75
-0.5
-0.25
0.25
0.5
0.75
1
Out[43]= Graphics
Qua possiamo vedere che, opportunamente scalato l'asse x, si vede la funzione modulata, che
effettivamente è una sinusoide. Possiamo, adesso, combinare entrambi i grafici in modo da ottenerne
uno unico:
Daniele Lupo Appunti di Mathematica
146Printed by Mathematica for Students
In[44]:= Show@globale,Epilog −>
Rectangle@86, −1<, 810, −0.3<,Show@
particolare,Background → [email protected],DefaultFont → 8"Courier", 7<,DisplayFunction → Identity
DD,
Background → [email protected],DisplayFunction → $DisplayFunctionD
2 4 6 8 10
-1
-0.5
0.5
1
1.351.41.451.51.551.61.65
-1-0.75
-0.5-0.25
0.250.5
0.751
Out[44]= Graphics
Possiamo vedere ed apprezzare la formattazioe che ha permesso la creazione di questa immagine:
dopo aver mostrato il grafico principale, abbiamo disegnato il rettangolo, e, dopo aver espresso le
sue coordinate in cui viene disegnato, invece di essere riempito con un colore è stato riempito con un
altro grafico, formattato a sua volta. Ho anche scalato il font del grafico più piccolo, altrimenti
avrebbe avuto la stessa dimensione di quello più grande, mostrando un brutto effetto. Le opzioni di
DisplayFunction sono necessarie perchè, in caso contrario, si sarebbero ottenuti delle immagini
distinte, invece che annidate, e non era l'effetto che volevamo.
Inoltre, il comando Show, ha anche la potenzialità notevole di formattare un grafico senza doverlo
ricalcolare. Quando creiamo un grafico con Plot, Mathematica valuta la funzione per calcolarsi i
punti della funzione, e poi applica la formattazione che abbiamo deciso. Se vogliamo cambiare lo
Daniele Lupo Appunti di Mathematica
147Printed by Mathematica for Students
stile del grafico, con Plot siamo costretti a rieseguire il comando, ricalcolandoci tutti i punti, e questo
può farci perdere tempo se la funzione è complicata. Invece, memorizzando il grafico in una
variabile, come abbiamo fatto prima per visualizzarli con Show, possiamo anche modificare la
formattazione senza doverci ricalcolare la funzione, che in effetti è già memorizzata nella variabile:
questo consente di rendere più veloce il nostro lavoro e, soprattutto, permette di memorizzare le
formattazioni che preferiamo in delle funzioni, e poi usarle a nostro piacimento per tutte le funzioni
che vogliamo, senza dover riscrivere ogni volta il risultato. Questo, però, lo lascio fare a voi, per
vedere se ci riuscite!!!! Mica devo servirvi tutto su un piatto d'argento! E dove siamo, dico io?!?!?!?
Funzioni a due variabili
Anche se probabilmente verrà subito voglia di effettuare, per queste funzioni, il grafico
tridimensionale, che comunque faremo subito dopo, è interessante notare che Mathematica permette
di visualizzare questo tipo di funzioni anche nel campo 2D, usando differenti tipi di comandi rispetto
a Plot, anche se sono effettivamente simili:
ContourPlot[f, {x, xmin,xmax}, {y, ymin, ymax}]
crea un grafico con contorni di f in funzione di x ed y
DensityPlot[f, {x, xmin,xmax}, {y, ymin, ymax}]
crea un grafico di densità f
Rappresentano su un piano la superfice, dove a diversi valori corrispondono diversi colori, un poco
come succede nelle cartine geografiche fisiche, possiamo vedere il seguente esempio, per capirne il
funzionamento:
In[45]:= f@x_, y_D := BesselJ@1, Sqrt@x^2 + y^2DD
Daniele Lupo Appunti di Mathematica
148Printed by Mathematica for Students
In[46]:= ContourPlot@f@x, yD, 8x, −10, 10<, 8y, −10, 10<D
-10 -5 0 5 10
-10
-5
0
5
10
Out[46]= ContourGraphics
Daniele Lupo Appunti di Mathematica
149Printed by Mathematica for Students
In[47]:= DensityPlot@f@x, yD, 8x, −10, 10<, 8y, −10, 10<D
-10 -5 0 5 10
-10
-5
0
5
10
Out[47]= DensityGraphics
Possiamo vedere come, nei due casi, le funzioni rappresentino i dati in modo diverso, anche se
simile; nel primo caso effettivamente vengono create delle curve a valori costanti per la funzione.
Per poter creare questo tipo di grafico, la funzione viene calcolata in maniera 'iterativa' da
Mathematica. Nel secondo caso, invece, il programma si limita a calcolare la funzione al centro delle
coordinate dei quadratini, e li rappresenta come farebbe il comando Raster, con la differenza che in
questo caso, di default, viene anche visualizzata la griglia, cosa che comunque possiamo
tranquillamente evitare mediante l'opportuna opzione. Inoltre, sempre di default, Mathematica colora
i grafici con tonalità di scala di grigi, con i valori più chiari corrispondenti ai valori più elevati. Ed,
anche in questo caso, siamo in grado di cambiare le cose giocando con le opzioni. Per esempio,
possiamo manipolare il secondo grafico, per poter ottenere un'immagine, secondo me, più
accattivante:
Daniele Lupo Appunti di Mathematica
150Printed by Mathematica for Students
In[48]:= DensityPlot@f@x, yD, 8x, −10, 10<, 8y, −10, 10<,Mesh → False,PlotPoints → 200,ColorFunction → HueD
-10 -5 0 5 10
-10
-5
0
5
10
Out[48]= DensityGraphics
Quello che è stato fatto, in questo caso, è stato nascondere le linee della griglia, con Mesh Ø False;
poi abbiamo aumentato il numero di quadrati della griglia, rendendoli più piccoli e quindi
l'immagine risulta più definita, anche se naturalmente aumenta il tempo e la memoria impiegati;
questo con l'opzione PlotPoints Ø 200. Ho anche modificato, mediante l'opzione
ColorFunction Ø Hue, anche il tipo di colorazione, che quindi non è più in scala di grigi, ma in
tonalità di colore (ricordo che Hue definisce un colore con i tre valori tonalità, luminosità e
saturazione). Le opzioni, in questo caso, sono simili, fra di loro e con Plot, tranne alcuni come Mesh,
appunto. Quindi vedetevi il manuale e giocateci un poco, perchè a volte permettono una
rappresentazione, magari meno scenografica, ma più chiara e diretta dei grafici tridimensionali. Non
sempre, però!!! :-)
Daniele Lupo Appunti di Mathematica
151Printed by Mathematica for Students
Introduzione al 3D
Quasi tutto quello che abbiamo applicato al 2D può essere applicato anche, con le opportune
modifiche ed osservazioni, anche al caso 3D. Per tracciare grafici tridimensionali, il comando
principale da usare è Plot3D:
Plot3D[f, {x, xmin, xmax},{y, ymin, ymax}]
crea un grafico tridimensionale di f in funzionedelle variabili x ed y
In questo caso, la funzione è molto simile a quella già vista Plot, con l'accortezza di tener conto
anche della seconda variabile:
In[49]:= f@x_, y_D := BesselJ@1, Sqrt@x^2 + y^2DD
In[50]:= Plot3D@f@x, yD, 8x, −10, 10<, 8y, −10, 10<D
-10
-5
0
5
10 -10
-5
0
5
10
-0.20
0.20.40.6
10
-5
0
5
Out[50]= SurfaceGraphics
Come possiamo vedere, la sintassi è effettivamente molto simile: anche Plot3D ha un considerevole
numero di opzioni. Ne ha anche qualcuna in più, per tener conto, per esempio, del punto di vista del
grafico e delle luci in gioco:
Daniele Lupo Appunti di Mathematica
152Printed by Mathematica for Students
In[51]:= Options@Plot3DD
Out[51]= 8AmbientLight → GrayLevel@0D, AspectRatio → Automatic, Axes → True,AxesEdge → Automatic, AxesLabel → None, AxesStyle → Automatic,Background → Automatic, Boxed → True, BoxRatios → 81, 1, 0.4<,BoxStyle → Automatic, ClipFill → Automatic, ColorFunction → Automatic,ColorFunctionScaling → True, ColorOutput → Automatic, Compiled → True,DefaultColor → Automatic, DefaultFont $DefaultFont,DisplayFunction $DisplayFunction, Epilog → 8<, FaceGrids → None,FormatType $FormatType, HiddenSurface → True, ImageSize → Automatic,Lighting → True, LightSources → 8881., 0., 1.<, RGBColor@1, 0, 0D<,881., 1., 1.<, RGBColor@0, 1, 0D<, 880., 1., 1.<, RGBColor@0, 0, 1D<<,
Mesh → True, MeshStyle → Automatic, Plot3Matrix → Automatic,PlotLabel → None, PlotPoints → 25, PlotRange → Automatic,PlotRegion → Automatic, Prolog → 8<, Shading → True,SphericalRegion → False, TextStyle $TextStyle,Ticks → Automatic, ViewCenter → Automatic,ViewPoint → 81.3, −2.4, 2.<, ViewVertical → 80., 0., 1.<<
Anche in questo caso ci sono numerose opzioni, e adesso le elenchiamo come prima, stavolta
evitando di dover spiegare quelle già viste, e concentrandosi più su quelle nuove. Se volete sapere
pure il sognificato di quelle di cui ometterò la spiegazione, andate a rivedervi le opzioni di Plot:
ø AmbientLight: definisce la quantità di illuminazione ambiente di un grafico tridimensionale, oltre al
colre di questa luce. Sicuramente chi avrà fatto almeno una volta grafica 3D conoscerà bene questo
concetto. Si usa definendo una delle funzioni colore come Hue o RGBColor e specificando un
colore, che verrà usato come luce ambiente.
ø AspectRatio: vedi Plot
ø Axes: vedi Plot
ø AxesEdge: definisce in quali lati della 'scatola' che contiene il grafico tridimensionale devono essere
disegnati gli assi; si definisce la lista 88diry, dirz<, 8dirx, dirz<, 8dirx, diry<<, dove i valori,
che possono essere + o -1, specificano se gli assi devono essere disegnati negli spigoli con valori più
grandi o più piccoli della coordinata corrispondente. Un elemento della lista può essere sostituito da
Automatic.
ø AxesLabel: vedi Plot
ø AxesStyle: vedi Plot
ø Background: vedi Plot
ø Boxed: specifica se il grafico deve oppure no essere contenuto in una scatola, visualizzandone gli
spigoli. Può essere, naturalmente, True oppure False.
Daniele Lupo Appunti di Mathematica
153Printed by Mathematica for Students
ø BoxRatios: definisce le proporzioni fra le varie coordinate x, y, z del grafico, deformando la scatola
in cui è contenuto. Si usa definendo una lista di tre valori che specificano il rapporto fra le tre
dimensioni.
ø BoxStyle: specifica lo stile con ciu devono essere disegnati gli spigoli della scatola. Di solito gli si
assegna un colore e/o uno spessore.
ø ClipFill: con questa opzione si decide se, quando il grafico non viene contenuto interamente
dall'asse z, le zone in cui il grafico è tagliato perchè è fuori dai margini, deve essere lasciato vuoto,
oppure riempito con zone. Si utilizza None, oppure una lista di due colori, che definiscono il colore
del grafico tagliato in alto ed in basso.
ø ColorFunction: vedi Plot
ø ColorFunctionScaling: è un parametro booleano che definisce se la funzione dei colori del grafico
deve essere scalata in modo da essere contenuta fra 0 ed 1, in modo da utilizzare tutta la scala di
colori della funzione.
ø ColorOutput: vedi Plot
ø Compiled: vedi Plot
ø DefaultColor: vedi Plot
ø DefaultFont: vedi Plot
ø DisplayFunction: vedi Plot
ø Epilog: vedi Plot
ø FaceGrids: specifica se devono essere visualizzate o meno le griglie nelle facce della scatola che
contiene il grafico. Settato su All definisce tutte le griglie, altrimenti bisogna specificare le facce.
Inoltre è possibile personalizzare la griglia come nel caso del comando Plot.
ø FormatType: vedi Plot
ø HiddenSurface: con questa opzione decidiamo se visualizzare o meno le facce nascoste; settato su
False, permette di rendere il grafico 'trasparente'.
ø ImageSize: vedi Plot
ø Lighting: con questa opzione booleana decidiamo se visualizzare o meno le luci per la superfice.
ø LightSources: definisce una lista di luci che verranno usate nel grafico. ogni elemento è una lista a
sua volta, conenente come primo elemento una lista di tre numeri che definiscono le coordinate della
Daniele Lupo Appunti di Mathematica
154Printed by Mathematica for Students
luce, e come secondo elemento il colore stesso della luce. Questa opzione è una delle prime da
cambiare, se volete modificare l'aspetto del grafico.
ø Mesh: definisce se visualizzare o meglio le linee che compongono la mesh del grafico
tridimensionale.
ø MeshStyle: definisce lo stile delle linee della mesh del grafico
ø Plot3Matrix: non usare questa opzione. Si mantiene solo per compatibilità con le vecchissime
versioni di Mathematica. Neanch'io so cosa faccia questa opzione, e vivo benissimo senza saperlo.
ø PlotLabel: vedi Plot
ø PlotPoints: vedi Plot, ma qui ricordo che definisce il numero di punti in cui viene diviso ognuno dei
due assi x ey in cui viene calcolata la funzione. Aumentare questo valore aumenterà la definizione
del grafico.
ø PlotRange: vedi Plot
ø PlotRegion: vedi Plot
ø Prolog: vedi Plot
ø Shading: definisce se la superfice debba essere o meno illuminata.
ø SphericalRegion: questa opzione specifica se l'immagine finale debba essere scalata in modo che
una sfera che contenga interamente la funzione sia visibile (teoricamente) nella figura. Alquanto
inutile...
ø TextStyle: vedi Plot
ø Ticks: vedi Plot
ø ViewCenter: scala l'immagine in modo che il punto selezionato appaia al centro dell'immagine
stessa. Questa opzione scala interamente il grafico, con assi e tutto quanto.
ø ViewPoint: definisce il punto di vista nello spazio tridimensionale dal quale si guarda il grafico.
rappresenta un'altra della opzioni più utilizzate per modificare l'aspetto del grafico.
ø ViewVertical: specifica, mediante una lista di tre valori, qual'è la direzione nello spazio del grafico
che deve apparire verticale nell'immagine finale. permette, in poche parole, di ruotare il grafico.
Vediamo di fare un esempio concreto di qualcuna di queste opzioni. Definiamo una funzione
sempilce, per adesso:
Daniele Lupo Appunti di Mathematica
155Printed by Mathematica for Students
In[52]:= f@x_, y_D := Exp@−Sqrt@x^2 + y^2DD
Adesso, visualizziamola:
In[53]:= Plot3D@f@x, yD, 8x, −3, 3<, 8y, −3, 3<D
-2
0
2
-2
0
2
0
0.2
0.4
-2
0
2
Out[53]= SurfaceGraphics
Come possiamo vedere, abbiamo la funzione che risulta 'tagliata' sopra. Possiamo vederlo meglio se
usiamo l'opzione ClipFill:
Daniele Lupo Appunti di Mathematica
156Printed by Mathematica for Students
In[54]:= Show@%, ClipFill → NoneD
-2
0
2
-2
0
2
0
0.2
0.4
-2
0
2
Out[54]= SurfaceGraphics
Ah! Adesso si vede che effettivamente c'è un buco!!! E vedete anche come posso ridisegnare il
grafico semplicemente usando il comando Show, evitando di dover calcolare tutti i punti. Adesso,
voglio visualizzarlo completamente, ed, in aggiunta, voglio eliminare la mesh e rendere il grafico più
dettagliato:
Daniele Lupo Appunti di Mathematica
157Printed by Mathematica for Students
In[55]:= Plot3D@f@x, yD, 8x, −3, 3<, 8y, −3, 3<,Mesh → False,PlotPoints → 80,PlotRange → 8Automatic, Automatic, 80, 1<<D
-2
0
2
-2
0
2
0
0.25
0.5
0.75
1
-2
0
2
Out[55]= SurfaceGraphics
Adesso si vede che, effettivamente, la curva è più ripida di quanto ci si aspettasse ad una prima
occhiata del primo grafico tagliato. Proviamo a cambiare le luci, ed ad eliminare la scatola che lo
racchiude. Inoltre, cambieremo anche punto di vista
Daniele Lupo Appunti di Mathematica
158Printed by Mathematica for Students
In[56]:= Show@%,LightSources → 888−3, 4, 3<, [email protected]<, 883, −3, 4<, [email protected]<<,Boxed → False,Axes → None
ViewPoint −> 8−0.894, 3.078, 1.083<D
Out[56]= SurfaceGraphics
Come possiamo vedere, anche se si tratta della stessa funzione, abbiamo ottenuto un aspetto alquanto
diverso da quello di partenza, e questo giocando soltanto con alcune delle opzioni disponibili.
In generale è possibile, come nel caso bidimensionale, andare a disegnare contemporaneamente più
superfici ma questo, a meno di casi specifici, è sconsigliabile, o almeno io lo sconsiglio, perchè se
non si sa bene quello che si vuole ottenere, si rischia di ottenere un'immagine confusa e non chiara,
soprattutto a causa di porzioni di superfici che rimangono invariabilmente scoperte. Anche perchè, in
questo caso, non sempre è possibile visualizzare correttamente i risultati.
Qua, infatti, sento personalmente una delle mancanze di questo programma rispetto a Matlab, ovvero
la possibilità di ruotare in tempo reale, col mouse, un grafico 3D. Questo ha un suo perchè,
ovviamente. Mathematica genera, una volta calcolati i dati, non un'immagine tridimensionale vera e
propria, ma un'immagine bidimensionale in formato Encapsulated PostScript, che rappresenta il
grafico tridimensionale. Tuttavia, l'immagine rimane bidimensionale a tutti gli effetti, con l'ovvia
Daniele Lupo Appunti di Mathematica
159Printed by Mathematica for Students
conseguenza dell'impossibilità di rotazione senza ricalcolo. Tuttavia questo permette di elaborare le
immagini, sovrapporle e modificarne l'aspetto con i semplici e potenti comandi che abbiamo
imparato, magari con un notevole risparmio di tempo e con la possibilità, per esempio, di
sovrapporre un'immagine bidimensionale ad una tridimensionale. Questo permette di ottenere un
layout più professionale e più personalizzabile. Ma se solo ci fosse pure la rotazione in tempo
reale!!!! Ah, non mi accontento mai...
Bisogna anche vedere come, effettivamente, avendo memorizzato il grafico tridimensionale in una
variabile, i valori calcolati sono disponibili anche per le altre visualizzazioni. Per esempio, posso
avere:
In[57]:= graf = Plot3D@10 Sin@x^2 + Sin@yD^2D,8x, −10, 10<, 8y, −10, 10<, PlotPoints → 200, Mesh → FalseD
-10
-5
0
5
10 -10
-5
0
5
10
-10
-5
0
5
10
10
-5
0
5
Out[57]= SurfaceGraphics
Adesso, possiamo anche visualizzare il grafico di densità, che mostra il grafico in maniera più chiara
di quanto possa fare il grafico tridimensionale, pur modificando punto di vista e colori:
Daniele Lupo Appunti di Mathematica
160Printed by Mathematica for Students
In[58]:= Show@DensityGraphics@grafDD
-10 -5 0 5 10
-10
-5
0
5
10
Out[58]= DensityGraphics
che, secondo me, da un'idea pioù chiara del comportamento della funzione. Una volta impratichiti
con le opzioni e le visualizzazioni, trovare il modo più elegante ed efficace di visualizzare dati sarà
una bella sfida, e non vi accontenterete mai, cercando sempre di meglio. D'altronde, qua è dove la
scienza finisce e dove inizia la sensibilità e la forma artistica e personale di ognuno, dove ci
possiamo esprimere individualmente al meglio. Non commettete l'errore di essere asettici.
L'obiettività è importante, ma l'aridità rende difficile e poco interessante anche il più utile dei lavori!
Daniele Lupo Appunti di Mathematica
161Printed by Mathematica for Students
Visualizzazione dati
Quando si tratta di visualizzare funzioni, si tratta semplicemente di inserire le formule che ci
interessano, e vedere come si comportano. Dobbiamo invece agire diversamente (ma non di molto),
quando si tratta di visualizzare dati numerici. Infatti, capita molto spesso di dover interpretare dei
dati sperimentali visualizzandoli in maniera opportuna. Questi devono usare, quindi, diversi comandi
rispetto a quelli per il tracciamento delle funzioni, anche se, in verità, sono molto simili:
ListPlot[{y1, y2, … }] disegna il grafico dei dati y1, y2, ... per valori di x paria 1, 2, ...
ListPlot[{{x1, y1}, {x2,y2}, … }]
disegna i punti Hx1,y1L, ...
ListPlot[list, PlotJoined-> True]
unisce i punti con delle linee
ListPlot3D[{{z11, z12, …}, {z21, z22, … }, … }]
crea un grafico tridimensionale dove la mesh rappresentai valori zyx della matrice
ListContourPlot[array] crea un grafico di contorno con curve di livello
ListDensityPlot[array] crea un grafico di densità
Naturalmente, per ora creeremo sempre le nostre liste a partire da funzioni. Vedremo più avanti
come fare per importare dati esterni nel programma. Possiamo cominciare a vedere come si
rappresenta una lista di dati:
In[59]:= lista = Table@Abs@RiemannSiegelTheta@xê2DD, 8x, 50<D;
Una volta creata la lista di dati, possiamo visualizzarla:
Daniele Lupo Appunti di Mathematica
162Printed by Mathematica for Students
In[60]:= ListPlot@listaD
10 20 30 40 50
1
2
3
4
Out[60]= Graphics
Come possiamo vedere, in questo caso vediamo solamente dei punti che rappresentano i dati. Se
volessimo un grafico a linea, dovremmo utilizzare l'opzione corretta, che abbiamo visto sopra:
In[61]:= grafico1 = ListPlot@lista, PlotJoined → TrueD
10 20 30 40 50
1
2
3
4
Out[61]= Graphics
Daniele Lupo Appunti di Mathematica
163Printed by Mathematica for Students
Possiamo vedere come sia relativamente semplice visualizzare dati ed, inoltre, questi comandi hanno
le stesse opzioni di quelli usati per le funzioni. Possiamo vedere anche come si comportano i grafici
di dati tridimensionali, e per farlo occorre definire una matrice di valori che devono essere
visualizzati:
In[62]:= lista3D = Table@BesselJ@0, Sqrt@Hxê3L^2 + Hyê3L^2DD + Random@Dê10,8x, 0, 60<, 8y, 0, 60<D;
In[63]:= ListPlot3D@lista3DD
20
40
60
20
40
60
-0.25
0
0.25
0.5
0.75
20
40
Out[63]= SurfaceGraphics
Daniele Lupo Appunti di Mathematica
164Printed by Mathematica for Students
In[64]:= Show@DensityGraphics@%D, Mesh → FalseD
0 10 20 30 40 50 60
0
10
20
30
40
50
60
Out[64]= DensityGraphics
Come potete vedere, la visualizzazione di dati non è niente di complicato, ammesso che si sia capito
come funzionano i comandi corrispondenti per il tracciamento delle funzioni. Si tratta solo di
sperimentare e, una volta che vi siete impratichiti, di provare ad elaborare dei dati reali, magari di cui
conoscete già risultati et similia, per essere sicuri di avere i risultati corretti.
Daniele Lupo Appunti di Mathematica
165Printed by Mathematica for Students
Grafici parametrici
A volte non è sufficiente usare i comandi sopra elencati, perchè alcune tipologie di grafico, come
appunto questi parametrici, non sono visualizzabili direttamente come funzioni ad una oppure a due
variabili, e questo perchè dipendono da essa (o da esse), sia i valori dell'ascissa che quelli
dello'ordinata. Per questi tipi di grafici esistono appositi comandi:
ParametricPlot[{ fx, fy},
{t, tmin, tmax}] crea un grafico parametrico
ParametricPlot[{{ fx, fy},
{gx, gy}, … }, {t, tmin, tmax}] disegna assieme diversi grafici parametrici
ParametricPlot[{ fx, fy},
{t, tmin, tmax}, AspectRatio-> Automatic]
conserva le proporzioni della funzione parametrica
ParametricPlot3D[{ fx ,
fy, fz}, {t, tmin, tmax}] crea il grafico di una superfice parametrica
ParametricPlot3D[{ fx ,
fy, fz}, {t, tmin, tmax}, {u,
umin, umax}]
indovia indovinello
ParametricPlot3D[{ fx, fy,
fz, s}, … ] disegna quella parte disuperfice concorde con l' equazione s
ParametricPlot3D[{{ fx ,
fy, fz}, {gx, gy, gz}, … }, …disegna assieme diverse superfici
Vediamo un esempio classico di curve parametriche, ovvero le figure di Lissajouis:
Daniele Lupo Appunti di Mathematica
166Printed by Mathematica for Students
In[65]:= lissajouis = ParametricPlot@8Sin@3 xD, Cos@7 xD<, 8x, 0, 2.2 Pi<D
-1 -0.5 0.5 1
-1
-0.5
0.5
1
Out[65]= Graphics
Potete vedere come abbiamo definito la lista delle due funzioni, e poi si siano disegnati i punti e la
funzione mediante il parametro x: dalla scala del grafico possiamo vedere come, in realtà, il rapporto
non sia 1:1. Possiamo correggerlo o ridisegnando la curva, oppure usando Show:
Daniele Lupo Appunti di Mathematica
167Printed by Mathematica for Students
In[66]:= Show@%, AspectRatio → AutomaticD
-1 -0.5 0.5 1
-1
-0.5
0.5
1
Out[66]= Graphics
Vediamo come ora le proporzioni siano corrette: dato che in questo caso entrambi gli assi sono
funzione di un parametro, la scala uguale o definita da voi in modo specifio può essere di maggiore
aiuto rispetto al caso di funzione normale, per capirne l'andamento e quello che sta dietro ad esso.
Anche in questo caso possiamo formattare la funzione come più ci aggrada:
Daniele Lupo Appunti di Mathematica
168Printed by Mathematica for Students
In[67]:= ParametricPlot@8Sin@3 xD, Cos@7 xD<, 8x, 0, 2.2 Pi<,Background → [email protected],PlotStyle → [email protected],AspectRatio → Automatic
D
-1 -0.5 0.5 1
-1
-0.5
0.5
1
Out[67]= Graphics
Ormai siete talmente bravi e 'pumatusi' da non dovervi spiegare come abbia ottenuto il risultato,
vero? Scommetto che lo sapete fare anche ad occhi chiusi, mangiando una pizza con una mano e con
il computer alle spalle, come ho fatto io...
Per i grafici parametridi 3D le cose sono molto simili, considerando anche il fatto che ci sono due
tipi di grafici: le curve parametriche e le superfici parametriche. La differenza principale consiste nel
fatto che nel primo caso occorre soltanto un parametro, mentre nel secondo ne occorrono
(indovinate?) due: possiamo definire, per cominciare, una curva parametrica:
Daniele Lupo Appunti di Mathematica
169Printed by Mathematica for Students
In[68]:= ParametricPlot3D@8Sin@7 xDêx, Cos@7 xDêx, xê6<, 8x, 1, 9<,PlotPoints → 700,DefaultColor → [email protected],BoxStyle → RGBColor@0, 1, 1D,Axes → None
D
Out[68]= Graphics3D
Notate come abbia anche applicato una formattazione: ormai i grafici puramente neri non sono più
così attraenti, una volta imparate le opzioni!!!
Se, invece, abbiamo bisogno di disegnare una superfice, dobbiamo considerare anche l'altro
parametro, e da curva si ottiene una superfice:
Daniele Lupo Appunti di Mathematica
170Printed by Mathematica for Students
In[69]:= ParametricPlot3D@8Sin@7 xDêHx yL, Cos@7 xDêHx yL, xê6<, 8x, 1, 9<, 8y, 1, 5<,PlotPoints → 8400, 10<,BoxRatios → 81, 1, 1.7<,LightSources → 888−3, 4, 3<, [email protected]<, 883, −3, 4<, [email protected]<<,Boxed → False,AxesEdge → 88−1, −1<, 81, −1<, 81, 1<<
D
-0.2
0
0.2-0.2
0
0.2
0
0.5
1
1.5
-0.2
0
0 2
0
0.
1
Out[69]= Graphics3D
Come possiamo vedere, abbiamo ottenuto la curva parametrica che volevamo in quattro e quattr'otto
(d'altronde, la matematica non è un opinione). Quello che succede nel disegno di curve
parametriche è il seguente: si fissa il secondo parametro, in questo caso y, e si disegna la curva
parametrica corrispondente in x: dopo averla disegnata, si incrementa il valore y, e si disegna la
seconda curva parametrica corrispondente. A questo punto, si uniscono i punti aventi lo stesso
Daniele Lupo Appunti di Mathematica
171Printed by Mathematica for Students
parametro x, per avere una striscia di poligoni, e poi si procede ad oltranza, fino ad avere la
rappresentazione completa della curva. Questo è il modo di disegnarle, semplice ed efficace. Notate
anche come abbia dovuto incrementare il numero di punti per avere una rappresentazione dettagliata,
e come, dato che ho bisogno di due parametri, i valori dei punti di disegno in PlotPoints sia definito
da una lista di due valori, uno per il primo parametro, e l'altro per il secondo.
Possiamo parametrizzare anche i solidi, come, per esempio, la classica e sottovalutata sfera:
In[70]:= sfera = ParametricPlot3D@8Cos@xD Cos@yD, Sin@xD Cos@yD, Sin@yD<,8x, 0, 2 Pi<, 8y, −Piê2, Piê2<,Boxed → False,Axes → None,AmbientLight → Yellow
D
Out[70]= Graphics3D
Daniele Lupo Appunti di Mathematica
172Printed by Mathematica for Students
Qua potete notare un'altra cosuccia interessante, fra le opzioni: riuscite a vederla? Mathematica ha
nel suo delicato e complicato pancino delle costanti con nomi di colore, che rappresentano appunto il
colore specificato, senza doverlo andare a scrivere come funzione di Hue oppure di RGBColor. Sono
presenti tutti i colori più comuni, considerando sempre i loro nomi inglesi.
In[71]:= sfera1 = ParametricPlot3D@8Cos@xD Cos@yD, Sin@xD Cos@yD, Sin@yD<,8x, 0, 2 Pi<, 8y, −Piê2, Piê2<,Boxed → False,Axes → None,AmbientLight → Yellow,LightSources → 8881.3, −2.4, 2.<, RGBColor@1, 1, 1D<<D;
sfera2 =
sfera = ParametricPlot3D@8Cos@xD Cos@yD, Sin@xD Cos@yD, Sin@yD<,8x, 0, 2 Pi<, 8y, −Piê2, Piê2<,Boxed → False,Axes → None,AmbientLight → Orange,LightSources → 8881.3, −2.4, 2.<, [email protected], .4, .4D<<
D;
sfera3 =
sfera = ParametricPlot3D@8Cos@xD Cos@yD, Sin@xD Cos@yD, Sin@yD<,8x, 0, 2 Pi<, 8y, −Piê2, Piê2<,Boxed → False,Axes → None,AmbientLight → Blue,LightSources → 8881.3, −2.4, 2.<, RGBColor@1, 1, 1D<<
D;
sfera4 =
sfera = ParametricPlot3D@8Cos@xD Cos@yD, Sin@xD Cos@yD, Sin@yD<,8x, 0, 2 Pi<, 8y, −Piê2, Piê2<,Boxed → False,Axes → None,AmbientLight → Brown,LightSources → 8881.3, −2.4, 2.<, [email protected], .4, .4D<<
D;
Daniele Lupo Appunti di Mathematica
173Printed by Mathematica for Students
Daniele Lupo Appunti di Mathematica
174Printed by Mathematica for Students
Daniele Lupo Appunti di Mathematica
175Printed by Mathematica for Students
In[75]:= Show@GraphicsArray@88sfera1, sfera2<, 8sfera3, sfera4<<,GraphicsSpacing → 0DD
Out[75]= GraphicsArray
Vediamo qua le sfere colorate in modo diverso dall'AmbientLight. Notate come, per far notare
meglio il colore, sia stato necessario ridefinire le luci di default di Mathematica, che sono colorate e
quindi falsificavano il vero colore della luce ambiente. Le figure, di default, non hanno colorazione
di superfice, per cui in questo caso il colore effettivo visualizzato corrisponde a quello della luce
ambiente. Non vi ho spiegato prima GraphicsArray, ma credo che non ci sia bisogno di spiegazioni.
D'altronde, come vi ho detto innumerevoli volte, il manuale on-line è indispensabile, quindi
leggetelo e, ogni volta che lo farete, scoprirete sempre cose nuove... Altro che "La Storia Infinita"!!!
Daniele Lupo Appunti di Mathematica
176Printed by Mathematica for Students
Suoni
La parte riguardante i suoni, lo ammetto, è una di quelle che conosco meno in assoluto di
Mathematica, perchè personalmente non ho mai avuto modo di usarla. Quindi, quello che dirò
saranno solamente le nozioni base. Prima di tutto, come per il caso dei grafici, possiamo decidere se
creare un suono da una funzione matematica, oppure da una lista di dati campionati. Per i due casi, ci
sono funzioni distinte, anche se simili:
Play[f, {t, 0, tmax}] genera un suono di ampiezza f come funzione del tempot espresso in secondi
ListPlay[{a1, a2, … }, SampleRate -> r]
genera un suono a partire dalla lista di dati campionati,con il Rate specificato
Possiamo molto facilmente definire delle armoniche, usando le funzioni sinusoidali:
In[76]:= Play@Sin@500 Pi tD, 8t, 0, 1<D
Out[76]= Sound
Possiamo vedere come, oltre al suono (che naturalmente non potete sentire, ma se eseguite il
comando lo sentirete), viene rappresentato anche un grafico con il campionamento del suono. Notate
come, nell'indicatore di cella a lato, compare una piccola frecca nella parte superiore. In questo
modo, facendo doppio clic sulla freccia, allora il suono riparte, senza bisogno di dover rieseguire il
comando.
Possiamo anche definire deli suoni più complicati come, in questo caso, l'accordo di do:
Daniele Lupo Appunti di Mathematica
177Printed by Mathematica for Students
In[77]:= Play@Sin@526 π tD +
Sin@526 21ê3 π tD +
Sin@526 27ê12 π tD +
Sin@1052 π tD,8t, 0, 1<D
Out[77]= Sound
Un altro aspetto interessante è il fatto che Mathematica è in grado anche di generare audio
multicanale, generando una lista di funzione, una per ogni canale:
In[78]:= suono1@t_D := Sin@4000 Pi tD + Sin@3990 Pi tD
In[79]:= suono2@t_D := Sin@4000 Pi tD + Sin@3990 Pi t + PiD
Daniele Lupo Appunti di Mathematica
178Printed by Mathematica for Students
In[80]:= Play@8suono1@tD, suono2@tD<, 8t, 0, 1<D
Out[80]= Sound
Possiamo vedere come, in questo caso, oltre al campionamento si vede che ogni singolo canale è
rappresentato da un colore diverso. Non ho sinceramente provato il suono con più canali, ma magari
voi siete tanto gentili da provare e farmi sapere, vero? Chi lo sa se con gli opportuni comandi
Mathematica è pure in grado di gestire suono surround...
Daniele Lupo Appunti di Mathematica
179Printed by Mathematica for Students
Importazione ed esportazione
ü Introduzione
Abbiamo visto le potenzialità di Mathematica per quanto riguarda il calcolo simbolico e numerico.
Tuttavia, nonostante abbiamo imparato a fare un sacco di cose, ci siamo limitati a lavorare sempre
all'interno del programma. Molte volte, invece (poche, a dire il vero, se siamo studenti), capita di
dover effettuare delle elaborazioni su dei dati acquisiti esternamente al programma, oppure vogliamo
esportare i dati in modo che possano essere utilizzati da altri programmi. Lo scambio dei dati fra
programmi è un concetto importante da imparare, specie se bisogna lavorare molto al calcolatore per
elaborare e sviluppare le opportune ricerche. Per esempio, si usa un programma in C ideato da
un'altra persona, per effettuare una simulazione, salvando i risultati in un file, e dopo si vogliono
importare questi dati per vedere se effettivamente sono come ce li aspetiamo. oppure, magari,
potremmo usare i dati derivati da un oscilloscopio campionatore per effettuare analisi che
l'oscilloscopio non è in grado di eseguire, per esempio se non è in grado di effettuare la trasformata
di Fourier dei campioni (anche se probabilmente riesce a farlo se è anche solo sufficiente come
strumento, ma parlo solo di esempi). Le applicazioni sono tutte importanti, e Mathematica le gestisce
praticamente tutte, da entrambi i sensi. Vediamo, quindi, cosa possiamo fare per elaborare con
Mathematica i nostri dati.
ü Importazione
Mathematica è in grado di importare una quantità di file di diverso formato: file di testo, immagini e
quant'altro. Esiste una variabile di sistema che elenca tutti i possibili formati di file che si possono
importare:
$ImportFormats
8AIFF, APS, AU, Bit, BMP, Byte, Character16, Character8, Complex128,Complex256, Complex64, CSV, DICOM, DIF, Dump, DXF, EPSTIFF,Expression, ExpressionML, FITS, GIF, HarwellBoeing, HDF, HDF5,Integer128, Integer16, Integer32, Integer64, Integer8, JPEG, Lines,List, MAT, MathML, MGF, MPS, MTX, NB, NotebookML, PBM, PCX, PGM,PNG, PNM, PPM, Real128, Real32, Real64, SDTS, SND, STL, String,SymbolicXML, Table, TerminatedString, Text, TIFF, TSV, UnicodeText,UnsignedInteger128, UnsignedInteger16, UnsignedInteger32,UnsignedInteger64, UnsignedInteger8, WAV, Words, XBitmap, XLS, XML<
Daniele Lupo Appunti di Mathematica
180Printed by Mathematica for Students
Fra i molti che non conosco neanch'io, potete notare i formati più conosciuti, come BMP, JPEG,
WAV, Text, e, importante soprattutto per la compatibilità con i programmi più moderni, XML.
Questa lista ovviamente dipende dalla versione del programma posseduta (la mia è la 5.1), ma la
maggior parte dei file più comuni rimane invariata.
Il comando usato per importare dei dati è il seguente:
Import["file", "Table"] importa una tavola di dati da un file
La seconda opzione dice in particolar modo al programma in quale modo sono organizzati i file nel
file. Per i file di testo le opzioni più comuni sono:
¤ CSV: valori tabulari separati da una virgola.
¤ Lines: linee di testo.
¤ List: linee che sono formate più valori.
¤ Table: matrice bidimensionale di numeri oppure stringhe.
¤ Text: strnga di caratteri ordinari.
¤ TSV: tabella di testo con valori separati da tabulazione.
¤ UnicodeText: stringhe di caratteri Unicode di 16 bit.
¤ Words: parole separate da spazi o da ritorni a capo.
¤ XLS: formato di foglio di calcolo di Excel.
Supponiamo di voler importare una lista di dati:
Come potete vedere, l'importazione di un'immagine è cosa alquanto semplice e rapida
dati = Import@"D:\\Documenti\\dati.txt", "List"D
812312, 124314, 1312, 3123, 123, 123, 1, 41, 4, 35, 4, 543,635, 67, 5735, 3, 524, 52, 6, 264, 2, 62, 46, 53, 4, 23, 542<
Prima di continuare, notate come sono definiti i percorsi di file in Mathematica: infatti, usa una
notazione propria, che è indipendente dalla macchina e dal sistema operativo che si sta usando. Per
poter importare un file, è necessario il percorso assoluto, a meno che non si trovi nella cartella del
programma, cosa che fra l'altro vi sconsiglio di fare. Meglio tenere sempre separati programmi e
dati, come chiunque in vita sua ha provato almeno una volta a fare un backup sa bene. Per
semplificarvi la vita, potete usare la voce di menù del programma Input->Get File Path, che vi scrive
Daniele Lupo Appunti di Mathematica
181Printed by Mathematica for Students
direttamente il percorso quando scegliete il file da una finestra di Esplora Risorse. Detto questo,
possiamo andare avanti...
Come possiamo vedere, abbiamo appena importato il nostro file, con i valori contenuti in esso
raggruppati nella lista:
ListPlot@dati, PlotJoined → TrueD
5 10 15 20 25
500
1000
1500
2000
2500
3000
Graphics
Avendo la lista, adesso possiamo trattarla esattamente come abbiamo imparato fino ad adesso
possiamo elaborarla, estrarre valori, farne la trasformata di Fourier... Tutto quello che ci serve,
insomma. Possiamo anche importare formati grafici:
cane = Import@"D:\\Documenti\\Immagini\\dog02.jpg"D
Graphics
E possiamo visualizzarlo esattamente come se fosse una primitiva grafica di tipo Raster:
Daniele Lupo Appunti di Mathematica
182Printed by Mathematica for Students
Show@caneD
Graphics
Tuttavia, sebbene sia abbastanza semplice importare le immagini, estrarne i dati per le elaborazioni
richede un passaggio in più.
evanescence = Import@"D:\\Documenti\\Immagini\\EvanescenceFallenGroupWallpaper.jpg"D;
Show@evanescenceD
Graphics
Daniele Lupo Appunti di Mathematica
183Printed by Mathematica for Students
Possiamo vedere come sia stata importata l'immagine nel suo complesso. Tuttavia, possiamo notare
che, nel caso di immagini, importiamo oggetti grafici, che possono essere usati solo come tali.
Invece, può capitare che un'immagine ci serva come matrice, nel senso che ogni pixel contiene valori
numerici che ci interessano per elaborazioni numeriche. In questo caso, ci serve la lista che
Mathematica usa per rappresentare l'immagine raster.
Shallow@InputForm@evanescenceDD
Graphics@Raster@<< 4 >>D, Rule@<< 2 >>D, Rule@<< 2 >>D, Rule@<< 2 >>DD
Il comando Shallow permette di rappresentare in forma abbreviata il contenuto di un comando o di
una variabile. Vedremo in una delle sezioni successive più in dettaglio questo comando. Per ora ci
basti sapere che serve per visualizzare brevemente il contenuto di qualsiasi cosa esista in
Mathematica.
Possiamo vedere che la variabile evanescence che rappresenta il formato grafico è formato dal
comando Raster, più tre regole. sappiamo che il comando Raster richiede una lista di dati da
visualizzare, per cui la lista che ci interessa si trova proprio lì dentro. Possiamo estrarre direttamente
la lista dal formato grafico, nel seguente modo:
dati = evanescence@@1, 1DD;
Short@dati, 4D
8 1 <
Con il comando Short vediamo una rappresentazione riassunta del contenuto di qualcosa. L'ho
dovuta usare perchè i dati di un'immagine sono numerosi, ed avrebbero riempito decine di pagine. Si
può vedere che, per un'immagine, i dati sono rappresentati da una matrice, i cui elementi sono a loro
volta delle liste di tre numeri, rappresentanti rispettivamente i valori Rosso, Verde e Blu del pixel.
Una volta ottenuta la lista, possiamo elaborarla come più ci piace.
Naturalmente, possiamo effettuare tutte le operazioni di elaborazione delle immagini che vogliamo.
Soltanto che non è che conosca bene cose come il filtro di Kalman oppure algoritmi di
convoluzione... accontentatevi di questo esempio stupido ed anzi, se sapete suggerirmi qualche
algoritmo di elaborazione dei segnali particolarmente simpatico, sarò bel lieto di usarlo...
In questo caso, andiamo ad usare una matrice di convoluzione per trasformare la nostra immagine da
matrice di tre valori, a matrice di singoli valori, applicando un certo effetto, quindi trasformata in
scala di grigi. Andiamo a definire il nostro tensore:
Daniele Lupo Appunti di Mathematica
184Printed by Mathematica for Students
kernel = 888−1, −1, 0<, 81, 0, 1<, 81, −1, 1<<,881, 1, 1<, 8−2, −5, −1<, 81, 1, 1<<,881, 1, 1<, 81, 1, 1<, 8−1, 0, −1<<<;
Una volta creata la nostra matrice di convouzione, andiamo ad applicarla alla nostra immagine, o
meglio, alla lista di valori ad essa correlata (dato che la sola importazione comporta la creazione non
della lista, ma di un elemento grafico Raster): dobbiamo elaborare ogni singolo canale di colore
datielaborati = ListConvolve@kernel, datiD;
datielaborati = datielaboratiê Max@datielaboratiD;
Quindi adesso, dopo aver elaborato e normalizzato la nostra lista di elementi dell'immagine,
possiamo andare a mostrare direttamente il risultato:
Daniele Lupo Appunti di Mathematica
185Printed by Mathematica for Students
Show@Graphics@
Raster@datielaboratiD
D,AspectRatio → Automatic
D
Graphics
Ho effettuato una scrittura annidata per farvi capire meglio dove stanno i vari elementi: prima di
tutto ho usato il comando Show per rappresentare l'oggetto grafico rappresentato da Raster.
Quest'ultimo, come dovreste sapere, deve contenere la matrice necessaria per la visualizzazione;
inoltre, ho anche specificato la funzione colore da utilizzare, che stavolta è GrayLevel, in quanto il
risultato della convoluzione è data da una matrice i cui elementi sono singoli valori, invece che lista
di tre come per il caso dell'immagine originale... A questo punto, ho impostato per Show il rapporto
originale dell'immagine, e il risultato è bell'e visualizzato.
Anche se vuole essere soltanto un mero esempio, mi scuso ancora per non aver trovato un filtro più
originale ed utile ma, come vi dicevo poco fa, non ho mai avuto a che fare con l'elaborazione delle
immagini, ed anzi, penso che come prima volta non sia andata poi tanto male... Tanto dovete essere
voi a definire le vostre operazioni da eseguire sui dati, non io, ed inventarsi di sana pianta qualcosa
(in dieci minuti, fra l'altro... mica ho tutta la vita da spendere!!!) non è cosa facile.
Daniele Lupo Appunti di Mathematica
186Printed by Mathematica for Students
A proposito, come avrete capito io adoro quest'album!!! Se qualcuno che legge queste righe, in
segno di riconoscimento volesse presentarmi la cantante...
ü Esportazione
Dati
E adesso guardiamo l'altra faccia della medaglia, ovvero l'esportazione dei dati. Come sicuramente
sapete, avere un programma che fa cose bellissime e fighissime, e poi non possiamo farle vedere a
nessuno, è cosa alquanto inutile. Basti pensare a quanto può essere utile scrivere al computer una
tesina, se poi il programma non è in grado di stamparla... Esportare i dati è altrettanto importante che
importarli, perchè ci permette di andarli ad usare dove più ci serve. Può capitare infatti che, per
esempio, preferiate redigere le vostre relazioni in Word, e vi piacerebbe avere i risultati dei dati
oppure delle immagini grafiche all'interno delle sue pagine pacioccose. Ma perchè non usate Open-
Office, dico io...
Comunque, vediamo che, effettivamente, esportare i dati è altrettanto semplice:
Export["file", list, "Table"] esporta i dati contenuti in list in un file come tavoladi valori
Export["name.ext", graphics] esporta l' immagine in graphics conil formato dedotto dall' estensione del file
E x p o r t [ "f i l e" ,graphics, "format"]
esporta la grafica nel formato specificato
Supponiamo di avere la seguente lista:
lista = 881, 2, 4, 5<, 82, 3, 1, 24<, 82, 2, 4, 4<, 85, 6, 3, 2<<;
Per esportarla nel file di testo esempio.txt, basta scrivere:
Export@"esempio.txt", listaD
esempio.txt
Se vogliamo vedere il contenuto del file, basta scrivere:
!! esempio.txt
{{1, 2, 4, 5}, {2, 3, 1, 24}, {2, 2, 4, 4}, {5, 6, 3, 2}}
Daniele Lupo Appunti di Mathematica
187Printed by Mathematica for Students
Come possiamo vedere, in questo caso la lista è stata esportata proprio come la scrive Mathematica,
cioè mediante le parentesi graffe. Un formato che evita questo è il seguente:
Export@"esempio.dat", listaD
esempio.dat
!! esempio.dat
1 2 4 52 3 1 242 2 4 45 6 3 2
Come possiamo vedere, stavolta, cambiando l'estensione del file, i dati vengono esportati nella
maniera corretta e leggibile da altri programmi come Excel, cioè come matrice bidimensionale
separati da tabulazioni.
In maniera analoga possiamo esportare le immagini che creiamo con il programma:
grafico = Plot3D@Sin@Sqrt@x^2 + y^2DD,8x, −12, 12<, 8y, −12, 12<, PlotPoints → 60D
-10
-5
0
5
10-10
-5
0
5
10
-1
-0.5
0
0.5
1
-10
-5
0
5
10
SurfaceGraphics
Daniele Lupo Appunti di Mathematica
188Printed by Mathematica for Students
Export@"grafico.bmp", graficoD
grafico.bmp
In questo caso abbiamo esportato l'immagine in formato bitmap. Tuttavia, se avete intenzione di
stampare i vostri lavori, e se il programma che usate ve lo consente, io vi consiglio di usare il
formato Encapsulated PostScript .eps, perchè è gestito meglio da Mathematica, e soprattutto perchè
è un formato vettoriale, e quindi indipendente dalla risoluzione. Inoltre, è nativamente supportato da
Adobe Acrobat, che vi permette quindi di mantenere le immagini al massimo della qualità con un
considerevole risparmio di dimensioni rispetto ai formati raster quali BMP, JPEG anche se
compresso e TIFF, tutti comunque supportati dal programma. Le eccezzioni sono i grafici a curve di
livello e quelli di densità, cioè quelli che capite è difficile da rappresentare vettorialmente, in quanto
le dimensioni del file crescerebbero alquanto, a vantaggio dei formati raster. Per farvi capire la
differenza, ingrandite le ultime due immagini, quella del grafico, disegnata in eps da Acrobat, e
quella degli Evanescence, in formato compresso, e vedere come i pixel si vedano in questo secondo
caso, mentre nel grafico vettoriale anche ingrandendo la definizione rimane invariata.
Formule
Mathematica è anche in grado, ovviamente, di esportare le formule create nei suoi notebook.
Supponiamo di avere la seguente espressione:
formula = Integrate@1êSqrt@x^4 − 3D, xD
è!!!!!!!!!!!!!3 − x4 EllipticF@ArcSin@ x31ê4 D, −1D
31ê4 è!!!!!!!!!!!!!!!!−3 + x4
Possiamo esportarla come file eps:
Export@"formula.eps", ToBoxes@formulaDD
formula.eps
Possiamo anche esportare l'espressione in notazione tradizionale, se vogliamo:
tradizionale = TraditionalForm@formulaD
è!!!!!!!!!!!!!3 - x4 FJsin-1J xÅÅÅÅÅÅÅÅÅÅè!!!!34 N À -1NÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅè!!!34 è!!!!!!!!!!!!!x4 - 3
Export@"formula.eps", ToBoxes@tradizionaleDD
formula.eps
Daniele Lupo Appunti di Mathematica
189Printed by Mathematica for Students
Notate come si debba usare la funzione ToBoxes, mi raccomando.
Questo permette di esportare le formule in formato grafico. Tuttavia, esiste anche un modo mogliore,
e cioè usare il formato TEX. Come molti di voi fedeli seguaci saprete sicuramente, TEX e LATEX sono
due importantissimi strumenti per la documentazione scientifica, che permettono con degli opportuni
comandi in file di testo ASCII di poter creare formule e documentazione di alta qualità e dall'aspetto
decisamente professionale.
Mica pensavate che i libri di matematica si facessero col ridicolo Equation Editor di Word, vero????
Per convertire la formula in formato TEX, basta usare l'opportuno comando:
TeXForm[expr] scrive expr in formato TeX
Possiamo fare l'esempio con la formula di sopra:
TeXForm@formulaD
\frac{\sqrt{3-x^4} F\left(\left.\sin ^{-1}\left(\frac{x}{\sqrt[4]{3}}\right)\r ight|-1\right)}{\sqrt[4]{3} \sqrt{x^4-3}}
Questo testo è pronto per essere copiato ed incollato nel vostro editor LATEX (che preferisco rispetto a
TEX), ed una volta compilato darà il risultato desiderato. Appena vete un poco di tempo, se non lo
conoscete, dateci uno sguardo, anche perchè se farete la tesi con questo programma invece che con
Word, un punticino in più per la presentazione è assicurato!!!
Naturalmente, è anche possibile fare l'operazione opposta, ovvero convertire in espressioni tipiche di
Mathematica quelle scritte con LATEX:
ToExpression@"\\frac8Hx+yL^2<8\sqrt8x y<<", TeXFormD
Hx + yL2è!!!!!!!x y
Inoltre, è anche possibile convertire unintero Notebook usando il comando di menù File->Save As
Special, generando così sia il file tex che tutte le immagini eps necessarie.
Un'altra interessantissimissima (a mio avviso) caratteristica è il poter convertire ed esportare le
espressioni anche in formato C (oppure Fortran):
Daniele Lupo Appunti di Mathematica
190Printed by Mathematica for Students
CForm@formulaD
(Sqrt(3 - Power(x,4))* EllipticF(ArcSin(x/Power(3,0.25)),-1)) /(Power(3,0.25)*Sqrt(-3 + Power(x,4)))
Come potete vedere, l'espressione adesso è pronta per essere copiata ed incollata nel vostro editor C,
ammesso che abbiate definito prima le opportune funzioni. Si potrebbe anche usare Mathematica
stessa, usando dal vostro programma C il suo kernel, ma è una cosa che non ho mai fatto, e che non
ho intenzione di affrontare, anche perchè non saprei da dove cominciare. Comunque, vivrete
tranquillamente anche senza, fidatevi.
Invece, può essere estremamente utile, in questo caso, il seguente comando:
Splice["file.mx"] elabora l'input di Mathematica contenuto nel filefile.mx, e scrive il risultato in file.x
Splice["infile", "outfile"] specifica file di input e di output
Ipotizziamo di dover scrivere un programma di simulazione fisica in C, e che non ci ricordiamo il
risultato di un'espressione. In questo caso, potremmo scrivere all'interno dello stesso file un input in
formato Mathematica, opportunamente definito da degli opportuni indicatori di inizio e fine
espressione:
......
double x;
double y;
....
y= <* Integrate[1/Sqrt[1+x^3],x] *>;
......
Notate come la definizione del comando Mathematica sia racchiuso fra <* *>, per permettere al
programma un parsing più veloce ed efficiente. Adesso, diamolo in pasto al comando:
Splice@"C:\\Documents and Settings\\Daniele\\Desktop\\prova.mc"D
Il risultato è un file contenente il seguente testo:
......
double x;
double y;
....
y= (2*Power(-1,0.16666666666666666)*
Daniele Lupo Appunti di Mathematica
191Printed by Mathematica for Students
Sqrt(-(Power(-1,0.16666666666666666)*
(Power(-1,0.6666666666666666) + x)))*
Sqrt(1 + Power(-1,0.3333333333333333)*x +
Power(-1,0.6666666666666666)*Power(x,2))*
EllipticF(ArcSin(Sqrt(-(Power(-1,0.8333333333333334)*(1 + x)))/
Power(3,0.25)),Power(-1,0.3333333333333333)))/
(Power(3,0.25)*Sqrt(1 + Power(x,3)));
......
Come potete vedere, questo comando è una figata pazzesca, e sono convinto che vi aiuterà in più di
un'occasione, fidatevi!!! Sempre se avrete a che fare con la programmazione, però, ovvio!!!
ü Packages
Introduzione
I packages sono, in poche parole, dei file che contengono definizioni di formule, costanti ed altro.
Vengono utilizzati quando avete delle funzioni che utilizzate spesso, specialmente in lavori diversi
fra di loro (per esempio, preferite usare un vostro set di funzioni personalizzate per eseguire delle
operazioni di routine, come importazione da file sempre uguali, oppure funzioni personalizzate che
vi servono, come delle equazioni differenziali che state studiando in quel periodo).
Memorizzarle una volta sola ha il vantaggio di non doverle riscrivere ogni volta che ne avete
bisogno, risparmiando tempo, ed evitando tra l'altro la possibilità di poter sbagliare le equazioni che
scrivete, facendolo una volta sola, ed, ovviamente, assicurandoci che in quell'unica volta siao
giuste!!!!!
Diciamo che i packages sono un poco come i file di header del C, contenenti funzioni e quant'altro,
già belli pronti all'uso.
Mathematica include già, in fase di installazione, un bel po' di packages, pronti per l'uso, che
contengono parecchie funzioni specialistiche. Quando volete utilizzare una particolare funzione,
basta caricare il package che la contiene. Se poi utilizzate spesso funzioni contenute in vari packages
(per esempio, se usate spesso avanzate funzioni di statistica), potete caricare questi file all'avvio di
Mathematica, che quindi avrà fin dall'inizio, nella sua pancia, quello che vi serve. Occhio, però, che
se utilizzate lo stesso file in un altro computer, dovete ricordarvi che probabilmente i file non
saranno pre-caricati, e dovrete caricarli di nuovo a mano.
Quindi, vedremo prima come realizzare i propri packages personali, come salvarli, come caricarli, e
come fare in modo che Mathematica li carici automaticamente. Dopo faremo una panoramica su vari
packages di Mathematica. Non avrò nè il tempo nè lo spazio di descriverli tutti, anche perchè di
solito variano in numero da varsione a versione di Mathematica (io sto usando la 5.1). Se non
Daniele Lupo Appunti di Mathematica
192Printed by Mathematica for Students
trovate qua quello che vi serve, probabilmente lo troverete nell'help di Mathematica nella sezione
Add-ons.
Salvataggio e caricamento
Caricare un package in Mathematica è abbastanza facile, a parte una cosa che, purtroppo, è
rognosetta per chi ha la tastiera italiana: un package predefinito si richiama con la seguente sintassi:
<< directorypackage`nome package`
I simboli che circondano il nome del package non sono i singoli apici della nostra tastiera itailana;
sono degli accenti gravi, che possiamo scrivere utilizzando il loro codice unicode 96: per poterlo
scrivere dobbiamo quindi battere da tastiera ALT+096, con i numeri del tastierino numerico, non
quelli della tastiera, per cui chi possiede un portatile (come me....), deve attivare la simulazione del
tastierino numerico. Tutavia basta farci l'abitudine, che si fa dopo qualche volta che si richiama un
package. In alternativa, è possiblile copiarlo dalla Mappa Caratteri di Windows, oppure dall'help di
Mathematica, ma imparare a scriverlo direttamente dalla tastiera sarà meglio... Inoltre, potete al
limite scrivere voi stessi un package personalizzato, dove andate a scrivere tutti i package predefiniti
che vi servono, senza bisogno di chiamarli, e chiamando solamente il file che avete creato, che sarà
senza caratteri strani, e soprattutto breve!!!
Comunque, vediamo dapprima di creare i nostri packages. Supponiamo di volerci definire una
funzione personalizzata; aprendo un nuovo file possiamo allora scrivere all'interno la nostra funzione
f@x_, y_D := x^4 + x^Cos@3 y xD
Una volta creato la funzione, o più probabilente le funzioni che vogliamo caricare nel package, non
abbiamo finito: prima di salvare il file, dobbiamo andare a convertire le celle in cui sono contenute le
funzioni, trasformandole in celle di inizializzazione. Per fare questo, selezioniamo una cella,
cliccando sulla corrispondente linea sulla destra del notebook, e andiamo su Cell->Cell Properties->-
Inialization Cell. Vediamo che il sibolo che contraddistingue la cella è cambiato. A questo punto
andiamo su File->Save As Special-> Package Format. In questa maniera andremo a creare in un file
con estensione .m il package desiderato. Adesso, se volete, cancellate con Clear la definizione della
funzione, e caricate il file in questa maniera:
<< file
Se salvate il file in una posizione precisa, per trovarlo potete utilizzare il comando di menù Input->-
Get File Path, permettendovi di selezionare dalla finestra di Explorer il vostro file. Nel mio caso ho:
<< "C:\\Documents and Settings\\Daniele\\Desktop\\prova.m"
Daniele Lupo Appunti di Mathematica
193Printed by Mathematica for Students
Una volta caricato, notiamo come la f sia direttamente disponibile:
f@5, 7D
625 + 5Cos@105D
Ovviamente, raramente si utilizzeranno packages per poter memorizzare funzioni semplici. Di solito
si utilizzano per memorizzare e precaricare funzioni abbastanza complicate, programmi di parecchie
pagine, e tutto il resto. Ovviamente anche definizioni semplici, magari se sono parecchie e se dovete
caricarle tutte ogni volta che iniziate un lavoro. Il mio consiglio è di non abusarne, andando a
memorizzare ogni cosa vi capiti, perchè in questo caso avrete un numero esagerato di packages e
non saprete più cosa contengono. Inoltre, createli organizzati, senza andare a mettere funzioni e
programmi a caso in un unico package. In questa maniera, ed utilizzando nomi appropriati, sarete in
grado di poter caricare ogni volta il package che vi serve.
Se andate ad aprire adesso il file .m, noterete che contiene la definizione della funzione:
f[x_, y_] := x^4 + x^Cos[3y x]
Quando avrete molte funzioni, potrebbe però essere difficile andarsi a ricordare quello che fanno,
anche se si guarda la definizione, se non opportunamente commentata. Tuttavia, possiamo anche
inserire nel package, assieme ad una funzione, anche una spiegazione riguardante la sua funzione,
che appare quando andiamo ad usare il comando ? sulla funzione, esattamente come per le funzioni
predefinite:
? Cos
Cos@zD gives the cosine of z. More…
Per questo è utile andare ad utilizzare parecchi commenti quando si vanno a creare questi files,
esattamente come le buone regole di programmazione.
Esiste uno standard de facto per il commento dei packages: di solito si inizia così:
Daniele Lupo Appunti di Mathematica
194Printed by Mathematica for Students
H∗:Mathematica Version:x.x∗LH∗:Package Version:y.y∗LH∗:Name:Nome`def`∗LH∗:Author:Nome Autore∗LH∗:URL:sito web del package∗LH∗:Summary:∗LH∗:History:v1 .00 H2003−02−20L:
Written v1 .01 H2003−10−18L:Modified now that Norm is
built in to v5.Updated context.HcL 2004 Autore∗LH∗:Keywords:∗LH∗:Requirements:None.∗LH∗:Discussion:∗LH∗:References:∗LH∗:Limitations:None known.∗L
Ogni riga rappresenta un commento, di conseguenza, tutto quello che avete visto finora è
completamente facoltativo... Mettete comunque qualche informazione, specialmente se fate un
package serio, e magari volete metterlo su Internet per poter condividerlo assieme agli altri...
Dopo aver scritto 'la presentazione', occorre il comando BeginPackage per cominciare il package
vero e proprio:
BeginPackage@"PersonalPack`Esempio`"D
"Esempio" rappresenta il context del package, e rappresenta il modo in cui si evita di sovrascrivere
altre definizioni di altri packages. Per intenderci, possiamo utilizzare due files, uno con context
"Esempio" e l'altro con context "Mare". Inoltre, può capitare che entrambi questi packages abbiano
definito una funzione con lo stesso nome, diciamo f . Allora, per distinguere la f di un package
rispetto all'altro, bisogna accodargli il context, per specificare a quale funzione ci riferiamo; se,
quindi, vogliamo utilizzare la funzione di Esempio, dobbiamo scrivere:
f`Esempio
Dove bisogna sempre utilizzare l'accento grave. Potete anche farne a meno, ed utilizzare soltanto il
nome principale, utilizzando però l'ultimo accento grave.
Dopo, seguono le descrizioni delle funzioni, che sono di questo tipo:
funzione::usage = "f@x,yD Spiegazione della funzione"
Daniele Lupo Appunti di Mathematica
195Printed by Mathematica for Students
Quando si creano riche di questo tipo, la stringa viene utilizzata per poter spiegare, tramite il
comando ?, il funzionamento della funzione (scusate il gioco di parole...), esattamente come per i
comandi predefiniti: per esempio, scritto questo nel nostro package, e ricaricato (dopo aver scritto
anche il resto, però...)
? f
f@x,yD Spiegazione della funzione
Come potete vedere, abbiamo inserito la spiegazione della funzione.
Dopo averle scritte, possiamo andare a definire le nostre funzioni, esattamente come faremmo
all'interno di Mathematica. Ricordatevi solamente che tutte le celle devono essere inizializzate, come
abbiamo visto poco fa. A questo punto, scriviamo le ultime due righe che finiscono il package:
End@D
EndPackage@D
A questo punto, salviamo il file come file .m ed il package è fatto, pronto per essere utilizzato
quando vogliamo.
Un'altra caratteristica dei package, sarà familiare a chi conosce il C++: sto parlando delle funzioni
pubbliche e private. Quando andiamo a creare le funzioni in questa maniera, tutte quante sono
disponibili da Mathematica quando si richiama il package. Tuttavia, ci possono essere funzioni e
variabili che non servono a noi direttamente, ma servono per valutare le funzioni all'interno del
package. Per evitare, allora, che nascondano altri nomi, oppure per evitare che le modifichiamo
acccidentalmente, occorre definire privati queste variabili, e funzioni, e questo si puù ottenere
facilmente inserendo le definizioni di queste funzioni in questo blocco:
Begin["`Private`"]
... ... ... ... ...
End@D
A questo punto, nessuno più vi toccherà queste funzioni, che saranno invisibili per voi, e non ve ne
dovrete preoccupare.
Vediamo di fare un esempio pratico: vogliamo creare un piccolo package che contenga alcune
funzioni per i numeri complessi. Vediamo quali sono le funzioni che vogliamo:
Daniele Lupo Appunti di Mathematica
196Printed by Mathematica for Students
à exptoalg[x] per convertire un numero complesso dalla forma esponenziale a quella algebrica.
à algtoexp[x] converte il numero complesso dalla forma algebrica a quella esponenziale
à retta[x,y] calcola l'equazione della retta che, nel piano, passa per i due numeri complessi specificati
La prima funzione sarà la seguente:
exptoalg@x_D := ComplexExpand@Re@xDD + I ComplexExpand@Im@xDD
Notate come abbia utilizzato ComplexExpand, per farlo funzionare anche con valori letterali.
La seconda funzione sarà definita nel seguente modo:
algtoexp@x_D := ComplexExpand@Abs@xDD Exp@I ComplexExpand@Arg@xDDD
La retta, invece, sarà costruita dalla seguente funzione:
retta@xx_, yy_D :=
Solve@ComplexExpand@Im@xx − yyDDêy ComplexExpand@Re@xx − yyDDêx, yD
Andiamo a scrivere il nostro file:
H∗:Mathematica Version:5.1∗L
H∗:Package Version:1.0∗L
H∗:Name:Complessi`Conversione`∗L
H∗:Author:Daniele Lupo∗L
BeginPackage@"Complessi`"D
algtoexp::usage =
"algtoexp@xD scrive il numero complesso x in forma algebrica"
exptoalg::usage =
"exptoalg@xD scrive il numero complesso x in forma esponenziale"
retta::usage =
"retta@x,yD restituisce l'equazionedella retta passante per i due numeri complessi"
exptoalg@x_D := ComplexExpand@Re@xDD + I ComplexExpand@Im@xDD
Daniele Lupo Appunti di Mathematica
197Printed by Mathematica for Students
algtoexp@x_D := ComplexExpand@Abs@xDD Exp@I ComplexExpand@Arg@xDDD
retta@xx_, yy_D := Solve@ComplexExpand@HIm@xxD − yLêHIm@xx − yyDLD
ComplexExpand@Re@xxD − xêRe@xx − yyDD,y
D
EndPackage@D
Una volta creato il nostro package, andiamo a richiamarlo nel notebook
<< "C:\\Documents and Settings\\Daniele\\Desktop\\complessi.m"
Adesso vediamo che, senza bisogno di riscrivere le funzioni, queste sono effettivamente già definite
(potete fare la prova richiudendo ed aprendo Mathematica, e caricare direttamente il package):
algtoexp@3 + 9 ID
3 è!!!!!!10 ArcTan@3D
exptoalg@%D
3 + 9
retta@9 + 9 I, 7 + 6 ID
99y →32H−12 + xL==
? retta
retta@x,yD restituisce l'equazionedella retta passante per i due numeri complessi
Come potete vedere, tutto funziona esattamente come volevamo...
Potete quindi notare come possiamo personalizzare in questa maniera Mathematica, andando a
crearci da soli quello che ci serve, se casomai non ci dovesse essere, ma mi sembra difficile... I primi
tempi probabilmente troverete più utili i packages nel creare alias molto brevi di funzioni che
utilizzate spesso e che sono lunghi, per esempio un comando Plot con diverse righe di opzioni di
formattazione...
Se poi vogliamo caricare automaticamente un package, basta usare la seguente funzione:
Daniele Lupo Appunti di Mathematica
198Printed by Mathematica for Students
DeclarePackage["context`",{"name1", "name2", … }]
dichiara che il package deve essere automaticamentecaricato quando un simbolo con uno qualsiasi deinomi namei viene utilizzato
In questo modo, specifichiamo le funzioni che vogliamo siano automaticamente caricate, e da quale
file vogliamo che vengano lette.
Ricordate soltanto (e lo ripeto per la seconda volta), di mantenere quanto più organizzati e specifici
possibili i vostri packages. Dovrebbero essere progettati inmodo da poter risolvere dei compiti
specifici, non per essere dei contenitori casuali di funzioni...
Nota
Abbiamo appena visto come poter creare i nostri packages. Tuttavia, Mathematica in fase di
installazione copia nel computer parecchi packages predefiniti, utilissimi in molti casi, semplificando
di molto la risoluzione di parecchi problemi. Nell'appendice A di questi appunti vi descriverò alcuni
dei tanti packages, quelli che ritengo più utili. Vedete se non trovate quello che fa al caso vostro!!!
Daniele Lupo Appunti di Mathematica
199Printed by Mathematica for Students
Programmazioneü Introduzione
Come potete vedere e avete visto finora, Mathematica dispone di potentissimi comandi che
permettono di eseguire operazioni e calcoli che richiederebbero un tempo notevole per poter essere
eseguiti in qualsiasi altro modo (a me conosciuto). Soprattutto i comandi per il calcolo simbolico
sono molto potenti, e permettono di poter effettuare cose che per esempio, in Fortran non si possono
neanche pensare.
Sembra naturale ed ovvio, quindi, disporre di strumenti per poter mettere assieme questi comandi, in
modo da poter eseguire una serie di operazioni in maniera automatizzata, esattaemente come si tratta
per i programmi veri e propri; anzi, Mathematica consiste proprio di in un linguaggi di
programmazione ad alto livello con comandi molto potenti, come avete anche visto con i vostri occhi
e le vostre agili dita sulla tastiera.
Vedremo adesso i concetti base di programmazione in Mathematica, anche se probabilmente sarà
una lettura molto veloce per molti di voi, dato che i principi base sono gli stessi per qualsiasi
linguaggio di programmazione.
Quello che permette Mathematica, invece, è un controllo più avanzato per quanto riguarda le
interfacce visuali, usando entrambi i sistemi Java e .NET. Tuttavia io non so ancora programmare ad
oggetti, per cui le interfacce grafiche in Mathematica, come in C++, mi sono oscure. Tuttavia
cercherò almeno di introdurvi nel discorso, in modo da poter cercare da soli la vostra strada per
raggiungere la meta (miiii, che poetaaaa!!!! da leggere alla Aldo...).
ü Comandi base
Cominciamo direttamente con un esempio...
Inizio
In[1]:= Print@"Ciao bello!"D
Ciao bello!
Quello che abbiamo ottenuto è l'equivalente in Mathematica del famoso programma "Hello World"
che qualsiasi professore di qualsiasi corso di qualsiasi università vi fa il primo giorno... Solo che qua
le cose sono decisamente più semplici, dato che non esistono main ed altre cavolatine varie
(qualcuno ha detto Basic?).
Daniele Lupo Appunti di Mathematica
200Printed by Mathematica for Students
Il comando Print, effettivamente, non fa altro che rappresentare il suo argomento sullo schermo; in
questo caso, una stringa. Ebbene sì, miei cari allievi pendenti dalle mie labbra: Mathematica
permette anche di gestire le stringhe, fra l'altro con la stessa potenza (quasi, va') del calcolo.
D'altronde, essendo un programma di calcolo simbolico, che difficoltà ha nel gestire stringhe che
altro non sono se una serie di simboli?
Abbiamo anche visto che le funzioni che possiamo definire in Mathematica possono fare ben più che
dare come risultato un mero numero: in effetti, possiamo anche pensarle come le funzioni dei
linguaggi di programmazione, che riescono a fare un compito assegnato qualsiasi, ammesso che si
riesca a programmarlo... Ma questa è un altra storia. Consideriamo, per esempio, la seguente
funzione:
In[2]:= esprod@x_, y_, t_, n_IntegerD := FullSimplify@Series@x y, 8t, 0, n<DD
In[3]:= esprod@x^2 + Sqrt@xD, Gamma@xD, x, 3D
Out[3]=1è!!!x − EulerGamma è!!!x + x +
112
H6 EulerGamma2 + π2L x3ê2 −
EulerGamma x2 +112
H−2 EulerGamma3 − EulerGamma π2 − 4 Zeta@3DL x5ê2 +
112
H6 EulerGamma2 + π2L x3 + O@xD7ê2
La nostra funzione, in questo caso, non restituisce un numeri, ma un'espressione, come potete ben
vedere. Possiamo considerarla come un sottoprogramma, come una macro, come quello che volete,
insomma. Le funzioni che si definiscono possono contenere un numero arbitrario di funzioni e
comandi, diventando dei veri e propri programmi che girano all'interno di Mathematica. Il concetto è
proprio questo, ed in questo risiede buona parte della potenza che un utente avanzato riesce a
spremere dal programma. Non per niente in giro esiste una guida in inglese di 3400 pagine su come
programmare in Mathematica... Brrrrrr.... mi vengono i brividi solo a pensare di aprire un simile
libro...
Tranquilli, le cose che faremo qua sono molto, mooolto più semplici (e con questo mi sono dato
dell'imbecille).
Cominciamo a vedere i comandi, per scrivere e ricevere dati.
Daniele Lupo Appunti di Mathematica
201Printed by Mathematica for Students
Input ed output
Abbiamo visto, prima, come importare ed esportare dati da files, in modo semplice e diretto.
Abibamo anche visto, appena sopra, che è possibile dare in pasto ad un programmino opportuni
argomenti, e inoltre abbiamo visto come stampare i risultati mediante il comando Print. Tuttavia, in
maniera analoga ad altri casi, possiamo anche introdurre dei dati mediante il comando Input:
Input["String"] richiede un valore, esplicitando la richiesta mediante string
Possiamo eseguire, per esempio, questo comando:
In[4]:= a = Input@"Inserisci il numero"D
Out[4]= 555
In[5]:= a
Out[5]= 555
Qua non posso mostrarlo, ma appena eseguiamo il comando, appare una finestra del kernel del
programma, dove compare sopra la stringa che abbiamo scritto, e sotto un riquadro dove scrivere il
valore desiderato. In questo modo ho introdotto il valore, che è stato assegnato, come avete visto,
alla variabile a. Questo è utile quando dobbiamo scrivere funzioni con molti parametri, e magari
utilizziamo alcuni solo in situazioni particolari. Tuttavia si tratta sempre di valori che dobbiamo
introdurre noi, per cui non è possibile effettuare Input se la funzione deve essere automatizzata, cioè
deve essere effettuata senza il nostro intervento, In questo caso bisogna passare tutti gli argomenti
necessari, oltre a magari definire prima delle variabili opportune.
Come abbiamo visto, per l'output su schermo possiamo usare il comando Print, oltre che i vari
comandi di disegno nel caso ci servano.
Daniele Lupo Appunti di Mathematica
202Printed by Mathematica for Students
In[6]:= disegno@D := Sequence@n = Input@"Inserisci il numero di seni:"D,Plot@
Evaluate@Table@
Sqrt@iD Sin@i xD, 8i, n<D
D,8x, 0, 10<,PlotStyle → [email protected],Print@"Hai disegnato " <> ToString@nD <> " seni."D
Clear@nDD
In[7]:= disegno@D;
2 4 6 8 10
-2
-1
1
2
Hai disegnato 6 seni.
In questo programmino abbiamo visto tutti e tre i metodi: il modo di avere un input al programma, e
due output: uno grafico, che si ottiene semplicemente con il comando Plot, e l'altro ottenuto
mediante Print.
Possiamo anche scrivere e leggere file che contengano espressioni di Mathematica, se non abbiamo
bisogno di importare ed esportare, semplificando la sintassi. Supponiamo che dobbiamo scrivere
un'espressione, e di volerla salvare su un file perchè, per esempio, dobbiamo uscire con la nostra
ragazza, ed al ritorno, se saremo tristi e soli perchè ci ha lasciati, possiamo aprire un nuovo file senza
dover ricaricare e valutare quello vecchio, continuando da dove ci siamo interrotti:
Daniele Lupo Appunti di Mathematica
203Printed by Mathematica for Students
Get: << legge un file contenente espressioni di Mathematica,restituendo il risultato dell' ultima
Put: >> scrive l' espressione in un file. Possiamo scriverne più diuna nello stesso file con la forma Put@ex1, ex2,...., " file "D
PutAppend: >>> accoda l' espressione nel file
Dicevamo, che avevamo il seguente output:
In[8]:= Expand@Hx − 6L^7D
Out[8]= −279936 + 326592 x − 163296 x2 + 45360 x3 − 7560 x4 + 756 x5 − 42 x6 + x7
Adesso, vogliamo memorizzarlo nel file
In[9]:= % >> "espanso"
Questo comando memorizza l'espressione nel file. Vediamo se lo contiene:
In[10]:= !! espanso
-279936 + 326592*x - 163296*x^2 + 45360*x^3 - 7560*x^4 + 756*x^5 - 42*x^6 + x^7
Abbiamo visto il contenuto del file. Se vogliamo ricaricarlo in memoria, a questo punto basta fare
In[11]:= espr = << espanso
Out[11]= −279936 + 326592 x − 163296 x2 + 45360 x3 − 7560 x4 + 756 x5 − 42 x6 + x7
In[12]:= espr
Out[12]= −279936 + 326592 x − 163296 x2 + 45360 x3 − 7560 x4 + 756 x5 − 42 x6 + x7
Come potete vedere, adesso espr contiene l'espressione che avevamo salvato in precedenza. Notate
come !! non restituisce l'espressione, ma solo il contenuto del file. Abbiamo comunque bisogno del
comando Get per poter leggere il file, interpretarlo e memorizzarlo nella variabile.
A volte, invece, mentre lavoriamo, può capitare di non dover memorizzare tutte le espressioni in una
volta, ma a poco a poco. In questo ci viene in aiuto il comando PutAppend:
Daniele Lupo Appunti di Mathematica
204Printed by Mathematica for Students
In[13]:= ExpandAll@Hx − 4L^5êHx − 2L^7D êê TraditionalForm
Out[13]//TraditionalForm=x5
ÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅx7 - 14 x6 + 84 x5 - 280 x4 + 560 x3 - 672 x2 + 448 x - 128
-
20 x4ÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅx7 - 14 x6 + 84 x5 - 280 x4 + 560 x3 - 672 x2 + 448 x - 128
+
160 x3ÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅx7 - 14 x6 + 84 x5 - 280 x4 + 560 x3 - 672 x2 + 448 x - 128
-
640 x2ÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅx7 - 14 x6 + 84 x5 - 280 x4 + 560 x3 - 672 x2 + 448 x - 128
+
1280 xÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅx7 - 14 x6 + 84 x5 - 280 x4 + 560 x3 - 672 x2 + 448 x - 128
-
1024ÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅx7 - 14 x6 + 84 x5 - 280 x4 + 560 x3 - 672 x2 + 448 x - 128
In[14]:= % >>> espanso
In[15]:= !! espanso
-279936 + 326592*x - 163296*x^2 + 45360*x^3 - 7560*x^4 + 756*x^5 - 42*x^6 + x^7-1024/(-128 + 448*x - 672*x^2 + 560*x^3 - 280*x^4 + 84*x^5 - 14*x^6 + x^7) + (1280*x)/(-128 + 448*x - 672*x^2 + 560*x^3 - 280*x^4 + 84*x^5 - 14*x^6 + x^7) - (640*x^2)/(-128 + 448*x - 672*x^2 + 560*x^3 - 280*x^4 + 84*x^5 - 14*x^6 + x^7) + (160*x^3)/(-128 + 448*x - 672*x^2 + 560*x^3 - 280*x^4 + 84*x^5 - 14*x^6 + x^7) - (20*x^4)/(-128 + 448*x - 672*x^2 + 560*x^3 - 280*x^4 + 84*x^5 - 14*x^6 + x^7) + x^5/(-128 + 448*x - 672*x^2 + 560*x^3 - 280*x^4 + 84*x^5 - 14*x^6 + x^7)
Come potete vedere adesso, il contenuto del file è cambiato, aggiungendo l'ultima espressione a
quella già memorizzata in precedenza. In questo caso, però, dobbiamo fare attenzione. Abbiamo
detto che il comando valuta tutte le espressioni, ma restituisce solamente l'ultima: se andiamo a
memorizzare il contenuto del file abbiamo:
Daniele Lupo Appunti di Mathematica
205Printed by Mathematica for Students
In[16]:= espr2 = << espanso êê TraditionalForm
Out[16]//TraditionalForm=x5
ÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅx7 - 14 x6 + 84 x5 - 280 x4 + 560 x3 - 672 x2 + 448 x - 128
-
20 x4ÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅx7 - 14 x6 + 84 x5 - 280 x4 + 560 x3 - 672 x2 + 448 x - 128
+
160 x3ÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅx7 - 14 x6 + 84 x5 - 280 x4 + 560 x3 - 672 x2 + 448 x - 128
-
640 x2ÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅx7 - 14 x6 + 84 x5 - 280 x4 + 560 x3 - 672 x2 + 448 x - 128
+
1280 xÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅx7 - 14 x6 + 84 x5 - 280 x4 + 560 x3 - 672 x2 + 448 x - 128
-
1024ÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅx7 - 14 x6 + 84 x5 - 280 x4 + 560 x3 - 672 x2 + 448 x - 128
In[17]:= Simplify@%D
Out[17]=H−4 + xL5H−2 + xL7
Possiamo vedere come solamente l'ultimo risultato memorizzato nel file venga poi effettivamente
memorizzato. Se vogliamo leggerli tutti dobbiamo utilizzare il comando ReadList:
In[18]:= espr3 = ReadList@"espanso"D;
In[19]:= Simplify@espr3D
Out[19]= 9H−6 + xL7, H−4 + xL5H−2 + xL7 =
Come possiamo vedere, stavolta abbiamo ottemuto una lista contente tutte le espressioni contenute
nel file.
A questo punto, ci si può chiedere perchè Get restituisce solamente l'ultima espressione valutata.
Questo dipende dal fatto che quando inseriamo una sequenza di operazioni un unico comando,
Mathematica restituisce solo l'ultimo, anche se li calcola tutti. Può sembrare uno svantaggio, ma
l'uso è invece specifico. Possiamo, infatti, memorizzare delle definizioni di funzioni o di programmi
personali nel file. Una volta che si legge, valuta e calcola tutte le funzioni, che quindi saranno
direttamente disponibili senza doverle riscrivere oppure senza dover aprire e valutare il notebook
dove sono contenute: in questo caso, infatti, non appena avremo eseguito Get ed il programma avrà
valutato ogni espressione, avrà tutto quanto in pancia, semplificandoci il lavoro. In effetti, Get viene
utilizzato spesso per caricare Packages esterni, ovvero file dove sono memorizzate definizioni,
costanti e funzioni che permettono di snellire il lavoro per un compito specifico, come quello
standard in Mathematica dedicato al calcolo vettoriale.
Daniele Lupo Appunti di Mathematica
206Printed by Mathematica for Students
Flusso di programma
Come certamente saprete, ci sono casi in cui il programma non deve svolgersi esattamente riga per
riga dall'inizio alla fine, ma bisogna effettuare delle scelte, ed eseguire determinate operazioni a
seconda del tipo di risposta ottenuta. Naturalmente cominceremo con il comando più conosciuto:
If[p, then, else] restituisce then se p è True, ed else se p è False
In altre parole, esegue l'operazione logica p, e decide cosa fare a seconda del risultato. Per scrivere
codice, userò l'annidamento, dato che ormai sapere che si possono annidare comandi senza problemi
(mica ve l'avevo fatto vedere per niente... tutto ha un fine!):
In[20]:= test@x_D :=
If@x^2 > 5,Print@"Il test è corretto, e risulta ", x^2D,Print@"Hai sbagliato tutto!!!"D
D
Non credo che il programmino (assimilabile ad una funzione personalizzata, ma abbiamo capito che
sono la stessa cosa), abbia bisogno di spiegazioni, vero?
In[21]:= test@2D
Hai sbagliato tutto!!!
In[22]:= test@4D
Il test è corretto, e risulta 16
Già da qua potete vedere come spuntano cosucce carine e notevoli, come il fatto che si possono
mischiare stringe e valori, e notando come non sia necessario, come il C, l'uso di caratteri e stringhe
come %d o %f. Risulta più semplice scrivere questo semplice programma in Mathematica che in C o
in Basic, figurarsi quelli complicati...
Per saggiare la flessibilità e la potenza dell'ambiente di programmazione, consideriamo quest'altro
programma:
Daniele Lupo Appunti di Mathematica
207Printed by Mathematica for Students
In[23]:= disegno@tipo_Integer, n_IntegerD :=
If@tipo 0,Plot@
Evaluate@Table@
BesselJ@q, xD, 8q, n<D, 8x, 0, 12<,PlotStyle →
Table@8Hue@rênD, [email protected] rênD<, 8r, n<DD
D,Plot@
Evaluate@Table@
BesselI@q, xD, 8q, n<D, 8x, 0, 12<,PlotStyle →
Table@8Hue@rênD, [email protected] rênD<, 8r, n<DD
DD;
In[24]:= disegno@0, 7D
2 4 6 8 10 12
-0.2
0.2
0.4
0.6
Out[24]= Graphics
Daniele Lupo Appunti di Mathematica
208Printed by Mathematica for Students
In[25]:= disegno@2, 5D
2 4 6 8 10 12
250
500
750
1000
1250
1500
Out[25]= Graphics
In[26]:=
Possiamo vedere come si possano effettuare e sintetizzare in un unico comando cose anche più
complicate. Provate a farlo in C...
Un piccolo limite (ma neanche tanto) della programmazione in Mathematica riguarda la
concatenazione di più comandi assieme: considerate, per esempio, il seguente programmino:
In[27]:= prova@c_D := Print@"Il sole è bello"Da = cPrint@"a"DClear@aD;
Out[28]= c
a
In[31]:= prova@4D
Il sole è bello
Come potete vedere, c'è qualcosa che non va. Prima di tutto, appena definita la funzione ho un
risultato, cosa che non dovrebbe succedere quando si dediniscono funzioni oppure programmi,
mentre una volta richiamato il programmino da l'output incompleto, restituendo solamente il primo
Daniele Lupo Appunti di Mathematica
209Printed by Mathematica for Students
comando. Per Mathematica, in effetti, abbiamo definito prima vari comandi tutti distinti fra di loro, e
quindi il secondo comando, quello di assegnamento, è disconnesso da tutto il resto. Possiamo
provare a visualizzare il contenuto del programma:
In[32]:= ?? prova
Global`prova
prova@c_D := Print@Il sole è belloD
Come potete vedere, la funzione è formato solo dal primo comando. Quindi non ci sono comandi
concatenati. Effettivamente, per poterli fare, opporre usare un altro comando, dove all'interno sono
contenuti tutti i comandi del programma:
Sequence[...] esegue in sequenza tutti i comandi racchiusiall'interno delle sue parentesi.
In[33]:= prova@c_D := Sequence@Print@"Il sole è bello"D,a = c,Print@aD,Clear@aDD;
Come potete vedere, abbiamo definito il programma come un'unica funzione. Vediamo adesso se
funziona:
In[34]:= prova@8D
Il sole è bello
8
Out[34]= Sequence@Null, 8, Null, NullD
In[35]:= prova@2D
Il sole è bello
2
Out[35]= Sequence@Null, 2, Null, NullD
Come potete vedere, questa volta il programma funziona, avendo eseguito tutti i comandi in
sequenza. Inoltre, si può vedere come ritorna anche Sequence con il risultato di ogni comando
Daniele Lupo Appunti di Mathematica
210Printed by Mathematica for Students
contenuto in esso, cioè tre Null dovuti ad un Print ed al Clear, ed l'8 dell'assegnazione: Print,
restituisce Null perchè stampa qualcosa sullo schermo, ma non memorizza niente all'interno del
programma come variabili od altro... Quindi se a noi restituisce un risultato, questo non è altrettanto
vero per Mathematica, e quindi, restituisce Null.
Ora sappiamo usare l'If e sappiamo anche come si realizza una sequenza di programmi, per cui
possiamo anche vedere gli altri comandi di controllo, che sono simili agli altri linguaggi di
programmazione:
lhs := rhs /; test usa la definizione solo se test risulta True
If[test, then, else] valuta then se test risulta True, ed else se risulta False
Which[test1, value1, test2, … ] valuta testi e quando trova il primo che risultaTrue, restituisce il corrispondente valore
Switch[expr, form1,value1, form2, … ]
compara expr con le forme in formi, restituendoil risultato della prima corrispondenza che trova
Switch[expr, form1,value1, form2, … , _, def]
usa def come valore di default
Piecewise[{{value1, test1},… }, def]
restituisce il primo valore testi che corrisponde a True
Sono tutte istruzioni condizionali, che permettono di scrivere in diverse maniere un algoritmo di
scelta, restituendo quella più opportuna. Si decide quale usare a seconda di quella che restituisce la
sintassi più breve e coincisa. In teoria, infatti, niente ci vieta di sostituire ogni comando con una serie
opportunamente annidata di If...
In[36]:= prova@x_D := Sequence@Print@"Inizio"D,Which@
x > 0, Print@"Il numero è positivo"D,x < 0, Print@"Il numero è negativo" D,x 0, Print@"Hai beccato lo zero!!!"DD,Print@"Il quadrato risulta ", x^2D,Print@"Fine programma. Ciao da Daniele"D
D
In[37]:= prova@4D;
Inizio
Il numero è positivo
Il quadrato risulta 16
Fine programma. Ciao da Daniele
Daniele Lupo Appunti di Mathematica
211Printed by Mathematica for Students
In questo esempio abbiamo visto come si usa Which, indicando ogni condizione ed ogni comando da
eseguire per la condizione giusta; notate anche come abbia potuto eseguire una formattazione della
scrittura tipica dei linguaggi di programmazione, dato che andando a capo non si interrompe la
sintassi del comando, esattamente come in C.
Non è che il programma sia complicatissimo... Tuttavia, serve solo per farvi capire come funzionano
i comando, dato che presumo che almeno qualcosina di programmazione la conoscete, e sapete cosa
fare, e come farlo.
In[38]:= altraprova@x_D := Sequence@Print@"Analisi del numero"D,Switch@PrimeQ@xD,
True, Print@"Il numero è primo"D,False,Print@"Il numero non è primo, e i suoi fattori sono:\n",
FactorInteger@xDDD
D
In[39]:= altraprova@7365576585D;
Analisi del numero
Il numero non è primo, e i suoi fattori sono:883, 1<, 85, 1<, 8877, 1<, 8559907, 1<<
In[40]:= altraprova@508969D;
Analisi del numero
Il numero è primo
Abbiamo visto un altro esempio, questa volta a proposito del comando Switch; prima di tutto
abbiamo testato se l'argomento era un numero primo, indicando, in caso affermativo, che era tale ed,
in caso alternativo, eseguiamo la fattorizzazione del numero primo, mostrandola attraverso il
comando Print.
Naturalmente, non sono queste le uniche istruzioni di flusso, come ben sapete; ci sono anche
istruzioni che determinano la ripetizione di un blocco di codice per un determinato numero di volte.
Uno dei comandi più utili ed importanti di questo tipo in Mathematica è il seguente:
Do[expr, {i, imax}] valuta expr per il numeri specificato di volte, con i
Daniele Lupo Appunti di Mathematica
212Printed by Mathematica for Students
che varia da 1 a imax con passo 1
Do[expr, {i, imin, imax, di}] valuta expr con i che varia da imin a imax con passo di
Do[expr, {n}] valuta expr n volte
Il comando è l'equivalente del For in C:
In[41]:= Do@Print@"Numero ", iD, 8i, 6<D
Numero 1
Numero 2
Numero 3
Numero 4
Numero 5
Numero 6
Possiamo vedere come si comporta esattamente come vogliamo, della maniera preferita. Un aspetto
interessante è che possiamo fare dei cicli annidati senza usare istanze multiple del comando, ma
semplicemente indicando tutte le variabili, come facciamo con il comando Table:
In[42]:= Do@Print@i, " x ", jD, 8i, 3<, 8j, 3<D
1 x 1
1 x 2
1 x 3
2 x 1
2 x 2
2 x 3
3 x 1
3 x 2
3 x 3
Possiamo vedere come il ciclo più interno sia quello corrispondente alla variabile che scriviamo per
ultima: con i pari ad 1, j varia da 1 a 3: poi i viene incrementato l'indice i e si ripete il ciclo j. Un
Daniele Lupo Appunti di Mathematica
213Printed by Mathematica for Students
altro comando simile, ma estremamente utile in alcuni casi, è il seguente:
FixedPoint[f, expr] comincia con expr, ed applica f iterativamente finoa quando il risultato non varia più
Come potete vedere, questo comando permette di avere una terminazione che non dipende dal ciclo,
ma dobbiamo stare attenti che effettivamente si arrivi ad un punto in cui la funzione non cambia più:
In pratica, effettua questi passaggi:
x, f @xD, f @ f @xDD, f @ f @ f @xDDD ...
Questo fino a quando il risultato non varia più. Di solito si usa per condizioni di convergenza:
In[43]:= FixedPoint@Function@t, Print@tD; Floor@Sqrt@tê2DDD, 2350D
2350
34
4
1
0
Out[43]= 0
Come potete vedere, abbiamo applicato la funzione Floor@Sqrt@xDD ripetitivamente. Ho usato le
funzioni pure, cosa che vedremo più avanti, ma per un utente avanzato questo può veramente
risolvere problemi difficili da studiare in altro modo. Un modo più semplice di usarlo è con il
comando ReplaceAll (//.), che esegue quasi esattamente la stessa cosa, in forma più sintetica
In[44]:= x^2 + y^6 êê. 8x → 2 + a, a → 3<
Out[44]= 25 + y6
In questo caso, le regole di sostituzione non vengono effettuate una volta sola, ma fino a quando il
risultato non varia più. Tuttavia si può notare come mostri soltanto il risultato finale, oltre ad avere
qualche problema di inizializzazione che invece risulta più semplice con FixedPoint.
Possiamo anche applicare la funzione in maniera iterativa per un numero determinato di volte,
mediante il seguente comando:
Daniele Lupo Appunti di Mathematica
214Printed by Mathematica for Students
Nest[f, expr, n] applica f iterativamente su expr n volte
Questo può essere utile per lavori iterativi:
In[45]:= f@x_D := 1êH1 + x^2L
In[46]:= Nest@f, q, 5D
Out[46]=1
1 + 1i
k
jjjjjjjjjjjjjjjjjjjjjjj
1+ 1i
k
jjjjjjjjjjjjjjj1+ 1
ikjjjjj1+ 1
H1+q2L2y{zzzzz2
y
{
zzzzzzzzzzzzzzz
2
y
{
zzzzzzzzzzzzzzzzzzzzzzz
2
Come possiamo vedere, come primo argomento abbiamo bisogno soltanto del nome della funzione,
non delle parentesi quadre. Se nella funzione sono presenti più argomenti, di cui tutti gli altri
specificati, conviene creare una nuova funzione che abbia come argomento un solo parametro:
In[47]:= g@x_D := fun@var1, x, var2D
ed usare questa nel comando Nest. Ci sarebbero funzioni più eleganti dal punto di vista di
programmazione avanzata, come le funzioni pure che abbiamo visto poco fa, ma al nostro livello
questa soluzione è sicuramente quella più facile da eseguire. Un comando simile è:
NestWhile[f, expr, test] cominica con expr, ed applica iterativamente f finoa quando test applicato al risultato non è più True
Quindi, cambia la condizione di terminazione, che diventa da determinata a condizionale; cioè non
viene applicata iterativamente f per un certo numero di volte predefinito, ma viene applicata fino a
quando non si raggiunge una condizione di stabilità. Ovviamente, anche in questo caso occorre che
la condizione di stabilità venga raggiunta, cosa che si deduce dal tipo di problema che si sta
elaborando.
Altri costrutti per poter eseguire ripetitivamente blocchi di codice, oltre al Do, sono:
While[test, body] valuta test e, se risulta True, esegue expr: dopo rivalutatest, e se risulta ancora True riesegue body, e così viafino a quando test risulta False
For[start, test, incr, body] valuta dapprima start e poi, ciclicamente, body e incrfino a quando test risulta True, e dopo si interrompe.
Come potete vedere, sono equivalenti ai corrispettivi comandi nei vari linguaggi di programmazione;
per esempio potremmo scrivere qualcosa come:
Daniele Lupo Appunti di Mathematica
215Printed by Mathematica for Students
In[48]:= For@n = 1; a = 8<, n <= 10, n++, a = Append@a, nD; Print@aDD
81<
81, 2<
81, 2, 3<
81, 2, 3, 4<
81, 2, 3, 4, 5<
81, 2, 3, 4, 5, 6<
81, 2, 3, 4, 5, 6, 7<
81, 2, 3, 4, 5, 6, 7, 8<
81, 2, 3, 4, 5, 6, 7, 8, 9<
81, 2, 3, 4, 5, 6, 7, 8, 9, 10<
Come abbiamo visto, abbiamo ottenuto una lista di dieci elementi, eseguendo il semplice comando.
Inoltre, in questi comandi possiamo anche introdurre i comandi Break@D e Continue@D, che conoscete
tutti; il primo serve per interrompere il ciclo più interno in cui si trova il comando, mentre il secondo
serve per saltare il restante ciclo e ricominciare il successivo. Io personalmente li uso poco, perchè,
anche se in maniera estremamente ridotta rispetto a Goto (che è presente ma che non menziono),
crea dei salti di flusso, cosa che a me non è mai piaciuta. Sappiate comunque che esistono e che, se
volete, potete anche usarli tranquillamente.
Daniele Lupo Appunti di Mathematica
216Printed by Mathematica for Students
Stringhe
Abbiamo visto che Mathematica è anche in grado di gestire le stringhe. In effeti, i suoi strimenti
sono abbastanza potenti, e questo perchè si deve poter eseguire anche un determinato numero di
operazioni che possono essere importanti dal punto di vista matematico e del lavoro che si sta
svolgendo: si pensi, ad esempio, all'importazione di una stringa di 1000000 caratteri, dove ogni
carattere corrisponde allo stato di un sistema e vedere, ad esempio, quando e quante volte il sistema,
nella sua storia, passa dallo stato T allo stato F, per effettuare delle necessarie statistiche. Le stringhe
possono quindi anche essere utili per il calcolo, e vengono trattate come tali. Le funzioni forse più
elementari per la gestione delle stringhe sono le seguenti:
s1 <> s2 <> … oppure StringJoin[{s1, s2, … }]
unisce assieme più stringhe per formarne una sola
StringLength[s] restituisce il numero di caratteri della stringa
StringReverse[s] inverte l'ordine dei caratteri della stringa
Definiamo, per capirci meglio, le seguenti stringhe:
In[49]:= stringa1 = "Io sono";
In[50]:= stringa2 = "un";
In[51]:= stringa3 = "gran figo...";
Se adesso andiamo ad unirle assieme, otteniamo:
In[52]:= stringa1 <> stringa2 <> stringa3
Out[52]= Io sonoungran figo...
Naturalmente, non appare nella forma voluta perchè non abbiamo considerato gli spazi, dato che lo
spazio è considerato come carattere equivalente agli altri, e Mathematica NON li aggiunge se non lo
specigichiamo noi:
In[53]:= stringa1 <> " " <> stringa2 <> " " <> stringa3
Out[53]= Io sono un gran figo...
Ora le cose sono più vicine alla realtà...
Possiamo anche contare i caratteri dell'ultima stringa:
Daniele Lupo Appunti di Mathematica
217Printed by Mathematica for Students
In[54]:= StringLength@%D
Out[54]= 23
Come potete vedere, 23 caratteri bastano per dire una grande verità. Vediamo adesso anche l'ultimo
comando dei tre:
In[55]:= StringReverse@"Alice attraverso lo specchio"D
Out[55]= oihcceps ol osrevartta ecilA
Naturalmente possiamo giocare anche con la lingua italiana... Consideriamo la frase "I topi non
avevano nipoti":
In[56]:= StringReverse@"itopinonavevanonipoti"D
Out[56]= itopinonavevanonipoti
Ah, potenza dell'italiano, che HA una lingua beLa aSai...
Operazioni un poco più avanzate (ma neanche di tanto, in fondo) che si possono fare nelle stringhe
sono le seguenti:
StringTake[s, n] crea una stringa formata dai primi n caratteri di s
Daniele Lupo Appunti di Mathematica
218Printed by Mathematica for Students
StringTake[s, {n}] estreae l' nth carattere da s
StringTake[s, {n1, n2}] crea una stringa estratta da s dal carattere n1 al carattere n2
StringDrop[s, n] crea una stringa ottenuta cancellando i primo nccaratteri da s
StringDrop[s, {n1, n2}] cancella i caratteri dalla posizione n1 fino a n2
StringInsert[s, snew, n] inserisce la stringa snew nella posizione n in s
StringInsert[s, snew,{n1, n2, … }]
inserisce più copie di snew into s nelle posizioni n1,
n2, …
StringReplacePart[s,snew, {m, n}]
sostituisce i caratteri da m a n nella stringa s con lastringa snew
StringReplacePart[s,snew, {{m1, n1}, {m2, n2}, …
sostituzioni multiple in s con snew
StringReplacePart[s,{snew1, snew2, … }, {{m1,n1}, {m2, n2}, … }]
sostituisce più sottostringhe in s dallecorrispondenti nuove sottostringhe snewi
StringPosition[s, sub] restituisce una lista di coppie di valori iniziali e finalidelle posizioni in cui sub compare come sottostringa in s
StringPosition[s, sub, k] mostra solo le prime k occorenze di sub in s
S t r i n g P o s i t i o n [s,{sub1, sub2, … }]
mostra le posizioni di più sottostringhe subi
StringCount[s, sub] conta quante volte sub compare in s
StringCount[s, {sub1, sub2,… }]
conta tutte le volte che compare una delle stringhe subi
StringFreeQ[s, sub] testa se s non contiene sub
StringFreeQ[s, {sub1, sub2,… }]
testa s non contiene nessuna delle stringhe subi
StringReplace[s, sb -> sbnew] sostituisce sb con sbnew ovunque compaia in s
StringReplace[s, {sb1
-> sbnew1, sb2 -> sbnew2, …sostituisce le sottostringhe sbi dalle corrispondentinuove sottostringhe sbnewi
StringReplace[s, rules, n] esegua al massimo n sostituzioni
StringReplaceList[s, rules] crea una lista delle stringhe ottenute effettuandoogni singola sostituzione
StringReplaceList[s,rules, n]
limita la lista a n risultati
StringSplit[s] divide s nelle sottostringhe delimitate dagli spazi
StringSplit[s, del] divide la stringa usando il delimitatore del
StringSplit[s, {del1, del2,… }]
usa più delimitatori deli
StringSplit[s, del, n] divide al massimo n sottostringhe
StringSplit[s, del -> rhs] inserisce rhs nella posizione di ogni delimitatore
Daniele Lupo Appunti di Mathematica
219Printed by Mathematica for Students
Come potete vedere, solo con questi comandi base possiamo fare veramente molte cose:
praticamente tutto quello che ci serve per gestire le stringhe ad un livello poco più avanzato di quello
base:
In[57]:= stringa = "Il mio nome è Daniele, e sonotalmente felice che tu abbia letto fino a qua che perfesteggiare me ne andrò al mare a fare un bel bagno";
Sapete com'è, fuori il tempo è bello, e ne devo approfittare prima di studiare per gli esami di
giugno-luglio...
Comunque, una volta creata la stringa, possiamo gestircela come più ci piace. Mettiiamo caso che
non mi piaccia più andare al mare (cosa impossibile):
In[58]:= StringReplace@stringa, "al mare" −> "in montagna"D
Out[58]= Il mio nome è Daniele, e sono talmentefelice che tu abbia letto fino a qua che perfesteggiare me ne andrò in montagna a fare un bel bagno
Ovviamente, il bagno me lo farò nel lago...
Vediamo di ordinare alfabeticamente le parole. In questo caso ho bisogno prima di separare le
parole, e dopo ordinare le singole stringhe ottenute. Indico come delimitatore solo lo spazio
(considerando, quindi, i segni di punteggiatura, come le virgole, caratteri). Dopo averlo fatto, ordino
le stringhe così ottenute.
In[59]:= StringSplit@stringa, " "D
Out[59]= 8Il, mio, nome, è, Daniele,, e, sono, talmente,felice, che, tu, abbia, letto, fino, a, qua, che, per,festeggiare, me, ne, andrò, al, mare, a, fare, un, bel, bagno<
In[60]:= Sort@%D
Out[60]= 8a, a, abbia, al, andrò, bagno, bel, che, che, Daniele,,e, è, fare, felice, festeggiare, fino, Il, letto, mare,me, mio, ne, nome, per, qua, sono, talmente, tu, un<
Se invece, voglio ordinarli in ordine inverso, basta considerare il fatto che abbiamo a che fare con
una lista, quindi basta usare il comando per invertire gli elementi di una lista, cosa che abbiamo visto
a suo tempo:
Daniele Lupo Appunti di Mathematica
220Printed by Mathematica for Students
In[61]:= Reverse@%D
Out[61]= 8un, tu, talmente, sono, qua, per, nome, ne, mio, me,mare, letto, Il, fino, festeggiare, felice, fare, è, e,Daniele,, che, che, bel, bagno, andrò, al, abbia, a, a<
Ovviamente potevamo ottenere tutto quanto in un unico comando con le funzioni annidate:
In[62]:= Reverse@Sort@StringSplit@stringaDDD
Out[62]= 8un, tu, talmente, sono, qua, per, nome, ne, mio, me,mare, letto, Il, fino, festeggiare, felice, fare, è, e,Daniele,, che, che, bel, bagno, andrò, al, abbia, a, a<
Nidificare le funzioni è una cosa che farete abbastanza spesso, una volta presa confidenza con il
programma. Anzi, sono sicuro che già l'avrete fatto molte volte, vero? Fate bene, perchè vi permette
di risparmiare tempo e spazio a meno che, naturalmente, non vi servano anche i risultati intermedi.
Supponiamo, adesso, di dover censurare delle parole: per esempio il mio nome non deve essere reso
pubblico. Non sapendo a priori la posizione in cui compaia il mio nome, basta fare:
In[63]:= StringPosition@stringa, "Daniele"D
Out[63]= 8815, 21<<
Ed, a questo punto:
In[64]:= StringReplacePart@stringa, "XXX", %@@1DDD
Out[64]= Il mio nome è XXX, e sono talmente felice che tu abbia letto fino aqua che per festeggiare me ne andrò al mare a fare un bel bagno
Notate come ho dovuto indicare l'indice, dato che il risultato di StringPosition è una lista doppia.
Naturalmente, potevo anche farlo direttamente:
In[65]:= StringReplace@stringa, "Daniele" −> "XXX"D
Out[65]= Il mio nome è XXX, e sono talmente felice che tu abbia letto fino aqua che per festeggiare me ne andrò al mare a fare un bel bagno
Queste sono solo alcuni esempi banali. I comandi esistono per fare enalisi più serie; per esempio, in
una stringa può essere memorizzata una sequenza di DNA, e vedere quando compare una specfica
sequenza, e dove. Possiamo analizzare direttamente il primer, senza dover per forza visualizzare
tutta la stringa, che può essere veramente grossa. Naturalmente dovrete essere voi a deciderne l'uso
da fare.
Daniele Lupo Appunti di Mathematica
221Printed by Mathematica for Students
Mathematica dispone anche di alcune funzioni per lavorare direttamente con i caratteri di una stringa:
Characters["string"] converte una stringa in una lista di caratteri
StringJoin[{"c1", "c2", … }] converte una lista di caratteri in una stringa
DigitQ[string] verifica se gli elementi della stringa sono tutte cifre
LetterQ[string] verifica se i caratteri della stringa sono tutte lettere
UpperCaseQ[string] testa se i caratteri sono tutti maiuscoli
LowerCaseQ[string] verifica se i caratteri sono tutti minuscoli
ToUpperCase[string] converte la stringa in una con le lettere tutte maiuscole
ToLowerCase[string] genera la stringa con tutte le lettere minuscole
CharacterRange["c1", "c2"] genera una lista con i caratteri da c1 a c2
Supponiamo, per esempio, di dover convertire in lista di caratteri la seguente stringa:
In[66]:= stringa = "Qualche Lettera Scelta A Caso";
In[67]:= Characters@stringaD
Out[67]= 8Q, u, a, l, c, h, e, , L, e, t, t, e,r, a, , S, c, e, l, t, a, , A, , C, a, s, o<
Notate come anche gli spazi siano considerati caratteri:
In[68]:= Sort@%D
Out[68]= 8 , , , , a, a, a, a, A, c, c, C, e,e, e, e, h, l, l, L, o, Q, r, s, S, t, t, t, u<
Supponiamo di fregarcene della netiquette di un newsgroup e di voler gridare questa frase in un
thread:
In[69]:= ToUpperCase@stringaD
Out[69]= QUALCHE LETTERA SCELTA A CASO
Al contrario, adesso siamo stati tirati per l'orecchio, e vogliamo fare i timidoni:
In[70]:= ToLowerCase@stringaD
Out[70]= qualche lettera scelta a caso
Daniele Lupo Appunti di Mathematica
222Printed by Mathematica for Students
Non credo che servano ulteriori commenti a questi comandi, molto semplici ma flessili, ammesso
ovviamente che ci dobbiate fare qualcosa!
Possiamo anche usare all'interno delle stringhe i caratteri speciali di Mathematica. Se avete
sperimentato un poco, avrete notato una Palette contenente le lettere greche e altri simboli
matematici, come le frecce. Avrete forse anche notato che potete scriverle direttamente da tastiera.
Per esempio, potete scrivere p sia con [Esc]pi[Esc], sia con \[pi]. Sono entrambe forme per scrivere
notaziona matematica. Quella ufficiale di Mathematica (se aprite un notebook con un editor di testo,
ve ne accorgerete), è quella estesa, cioè la seconda. Possiamo usarla anche per scrivere i caratteri
speciali all'interno delle stringhe:
In[71]:= stringa = "Questa contiene i caratteri α e β"
Out[71]= Questa contiene i caratteri α e β
In[72]:= FullForm@%D
Out[72]//FullForm= "Questa contiene i caratteri \[Alpha] e \[Beta]"
Come potete vedere, se scrivete la stringa qua sopra ottenete le lettere greche. Non posso farvelo
vedere direttamente perchè Mathematica sostituisce automaticamente le lettere non appena sono
scritti i giusti codici, ma il comando FullForm fa vedere a cosa corrispondono effettivamente le
lettere greche. Se vogliamo includere nella stringa caratteri come \ oppure come ", dobbiamo farli
precedere da \:
In[73]:= stringa1 = "Questo \ e questo " non si vedono
Out[73]= Questo e questo non si vedono
Invece, scritto in questa maniera:
In[74]:= stringa2 = "Questo \" e questo \\ si vedono"
Out[74]= Questo " e questo \ si vedono
Vedete come occorra in questi casi usare un piccolo accorgimento, ma non è niente che non abbiate
anche visto in C. E, come in C, possiamo definire i caratteri speciali, come \n:
In[75]:= stringa = "E' un'unica stringa. \nMa vado a capo"
Out[75]= E' un'unica stringa.Ma vado a capo
Daniele Lupo Appunti di Mathematica
223Printed by Mathematica for Students
Vedete come sia stato inserito il carattere speciale di ritorno a capo. Possiamo anche includere la
tabulazione:
In[76]:= stringa = "Primo\tSecondo\tTerzo"
Out[76]= Primo Secondo Terzo
E con questo, credo di aver detto abbastanza sulle stringhe... Anche voi ne avete abbastanza? Ma
sono cose tanto facili e carucce....
Comunque, una volta imparati questi comandi, se riuscite ad inventare qualcosa che non si possa
risolvere con questi (e ovviamente usando le solite funzioni di Mathematica), esistono altri comandi
avanzati per la programmazione e la gestione di file (come comandi per criptare i vostri files).
Andate a vedere quello che vi servirà, d'accordo? Troverete sempre di tutto....
Daniele Lupo Appunti di Mathematica
224Printed by Mathematica for Students
Formattazioneü Introduzione
Abbiamo fatto un bel po' di lavoro con Mathematica, vero? Abbiamo visto come creare, valutare,
semplificare, disegnare, programmare, cucinare, pescare, ed anche come sfilare in passerella...
Tuttavia, adesso dobbiamo vedere come mettere in ordine tutto quel popò di cose che abbiamo
scritto. Difficilmente, infatti, potremmo ottenere qualcosa di utile e di presentabile utilizzando solo le
formule di Mathematica. Occorrono dei commenti, dell'organizzazione, qualcosa che legga leggibile
quello che abbiamo scritto anche chi non conosce Mathematica e anche a noi stessi, che sicuramente
non capiremo niente di quello che abbiamo scritto una settimana dopo che l'abbiamo fatto. E' lo
stesso concetto dei commenti nei linguaggi di programmazione, con la differenza che qua la
formattazione permette di creare notebook che possono anche essere stampati ed utilizzati come
formato per presentare articoli, relazioni, tesine e tesi.
Con cosa credete che stia scrivendo tutto questo? Con Word?????
ü Celle
Abbiamo visto all'inizio di questi appunti, e l'avete notato anche voi mentre scrivevate con le vostra
mani pacioccose ed unte di cioccolato, che quando digitiamo qualsiasi cosa all'interno di un
Notebook, Mathematica organizza tutto quanto in celle. Una cella all'interno di un notebook è un
contenitore di informazione, che può essere di qualsiasi tipo. Quando scriviamo formule,
automaticamente vengono inserite in una cella, visibile dai delimitatori che compationo nel lato
destro del notebook:
Come potete vedere, le celle sono auto-organizzate: si nidificano da sole raggruppando Input ed
Output. In questo caso, una singola cella ne contiene altre due: se notate la figura che compare nella
parte superiore della cella, potete notare come si diversifichino fra di loro. Il simbolo di una cella
contenitore è diversa da quella di una cella contenente in Input, che è diversa da quella che contiene
un Output.
Inoltre, le celle hanno anche la caratteristica di potersi comprimere, per risparmiare spazio e non
visualizzare i dati che per il momento non ci servono. Per esempio, vediamo il seguente risultato:
Daniele Lupo Appunti di Mathematica
225Printed by Mathematica for Students
Se adesso, per esempio, non ci interessa visualizzare il risultato dell'operazione, considerando che
occupa più righe, possiamo fare doppio clic sulla cella contenitore:
Come possiamo vedere, in questo caso la cella è stata compressa, mostrando solamente la prima riga:
ciò è evidenziato dal fatto che la cella contenitore ha una freccia rivolta verso il basso, che significa,
appunto, che è stata compressa e che ci sono altri risultati non visualizzati. A questo punto, basta fare
di nuovo doppio clic su di essa per rivedere un'altra volta la cella nel suo complesso. Questo è
estremamente utile se, per esempio, all'inizio di un notebook si eseguono le definizioni di numerose
funzioni. Questo è ancora più vero quando si divide il notebook in sezioni.
Daniele Lupo Appunti di Mathematica
226Printed by Mathematica for Students
ü Sezioni
Quando andiamo a scrivere un articolo, un libro, o qualsiasi altra cosa, quello che di solito si fa è
dividere gli argomenti. Di solito si assegna un titolo al lavoro, poi si divide tutto quando in capitoli,
sezioni e così via, per poter strutturare al meglio i risultati ottenuti e darne una rappresentazione
chiara. Mathematica segue lo stesso principio per poter organizzare i suoi lavori. Se andare nella
voce di menù Format Ø Style, potrete notare varie opzioni. Ognuna rappresenta una forma di
formattazione della cella in questione.
In pratica, quando scriviamo una cella, con questi comandi (meglio se imparate da subito ad usare le
scorciatoie da tastiera), è possibile formattarla nella maniera desiderata. Se, per esempio, vogliamo
che la cella che scriviamo non sia una formula, ma, ad esempio, il titolo della nostra tesina, basta
premere Alt+1, per ottenere l'aspetto voluto del titolo. Allo stesso modo definiremo i sottotitoli, se
sezioni e così via:
Come potete vedere, usando queste formattazioni, possiamo facilmente scrivere relazioni altamente
organizzate. Ma c'è anche di più: se notate le celle riguardanti le sezioni, potete vedere che sono
annidate fra di loro. Quindi, se scrivete una sottosezione, per fare un esempio, poi potete facilmente
nasconderla per intero, in modo da visualizzare solo il titolo e risparmiarvi, magari, parecchie pagine
di scrolling, permettendovi di concentrarvi solo sulla parte del lavoro in cui state lavorando.
Ricordatevi solo che, al momento della stampa, Mathematica non espande le celle, per cui, se una
sezione è compressa, non apparirà neanche in fase di stampa. Quindi, assicuratevi che tutto quello
Daniele Lupo Appunti di Mathematica
227Printed by Mathematica for Students
che volete sia stampato sia visibile anche nel notebook.
Questo aspetto di organizzazione è importante in Mathematica, come per esempio accade in LATEX, e
permette di ragionare su quello che scriviamo in maniera diversa: con Word, per esempio, passiamo
il tempo ad organizzare la visualizzazione della pagine, come i margini, l'aspetto del titolo e così via,
con notevole perdita di tempo. In questo modo, invece, si pone più attenzione al contenuto ed alla
struttura del documento, invece che su come verrà visualizzato. Questo si potrà decidere, se
necessario, in un secondo momento. Infatti, da Format Ø Style Sheet, possiamo decidere che stile
dare al nostro documento. Una volta gestiti i titoli e l'organizzazione, da questa voce di menù
possiamo decidere, per esempio, l'aspetto dei titoli, inece che quello delle sezioni. Possiamo
formattare il documento tutto assieme, senza dover decidere ogni volta quale sia lo stile mogliore per
i titoli. Se poi, per esempio, non ci piace, possiamo cambiare lo stile del lavoro, lasciandone
inalterata la struttura complessiva, che non verrà modificata. Sono presenti, come potete vedere,
diversi formati standard ma, se volete, potete anche naturalmente definire i vostri stili personalizzati.
Se infatti, una volta scelto lo stile, usate il comando Format Ø Edit Style Sheet, apparirà un nuovo
notebook, contenente tutte le opzioni necessarie per personalizzare lo stile del documento come più
vi piace, andandolo a memorizzare, alla fine, come un nuovo stile che potrete modificare come
vorrete.
Daniele Lupo Appunti di Mathematica
228Printed by Mathematica for Students
Come potete vedere, questo è quello che compare una volta usato il comando. Andando ad
espandere le relative sezioni, è possibile andare a modificare quello che vogliamo e, salvando questo
file, possiamo riutilizzarlo quando vogliamo. Tuttavia credo che le impostazioni base siano già
abbastanza diversificate per cui, almeno per i primi tempi, dubito che sentiate il bisogno di creare
nuovi stili.
Anche all'interno della stessa cella, comunque, valgono le combinazioni standard. Per esempio,
selezionando del testo e premendo CTRL+b, si ottiene del testo in grassetto, come questo. Con
CTRL+i, del testo in corsivo, e così via. Comunque, in caso di formattazione, il menù Format è
quello che fa per voi. Lì c'è praticamente tutto quello che vi serve per tirare avanti.
Daniele Lupo Appunti di Mathematica
229Printed by Mathematica for Students
Non c'è niente da imparare su questo, per cui questo breve capitoletto volge al termine.
Daniele Lupo Appunti di Mathematica
230Printed by Mathematica for Students
Mathematica Avanzataü Introduzione
Quello che abbiamo visto finora, probabilmente servirà ed avanzerà per tutto quello che vi verrà in
mente. Tuttavia, ci sono alcuni aspetti avanzati che è sempre bene conoscere, sia perchè a volte
potranno snellirvi il compito e rendere più semplice la risoluzione di problemi avanzati, sia perchè
vorrete fare i fricchettoni davanti a chi chiederà aiuto a dei guru di Mathematica come voi...
vedremo come vengono effetivamente fatti i conti con il programma, come lavorare con funzioni
pure e generiche, usare variabili locali nei programmi e così via.
Ho detto che il capitolo più lungo era quello della grafica? Mi sbagliavo, sarà questo... E stavolta
non ci sono belle immagini a dimunuire la quantità di testo. Adesso si fa sul serio!!!
Cominciamo, quindi, perchè di carne al fuoco ce ne sarà davvero tanta...
ü Espressioni
Cosa sono
Consideriamo i seguenti
comandi:
Head[expr] restituisce l'head dell'espressione
FullForm[expr] visualizza l'espressione nella forma piena di Mathematica
Vediamo cosa fanno queste funzioni. Consideriamo, per esempio, il seguente comando:
In[1]:= Head@81, 2, 3<D
Out[1]= List
Quello che ha fatto, apparentemente, è riconoscere il suo argomento come una lista, ma
effettivamente non è così:
In[2]:= Head@a − b ∗ cD
Out[2]= Plus
A questo punto, le cose si fanno un pochetto più confuse. Cosa significa Plus, considerando fra
l'altro che non compare il segno di addizione nell'espressione?
Daniele Lupo Appunti di Mathematica
231Printed by Mathematica for Students
Il fatto è che Mathematica tratta tutto quanto viene scritto come combinazione di funzioni: quando
scriviamo qualcosa come a + b, in realtà il programma interpreta quanto scritto come la funzione
allegata a + da applicare con argomento a, b. Il comando FullForm permette di vedere meglio ciò:
In[3]:= FullForm@81, 2, 3<D
Out[3]//FullForm= List@1, 2, 3D
Da qua, possiamo vedere che quando noi scriviamo la lista, l'interprete del kerner di Mathematica
considera le parentesi graffe come la funzione List, avente come argomenti proprio gli elementi che
compongono la lista. Vedete come la funzione List può essere chiamata con un numero arbitrario di
argomenti, ma anche questo lo vedremo più avanti. Naturalmente, se effettuiamo operazioni
multiple, le rispettive funzioni saranno annidate nel modo opportuno:
In[4]:= FullForm@Sqrt@a + b − cDêf@x, yDD
Out[4]//FullForm= Times@Power@Plus@a, b, Times@−1, cDD, Rational@1, 2DD,Power@f@x, yD, −1DD
Come potete vedere, l'espressione viene interpretata da Matematica come funzioni. Da questo deriva
la potenza del programma in effetti. Sebbebe il funzionamento sia complicato, il concetto che sta alla
base è relativamente semplice: considera l'albero delle funzioni, e poi esegue le operazioni
effettuando le opportune sostituzioni nell'albero. Le regole di sostituzione variano a seconda del
comando o della funzione, e, da un albero, ne risulta un altro: di conseguenza, da un input simbolico
ne esce un altro simbolico. Semplice e potente. D'altronde, la potenza del programma sta nella
sofisticazione delle regole di sostituzione. Nell'esempio di sopra, potete anche vedere che la forma
piena tratta nella stessa maniera le funzioni definite e quelle non definite, come la f. Il fatto che non
venga calcolata viene dal fatto che, non essendo definita, non esistono regole per la sua
manipolazione, e Mathematica la lascia come tale.
In[5]:= Head@%D
Out[5]= Times
A questo punto, si comprende meglio anche il signidicato di Head. Restituisce, in pratica, il nome
della funzione principale dell'espressione, quella che contiene tutte le altre. In questo caso, è appunto
Times, cioè la funzione che moltiplica fra loro i suoi argomenti. Possiamo anche avere una
rappresentazione più esplicita, mediante il seguente comando:
TreeForm[expr] mostra l'espressione con notazione ad albero testuale
Considerando sempre l'espressione di prima, in questo caso abbiamo:
Daniele Lupo Appunti di Mathematica
232Printed by Mathematica for Students
In[6]:= TreeForm@Sqrt@a + b − cDêf@x, yDD
Out[6]//TreeForm= TimesA »PowerA »
PlusAa, b, »Times@−1, cD
E, »
Rational@1, 2DE
,
»PowerA »
f@x, yD, −1E
E
Il comando mostra una rappresentazione in caratteri ASCII dell'albero di parsing dell'espressione.
Questo permette di avere una rappresentazione più chiara della nidificazione delle funzioni.
Inoltre, possiamo vedere come, nell'interpretazione della forma normale in cui scriviamo, in
notazione FullForm, Mathematica sia in grado di riconoscere correttamente le precedenze,
applicando Times prima di Sqrt, per esempio. Questo permette di eeguire correttamente le
espressioni, ed il suo parsing ci evita di dover scrivere esplicitamente queste condizioni standard per
la matematica.
Quando definiamo una funzione, possiamo anche definire il modo in cui deve essere scritta: Una
volta dato il nome alla funzione, possiamo scriverla nei seguenti modi:
f [x, y] notazione standard f [x, y]
f @ x notazione prefissa f [x]
x // f notazione postfissa f [x]
x ~ f ~ y notazione infissa f [x, y]
Possiamo quindi vedere come, una volta definita una funzione, possiamo scriverla in uno dei modi
seguenti. Da questo si vede come possiamo scrivere in maniera differente le funzioni, che
Mathematica interpreta sempre in notazione Standard. Effettivamente, abbiamo già visto i diversi
modi di scrivere una funzione:
In[7]:= 881, 2<, 83, 4<< êê MatrixForm
Out[7]//MatrixForm= J 1 23 4
N
corrisponde a:
In[8]:= MatrixForm@881, 2<, 83, 4<<D
Out[8]//MatrixForm= J 1 23 4
N
Daniele Lupo Appunti di Mathematica
233Printed by Mathematica for Students
In[9]:= MatrixForm@881, 2<, 83, 4<<
Out[9]//MatrixForm= J 1 23 4
N
Questo modo di trattare le espressioni in Mathematica ha un importante aspetto, cioè quello di poter
trattare separatente le sue parti. Consideriamo, per esempio:
In[10]:= a = 81, 2, 3, 4, 5<
Out[10]= 81, 2, 3, 4, 5<
Sappiamo come fare per estrarre un elemento dalla lista:
In[11]:= a@@4DD
Out[11]= 4
Tuttavia, sappiamo ora anche come vengono trattate le liste in Mathematica:
In[12]:= FullForm@aD
Out[12]//FullForm= List@1, 2, 3, 4, 5D
A questo punto, possiamo dire che le doppie parentesi quadre, che corrispondono al comando Part in
notazione piena, funzionano effettivamente per qualsiasi espressione nella forma che abbiamo visto,
cioè con una funzione ed il numero di argomenti. Il comando estrare e visualizza l'n-simo argomento
della funzione.
Ipotizziamo di avere la seguente somma:
In[13]:= somma = h + t + q + w + r + p
Out[13]= h + p + q + r + t + w
In[14]:= FullForm@sommaD
Out[14]//FullForm= Plus@h, p, q, r, t, wD
Possiamo quindi pensare di usare lo stesso comando, per poter estrarre un generico argomento della
funzione:
In[15]:= somma@@3DD
Out[15]= q
Daniele Lupo Appunti di Mathematica
234Printed by Mathematica for Students
E questo è quello che accade. Vedete anche che, nonostante la somma goda della proprietà
commutativa, la funzione abbia comunque gli argomenti ordinati per come li abbiamo scritti. Questo
permette di poter effettuare con facilità queste operazioni anche nelle espressioni: la proprietà
commutativa viene applicata nella definizione della somma. Non è detto che in un qualsiasi funzione
f gli argomenti godano di proprietà commutativa, e quindi è giusto mantenerli ordinati.
Nella stessa maniera, possiamo anche considerare di estrarre parti annidate da più funzioni:
supponiamo di avere un'espressione del tipo:
In[16]:= es = t + u^Hx^2 + v x + iL
Out[16]= t + ui+v x+x2
In[17]:= TreeForm@esD
Out[17]//TreeForm= PlusAt, »PowerAu, »
PlusAi, »Times@v, xD
, »Power@x, 2D
EEE
Possiamo vedere che, se vogliamo estrarre l'esponente, basta indicare con un opportuno indice quello
che vogliamo. Vediamo che, nel primo livello, l'esponente si trova nella posizione 2: nel secondo
livello, alla posizione 2. Per cui, per estrarlo, possiamo scrivere:
In[18]:= es@@2, 2DD
Out[18]= i + v x + x2
E abbiamo ottenuto l'esponente. Analogamente, potremmo anche sostituirlo. Per esempio, pensiamo
di aver sbagliato, e che in realtà sia una cubica, e ci siamo scordati di scrivere w x3: a questo punto,
basta fare:
In[19]:= es@@2, 2DD += w x^3
Out[19]= i + v x + x2 + w x3
In[20]:= es
Out[20]= t + ui+v x+x2+w x3
Al posto di andare a modificare l'espressione con il mouse, abbiamo introdotto la modifica
direttamente dal notebook con un opportuno comando. Notate anche come, per brevità, abbia usato
+=, comando assolutamente analogo a quanto compare in C. D'altronde, se avete perso tempo a
programmare in Mathematica dovreste essere a conoscenza di questo simbolo.
Daniele Lupo Appunti di Mathematica
235Printed by Mathematica for Students
Possiamo usare anche le regole per modificare la struttura delle espressioni. Per esempio, se
volessimo trasformare tutte le somme in moltiplicazioni, basterebbe fare:
In[21]:= es ê. Plus → Times
Out[21]= t ui v w x6
Cambiando il nome delle funzioni opportune:
In[22]:= FullForm@%D
Out[22]//FullForm= Times@t, Power@u, Times@i, v, w, Power@x, 6DDDD
Qua si può vedere meglio come abbiamo effettuato le sostituzioni delle funzioni Plus.
Possiamo anche applicare le altre funzioni tipiche delle liste:
In[23]:= Position@es, xD
Out[23]= 882, 2, 2, 2<, 82, 2, 3, 1<, 82, 2, 4, 2, 1<<
Indica le posizioni, nella nidificazione, dove compare l'elemento x. Compare tre volte, ed infatti
abbiamo tre liste di indici.
A questo punto, si tratta solo di trovare il problema che può essere risolto efficacemente in questa
maniera. Tuttavia, a me è capitato raramente di dover usare queste notazioni, e soprattutto quando si
trattava di correggere alcuni particolari errori. Probabilmente sono ancora troppo ingnorante per
usarle al mio livello...
Valutazione delle espressioni
Come abbiamo potuto vedere, ci sono un sacco di funzioni in Mathematica, molte più di quanto ve
ne servirebbero... Tutte, però, godono di una proprietà importante, e cioè quella di restituire sempre
il risultato standard. Per esempio, vengono tolte automaticamente le parentesi dalle somme:
In[24]:= Ha + b + Hc + t + aLL
Out[24]= 82 + b + c + t, 4 + b + c + t, 6 + b + c + t, 8 + b + c + t, 10 + b + c + t<
Questo funziona, in genere, per tutte le funzioni associative, e comunque per funzioni che godono di
determinate proprietà. Naturalmente (e lo vedremo fra qualche pagina), anche noi siamo in grado di
creare funzioni che sfruttino le medesime proprietà, come quella commutativa.
Daniele Lupo Appunti di Mathematica
236Printed by Mathematica for Students
Per valutare le espressioni, Mathematica prima valuta e capisce cosa rappresenta l'head principale, e
poi va a valutare, ricorsivamente, i singoli elementi dell'espressione. Per esempio, se scriviamo
qualcosa come:
In[25]:= seno = Sin;
In[26]:= Simplify@Cos@xD2 + seno@xD2D
Out[26]= 1
Vediamo come abbia riconosciuto che seno rappresenta Sin, e poi abbia valutato tutto quanto. Per
vedere le sottoespressioni utilizzate nella valutazione, possiamo utilzzare il seguente comando:
Trace[espr] restituisce la lista delle sottoespressioni generatedurante il calcolo dell'espressione
In[27]:= Trace@Simplify@Cos@xD2 + seno@xD2DD
Out[27]= 88888seno, Sin<, Sin@xD<, Sin@xD2<, Cos@xD2 + Sin@xD2<,Simplify@Cos@xD2 + Sin@xD2D, 1<
Come possiamo vedere, prima passa da seno a Sin, applicandolo poi alla corrispondente funzione, e
poi ne calcola il quadrato. Poi fa la somma fra i due addendi, ed applica la semplificazione.
Esattamente la ricorsività che ci aspettavamo dalla valutazione standard.
Possiamo, volendo, anche cambiare la valutazione standard esplicitamente, associando delle
specifiche regole a delle specifiche funzioni: per esempio, in questa espressione:
In[28]:= f@g@xDD
Out[28]= f@g@xDD
Vediamo che, dalla natura ricorsiva, prima viene applicata la g, con le sue regole e definizioni, e poi
la f . Se creiamo delle regole per questo particolare pattern, possiamo associarle in modo distinto alle
due funzioni:
In[29]:= f ê: f@g@x_DD := regolaf@xD
In[30]:= g ê: f@g@x_DD := regolag@xD
— General::spell1 : Possible spelling error: new symbolname "regolag" is similar to existing symbol "regolaf". More…
Daniele Lupo Appunti di Mathematica
237Printed by Mathematica for Students
Adesso, per lo stesso pattern dell'espressione, abbiamo due differenti regole. Dato che, però, la g
viene valutata prima nell'ordine delle espressioni, otterrò:
In[31]:= f@g@zDD
Out[31]= regolag@zD
Viene applicata la regola associata alla g. Cancelliamola, e vediamo che succede:
In[32]:= Clear@gD; f@g@zDD
Out[32]= regolaf@zD
In questa maniera, prima viene valutata la g ma, dato che adesso non ha più nessuna definizione e
nessuna regola, la sua valutazione lascia l'espressione inalterata. Dopo viene valutata la f che,
riconoscendo il particolare tipo di espressione, applica la sua regola.
f/:espr:=def applica la definizione specificata quando la fcompare nell'espressione specificata
Lavorando con queste regole, siamo in grado di modificare a piacimento, e nel modo che ci serve, il
modo in cui vengono calcolate determinate espressioni, dando il risultato nella forma che ci serve.
Un altro modo per modificare il calcolo delle espressioni consiste nello specificare quali parti
debbano essere calcolate e quali no:
Hold[expr] lascia expr in forma non valutata
HoldComplete[expr] lascia expr non valutata ed evita che venga modificatada ulteriori calcoli a livelli superiori
HoldForm[expr] mantiene expr non valutata, e scrive l'espressionesenza l'head HoldForm
ReleaseHold[expr] rimuove Hold e HoldForm da expr
Extract[expr, index, Hold] prende una parte di expr, modificandola con Holdper prevenire la valutazione
ReplacePart[expr,Hold[value], index, 1]
sostituisce una parte di expr, estraendo valuesenza valutarlo
Consideriamo, per esempio, la seguente espressione:
In[33]:= 3 + 4 + 5 + Sin@4 ∗ 7D
Out[33]= 12 + Sin@28D
Daniele Lupo Appunti di Mathematica
238Printed by Mathematica for Students
Vogliamo, adesso, valutarla, ma stavolta non vogliamo che venga calcolato l'argomento del seno:
In[34]:= 3 + 4 + 5 + Sin@Hold@4 ∗ 7DD
Out[34]= 12 + Sin@Hold@4 7DD
Vediamo come non venga valutato, Tuttavia, se ci interessa un output più pulito, conviene utilizzare
HoldForm:
In[35]:= 3 + 4 + 5 + Sin@HoldForm@4 ∗ 7DD
Out[35]= 12 + Sin@4 7D
In questa maniera, nascondiamo l'head, che è utile quando magari dobbiamo stampare la formula
(per esempio quando la esportiamo in LATEX oppure in Publicon).
L'ordine della valutazione è importante speciamente quando andiamo a usare espressioni in confroni
e specialmente nei pattern (che vedremo fra poco). Supponiamo, per esempio, di vole creare una
regola per modificare una funzione quando compare un determinato argomento. Per esempio,
vorremmo fare questo:
In[36]:= regola = f@x_ + 3 ∗ 5D → Exp@xD;
— General::spell : Possible spelling error: new symbolname "regola" is similar to existing symbols 8regolaf, regolag<. More…
Vediamo quando la regola viene applicata:
In[37]:= f@4D ê. regola
Out[37]= f@4D
In[38]:= f@w + 15D ê. regola
Out[38]= w
Come possiamo vedere, in quest'ultimo caso Mathematica ha considerato equivalenti gli argomenti
delle funzioni, anche se nel primo caso abbiamo scritto una moltiplicazione, e nel secondo invece un
numero.
In[39]:= f@i + 12 + 3D ê. regola
Out[39]= i
Daniele Lupo Appunti di Mathematica
239Printed by Mathematica for Students
Vediamo che anche in questo caso abbiamo ottenuto la sostituzione, perchè la somma contenuta
nell'argomento, se valutata, coincide sempre con quella valutata della regola. Quindi gli argomenti
coincidono perchè, analogamente all'argomento della funzione, anche il contenuto della regola viene
prima valutato. Possiamo lasciarlo in forma non valutata, se lo specifichiamo:
In[40]:= regola2 = HoldForm@f@x_ + 3 ∗ 5DD → Exp@xD;
In questo caso, evitiamo che venga valutata, impedendo di eseguire la moltiplicazione. Di
conseguenza gli argomenti delle funzioni, pur essendo comunque equivalenti, non combacieranno
più nel modo in cui sono scritte, e la regola non viene applicata:
In[41]:= f@w + 15D ê. regola2
Out[41]= f@15 + wD
Invece, se andiamo a creare un argomento strutturalmente identico a quello ottenuto prima, la
sostituzione avviene comunque, perchè in questo caso abbiamo veramente due argomenti che sono
identici:
In[42]:= f@w + 3 5D ê. regola2
Out[42]= f@15 + wD
Come vediamo, neanche in questo caso combaciano. Perchè? Sebbene abbiamo imposto la non
valutaione della regola, la funzione viene comunque valutata prima di applicare la regola. Dobbiamo
quindi lasciare senza valutazione anche l'argomento:
In[43]:= HoldForm@f@w + 3 5DD ê. regola2
Out[43]= w
In questo caso si vede che strutturalmente gli argomenti coincidono, oltre che algebricamente, per
cui la sostituzione viene regolarmente effettuata. Notiate, quindi, come sia necessaria una certa
attenzione quando dobbiamo effettuare operazioni che coinvolgano l'ordine ed il momento in cui le
espressioni vengono valutate, perchè ciò potrebbe portare ad un risultato diverso da quello che
volevamo.
Possiamo anche lasciare inalterata solamente la parte destra della regola di sostituzione:
lhs -> rhs valuta entrambi lhs e rhs
lhs :> rhs lascia senza valutazione rhs
Supponiamo di avere quest'espressione:
Daniele Lupo Appunti di Mathematica
240Printed by Mathematica for Students
In[44]:= Hold@xD ê. x → 3 + 7
Out[44]= Hold@10D
Come potete vedere, tutto va per il verso giusto:
In[45]:= Hold@xD ê. x 3 + 7
Out[45]= Hold@3 + 7D
Come potete vedere, nel primo caso prima viene valutata la regola, poi viene applicata: in questa
maniera Hold ha già come argomento 10. Nel secondo caso, invece, viene sostituita la regola senza
averla valutata, quindi non andrò a sostituire con 10, ma con 3 + 7. Di conseguenza, Hold avrà come
argomento 3 + 7, che resterà non valutato, come abbiamo appena visto.
Ripeto, quindi: quando volete eseguire e creare regole complicate, state sempre attenti all'ordine di
valutazione delle espressioni, mettendo magari le cose nel modo che preferite utilizzando nei punti
giusti Hold assieme alle sue varianti.
Capito?
ü Pattern
Cosa sono
I pattern sono un metodo avanzato per l'utilizzo delle espressioni e, fra l'altro, sono uno dei motivi
principali della potenza di calcolo simbolico offerta da Mathematica. Permettono, ua volta capito
bene il concetto, di definire funzioni che creano operazioni algebriche simboliche di qualsiasivoglia
complessità. Consideriamo quello che succede quando definiamo una funzione:
In[46]:= f@x_D := x^4 + Sin@xD
Quando andiamo ad usarla, al posto di x_ andiamo a mettere quello che ci serve:
In[47]:= f@81, 45, 5<D
Out[47]= 81 + Sin@1D, 4100625 + Sin@45D, 625 + Sin@5D<
In[48]:= f@Cos@rDD
Out[48]= Cos@rD4 + Sin@Cos@rDD
In[49]:= Clear@fD
Daniele Lupo Appunti di Mathematica
241Printed by Mathematica for Students
Tuttavia, come abbiamo visto prima, quello che andiamo ad introdurre come argomento di una
funzione, qualsiasi forma sia, è un'espressione: Anche i numeri stessi, sebbene non appaia in Full-
Form, hanno un head:
In[50]:= Head@5D
Out[50]= Integer
In[51]:= [email protected]
Out[51]= Real
Qualsiasi espressione è accetta come argomento, e questo è dovuto a x_ che rappresenta un pattern:
in altre parole, pattern sta per qualsiasi cosa. Possiamo considerarlo, per chi programma, come la
rappresentazione della radice dell'albero dell'espressione. Quando andiamo a definirlo in una
funzione, come argomento, diciamo al programma che al posto dell'argomente può andare bene
qualsiasi espressione. Quindi, il pattern rappresenta soltanto un'espressione qualsiasi.
Un caso in cui si possono usare i pattern riguarda le regole di sostituzione: supponiamo, per
esempio, di avere la seguente lista:
In[52]:= lista = 8a^r, b^Hc^2 + e + b xL, v, 34, 23^t<
Out[52]= 981, 2r, 3r, 4r, 5r<, bc2+e+b x, v, 34, 23t=
Possiamo trovare, in questo caso, sostituire tutti gli elementi in cui compare un esponente, di
qualsiasi tipo esso sia:
In[53]:= lista ê. x_ ^y_ → esponente
Out[53]= 881, esponente, esponente, esponente, esponente<,esponente, v, 34, esponente<
Quello che abbiamo fatto è abbastanza comprensibile: abbiamo utilizzato un'espressione, in cui era
presente una regola di sostituzione così definita: se ci sono elementi formati da una qualsiasi
espressione, elevata ad un'altra espressione qualsiasi, allora sostituisci l'elemento. In questo caso ci
basiamo sulla struttura dell'espressione, pià che sul suo contenuto. Mentre prima potevamo sostituire
casi in cui, per esempio, l'esponente era un incognita specifica, adesso possiamo introdurre il
concetto di espressione generica nella sostituzione.
Daniele Lupo Appunti di Mathematica
242Printed by Mathematica for Students
In[54]:= TreeForm@listaD
Out[54]//TreeForm= ListA »ListA1, »
Power@2, rD, »
Power@3, rD, »
Power@4, rD, »
Power@5, rDE
,
»PowerAb, »
PlusA »Power@c, 2D
, e, »Times@b, xD
EE
, v, 34, »Power@23, tD
E
In questo caso, quello che Mathematica fa è trovare nell'albero della espressione le funzioni che
combaciano col pattern: in questo caso x_^y_ sta per Power[x_,y_]. A questo punto, quando le trova,
sostituisce tutta la funzione (non solo gli argomenti, quindi), con quello che definisce la regola.
Imparare ad usare i pattern significa possedere strumenti molto potenti per poter effettuare
manipolazioni sulle espressioni, concentrandoci sulla struttura delle ultime. In questo modo si
possono definire, per esempio, regole di sostituzione se volessimo creare una funzione che faccia
l'integrale dell'argomento. Nell'help di Mathematica c'è un esempio al riguardo, nella sezione
Patterns, che vi consiglio di andare a vedere.
Possiamo anche usare le regole di sostituzione per poter modificare le espressioni mantenendo i
pattern:
In[55]:= f@xD + t@xD + c@x^2, r^5D + c@4D ê. c@x_, y_D → x + y
Out[55]= r5 + x2 + c@4D + f@xD + t@xD
Qua possiamo vedere come si usa una regola di sostituzione per modificare le funzioni usando i
pattern stessi. Mathematica cerca la forma c@x_, y_D nell'espressione e, quando la trova, la modifica
con x + y. Notate come la funzione c@4D non viene toccata, in quanto non corrispondono i pattern.
Infatti, pur essendo la stessa funzione, viene chiamata solamente con un argomento.
Un'altra cosa importante da capire è il fatto che i patten si basano sulla struttura delle espressioni, e
che bisogna impararle bene. supponiamo di avere la seguente lista:
In[56]:= lista = 8a, têy, Sin@cDêH6 fL, 1êp<
Out[56]= 981, 2, 3, 4, 5<, ty
, Sin@cD6 f
, 1p=
Eseguiamo, adesso, una sostituzione mediante i pattern:
Daniele Lupo Appunti di Mathematica
243Printed by Mathematica for Students
In[57]:= lista ê. x_ êy_ → x y
Out[57]= 981, 2, 3, 4, 5<, t y, 16
f Sin@cD, 1p=
Quello che succede non è esattamente quello che ci aspettavamo, volevamo che tutti i rapporti
fossero stati modificati a prodotti: invece, soltanto il secondo elemento si è comportato come
volevamo, mentre il terzo è stato modificato soltanto parzialmente (il 6 è rimasto al denominatore),
mentre il quarto è rimasto tale e quale a prima. Questo accade perchè, sebbene in apparenza
appaiano simili come struttura, in realtà non lo sono dal punto di vista delle espressioni: Andiamo a
vedere la forma degli elementi:
In[58]:= TreeForm@têyD
Out[58]//TreeForm= TimesAt, »Power@y, −1D
E
In[59]:= TreeForm@Sin@cDêH6 fLD
Out[59]//TreeForm= TimesA »Rational@1, 6D
, »Power@f, −1D
, »Sin@cD
E
In[60]:= TreeForm@1ê pD
Out[60]//TreeForm= Power@p, −1D
Adesso, vediamo la struttura del pattern:
In[61]:= TreeForm@x_ êy_D
Out[61]//TreeForm= TimesA »PatternAx, »
Blank@DE
, »PowerA »
PatternAy, »Blank@D
E, −1E
E
Vediamo che i pattern in Tree e FullForm, sono visti come funzioni che si chiamano Pattern, per
l'appunto. Se si osservano bene tutte queste strutture, possiamo vedere come, effettivamente,
solamente il secondo elemento della lista disponga di una struttura analoga a quella definita dal
pattern: Infatti, è nella forma Times@x_, Power@y_, -1DD. E viene sostituita dalla regola del pattern in
maniera corretta. Il terzo elemento della lista, invece, ha la seguente forma:
Times@x_, Power@y_, -1D, z_D, il che non corrisponde esattamente a quanto visto in precedenza, dato
che il pattern ha due argomenti, se pur qualsiasi, mentre l'espressione ha tre argomenti qualsiasi in
Times. Allora esegue solo una sostituzione, dando quindi il risultato mostrato. Nel quarto elemento
della lista, invece, sebbene appaia il simbolo di divisione, l'albero dell'espressione è differente, e non
combacia con quello del pattern, vanificando quindi il nostro tentativo di sostituzione, perchè non è
Daniele Lupo Appunti di Mathematica
244Printed by Mathematica for Students
nella forma corretta.
Si nota, quindi, come bisogna prestare attenzione, in alcuni casi, per la corretta manipolazione. In
effetti, anche x ed x^2 possono essere visti come casi di x^n_, dove nel primo caso il pattern
rappresenta l'unità; tuttavia, pur essendo matematicamente equivalenti, non lo sono dal punto di vista
della struttura, per cui è consigliabile, prima, cercare di modificare l'espressione nella forma voluta,
prima di effettuare le operazioni con i pattern, che sono, come abbiamo visto, molto sensibili alle
differenti strutture (essendo, a tutti gli effetti, essi stessi delle strutture).
Inoltre, possiamo vedere che, anche se non esplicitamente, anche i valori numerici possono essere
visti come strutture. Anche se la rappresentazione non lo da a vedere:
In[62]:= [email protected]
Out[62]//FullForm= 45.3`
In effetti anche i numeri hanno un head, che definisce il tipo di numero con cui abbiamo a che fare:
In[63]:= Head@5D
Out[63]= Integer
In[64]:= Head@5ê9D
Out[64]= Rational
In[65]:= Head@1 − ID
Out[65]= Complex
e così via. Questo è utile, come vedremo più avanti, per poter definire particolari tipi di funzioni.
Daniele Lupo Appunti di Mathematica
245Printed by Mathematica for Students
Ricerca di Pattern, e modifica
Una volta definiti i pattern, e capito cosa sono, una delle prime applicazioni che ci vengono in mente
riguardano proprio la ricerca: per certi versi è simile a quanto visto finora, solo che nelle ricerche, al
posto di rispondere alla domanda "Quali espressioni contengono questi valori?" si risponde alla
domanda "Quali espressioni hanno questa struttura?". Il cambio della domanda è importante, e
permette di trovare soluzioni difficilmente ottenibili per altra via.
Alcuni dei comandi più utilizzati sono i seguenti:
Cases[list, form] restituisce gli elementi di list che corrispondono a form
Count[list, form] restituisce il numero di elementi in list checorrispondono a form
Position[list, form, {1}] restituisce le posizioni degli elementi in listche corrispondono a form
Select[list, test] restituisce gli elementi di list per i quali test è True
Pick[list, sel, form] restituisce gli elementi di list per i quali icorrispondenti elementi di sel corrispondono a form
Come possiamo vedere, sono pressochè analoghi alle funzioni già viste, con l'opprortuna modifica di
trattare pattern invece che elementi.
Riprendiamo una lista che avevamo visto qualche pagina prima:
In[66]:= lista = 8a^r, b^Hc^2 + e + b xL, v, 34, 23^t<;
Supponiamo di voler ottenere una lista degli elementi aventi la forma esponenziale:
In[67]:= Cases@lista, x_ ^c_D
Out[67]= 9bc2+e+b x, 23t=
Abbiamo ottenuto la lista che volevamo. Naturalmente, abbiamo visto che queste funzioni non si
applicano solamente alle liste:
In[68]:= espr = x^3 + b^5 ∗ c^Hx + 9L + Sin@xD + Cos@s^3D;
In[69]:= Cases@espr, x_ ^c_D
Out[69]= 8x3<
Se avete letto attentamente finora, dovreste aver capito che la risposta è corretta: infatti, nel secondo
termine compare Times, con la c, e poi gli altri esponenziali sono nidificati in altre funzioni, mentre
Daniele Lupo Appunti di Mathematica
246Printed by Mathematica for Students
così com'è Cases si applica solo al primo livello dell'albero. Se vogliamo che funzioni su più livelli,
dobbiamo specificarlo:
In[70]:= Cases@espr, x_ ^c_, InfinityD
Out[70]= 8b5, c9+x, x3, s3<
In questo caso, abbiamo definito che il comando cercata tutti i pattern in tutti il livelli
dell'espressione; nel casi particolare, vediamo come un esponenziale compaia anche a sinistra della
moltiplicazione, quindi ad un livello superiore, e compaiano esponenti anche all'interno di Cos:
In[71]:= TreeForm@esprD
Out[71]//TreeForm= PlusA »TimesA »
Power@b, 5D, »
PowerAc, »Plus@9, xD
EE
,
»Power@x, 3D
, »CosA »
Power@s, 3DE
, »Sin@xD
E
Analizzandolo, vedrete come abbiamo potuto prendere tutti i casi possibili. Potevamo, naturalmente,
fermarci al livello che ci interessava, specificando il numero, invece che ¶, che indica tutti i livelli
dell'espressione. Tenete sempre conto, però, che non esiste numero di livelli che possa risolvere il
problema di non corrispodenza di pattern che abbiamo visto poco fa.
In[72]:= Cases@espr, x_Integer, InfinityD
Out[72]= 85, 9, 3, 3<
Qua abbiamo fatto una cosa leggermente diversa; avevamo visto che qualsiasi cosa ha un head,
anche i numeri. Specificando l'head nel pattern, gli abbiamo detto di estrapolare dall'espressione tutte
le sottoespressioni aventi il corrispondente head. Questo può essere più semplice, a volte, che andare
a ricostruire il pattern tramite gli operatori:
x_h un espressinone avente head h
x_Integer un numero intero
x_Real numero reale approssimato
x_Complex numero complesso
x_List lista
x_Symbol simbolo (incognita)x_Rational numero razionale
Daniele Lupo Appunti di Mathematica
247Printed by Mathematica for Students
Possiamo vedere come possiamo riconoscere sia il tipo di valore numerico, sia il tipo di espressione
da un punto di vista più generale.
In[73]:= Cases@espr, x_Power, InfinityD
Out[73]= 8b5, c9+x, x3, s3<
In questo caso siamo andati a beccare il pattern Power, cioè abbiamo estratto tutte le sottoespressioni
aventi Power come head.
In[74]:= Position@espr, _PowerD
Out[74]= 881, 1<, 81, 2<, 82<, 83, 1<<
In questo caso, invece, abbiamo visto le posizioni che occupano nell'espressione le sottoespressioni
Power. Avete anche notato come il pattern, in questo caso, sia privo di nome. Effettivamente, se non
bisogna usarlo, ma solamente riconoscerlo, possiamo anche farne a meno: consideriamo questa
nuova lista:
In[75]:= lista = 8Sin@Cos@xDD, c^3, 4êHr^3L<;
Supponiamo di voler sostituire i pattern esponenziali con un altro valore definito:
In[76]:= lista ê. _ ^ _ → cost
Out[76]= 8Sin@Cos@xDD, cost, 4 cost<
In questo caso, nella sostituzione non abbiamo avuto bisogno di usare i pattern che avevamo.
Adesso, invece, supponiamo di voler scambiare mantissa ed esponente:
In[77]:= lista ê. x_ ^y_ → y^x
Out[77]= 8Sin@Cos@xDD, 3c, 4 H−3Lr<
Adesso, invece, avevamo due pattern distinti, e dovevamo riutilizzarli per poter modificare le
espressioni nel modo che volevamo. In questo caso, dovevamo specificare quale pattern
rappresentava la mantissa, quale l'esponente, e poi li riutilizzavo. Un poco come definire delle
variabili ma, mentre le variabili hanno memorizzati dei dati o espressioni, i pattern siffatti
memorizzano solamente strutture.
_ qualsiasi espressione
x_ un'espressione qualsiasi che verrà chiamata x
x:pattern un'espressione che verrà chiamatra x, che soddisfail pattern
Daniele Lupo Appunti di Mathematica
248Printed by Mathematica for Students
L'ultima espressione delle tre è nuova, ed ancora non l'avevamo vista: mentre negli altri due casi
avevo una rappresentazione di un pattern qualsiasi, nel terzo caso x rappresenta non un pattern, ma la
struttura che lega i pattern fra di loro: se scriviamo x : r_ ê e_, r ed e rappresentano i pattern, mentre x
rappresenta l'espressione che li lega, ovvero la divisione.
In[78]:= espr = 4êHa + bL
Out[78]= 9 41 + b
, 42 + b
, 43 + b
, 44 + b
, 45 + b
=
In[79]:= espr ê. x : z_ + t_ → xêt
Out[79]= 9 41 + b
, 82 + b
, 123 + b
, 164 + b
, 205 + b
=
Quello che abbiamo fatto è questo: abbiamo scritto l'espressione, poi l'abbiamo modificata tramite le
regole con il pattern. Abbiamo visto dove compariva una somma, chiamando x la somma stessa, e
siamo andati a sostituirla con il rapporto fra la somma stessa ed il suo addendo. Dato che la somma
compare al denominatore, il divisore della regola di sostituzione comparirà al numeratore. Il
vantaggio consiste nel fatto che, invece di andare a riscrivere il pattern per intero nella parte destra
della regola di sostituzione, è bastato usare il suo nome. Questo può semplificare parecchio la
scrittura di queste regole avanzate.
Inoltre, pattern con lo stesso nome indicano pattern che sono identici in tutto:
In[80]:= lista = 8a Sin@aD, b Sin@aD, v, b a Sin@bD<;
In[81]:= Cases@lista, _ Sin@_DD
Out[81]= 8<
In[82]:= Cases@lista, x_ Sin@x_DD
Out[82]= 8<
Come possiamo vedere qua sopra, nel primo caso il comando restituisce tutti gil elementi del tipo
"seno di qualcosa che moltiplica qualcos'altro". Nel secondo caso, invece, i due pattern che usiamo
hanno lo stesso nome, per cui non sono devono essere pattern, ma devono essere lo stesso pattern.
Restituisce, in pratica, gli elementi del tipo "seno di un argomento che sono moltiplicati dallo stesso
argomento". I pattern devono coincidere perfettamente, e ribadisco perfettamente, come potete
notare dal fatto che l'ultimo comando non restituisce l'ultimo elemento, e neanche il secondo, per il
banale motivo che non hanno un pattern corrispondente.
Daniele Lupo Appunti di Mathematica
249Printed by Mathematica for Students
Inoltre, possiamol anche introdurre delle condizioni per il pattern; possiamo scegliere e modificare sì
un determinato pattern, ma anche un pattern con delle limitazioni ben specifiche. Per esempio,
sempre considerando gli esponenti, possiamo sostituire il pattern solo se l'esponente è un numero
positivo, lasciando tutto inalterato quando è, invece, negativo oppure simbolico:
pattern /; condition un pattern corrispondente soltanto quando la condizioneè soddisfatta
lhs :> rhs /; condition una regola che viene applicatasolamente se sono soddisfatte le condizioni
lhs := rhs /; condition una definizione che viene applicata solamentesotto opportune condizioni
Le condizioni, a loro volta, possono essere espressioni logiche, oppure comunque funzioni che
restituiscono come risultato True oppure False:
IntegerQ[expr] verifica se l'espressione è un numero intero
EvenQ[expr] verifica se l'espressione è un numero pari
OddQ[expr] come sopra, ma se il numero è dispari
PrimeQ[expr] verifica un numero primo
NumberQ[expr] un valore numerico esplicito qualsiasi
NumericQ[expr] una quantità numerica
PolynomialQ[expr, {x1, x2,… }]
verifica se l'espressione è una forma polinomiale inx1, x2, ...
VectorQ[expr] verifica se ho una lista scritta in forma di vettore
MatrixQ[expr] una lista di liste rappresentanti una matrice
V e c t o r Q [e x p r,NumericQ], Matrix
verifica se l' espressione è unvettore Hoppure una matriceL numerica
VectorQ[expr, test], Matrix
Q[expr, test] verifica i vettori e le matrici per cui test restituisceTrue per ogni elemento
ArrayQ[expr, d] array con profondità d
Supponiamo di volere una funzione definita solamente per valori positivi dell'argomento; possiamo
specificare questo nella funzione:
In[83]:= f@x_D := x^2 + BesselJ@4, xD ê; x > 0
Se, adesso, andiamo a scrivere la funzione con un numero positivo, otteniamo il risultato:
In[84]:= [email protected]
Out[84]= 22.9746
Se, invece, il numero è negativo, non soddisfa le condizioni, per cui la funzione non viene valutata:
Daniele Lupo Appunti di Mathematica
250Printed by Mathematica for Students
In[85]:= f@−9.214D
Out[85]= f@−9.214D
In questo caso viene lasciata inalterata, perchè non è possibile valutarla.
In[86]:= f@gD
Out[86]= f@gD
Come possiamo vedere, anche in questo caso la funzione non viene valutata, perchè g rappresenta
un'incognita, e Mathematica non è in grado di stabilire se essa rappresenta una quantità positiva,
negativa o quant'altro, rispettando le regole stabilite, quindi:
In[87]:= f@Sin@40 °DD
Out[87]= BesselJ@4, Sin@40 °DD + Sin@40 °D2
In questo caso, anche se abbiamo inserito una funzione, Mathematica è in grado di stabilire che il
risultato è una quantità positiva, per cui riesce a valutare la funzione anche se non esplicita
l'argomento, che rimane infatti in forma simbolica. Naturalmente, se volessimo, potremmo anche
avere il valore approssimato, ma ormai siete troppo bravi (e pazienti...), per farvi vedere come si fa,
vero????
Possiamo anche vedere come le funzioni si applicano alle liste:
In[88]:= f@8−3, 4, 2, −432, t, 5 r<D
Out[88]= f@8−3, 4, 2, −432, t, 5 r<D
Definiamo la stessa funzione, adesso, però senza la restrizione, ed applichiamo la stessa lista:
In[89]:= g@x_D := x^2 + BesselJ@4, xD
In[90]:= g@8−3, 4, 2, −432, t, 5 r<D
Out[90]= 89 + BesselJ@4, −3D, 16 + BesselJ@4, 4D, 4 + BesselJ@4, 2D,186624 + BesselJ@4, −432D, t2 + BesselJ@4, tD, 25 r2 + BesselJ@4, 5 rD<
Come possiamo vedere, le due funzioni si comportano diversamente: effettivamente, uno si
aspetterebbe che la funzione venisse applicata agli elementi della lista, valutandola soltanto per
quegli elementi positivi. Tuttavia, possiamo notare che come argomento diamo una lista, non un
numero, per cui rigorosamente non abbiamo una corrispondenza del pattern, dato che una lista non è
un numero, e non possiamo quindi verificare se è maggiore o minore di 0, non viene valutato in
Daniele Lupo Appunti di Mathematica
251Printed by Mathematica for Students
quando i pattern non coincidono. per risolvere questo problema possiamo usare il comando Map, che
applica la funzione che ha come primo argomento, agli elementi della lista che ha come secondo
argomento
In[91]:= Map@f, 8−3, 4, 2, −432, t, 5 r<D
Out[91]= 8f@−3D, 16 + BesselJ@4, 4D, 4 + BesselJ@4, 2D, f@−432D, f@tD, f@5 rD<
Vedremo più avanti altri aspetti di Map. Per ora vi basti sapere che con questo comando possiamo
applicare la funzione con le condizioni dei pattern anche ad elementi della lista.
In[92]:= espr = x^2 + t^5 x + 4 − 5^e;
In[93]:= espr ê. x_ x + 6 ê; IntegerQ@xD
Out[93]= 10 + 5 11e + t11 x + x8
In quest'altro esempio abbiamo visto una sostituzione condizionata: avevamo un'espressione
qualsiasi, dove comparivano anche dei numeri interi, e poi abbiamo applicato la seguente regola di
sostituzione: "somma il valore 6 ad ogni elemento dell'espressione, che risulti essere un valore
intero".
Tuttavia, a volte è possibile forzare il riconoscimento dei pattern, anche se in teoria non sarebbe
possibile: per esempio, è possibile forzare Mathematica a riconoscere un incognita come un valore
di un certo tipo:
In[94]:= h ê: IntegerQ@hD = True
Out[94]= True
Si vede, in questo caso, che abbiamo forzato il valore h ad assumere un valore intero:
In[95]:= h^t ê. x_ x + 6 ê; IntegerQ@xD
Out[95]= H6 + hLt
Applicando adesso la stessa regola di trasformazione di prima, vediamo che stavolta Mathematica,
pur vedendo h sempre come un'incognita, adesso sa che, qualsiasi cosa rappresenti, sarà sempre un
numero intero. In questo modo, riconosciuto il numero intero, gli va a sommare il valore 6 come da
regola, mentre all'incognita t non succede niente, perchè è un incognita che rimane tale, in quanto
non abbiamo specificato niente per quest'ultima.
Daniele Lupo Appunti di Mathematica
252Printed by Mathematica for Students
In[96]:= h^t + 3 ê. x_ x + 6 ê; NumberQ@xD
Out[96]= 9 + ht
Qua possiamo vedere la rigidità di questo ragionamento: pur avendo assegnato ad h il significato di
valore intero, non viene comunque riconosciuto come valore numerico, sebbene un numero intero
sia anche, ovviamente, un numero; infatti la costante numerica, è riconosciuta sia come intero, sia
come numero, e la regola viene applicata comunque. Questo perchè dobbiamo esplicitamente
dichiarare ogni cosa che imponiamo all'incognita. Possiamo dire che un numero intero ha entrambi
gli attributi, Number e Numeric, mentre h ne possiede uno soltanto. Per cui è necessario specificare
ogni volta quello che vogliamo che l'incognita sia. Può essere estremamente utile quando trattiamo
espressioni simboliche non definite, ma, che per esempio, sappiamo che l'argomento deve essere per
forza di un certo tipo (diciamo intero). In questo modo possiamo applicare le regole anche se non
abbiamo definito la funzione, permettendoci uno studio ed un'elaborazione delle formule più spedito,
dato che non ci serve definire le funzioni completamente, ma solamente nelle loro proprietà che ci
servono. Però, Mathematica non riesce, da sola, a propagare le proprietà: se, per esempio, h è intero,
anche h2 lo è, e tuttavia Mathematica non riesce a riconoscerlo:
In[97]:= IntegerQ@h^2D
Out[97]= False
Occorrono opportuni strumenti che permettano a Mathematica di fare queste asserzioni, cosa che
vedremo sempre più avanti.
Possiamo anche fare test sulle strutture, un po' come accade negli operatori logici:
SameQ[x, y] or x === y x e y sono identici
UnsameQ[x, y] or x =!= y x e y non sono identici
OrderedQ[{a, b, … }] a, b, ... sono in ordine standard
MemberQ[expr, form] form combacia con un elemento di expr
FreeQ[expr, form] form non compare in expr
MatchQ[expr, form] expr corrisponde al pattern form
ValueQ[expr] un valore definito per expr
AtomQ[expr] expr non ha sottoespressioni
Possiamo considerare === come un operatore che, più che sui valori, lavora sulle strutture:
In[98]:= q t
Out[98]= q t
Daniele Lupo Appunti di Mathematica
253Printed by Mathematica for Students
In questo caso, si lascia inalterata, perchè Mathematica non sa se il valore q corrisponde a quello di t:
In[99]:= q === t
Out[99]= False
In questo caso, i due pattern non sono identici (sebbene rappresentino entrambi delle incognite,
avendo lettere diverse), per cui a questo test non importa il valore delle incognite, ma solamente la
struttura, che è diversa:
In[100]:= q = 3; t = 3;
In[101]:= q === t
Out[101]= True
In questo caso, però, Mathematica esegue il confronto non fra i pattern delle espressioni, ma fra i
pattern di quello che rappresentano:
In[102]:= Log@4^5D 5 Log@4D
— N::meprec : Internal precision limit $MaxExtraPrecision =49.99999999999999` reached while evaluating −5 Log@4D + Log@1024D. More…
Out[102]= Log@1024D 5 Log@4D
OOPs..... Questo non me l'aspettavo... comunque, niente di difficile: proviamo a vederlo
numericamente...
In[103]:= Log@4^5.D 5. Log@4D
Out[103]= True
Ci siamo riusciti... Come potete vedere, il risultato è True, perchè entrambe le espressioni portano al
medesimo risultato. Vediamo adesso, invece:
In[104]:= Log@4^5D === 5 Log@4D
Out[104]= False
Come potete vedere, in questo caso, sebbene abbiano lo stesso valore numerico, e rappresentino la
stessa quantità, le espressioni hanno forme diverse:
Daniele Lupo Appunti di Mathematica
254Printed by Mathematica for Students
In[105]:= FullForm@Log@4^5DD
Out[105]//FullForm= Log@1024D
In[106]:= FullForm@4 Log@5DD
Out[106]//FullForm= Times@4, Log@5DD
Non corrispondendo le espressioni, l'uguaglianza strutturale non è verificata, anche se lo è quella
logica.
Un altro aspetto interessante, consiste nel fatto che possiamo considerare pattern alternativi: finora
abbiamo considerato le regole e tutto quanto con un singolo pattern, per esempio possiamo sostituire
tutti gli elementi di una lista del tipo Sin[_], con Cos[_]. Tuttavia, come possiamo fare se vogliamo
che sia Sin[_], sia Log[_] siano sostutiti con la stessa quantità? I pattern alternativi esistono proprio
per questo!!!
patt1 | patt2 | … pattern che può assumere una delle forme specificate
Supponiamo, di avere un espressione dove compaiano sia seni che coseni, e che vogliamo cambiarli
con un altra funzione:
In[107]:= lista = 8Sin@xD, Cos@sD, v^u, Tan@Cos@eDD, f@Sin@xDD<;
Supponiamo di volerli cambiare con un logaritmo:
In[108]:= lista ê. HSin » CosL@x_D → Log@xD
Out[108]= 8Log@xD, Log@sD, vu, Tan@Log@eDD, f@Log@xDD<
Come abbiamo visto, in questo caso abbiamo sostituito tutte le funzioni trigonometriche seno e
coseno. Notate, tuttavia, come la tangente, sebbene esprimibile come rapporto fra queste due
funzioni, non venga toccata, grazie al fatto che nel suo pattern non compaiono le funzioni seno e
coseno:
In[109]:= FullForm@Tan@xDD
Out[109]//FullForm= Tan@xD
Quindi, non è espressa in funzione di seno e coseno.
Notate anche come ho scritto la regola; dato che mi importava l'head della funzione, cioè Sin oppure
Cos, l'ho scritta nella forma HSin » CosL@x_D, per far capire meglio che intendevo uno dei due head.
Daniele Lupo Appunti di Mathematica
255Printed by Mathematica for Students
Tuttavia, avrei avuto, naturalmente, lo stesso risultato anche se avessi specificato le due funzioni,
cosa che magari avreste fatto voi:
In[110]:= lista ê. Sin@x_D » Cos@x_D → Log@xD
Out[110]= 8Log@xD, Log@sD, vu, Tan@Log@eDD, f@Log@xDD<
Anche in questo caso ho effettuato la sostituzione, ma ho posto maggior attenzione all'intero pattern,
piuttosto che nel'head principale. Tuttavia, si tratta nella maggior parte dei casi solamente di
differenti stili di scrittura. Ognuno, poi, sceglie il suo stile, esattamente come in qualsiasi linguaggio
di programmazione.
Funzioni con argomenti variabili
Finora abbiamo considerato sempre funzioni specifiche, creando funzioni che abbiano sempre un
numero ben determinato di funzioni: tuttavia, guardate qua:
In[111]:= FullForm@a + bD
Out[111]//FullForm= List@Plus@1, bD, Plus@2, bD, Plus@3, bD, Plus@4, bD, Plus@5, bDD
In[112]:= FullForm@a + b + c + d + e + fD
Out[112]//FullForm= List@Plus@1, b, c, d, e, fD, Plus@2, b, c, d, e, fD,Plus@3, b, c, d, e, fD, Plus@4, b, c, d, e, fD, Plus@5, b, c, d, e, fDD
Come potete vedere, Mathematica è in grado anche di gestire funzioni che abbiano un arbitrario
numero di argomenti al suo interno. Questo può essere utile, per esempio, quando si definiscono
funzioni che devono lavorare su un arbitrario numero di elementi di una lista, quando si devono
accodare varie operazioni etc.
Si possono specificare argomenti multipli mediante underscore multipli nella definizione dei pattern:
_ una singola espressione
x_ una singola espressione chiamata x
__ una sequenza di più espressioni
x__ una sequenza di più espressioni chiamata x
x__h una sequenza di espressioni aventi tutti lo stesso head h
___ una sequenza nulla, con una o più espressioni
x___ una sequenza nulla, con una o più espressioni cheviene chiamata x
x___h una sequenza nulla, con una o più espressioni chehanno tutte come head h
Daniele Lupo Appunti di Mathematica
256Printed by Mathematica for Students
Notate che __ è rappresentato da due underscore _ _ , mentre ___ da tre underscore _ _ _. Mi
raccomando, state attenti a quanti ne mettete!!!
Naturalmente, questa generalizzazione degli argomenti permette di creare regole e definizioni più
particolari e potenti. Per esempio, potremmo definire delle sostituzioni che usino funzioni con un
numero diverso di argomenti:
In[113]:= r@a, g, bD ê. r@x__D → f@x, x, x + 1, x^2, t@xDD
Out[113]= fA81, 2, 3, 4, 5<, g, b, 81, 2, 3, 4, 5<, g,
b, 82 + b + g, 3 + b + g, 4 + b + g, 5 + b + g, 6 + b + g<,
91, 2gb2
, 3gb2
, 4gb2
, 5gb2=, 3@81, 2, 3, 4, 5<, g, bDE
Notiamo in questa espressione diverse cosucce: prima di tutto, vediamo come il pattern definisca,
questa volta, tutti e tre gli argomenti. In questa maniera possiamo trattarli tutti in una volta. nella f, i
primi due argomenti sono due volte la x, che si traduce nella ripetizione per due volte di a, g, b. Il
terzo e quarto argomento della f, sono invece delle funzioni. Abbiamo detto a Mathematica, nel terzo
argomento, di prendere tutto il pattern, e di sommargli uno:
In[114]:= r@a, g, bD ê. r@x__D → x + 1
Out[114]= 82 + b + g, 3 + b + g, 4 + b + g, 5 + b + g, 6 + b + g<
In[115]:= FullForm@%D
Out[115]//FullForm= List@Plus@2, b, gD, Plus@3, b, gD,Plus@4, b, gD, Plus@5, b, gD, Plus@6, b, gDD
In pratica, abbiamo introdotto nella funzione plus sia 1, sia il pattern, che è rappresentato dai tre
argomenti. In questo modo ho ottenuto la funzione Plus con quattro argomenti, effettuando, così, la
somma di tutti e quattro, come si evince dal risultato:
In[116]:= r@a, g, bD ê. r@x__D → x^2
Out[116]= 91, 2gb2
, 3gb2
, 4gb2
, 5gb2=
In[117]:= FullForm@%D
Out[117]//FullForm= List@1, Power@2, Power@g, Power@b, 2DDD,Power@3, Power@g, Power@b, 2DDD,Power@4, Power@g, Power@b, 2DDD, Power@5, Power@g, Power@b, 2DDDD
In questo caso le cose sono andate diversamente. Infatto, Power è una funzione che richiete
esattamente due argomenti: dato che con la nostra sostituzione non si poteva calcolare, allora sono
Daniele Lupo Appunti di Mathematica
257Printed by Mathematica for Students
state gestite le cose in modo da avere una ripartizione fra gli argomenti esatta, in modo da poter
creare una funzione così fatta. Mathematica applica iterativamente la funzione. Prima inserisce
dentro la funzione Power il primo argomento, a, poi il secondo b. Dopo ancora inserisce il terzo ma,
dato che non rientra nella definizione della funzione, combina il secondo ed il terzo in una nuova
funzione Power, in modo che la funzione più esterna sia formata sempre da due argomenti. Infine
ripete lo stesso procedimenti per il 2.
Mathematica effettua questa sostituzione solo quando sa il numero di argomenti di una funzione:
In[118]:= r@a, g, bD ê. r@x__D → t@xD
Out[118]= 3@81, 2, 3, 4, 5<, g, bD
In questo caso, infatti, la funzione t@xD non è stata definita, e Mathematica non è in grado di
conoscere il numero dei suoi argomenti, per cui la lascia così com'è, non essendo in grado di
valutarla.
Inoltre, quando si effettuano sostituzioni con pattern multipli, di solito sono possibili più
combinazioni. Per esempio, se prendiamo f @a, b, cD e consideriamo f @x__, y__D, allora posso avere
sia x__ = a, y__ = b, c, sia x__ = a, b; y__ = c. In questo modo dobbiamo poter essere in grado di
riconoscere tutte le combinazioni:
In[119]:= ReplaceList@t@a, b, c, dD, t@x__, y__, z__D → 88x<, 8y<, 8z<<D
Out[119]= 88881, 2, 3, 4, 5<<, 8b<, 8c, d<<,8881, 2, 3, 4, 5<<, 8b, c<, 8d<<, 8881, 2, 3, 4, 5<, b<, 8c<, 8d<<<
Come possiamo vedere, abbiamo ottenuto in questo esempio tutte le partizioni che Mathematica
riesce a fare con questi argomenti. Tuttavia, abbiamo considerato i pattern che devono contenere
almeno un argomento. Se usiamo ___ invece di __, possiamo tener conto anche dei pattern vuoti:
In[120]:= ReplaceList@t@a, b, c, dD, t@x___, y___, z___D → 88x<, 8y<, 8z<<D
Out[120]= 888<, 8<, 881, 2, 3, 4, 5<, b, c, d<<,88<, 881, 2, 3, 4, 5<<, 8b, c, d<<, 8881, 2, 3, 4, 5<<, 8<, 8b, c, d<<,88<, 881, 2, 3, 4, 5<, b<, 8c, d<<, 8881, 2, 3, 4, 5<<, 8b<, 8c, d<<,8881, 2, 3, 4, 5<, b<, 8<, 8c, d<<, 88<, 881, 2, 3, 4, 5<, b, c<, 8d<<,8881, 2, 3, 4, 5<<, 8b, c<, 8d<<, 8881, 2, 3, 4, 5<, b<, 8c<, 8d<<,8881, 2, 3, 4, 5<, b, c<, 8<, 8d<<, 88<, 881, 2, 3, 4, 5<, b, c, d<, 8<<,8881, 2, 3, 4, 5<<, 8b, c, d<, 8<<, 8881, 2, 3, 4, 5<, b<, 8c, d<, 8<<,8881, 2, 3, 4, 5<, b, c<, 8d<, 8<<, 8881, 2, 3, 4, 5<, b, c, d<, 8<, 8<<<
Come potete vedere, in questo caso compaiono anche pattern che non sono composti da nessun
elemento, Per questo bisogna stare attenti quando si decide di usare tre underscore invece di due; è
possibile infatti insorgere in qualche problema di rappresentazione, come è facile anche insorgere in
Daniele Lupo Appunti di Mathematica
258Printed by Mathematica for Students
loop infiniti quandi si eseguono funzioni come ReplaceAll.
Possiamo che utilizzare degli altri modi per definire le funzioni con un numero variabile di
argomenti. Per esempio, possiamo considerare il seguente esempio:
In[121]:= disegno@order_: 4, start_: 0, end_: 15, thick_: 0.03D :=
Plot@BesselJ@order, xD,8x, start, end<,PlotStyle → 8Thickness@thickD, Blue<, PlotRange → All
D
In[122]:= disegno@D
2 4 6 8 10 12 14
-0.2
-0.1
0.1
0.2
0.3
0.4
Out[122]= Graphics
In[123]:= disegno@2, 3, 30, .051D
10 15 20 25 30
-0.2
0.2
0.4
Out[123]= Graphics
Daniele Lupo Appunti di Mathematica
259Printed by Mathematica for Students
Come possiamo vedere, abbiamo definito una funizione con un numero variabile di argomenti.
Tuttavia, ciò è vero soltanto in apparenza. In effetti, le variabili sono sempre in numero definito,
solamente che abbiamo posto, questa volra, dei valori di default:
x_:v espressione che, se omessa, viene definita con il valoredi default v
x_h:v un'espressioned con head h e valore di default pari a v
x_. espressione con valore di default predefinito
x_ + y_. valore di default pari al valore 0
x_ y_. valore di default 1
x_^y_. valore di default 1
Nella funzione di sopra, abbiamo definito degli argomenti aventi dei valori di default. Se, quando la
funzione viene chiamata, non si specificano argomenti, allore viene disegnata con tutti i valori di
default. Se invece andiamo a scrivere nuo o più argomenti, allora i valori di default nella definizione
della funzione sono sostituiti da quelli che andiamo a scrivere. Inoltre, possiamo anche utilizzare,
come si vede dalle ultime quattro definizioni della tabella, dei valori iniziali di default per
Mathematica, pari all'elemento predefinito per l'operazione. Per esempio, se l'argomento viene
sommato, come valore di default predefinito viene posto lo 0, mentre per la moltiplicazione viene
posto pari ad 1; in pratica, è come se non lo considerassimo, dato che il risultato è lo stesso che si ha
ignorando questi valori nell'espressione. Quindi la loro scelta non è stata casuale, come potete ben
vedere.
Questo tipo di definizione è particolarmente utile, specialmente per le funzioni più complicate.
Possono anche essere viste, sotto un determinato punto di vista, anche come delle opzioni per la
funzione: certe volte è utile vederle sotto questi punto di vista, per esempio quando si definisce una
funzione risolvibile con più algoritmi: se si omette l'argomento, allora si utilizza il metodo standard,
altrimenti si sceglie esplicitamente il metodo. Possiamo anche esplicitare il fatto che si tratta di
opzioni per la nostra funzione:
f[x_, opts___] := value tipica definizione con zero, oppure piùargomenti opzionali
name /. {opts} /. Options[f] sostituzione usata per ottenere il valore di unargomento opzionale nel corpo della funzione
Possiamo definire in particolar modo esplicitamente le opzioni di default per una funzione:
In[124]:= Options@fD = 8option1 → 12, option2 → q, option3 → 652 Sqrt@4D<
Out[124]= 8option1 → 12, option2 → 3, option3 → 1304<
Daniele Lupo Appunti di Mathematica
260Printed by Mathematica for Students
In[125]:= Options@fD
Out[125]= 8option1 → 12, option2 → 3, option3 → 1304<
Come possiamo vedere, abbiamo le opzioni della funzione, sotto forma di regole di sostituzione.
Possiamo vedere come si comportano, e in particolar modo, possiamo vedere il valore di default di
un'opzione di una funzione, nella maniera solita delle regole di sostituzione:
In[126]:= option2 ê. Options@fD
Out[126]= 3
Abbiamo semplicemente sostituito il valore option2 con quello corrispondente nelle regole di
sostituzione di Options[f].
Possiamo definire meglio la funzione, una volta definite le sue opzioni:
In[127]:= f@x_, op___D := funzione@x,option1 ê. 8op< ê. Options@fD,option2 ê. 8op< ê. Options@fD,option3 ê. 8op< ê. Options@fDD
In[128]:= f@5D
Out[128]= 25 + BesselJ@4, 5D
Come possiamo vedere, se chiamiamo la funzione senza nessun argomento opzionale, cioè senza
nessuna opzione, viene restituita con i valori standard:
In[129]:= f@5, option1 −> "cambio!!!"D
Out[129]= funzione@5, cambio!!!, 3, 1304D
In[130]:= Clear@fD
In questo caso, sono state lasciate le opzioni di default, tranne la prima, che viene sostituita con il
valore imposto da noi... Non vi sembra il modo con cui si definiscono le opzioni per le funzioni e
comandi standard, come Plot? Adesso capite perchè li definiamo in quel modo? Certo che l'avete
capito!!! Siete talmente bravi che mi fate paura!!!
Un modo per definire argomenti variabili, utili soprattutto nella ricerca di particolari pattern, sono i
pattern ripetuti:
Daniele Lupo Appunti di Mathematica
261Printed by Mathematica for Students
expr.. un pattern od un'altra espressione ripetuta una o più volte
expr... un pattern od altra espressione ripetuta zero,una oppure più volte
Permettono di ricercare funzioni con pattern ripetuti come argomenti. Consideriamo la lista di
funzioni:
In[131]:= lista = 8f@qD, f@a, a, a, aD, f@f, e, e, g, hD, f@e, e, rD<;
Andiamo ad eseguire una ricerca vedendo gli elementi della lista dove compaiono patten ripetuti:
In[132]:= Cases@lista, f@a ..DD
Out[132]= 8f@81, 2, 3, 4, 5<, 81, 2, 3, 4, 5<, 81, 2, 3, 4, 5<, 81, 2, 3, 4, 5<D<
Come potete vedere, viene scelta solamente la funzione avente quel pattern ripetuto. Vediamo
adesso:
In[133]:= Cases@lista, f@___, e .., ___DD
Out[133]= 8f@f, e, e, g, hD, f@e, e, rD<
In questo caso, siamo andati a trovare gli elementi della lista dove all'interno compare una
ripetizione di argomenti e, in qualsiasi posizione, in mezzo, all'inizio od alla fine della dichiarazione
degli argomenti. Infatti, come primo e terzo argomento del pattern ho usato il triplo underscore, che
significa che possono anche esserci zerio elementi prima del pattern ripetuto, come infatti accade
nell'ultimo elemento della lista, che viene comunque selezionato.
ü Operazioni su funzioni
Introduzione
Abbiamo visto come manipolare le espressioni di qualsiasi tipo, siano esse liste, espressioni,
considerato che tutte rappresentano, in fondo, la stessa cosa. Quello che vedremo adesso è una cosa
analoga, fatta però per le funzioni. Al contrario delle espressioni, possono avere differenti tipi di
manipolazioni. Per esempio, ci piacerebbe applicarle soltanto ad argomenti specifici, oppure
iterativamente. Sebbene alcune cose si possano fare anche tramite le regole di sostituzione che
abbiamo visto prima, ci sono alcune cose che possiamo fare solamente tramite altri tipi di operazioni,
che adesso vedremo.
Manipolazioni base
Come possiamo vedere adesso, possiamo effettuare alcune operazioni sempre usando le regole di
sostituzione:
Daniele Lupo Appunti di Mathematica
262Printed by Mathematica for Students
In[134]:= Sin@xD + Cos@Sin@xDD ê. Sin → Log
Out[134]= Cos@Log@xDD + Log@xD
In questo caso siamo andati semplicemente a cambiare l'head Sin con l'head Cos, trasformando di
conseguenza tutti i seni in logaritmi. Quindi possiamo trattare gli head come espressioni. Possiamo
anche assegnargli dei nomi, se vogliamo:
In[135]:= pop = pip;
In[136]:= pop@xD
Out[136]= pip@xD
In questo caso, andando a memorizzare il nome della funzione, possiamo sostituirla ed usarla come
ci piace. Questo puù essere utile, ad esempio, quando usiamo spesso funzioni predefinite dal nome
lungo, come InverseLaplaceTransform, che possiamo memorizzarla in ilp:
In[137]:= ilp = InverseLaplaceTransform;
In[138]:= ilp@s Hs − 8L Hs^2 − s + 3LêHHs − 4L Hs^3 + 5LL, s, tD êê TraditionalForm
Out[138]//TraditionalForm=
-80 ‰12ÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅ
23+
1ÅÅÅÅÅÅÅÅÅÅÅÅÅ690
‰- 3ÅÅÅÅ2è!!!!53 I2+Â
è!!!!3 M
JI-350 + 215 è!!!53- 215 Â
è!!!3 è!!!53+ 113 52ê3 + 113 Â
è!!!3 52ê3M ‰9 è!!!!53ÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅ2 - 2 I175 + 215 è!!!53
+ 113 52ê3M
‰3ÅÅÅÅ2 Â
è!!!!3 è!!!!53
+ I-350 + 215 è!!!53+ 215 Â
è!!!3 è!!!53+ 113 52ê3 - 113 Â
è!!!3 52ê3M ‰3ÅÅÅÅ2
è!!!!53 I3+2 Âè!!!!3 MN
Come possiamo vedere, abbiamo usato un alias per la funzione, rendendola più corta, anche se non
si può dire lo stesso del risultato...
Alla stessa maniera, possiamo utilizzare gli head come argomento di una funzione, cosa che può
risultare estremamente utile in alcuni casi:
In[139]:= pp@f_, x_D := f@x^2D
In[140]:= pp@Log, 6D
Out[140]= Log@36D
Esistono alcune funzioni predefinite in Mathematica che vogliono come argomento proprio un head:
Daniele Lupo Appunti di Mathematica
263Printed by Mathematica for Students
In[141]:= InverseFunction@LogD
Out[141]= Exp
Questo, in particolare, restituisce la funzione inversa di quella scritta come argomento, se esiste. Puo
funzionare anche con le funzioni che non sono state definite in precedenza, anche se in questo caso
non restituisce l'inversa, dato che non può farlo, ma il simbolo dell'inversa:
In[142]:= InverseFunction@fD
Out[142]= fH−1L
Un aspetto importante nello studio delle funzioni si ha quando bisogna iterativamente applicarle ad
un argomento:
Nest[f, x, n] applica la funzione f nidificandola n volte all'argomento x
NestList[f, x, n] genera la lista {x, f[x], f[f[x]], … }, dove f èapplicata iterativamente per ogni elemento, fino adessere applicata n volte
FixedPoint@ f , xD Applica iterativamente la funzionefino a quando il risultato non varia più
FixedPointList@ f , xD genera la lista 8x, f @xD, f @ f @xDD, … <,fermandosi quando il risultato non varia più
Bisogna notare che f in questo caso rappresenta non tanto la funzione completa, quanto il suo
argomento:
In[143]:= Clear@g, zD
In[144]:= Nest@g, z, 7D
Out[144]= g@g@g@g@g@g@g@zDDDDDDD
Questo permette, come potete vedere, di applicare la funzione per un determinato numero di volte. E'
necessario a volte, perchè, come potete vedere qua sotto, se la variabile z non è definita,
l'assegnazione z = g@zD porta ad un errore di ricorsione in Mathematica:
In[145]:= z = g@zD;
— $RecursionLimit::reclim : Recursion depth of 256 exceeded. More…
In[146]:= Clear@zD
Daniele Lupo Appunti di Mathematica
264Printed by Mathematica for Students
Perchè applica la sostituzione all'infinito (fino a quando non supera il numero massimo di ricorsioni,
ovviamente). È anche possibile ottenere la lista di tutti gli elementi intermedi dell'operazione:
In[147]:= NestList@g, z, 7D
Out[147]= 8z, g@zD, g@g@zDD, g@g@g@zDDD, g@g@g@g@zDDDD,g@g@g@g@g@zDDDDD, g@g@g@g@g@g@zDDDDDD, g@g@g@g@g@g@g@zDDDDDDD<
Un esempio classico di programmazione di questo tipo (presente anche nell'help di Mathematica,
tanto è famoso), è dato dalla funzione reciproca, che abbiamo visto qualche tempo fa (in una galassia
lontana, lontana...) per le sostituzioni:
In[148]:= inv@x_D := 1êH1 + xL
Proviamo ad usare il comando:
In[149]:= Nest@inv, x, 6D
Out[149]=1
1 + 11+ 1
1+ 1
1+ 1
1+ 11+x
I comandi FixedPoint e FixedPointList sono importanti specialmente quando abbiamo a che fare con
problemi di convergenza. In questi problemi (come ad esempio l'algoritmo delle secanti), si applica
ripetutamente la funzione al risultato ottenuto precedentemente, fino a quando tutto quanto non si
stabilizza, ovvero fino a quando x = f @xD. In questo caso si dice che si è raggiunta la convergenza.
Inoltre, con il comando che visualizza le liste, è anche possibile visualizzare tutti i passi intermedi.
Proviamo a fare l'esempio per il la funzione inv che abbiamo già definito:
In[150]:= FixedPoint@inv, 3.D
Out[150]= 0.618034
Abbiamo ottenuto il risultato corretto. Naturalmente possiamo anche vedere i passi intermedi,
esattamente come prima
In[151]:= FixedPointList@inv, 3.D
Out[151]= 83., 0.25, 0.8, 0.555556, 0.642857, 0.608696, 0.621622, 0.616667,0.618557, 0.617834, 0.61811, 0.618005, 0.618045, 0.61803, 0.618036,0.618033, 0.618034, 0.618034, 0.618034, 0.618034, 0.618034, 0.618034,0.618034, 0.618034, 0.618034, 0.618034, 0.618034, 0.618034, 0.618034,0.618034, 0.618034, 0.618034, 0.618034, 0.618034, 0.618034,0.618034, 0.618034, 0.618034, 0.618034, 0.618034, 0.618034<
Daniele Lupo Appunti di Mathematica
265Printed by Mathematica for Students
Abbiamo visto come siano necessari parecchi passaggi, prima di ottenere la convergenza numerica;
notate come già dalla prima metà della lista i numeri compaiono tutti uguali: questo perchè la
rappresentazione, di default, visualizza un numero di cifre significative minore di quelle che usa
Mathematica per il calcolo interno, e quindi sono effettivamente diversi, tranne gli ultimi due che
devono essere uguali per la condizione di raggiungimento della convergenza.
Bisogna notare come abbia esplicitamente richiesto un calcolo numerico, invece che esatto,
scrivendo 3. invece che 3 ; questo è stato necessario perchè, in quest'ultimo caso, avrei ottenuto una
serie di frazioni che sarebbero state s' convergenti, ma non avrei avuto mai due elementi consecutivi
esattamente uguali, perchè numeratore e denominatore saranno sempre diversi. Possiamo vederlo,
andando ad aggiungere agli argomenti di FixedPoint il numero massimo di iterazioni che vogliamo:
è un parametro importante da aggiungere, se non siete sicuri della convergenza del metodo che state
usando. Vediamo l'esempio di prima: la convergenza si ottiene dopo aver calcolato n elementi:
In[152]:= n = Length@%D
Out[152]= 41
Vediamo di vedere lo stesso risultato senza però utilizzare l'approssimazione numerica:
In[153]:= Take@FixedPointList@inv, 3, 41D, −3D
Out[153]= 9 180510493292072113
, 292072113472582606
, 472582606764654719
=
Come potete vedere in questo caso, anche se numericamente (quindi con approssimazione) i valori
sono uguali, lo stesso non si può dire per le frazioni. Questo non cambia neanche se andiamo avanti
con il calcolo:
In[154]:= Take@FixedPointList@inv, 3, 100D, −3D
Out[154]= 9 386165282814252014980624828552868675407173
,
6248285528686754071731010993835682927422153
, 10109938356829274221531635822388551602829326
=
Come potete vedere non si raggiunge mai la convergenza, perchè non potranno mai esistere due
frazioni uguali per n che è finito, per quanto grande. Ponete sempre attenzione a questo, mi
raccomando, perchè calcoli esatti possono portare problemi, come in questo caso, se non sono presi
con la dovuta cautela, anche se sono sempre di più i vantaggi che gli svantaggi!!!!
Per casi come questo, piùttosto che verificare se gli ultimi elementi sono uguali, possono essere utili
delle condizioni di terminazione, che bloccano il calcolo quando si verifica un determinato test: per
esempio, se la differenza fra i due termini successivi è minore di una determinata tolleranza. Questo
si può fare anche con numeri esatti:
Daniele Lupo Appunti di Mathematica
266Printed by Mathematica for Students
NestWhile[f, x, test] applica ripetitivamente f calcolando test ad ogniiterazione, e bloccandosi se non restituisce più True
NestWhileList[f, x, test] genera la lista {x, f[x], f[f[x]], … }, fermandosialle stesse condizioni della funzione di sopra
NestWhile[f, x, test, m],NestWhileList[f, x, test, m]
usa gli m risultati più recenti per calcolare test adogni passo
NestWhile[f, x, test, All],NestWhileList[f, x, test, All]
usa tutti i risultati calcolati come argomento per test
Possiamo, per esempio, ripetere l'esempio di prima, con risultati esatti, e porre una tolleranza fra gli
ultimi due elementi, in modo da poter verificare la convergenza come faremmo in calcolo numerico,
pur non utilizzando valori approssimati:
In[155]:= tolleranza@x_, y_D := N@Abs@y − xDD > 10^−17
In[156]:= NestWhile@inv, 3, tolleranza, 2D
Out[156]=12372373252001892044
Come abbiamo potuto vedere, in questo caso abbiamo creato una funzione con due argomenti che
calcola la differenza in modulo di due valori, e verifica se è maggiore della tolleranza. Quindi,
restituisce True oppure False. Dopo, l'abbiamo utilizzata nel comando NestWhile, e abbiamo anche
specificato che per utilizzare quella funzione abbiamo bisogno degli ultimi due elementi. Notate
tuttavia che in questo esempio, anche se abbiamo ottenuto un risultato scritto in forma esatta, non sia
detto che sia esatto, nel senso che per questo valore non è vero che x = inv@xD. Non confondete i due
concetti, di numero esatto e risultato esatto. L'abbiamo ottenuto a meno di un'approssimazione, e va
considerato sempre come tale.
Vediamo la lista dei valori delle varie iterazioni, adesso:
In[157]:= NestWhileList@inv, 3, tolleranza, 2D
Out[157]= 93, 14
, 45
, 59
, 914
, 1423
, 2337
, 3760
, 6097
, 97157
, 157254
, 254411
, 411665
,
6651076
, 10761741
, 17412817
, 28174558
, 45587375
, 737511933
, 1193319308
, 1930831241
,
3124150549
, 5054981790
, 81790132339
, 132339214129
, 214129346468
, 346468560597
, 560597907065
,
9070651467662
, 14676622374727
, 23747273842389
, 38423896217116
, 621711610059505
, 1005950516276621
,
1627662126336126
, 2633612642612747
, 4261274768948873
, 68948873111561620
, 111561620180510493
,
180510493292072113
, 292072113472582606
, 472582606764654719
, 7646547191237237325
, 12372373252001892044
=
Daniele Lupo Appunti di Mathematica
267Printed by Mathematica for Students
E che ci vuole, adesso, a ricopiarsi i valori nel quaderno???? :-)
Il limite di questo ragionamento è che si tratta di elaborare funzioni ad un solo argomento; invece, a
volte sarebbe utile poter avere funzioni a due argomenti da trattare in maniera simile, cioè iterarle:
per questo basta usare i seguenti comandi:
FoldList[f, x, {a, b, … }] crea la lista {x, f[x, a], f[f[x, a], b], … }
Fold[f, x, {a, b, … }] restituisce l'ultimo elemento di FoldList[f, x, {a,b, … }]
Supponiamo di avere la seguente funzione:
In[158]:= g@x_, y_D := inv@xD − inv@yD
In[159]:= Clear@gD
Vediamo il comportamento con FoldList. Supponiamo di voler usare i seguenti valori come secondo
argomento nell'applicazione iterativa:
In[160]:= lista = 8a, c, b, 2, 6<;
Basta applicare alla lettera il comando:
In[161]:= FoldList@g, x, listaD
Out[161]= 8x, g@x, 81, 2, 3, 4, 5<D,g@g@x, 81, 2, 3, 4, 5<D, cD, g@g@g@x, 81, 2, 3, 4, 5<D, cD, bD,g@g@g@g@x, 81, 2, 3, 4, 5<D, cD, bD, 2D,g@g@g@g@g@x, 81, 2, 3, 4, 5<D, cD, bD, 2D, 6D<
Vediamo qualcosa di più comprensibile, va':
In[162]:= Fold@f, x, listaD
Out[162]= f@f@f@f@f@x, 81, 2, 3, 4, 5<D, cD, bD, 2D, 6D
Come potete vedere, si applica iterativamente una funzione a due variabili, cosa che vi può tornare
utile in alcuni algoritmi: io siceramente mi ricordo di averla usata solamente una volta in anni di
utilizzo di Mathematica, ma ognuno è diverso dagli altri...
Un altro comando utile nel trattamento di funzioni, è il seguente:
Daniele Lupo Appunti di Mathematica
268Printed by Mathematica for Students
Apply[f, {a, b, … }] applica f ad una lista, restituendo f[a, b, … ]
Apply[f, expr] or f @@ expr applica f al livello più alto dell'espressione
Apply[f, expr, {1}] or f@@@ expr
applica f al primo livello dell'espressione
Apply[f, expr, lev] applica f ai livelli specificati dell'espressione
Può capitare, durante i nostri calcoli, che otteniamo una lista di valori da usare come argomento per
una funzione: per esempio, potremmo ottenere una lista contenente come primo elemento l'ordine
della funzione (per esempio, l'ordine di BesselJ), e come secondo argomento il punto dove vogliamo
che sia calcolata.
In[163]:= Apply@BesselJ, 85, 87<D êê N
Out[163]= −0.0855539
Naturalmente, potremmo applicare la funzione anche ad elementi che non siano quelli di una lista.
Sappiamo, infatti, che le liste non sono altro che espressioni: di conseguenza, possiamo applicare il
comando Apply anche alle espressioni generali:
In[164]:= f @@ Hx^3 + x^2 + Sin@yDL
Out[164]= f@x2, x3, Sin@yDD
Come potete vedere, è stato scambiato l'head principale, che è rappresentato da Plus, con l'head che
abbiamo scelto noi, cioè f . Questo permette di poter organizzare e manipolare le espressioni in
maniera avanzata. Possiamo anche cambiare il livello di nidificazione successivo:
In[165]:= f @@@ Hx^3 + x^2 + Sin@yDL
Out[165]= f@yD + f@x, 2D + f@x, 3D
Vediamo meglio quello che abbiamo fatto. Consideriamo l'espressione iniziale:
In[166]:= TreeForm@x^3 + x^2 + Sin@yDD
Out[166]//TreeForm=
PlusA »Power@x, 2D
, »Power@x, 3D
, »Sin@yD
E
Adesso, applicando il comando come per il primo esempio, otteniamo:
Daniele Lupo Appunti di Mathematica
269Printed by Mathematica for Students
In[167]:= TreeForm@f @@ Hx^3 + x^2 + Sin@yDLD
Out[167]//TreeForm=
fA »Power@x, 2D
, »Power@x, 3D
, »Sin@yD
E
Come possiamo vedere, abbiamo scambiato l'head principale, quello al livello più alto dell'albero
rovesciato che abbiamo ottenuto. Di conseguenza i più se ne vanno. Consideriamo adesso il secondo
esempio:
In[168]:= TreeForm@f @@@ Hx^3 + x^2 + Sin@yDLD
Out[168]//TreeForm=
PlusA »f@yD
, »f@x, 2D
, »f@x, 3D
E
In questo caso, siamo andati ad applicare la f , sostituendola a 'qualsiasi' head che si trovava al primo
livello. La potenza di questo comando risiede nel fatto che permette di sostituire gli head in base al
livello in cui si trova, non in base al nome dell'head. Ovviamente, la necessità dell'uso di questo
comando, come fra l'altro come quasi tutti quelli riguardanti la manipolazione avanzata, dipende da
quello che volete fare.
Possiamo anche applicarla a più livelli contemporaneamente. Consideriamo questa espressione:
In[169]:= a^b^c^d^e^f^g
Out[169]= 91, 2bcdefg
, 3bcdefg
, 4bcdefg
, 5bcdefg
=
Daniele Lupo Appunti di Mathematica
270Printed by Mathematica for Students
In[170]:= TreeForm@%D
Out[170]//TreeForm=
ListA1,
»PowerA2, »
PowerAb, »PowerAc, »
PowerAd, »PowerAe, »
Power@f, gDEEEEE
,
»PowerA3, »
PowerAb, »PowerAc, »
PowerAd, »PowerAe, »
Power@f, gDEEEEE
,
»PowerA4, »
PowerAb, »PowerAc, »
PowerAd, »PowerAe, »
Power@f, gDEEEEE
,
»PowerA5, »
PowerAb, »PowerAc, »
PowerAd, »PowerAe, »
Power@f, gDEEEEEE
Ipotizziamo, adesso, di voler cambiare la funzione di potenza dal primo al terzo livello:
In[171]:= Apply@f, %%, 81, 3<D
Out[171]= 91, fA2, fAb, fAc, defgEEE, fA3, fAb, fAc, defgEEE,
fA4, fAb, fAc, defgEEE, fA5, fAb, fAc, defgEEE=
Daniele Lupo Appunti di Mathematica
271Printed by Mathematica for Students
In[172]:= TreeForm@%D
Out[172]//TreeForm=
ListA1, »fA2, »
fAb, »fAc, »
PowerAd, »PowerAe, »
Power@f, gDEEEEE
,
»fA3, »
fAb, »fAc, »
PowerAd, »PowerAe, »
Power@f, gDEEEEE
,
»fA4, »
fAb, »fAc, »
PowerAd, »PowerAe, »
Power@f, gDEEEEE
,
»fA5, »
fAb, »fAc, »
PowerAd, »PowerAe, »
Power@f, gDEEEEEE
Come possiamo vedere, abbiamo ottenuto proprio quello che desideravamo.
Tuttavia, a volte non è questo quello che desideriamo: a volte capita di volere che una funzione si
inserisca nell'albero, cioè che la funzione vada ad agire sugli argomenti che abbiamo ad un certo
livello, non che vada a sostituire gli head. Per esempio, ci piacerebbe che le incognite di un
polinomio cubico siano espresse sotto forma di seni, da così:
In[173]:= espr = a x^3 + b x^2 + c x + d;
a così:
Daniele Lupo Appunti di Mathematica
272Printed by Mathematica for Students
In[174]:= a Sin@xD^3 + b Sin@xD^2 + c Sin@xD + d
Out[174]= 8d + c Sin@xD + b Sin@xD2 + Sin@xD3,d + c Sin@xD + b Sin@xD2 + 2 Sin@xD3, d + c Sin@xD + b Sin@xD2 + 3 Sin@xD3,d + c Sin@xD + b Sin@xD2 + 4 Sin@xD3, d + c Sin@xD + b Sin@xD2 + 5 Sin@xD3<
Andando ad usare Apply, non otterremmo il risultato voluto:
In[175]:= Sin @@ espr
— Sin::argx : Sin called with 5 arguments; 1 argument is expected. More…
Out[175]= Sin@d + c x + b x2 + x3, d + c x + b x2 + 2 x3,d + c x + b x2 + 3 x3, d + c x + b x2 + 4 x3, d + c x + b x2 + 5 x3D
Come potete vedere, non otteniamo quello che vogliamo. Il risultato voluto si può applicare invece
con il seguente comando (ne avevamo accennato qualche pagina fa, se ricordate...):
Map[f, expr] or f /@ expr applica f alle parti del primo livello di expr
MapAll[f, expr] or f //@ expr applica f a tutte le singole parti di expr
Map[f, expr, lev] applica f ai livelli di expr spedificati da lev
MapAt[f, expr, {part1, part2,… }]
applica f in specifiche parti dell' espressione
Proviamo a ripetere il procedimento, con questo nuovo comando:
In[176]:= Sin ê@ espr
Out[176]= 8Sin@d + c x + b x2 + x3D, Sin@d + c x + b x2 + 2 x3D,Sin@d + c x + b x2 + 3 x3D, Sin@d + c x + b x2 + 4 x3D, Sin@d + c x + b x2 + 5 x3D<
Quello che abbiamo ottenuto è simile a quello che volevamo: non è uguale per il seguente motivo:
Daniele Lupo Appunti di Mathematica
273Printed by Mathematica for Students
In[177]:= TreeForm@esprD
Out[177]//TreeForm=
ListA »PlusAd, »
Times@c, xD, »
TimesAb, »Power@x, 2D
E, »
Power@x, 3DE
,
»PlusAd, »
Times@c, xD, »
TimesAb, »Power@x, 2D
E, »
TimesA2, »Power@x, 3D
EE
,
»PlusAd, »
Times@c, xD, »
TimesAb, »Power@x, 2D
E, »
TimesA3, »Power@x, 3D
EE
,
»PlusAd, »
Times@c, xD, »
TimesAb, »Power@x, 2D
E, »
TimesA4, »Power@x, 3D
EE
,
»PlusAd, »
Times@c, xD, »
TimesAb, »Power@x, 2D
E, »
TimesA5, »Power@x, 3D
EEE
Come è possibile vedere, al primo livello compaiono le funzioni che eseguono le moltiplicazioni,
non l'elevamento a potenza. Dato che ci interessa soltanto inserire il seno, abbiamo praticamente
sbagliato livello. Invece che applicare la funzione agli elementi del primo livello, dobbiamo
applicarla agli elementi specifici: vediamo prima dove compaiono gli esponenti:
In[178]:= Position@espr, xD
Out[178]= 881, 2, 2<, 81, 3, 2, 1<, 81, 4, 1<, 82, 2, 2<, 82, 3, 2, 1<,82, 4, 2, 1<, 83, 2, 2<, 83, 3, 2, 1<, 83, 4, 2, 1<, 84, 2, 2<,84, 3, 2, 1<, 84, 4, 2, 1<, 85, 2, 2<, 85, 3, 2, 1<, 85, 4, 2, 1<<
Una volta visto dove compaiono le incognite, possiamo applicare le sostituzioni:
In[179]:= MapAt@Sin, espr, %D
Out[179]= 8d + c Sin@xD + b Sin@xD2 + Sin@xD3,d + c Sin@xD + b Sin@xD2 + 2 Sin@xD3, d + c Sin@xD + b Sin@xD2 + 3 Sin@xD3,d + c Sin@xD + b Sin@xD2 + 4 Sin@xD3, d + c Sin@xD + b Sin@xD2 + 5 Sin@xD3<
Come possiamo vedere, questa volta abbiamo ottenuto il risultato voluto. Notate come si siano usato
un comando descritto in precedenza, Position. Questo vi fa capire come bisogna sempre collegare
Daniele Lupo Appunti di Mathematica
274Printed by Mathematica for Students
tutto quello che si sa per poter ottenere il risultato voluto velocemente. Se non l'avessi usato, avrei
dovuto trovarmi a mano le singole posizioni delle varie incognite che compaiono nell'espressione,
cosa già non facilissima con una cubica, figurarsi con un'espressione più complicata!
Naturalmente, se avessimo potuto, e soprattutto se ci sarebbe servito, avremmo potuto anche
mappare ogni singolo elemento con la funzione seno:
In[180]:= Sin êê@ espr
Out[180]= 8Sin@Sin@Sin@dD + Sin@Sin@cD Sin@xDD +
Sin@Sin@xDSin@3DD + Sin@Sin@bD Sin@Sin@xDSin@2DDDDD,
Sin@Sin@Sin@dD + Sin@Sin@cD Sin@xDD + Sin@Sin@bD Sin@Sin@xDSin@2DDD +
Sin@Sin@2D Sin@Sin@xDSin@3DDDDD,Sin@Sin@Sin@dD + Sin@Sin@cD Sin@xDD + Sin@Sin@bD Sin@Sin@xDSin@2DDD +
Sin@Sin@3D Sin@Sin@xDSin@3DDDDD,Sin@Sin@Sin@dD + Sin@Sin@cD Sin@xDD + Sin@Sin@bD Sin@Sin@xDSin@2DDD +
Sin@Sin@4D Sin@Sin@xDSin@3DDDDD,
Sin@Sin@Sin@dD + Sin@Sin@cD Sin@xDD + Sin@Sin@bD Sin@Sin@xDSin@2DDD +
Sin@Sin@5D Sin@Sin@xDSin@3DDDDD<
Tuttavia, non capita spesso di dover usare comandi come questo. Di solito si usa Map, oppure
MapAt.
Tuttavia, a volte ci capita di aver a che fare non con funzioni ad un argomento, ma con funzioni a
due o più argomenti. Se vogliamo mappare nell'espressione queste funzioni, ci torna utile il seguente
comando:
MapThread[f, {expr1, expr2,… }]
applica f facendo corrispondere fra di loro gli elementidi expri
MapThread[f, {expr1, expr2,… }, lev]
applica f alle varie parti di expri nei livelli specificati
In questo caso abbiamo bisogno di tante espressioni quanti sono gli argomenti della funzione: in
questo modo si creerà l'espressione corrispondente prendendo la funzione, il primo argomento che si
trova nella prima espressione, il secondo che si trova nella seconda espressione e così via:
In[181]:= lista1 = 86, 5, 6, 5<; lista2 = 88, 2, 9, 4<;
In[182]:= MapThread@HarmonicNumber, 8lista1, lista2<D
Out[182]= 9 168646392872321167961600000000
, 52693600
, 373997614931101373248000000000
, 1400136112960000
=
Come potete vedere, in questo caso abbiamo applicato la funzione con i corrispettivi argomenti:
Daniele Lupo Appunti di Mathematica
275Printed by Mathematica for Students
In[183]:= Table@HarmonicNumber@lista1@@nDD, lista2@@nDDD, 8n, 4<D
Out[183]= 9 168646392872321167961600000000
, 52693600
, 373997614931101373248000000000
, 1400136112960000
=
Come potete vedere le due liste corrispondono, per cui da qua si comprende il funzionamento di
questo comando.
L'ultimo comando da vedere è questo:
Scan[f, expr] valuta f applicata ad ogni elemento di expr in sequenza
Scan[f, expr, lev] valuta f applicata alle parti di expr che si trovanonei livelli specificati da lev
Riconsideriamo il polinomio di prima:
In[184]:= espr = a x^3 + b x^2 + c x + d;
Facendo qualcosa del tipo
In[185]:= Map@f, esprD
Out[185]= 8f@d + c x + b x2 + x3D, f@d + c x + b x2 + 2 x3D,f@d + c x + b x2 + 3 x3D, f@d + c x + b x2 + 4 x3D, f@d + c x + b x2 + 5 x3D<
Otteniamo, in pratica, una nuova espressione. Tuttavia con Scan possiamo valutare, al posto
dell'intera espressione, solamente i risultati che si hanno applicando la funzione ai vari elementi
dell'espressione:
In[186]:= Scan@Print, esprD
d + c x + b x2 + x3
d + c x + b x2 + 2 x3
d + c x + b x2 + 3 x3
d + c x + b x2 + 4 x3
d + c x + b x2 + 5 x3
In[187]:= Scan@f, esprD
Come possiamo vedere, nel secondo caso manca l'output. Questo perchè Scan di suo non scrive il
risultato delle funzioni, ma le valuta solamente: questo può essere utile quando ci sono determinate
Daniele Lupo Appunti di Mathematica
276Printed by Mathematica for Students
assegnazioni e funzioni. Nel primo caso Print valutato restituisce una cosa scritta su schermo, quindi
non è Mathematica stessa che scrive l'output, ma è una conseguenza della valutazione del comando
Print.
Modifiche strutturali delle espressioni e funzioni
Finora abbiamo visto come possiamo andare a sostituire e modificare parti di un'espressione.
Tuttavia, la struttura delle espressioni rimaneva pressochè invariata: è vero che a volte andiamo a
sostituire degli argomenti con altre funzioni, modificando l'albero, ma è pur sempre vero che quelle
funzioni rappresentano comunque dei valori; la struttura originale dell'espressione viene comunque
preservata. Tuttavia ci sono casi (specialmente nelle liste), in cui invece non vogliamo andare a
manipolare i vari valori memorizzati nell'epressione, ma vogliamo, invece, andare a modificarne
direttamente la struttura.
Una cosa che si può fare, per esempio, è considerare le operazioni non tanto sugli argomenti, quanto
sugli head: possiamo considerare questo ragionamento se li consideriamo come se fossero degli
operatori che agiscono sul loro argomento, e quindi, come per gli operatori, possiamo appiccicargli
un algebra, propria degli operatori:
Composition[f, g, … ] composizione degli operatori f, g, …
InverseFunction[f] l'inverso della funzione f
Identity la funzione identità Through@p@ f1, f2D@xD, qD restituisce p@ f1@xD, f2@xDD se p è lo stesso di q
Operate@p, f @xDD restituisce p@ f D@xDOperate@p, f @xD, nD applica l' operatore p nel livello n di f
MapAll@p, expr, Heads−>TrueD applica p in tutte le parti di f , head incluso
Supponiamo di avere degli operatori e di volerli comporre:
In[188]:= operatore = Composition@op1, op2, op3D
Out[188]= Composition@op1, op2, op3D
Se adesso vado ad applicare l'operatore ottenuto ad un valore, ottengo:
In[189]:= operatore@xD
Out[189]= op1@op2@op3@xDDD
Come possiamo vedere, si può considerare come funzione di funzione. Possiamo anche effettuare le
opportune operazione. Per esempio possiamo scrivere la somma di due operatori in questa maniera:
Daniele Lupo Appunti di Mathematica
277Printed by Mathematica for Students
In[190]:= Hop1 + op2L@xD
Out[190]= Hop1 + op2L@xD
E, se abbiamo definito da qualche parte questi due operatori, possiamo scrivere il tutto in maniera
esplicita, permettendo a Mathematica di calcolarlo:
In[191]:= Through@%, PlusD
Out[191]= op1@xD + op2@xD
Toh, abbiamo appena definito la linearità fra gli operatori....
Possiamo anche espandere e creare manipolazioni per gli operatori: per esempio:
In[192]:= Hop1 + op2 + op3L2@xD
Out[192]= Hop1 + op2 + op3L2@xD
Può essere esteso facilmente:
In[193]:= MapAll@Expand, %, Heads → TrueD
Out[193]= Hop12 + 2 op1 op2 + op22 + 2 op1 op3 + 2 op2 op3 + op32L@xD
Come possiamo vedere, le manipolazioni che possiamo eseguire sono veramente tante...
Oltre che dal punto di vista degli operatori, quindi eseguendo espressioni e modifiche tramite heads,
possiamo anche correggere direttamente la struttura delle espressioni:
Daniele Lupo Appunti di Mathematica
278Printed by Mathematica for Students
Sort[expr] ordina gli elementi dell'espressione in ordine standard
Sort[expr, pred] ordina gli elementi usando pred per determinarel'ordine degli elementi
Ordering[expr] restituisce la lista contenente gli indici diordinamento dell'espressione
Ordering[expr, n] come sopra, ma per i primi n elementi
Ordering[expr, n, pred] usa pred per determinare il tipo di ordine
OrderedQ[expr] restituisce True se gli elementi di expr sono ordinatiin maniera standard
Order[expr1, expr2] restituisce 1 se expr1 precede expr2 nell'ordine standard,e -1 altrimenti
Flatten[expr] appiattisce le funzioni nidificate dell'alberodelle espressioni con lo stesso head di expr
Flatten[expr, n] appiattisce al massimo n livelli di nidificazione
Flatten[expr, n, h] appiattisce tutte le funzioni con head h
FlattenAt[expr, i] appiattisce soltanto l' i-simo elemento di expr
Distribute[f[a + b + … , … ]] destribuisce f nella somma per avere f[a, … ] + f[b,… ] + …
Distribute[f[args], g] distribuisce f su qualsiasi argomento avente head g
Distribute[expr, g, f] distribuisce solamente quando l'head è f
Distribute[expr, g, f, gp, fp] distribuisce f su g, sostituendoli con fp egp, rispettivamente
Thread[f[{a1, a2}, {b1, b2}]] inserisce f nella lista per ottenere {f[a1, b1],f[a2, b2]}
Thread[f[args], g] inserisce f negli oggetti con head g in args
Outer[f, list1, list2] prodotto esterno generalizzato
Inner[f, list1, list2, g] prodotto interno generalizzato
Come potete vedere, le funzioni per manipolare le strutture non sono in fondo così poche, ma vi
posso assicurare che non sono difficili da capire e da usare, sempre, ovviamente, se si sa quello che
si sta facendo.
Vediamo prima di tutto la prima parte della lista dei comandi, cioè quelli riguardanti l'ordinamento.
Sappiamo che Sort ordina gli argomenti di una funzione in maniera standard:
In[194]:= Sort@8a, f, r, t, i, b, x<D
Out[194]= 83, b, f, i, r, x, 81, 2, 3, 4, 5<<
Daniele Lupo Appunti di Mathematica
279Printed by Mathematica for Students
In[195]:= Sort@f@a, v, f, e, q, v, c, h, bDD
Out[195]= f@3, b, c, e, f, h, v, v, 81, 2, 3, 4, 5<D
Come potete vedere, il risultato è questo, ed è ovvio. Tuttavia, supponiamo di aver bisogno di un
ordinamneto inverso, come possiamo fare? Naturalmente, conoscete benissimo le funzioni pure...
Aggiungiamo il fatto che possiamo usare Sort con la funzione di ordinamento, ed abbiamo ottenuto
quello che volevamo:
In[196]:= Sort@f@a, v, f, e, q, v, c, h, bD,Sort@ToString ê@ 8#1, #2<D@@1DD === ToString@#2D &D
Out[196]= f@v, v, h, f, e, c, b, 3, 81, 2, 3, 4, 5<D
Vediamo di capire bene quello che abbiamo appena fatto, anche per riassumere un poco quello che
abbiamo fatto (e che ho pazientemente spiegato...) sinora. Come sappiamo, Mathematica non è in
grado di ordinare due simboli, perchè li dovrebbe ordinare in base al contenuto, e lascia le cose come
sono se non contengono niente:
In[197]:= a > b
Out[197]= 81, 2, 3, 4, 5< > b
Analogamente, senza la funzione Sort, non riesce neanche a distinguere se una stringa viene prima o
dopo di un'altra: in C questa disuguaglianza darebbe il risultato corretto, invece:
In[198]:= "grge" > "asdaf"
Out[198]= grge > asdaf
Però, siamo comunque in grado di ordinare le stringhe, anche se non direttamente, utilizzando la
funzione Sort:
In[199]:= Sort@8"grge", "asdaf"<D
Out[199]= 8asdaf, grge<
Quello che ci serve, allora, è convertire i nomi delle variabili, usate come argomenti nella funzione,
in stringhe, ed ordinarle. A questo ci pensa il comando
In[200]:= ToString ê@ 8#1, #2<
Out[200]= 8#1, #2<
Daniele Lupo Appunti di Mathematica
280Printed by Mathematica for Students
In questo caso, al posto di scrivere due volte ToString, abbiamo mappato il comando, in modo che
risultasse, alla fine, in ogni argomento della lista; in effetti è equivalente a scrivere:
In[201]:= 8ToString@#1D, ToString@#2D<
Out[201]= 8#1, #2<
Ed abbiamo scritto in quella maniera per essere più brevi e coincisi. Adesso, ottenuta la lista di
stringhe, la ordiniamo mediante Sort:
In[202]:= Sort@ToString ê@ 8#1, #2<D
Out[202]= 8#1, #2<
In questo modo riusciamo a riorganizzare la lista di stringhe in modo che risultino in ordine
alfabetico. Una volta fatto questo, si tratta di vedere se l'ordine era giusto oppure no: prendiuamo il
primo elemento della lista ordinata che abbiamo appena ottenuto:
In[203]:= Sort@ToString ê@ 8#1, #2<D@@1DD
Out[203]= #1
Adesso, se il primo elemento di questa lista coincide con il secondo elemento della lista non
ordinata, allora gli elementi nella lista ordinata erano in ordine inverso: guardate qua:
In[204]:= lista = 83, 1<; listaordinata = Sort@listaD
Out[204]= 81, 3<
In[205]:= listaordinata@@1DD == lista@@2DD
Out[205]= True
Come abbiamo visto, questo risultato è True, perchè gli elementi della lista originale erano in ordine
inverso. Facciamo lo stesso identico ragionamento per la coppia ordinata di stringhe. Per vedere se il
primo elemento della lista ordinata di stringhe che abbiamo ottenuto è uguale al secondo elemento
della coppia non ordinata (che corrisponde al secondo argomento della funzione pura), ne
verifichiamo l'uguaglianza:
In[206]:= Sort@ToString ê@ 8#1, #2<D@@1DD === ToString@#2D
Out[206]= False
Daniele Lupo Appunti di Mathematica
281Printed by Mathematica for Students
Notate come, dato che la lista è ora formata da stringhe, anche il secondo argomento debba essere
una stringa, e come, inoltre, abbia eseguito l'uguaglianza esatta fra pattern ===, e non ==, in quanto
in questo secondo caso, non sapendo Mathematica ordinare da sola le stringhe, non saprebbe se sono
uguali, per cui devo eseguire un' uguaglianza fra pattern. Infine aggiungo il simbolo della funzione
pura, per completare il tutto:
In[207]:= Sort@ToString ê@ 8#1, #2<D@@1DD === ToString@#2D &
Out[207]= Sort@ToString ê@ 8#1, #2<DP1T === ToString@#2D &
Visto quante cose siamo riusciti a fare in molto meno di un rigo? Provate a farlo dichiarando tutte le
funzioni etc etc, e vedete quanto dovrete scrivere....
Comunque, una volta ottenuta la nostra funzione di ordinamento, vediamo che effettivamente
funziona, ed ordina tutti gli argomenti in modo inverso. Naturalmente, se avessimo avuto valori
numerici, le cose sarebbero state molto più semplici:
In[208]:= Sort@f@3, 1, 6, 7, 2, 4, 2, 9, 2, 6D, #1 > #2 &D
Out[208]= f@9, 7, 6, 6, 4, 3, 2, 2, 2, 1D
In questo caso basta fare il confronto diretto fra gli argomenti, dato che non c'è bisogno di convertire
alcunchè, perchè gli operatori logici naturalmente lavorano direttamente sui numeretti...
Aaahhh!!!! Scommetto che dopo questo esempio andrete a prendervi un bel caffè, oppure vi tufferete
al manre o vi rinchiuderete in qualche pub... Fate bene, bisogna uscire!!!! Comunque, sempre qua
dovete tornare!!! Aspetterò con calma...
Ancora qui? Bene, vuol dire che continuerò a rubarti quel poco di vita sociale che ti resta,
succhiandoti la linfa vitale... Benvenuto!!!
Abbiamo visto come possiamo usare Sort per modificare il pattern di una funzione. Adesso vediamo
il comando Flatten. Come dice la definizione, serve per appiattire l'espressione. Vediamo cosa
intendo per appiattire. Considera questa espressione:
In[209]:= f@a, f@f@b, g, f@rD, e, f@f@f, f@3DDDD, rD, 2D;
Daniele Lupo Appunti di Mathematica
282Printed by Mathematica for Students
In[210]:= TreeForm@%D
Out[210]//TreeForm=
fA »List@1, 2, 3, 4, 5D
, »fA »
fAb, g, »f@rD
, e, »fA »
fAf, »f@3D
EEE
, rE, 2E
Mamma mia, quanti livelli ha questa funzione cattiva cattiva!!!!!
Vediamo di applicare al risultato il comando:
In[211]:= Flatten@%%D
Out[211]= f@81, 2, 3, 4, 5<, b, g, r, e, f, 3, r, 2D
E che è successo??? Esattamente quello che ho detto: abbiamo appiattito l'espressione:
In[212]:= TreeForm@%D
Out[212]//TreeForm=
fA »List@1, 2, 3, 4, 5D
, b, g, r, e, f, 3, r, 2E
Anche in questo caso abbiamo modificato (abbastanza pesantemente, direi) la struttura
dell'espressione originale. Possiamo considerarlo, in un certo modo, come se avessimo dato alla
funzione f che non è definita, la proprietà dell'associatività, esattamente come per l'addizione o la
moltiplicazione. Vedendola in questa maniera, si nota già un certo modo di operare del programma
che è propenso al calcolo puramente simbolico, basato sulle proprietà delle funzioni. Lo è anche per
questo motivo.
In[213]:= f@g, r, t@r, tD, t@f@g, f@gDDDD;
In[214]:= Flatten@%D
Out[214]= f@g, r, 3@r, 3D, 3@f@g, f@gDDDD
In questo caso, abbiamo visto che il lavoro di Flatten si blocca non appena trova una
sottoespressione che ha un head non conforme a quello principale. Appiattisce, insomma, solamente
le sottoespressioni con lo stesso head. Un comando che fa una cosa in più, ma anche una in meno, è
Sequence:
Daniele Lupo Appunti di Mathematica
283Printed by Mathematica for Students
In[215]:= Sequence@a, b, fD
Out[215]= Sequence@81, 2, 3, 4, 5<, b, fD
In apparenza da solo non fa niente. L'abbiamo visto a proposito della programmazione, ed
effettivamente fa qualcosa... accoda fra di loro i suoi argomenti. Possiamo vederlo meglio qua:
In[216]:= f@a, b, Sequence@g, h, tD, gD
Out[216]= f@81, 2, 3, 4, 5<, b, g, h, 3, gD
L'utilità di questa funzione, però, si vede soprattutto quando dobbiamo andare a fare delle
sostituzioni. Si può vedere l'utilità (sempre se usato al momento giusto!!!) da questo esempio:
In[217]:= f@g@x, dD, g@f@g@f, g@hDD, u, rD, eDD ê. g → Sequence
Out[217]= f@x, d, f@f, h, u, rD, eD
Come abbiamo potuto vedere, possiamo appiattire varie funziono con Sequence. Il vantaggio rispetto
a Flatten è che possiamo farlo, usando i pattern alternativi, anche per più funzioni in una volta sola:
In[218]:= f@g@r, t, w@e, tD, u, g@f@g@t, yDD, yD, w@tDDD ê. Hw » gL → Sequence
Out[218]= f@r, 3, e, 3, u, f@3, yD, y, 3D
Lo svantaggio, invece, rispetto a Flatten, consiste nel fatto che se si appiattisce una funzione che
compare anche nell'head principale (cosa per cui è fatto Flatten), sostituisce anche quello:
In[219]:= f@f@c, rD, tD ê. f → Sequence
Out[219]= Sequence@c, r, 3D
E non è quello che vogliamo. Quindi, se bisogna appiattire più funzioni, tenendo sempre conto
dell'head, possiamo anche usarli in maniera combinata, appiattendo le funzioni con head uguale a
quello principale con Flatten, e gli altri con Sequence:
In[220]:= f@f@t, g@r, e, f@rDD, r, t, g@eDDD;
In[221]:= Flatten@%D ê. g → Sequence
Out[221]= f@3, r, e, f@rD, r, 3, eD
Notate come in questo caso permane all'interno della funzione un'altra annidata. Questo perchè,
come abbiamo visto prima, quando compare un'altra funzione con head diverso da quello usato da
Daniele Lupo Appunti di Mathematica
284Printed by Mathematica for Students
Flatten, il comando si interrompe. Da come è scritto il comando, Mathematica prima esegue la
funzione Flatten, quindi facendo restare la f residua, e dopo applica la sostituizione. Se vogliamo
invece che applichi prima la regola, dobbiamo sostituirla e metterla all'interno di Flatten, in modo
che lo scavalchi in precedenza il comando
In[222]:= Flatten@%% ê. g → SequenceD
Out[222]= f@3, r, e, r, r, 3, eD
Stavolta, prima abbiamo effettuato la sostituzione con Sequence, e poi abbiamo applicato Flatten,
quindi la f dentro la g stavolta era scoperta e il comando l'ha appiattita.
Adesso, dopo aver visto Flatten, ed averlo considerato coma proprietà associativa, vediamo come
possiamo considerare quella distributiva. Come? Qualcuno ha detto Distribute??? Spero di no, non
vorrei che foste giunti al punto che parlate da soli...
Comunque, distribute, come avete letto, fa proprio questo; nella sua forma più semplice, distribuisce
la funzione, avente come argomento una somma, fra gli addendi stessi:
In[223]:= Distribute@f@a + b + f + g + eDD
Out[223]= f@81 + b + e + f + g, 2 + b + e + f + g,3 + b + e + f + g, 4 + b + e + f + g, 5 + b + e + f + g<D
Esattamente quello che ci aspettavamo, vero?
In[224]:= Distribute@f@a, b, cDD
Out[224]= f@81, 2, 3, 4, 5<, b, cD
Sembra che questo non lavori con gli argomenti generici, ma guardate qua:
In[225]:= Distribute@f@a + b, c + d, e + fDD
Out[225]= f@81 + b, 2 + b, 3 + b, 4 + b, 5 + b<, c, eD +
f@81 + b, 2 + b, 3 + b, 4 + b, 5 + b<, c, fD +
f@81 + b, 2 + b, 3 + b, 4 + b, 5 + b<, d, eD +
f@81 + b, 2 + b, 3 + b, 4 + b, 5 + b<, d, fD
Come possiamo vedere, esegue la proprietà distributiva fra gli argomenti della funzione. Prima non
si vedeva perchè gli argomenti non erano somme. Effettivamente, nel primo esempio, il comando
eseguiva esattamente la stessa cosa, ma l'argomento era uno soltanto. Nel secondo, avevamo tre
argomenti, ciascuno però formato, possiamo dire, da un unico addendo, per cui il risultato era uguale
a prima. Nel terzo, invece, abbiamo visto la proprietà distributiva nel senso più generale, dove
compaiono più argomenti, ognuno somma di più addendi.
Daniele Lupo Appunti di Mathematica
285Printed by Mathematica for Students
Quindi, Distribute viene eseguito di default sulla somma o, più in generale, nelle espressioni con
head Plus. Adesso, vorremmo definire questa proprietà anche per altre funzioni; naturalmente
possiamo farlo, esplicitando di quale funzione stiamo parlando, naturalmente:
In[226]:= Distribute@f@g@a, bD, g@c, dDD, gD
Out[226]= g@f@81, 2, 3, 4, 5<, cD, f@81, 2, 3, 4, 5<, dD, f@b, cD, f@b, dDD
In questo caso abbiamo dichiarato che g, pur non essendo definita, gode della proprietà distributiva,
e Mathematica si è comportato di conseguenza.
In[227]:= Distribute@f@g@a, bD, g@a, b, cDD, gD
Out[227]= g@f@81, 2, 3, 4, 5<, 81, 2, 3, 4, 5<D, f@81, 2, 3, 4, 5<, bD,f@81, 2, 3, 4, 5<, cD, f@b, 81, 2, 3, 4, 5<D, f@b, bD, f@b, cDD
Qua vediamo come si comporta bene, anche se gli argomenti sono in numero diverso. D'altronde, la
proprietà distributiva permette, per definizione, di non tener conto del numeri degli argomenti della
funzione. Un uso più avanzato si può avere anche considerando di sostituire gli head:
In[228]:= Distribute@f@g@a, bD, g@c, dDD, g, f, nuovaf, nuovagD
— General::spell1 : Possible spelling error: new symbolname "nuovag" is similar to existing symbol "nuovaf". More…
Out[228]= nuovaf@nuovag@81, 2, 3, 4, 5<, cD,nuovag@81, 2, 3, 4, 5<, dD, nuovag@b, cD, nuovag@b, dDD
In questo caso, non solo abbiamo sfruttato la proprietà distributiva, ma abbiamo anche cambiato gli
head con quelli nuovi. Questa manipolazione è, effettivamente, abbastanza inusuale, e serve
principalmente per effettuare operazioni con funzioni predefinite che non consentirebbero di fare.
Però credo che la userete veramente poco, indipendentemente da quanto diventerete bravi con
Mathematica.
Uno degli ultimi comando che analizziamo in questa sezione (non manca molto, coraggio!) è quello
che permette di 'infilare' una funzione fra le altre, cioè Thread:
In[229]:= Thread@f@8a, b<, 8c, d<DD
Out[229]= 8f@81, 2, 3, 4, 5<, cD, f@b, dD<
In pratica, abbiamo delle liste di argomenti, e tramite il comando Thread siamo in grado di
trasportare la f all'interno delle liste, permettendo quindi di valutare la funzione avendo come
argomento gli elementi delle liste.
Daniele Lupo Appunti di Mathematica
286Printed by Mathematica for Students
In[230]:= Thread@f@8a, b<, 8c, d<, f, 8t, y<DD
Out[230]= 8f@81, 2, 3, 4, 5<, c, f, 3D, f@b, d, f, yD<
Come possiamo vedere in questo esempio, notiamo come le costanti vengano sempre ripetute nei
vari pattern. Questa è la caratteristica con cui possiamo dare in pasto a molte fiunzioni predefinite
delle liste:
In[231]:= Sin@81, 2, 3, 4<D
Out[231]= 8Sin@1D, Sin@2D, Sin@3D, Sin@4D<
Vediamo come abbiamo fatto agire il seno ad ogni elemento della lista
In[232]:= Thread@f@81, 2, 3, 4<D, ListD
Out[232]= 8f@1D, f@2D, f@3D, f@4D<
Per l'esattezza, questo è il modo in cui le funzioni predefinite in Mathematica agiscono quando gli
diamo come argomento delle liste; possiamo anche fare in modo che funzionino in questa maniera
funzioni che hanno bisogno di più argomenti:
In[233]:= Thread@f@81, 2, 3, 4<, 8a, b, c, d<D, ListD
Out[233]= 8f@1, 81, 2, 3, 4, 5<D, f@2, bD, f@3, cD, f@4, dD<
Come possiamo vedere, abbiamo preso il primo argomento dalla prima lista, ed il secondo dalla
seconda lista. Anche questo metodo è standard per le funzioni di Mathematica:
In[234]:= BesselI@81, 2, 3, 4<, 8a, b, c, d<D
Out[234]= 88BesselI@1, 1D, BesselI@1, 2D, BesselI@1, 3D, BesselI@1, 4D,BesselI@1, 5D<, BesselI@2, bD, BesselI@3, cD, BesselI@4, dD<
Questo modo di combinare gli argomenti è molto pulito: tuttavia a volte ci serve qualcosa di più
efficace, come creare funzioni che abbiamo tutte le combinazioni fra primo e secondo argomento,
invece di prendere in considerazione soltanto le coppie ordinate: primo con il primo, secondo con il
secondo e così via. Per ottenere tutte le combinazioni ci vuole Outer:
In[235]:= Outer@f, 8a, b, c, d<, 81, 2, 3<D
Out[235]= 888f@1, 1D, f@1, 2D, f@1, 3D<, 8f@2, 1D, f@2, 2D, f@2, 3D<,8f@3, 1D, f@3, 2D, f@3, 3D<, 8f@4, 1D, f@4, 2D, f@4, 3D<,8f@5, 1D, f@5, 2D, f@5, 3D<<, 8f@b, 1D, f@b, 2D, f@b, 3D<,
8f@c, 1D, f@c, 2D, f@c, 3D<, 8f@d, 1D, f@d, 2D, f@d, 3D<<
Daniele Lupo Appunti di Mathematica
287Printed by Mathematica for Students
Notiamo che, dato che esegue tutte le combinazioni possibili, e non li ordina in sequenza, non è più
necessario in questo caso che le liste siano di lunghezza uguale. D'altronde, Outer funziona anche se
non tratto liste, ma espressioni con lo stesso head:
In[236]:= Outer@f, g@a, b, c, dD, g@1, 2, 3DD
Out[236]= g@g@f@81, 2, 3, 4, 5<, 1D, f@81, 2, 3, 4, 5<, 2D, f@81, 2, 3, 4, 5<, 3DD,g@f@b, 1D, f@b, 2D, f@b, 3DD,g@f@c, 1D, f@c, 2D, f@c, 3DD, g@f@d, 1D, f@d, 2D, f@d, 3DDD
Otteniamo esattamente la stessa cosa, e magari possiamo accorgercene meglio così:
In[237]:= % ê. g → List
Out[237]= 88f@81, 2, 3, 4, 5<, 1D, f@81, 2, 3, 4, 5<, 2D, f@81, 2, 3, 4, 5<, 3D<,8f@b, 1D, f@b, 2D, f@b, 3D<,8f@c, 1D, f@c, 2D, f@c, 3D<, 8f@d, 1D, f@d, 2D, f@d, 3D<<
Come vedete, i risultati sono identici...
Riconsideriamo Outer:
In[238]:= Outer@f, 8a, b<, 8c, d<D
Out[238]= 888f@1, cD, f@1, dD<, 8f@2, cD, f@2, dD<, 8f@3, cD, f@3, dD<,8f@4, cD, f@4, dD<, 8f@5, cD, f@5, dD<<, 8f@b, cD, f@b, dD<<
E vediamo adesso il suo duale, Inner:
In[239]:= Inner@f, 8a, b<, 8c, d<D
Out[239]= f@b, dD + f@81, 2, 3, 4, 5<, cD
Vediamo, in questo caso, un comportamento simile a Thread (mentre prima era simile a Distribuite).
Però fa anche qualcosa in più:
In[240]:= Inner@f, 8a, b<, 8c, d<, gD
Out[240]= g@f@81, 2, 3, 4, 5<, cD, f@b, dDD
In questo caso abbiamo anche specificato l'head principale, mentre nel casi di Thread avevamo per
forza di cose una lista di risultati. Quindi è più generale, e si può anche usare al posto di Thread, dato
che il risultato, se hanno i medesimi argomenti, è uguale.
Daniele Lupo Appunti di Mathematica
288Printed by Mathematica for Students
Funzioni pure
Le funzioni pure sono un aspetto abbastanza avanzato in Mathematica, specificato quando
occorrono usi particolari. Se appresi bene, permettono di risolvere problemi scrivendo molto meno,
anche se in genere il codice risulerà alquanto criptico, dato che si fa uso di simboli, anche se, come
tutto il resto, si possono scrivere come funzioni:
Function[x, body] una funzione pura in cui x è sostituitadall'argomento voluto
Function[{x1, x2, … }, body] una funzione pura con più argomenti
body & una funzione pura i cui argomenti sono indicati da# oppure (se sono più di uno) da #1, #2, #3, etc.
Le funzioni pure hanno il compito di usare delle definizioni di funzioni, senza che sia stata definita
la funzione stessa. Per esempio, se ci occorre una funzione a due argomenti, che sarebbe definita
come il prodotto di due funzioni note ognuna avente un argomento, potremmo scrivere così:
In[241]:= f@x_, y_D := q@xD w@yD
Per ora, tuttavia cominciamo a considerare il caso di un solo argomento:
In[242]:= Clear@fD
In[243]:= f@x_D := q@xD w@xD
Una volta definita la funzione, possiamo utilizzarla dove più ci serve:
In[244]:= Map@f, a + b + v + d + eD
Out[244]= 83@1 + b + d + e + vD w@1 + b + d + e + vD,3@2 + b + d + e + vD w@2 + b + d + e + vD, 3@3 + b + d + e + vD w@3 + b + d + e + vD,3@4 + b + d + e + vD w@4 + b + d + e + vD, 3@5 + b + d + e + vD w@5 + b + d + e + vD<
Tuttavia possiamo anche evitare di utilizzare la definizione, ed utilizzare direttamente il corpo della
funzione:
In[245]:= Map@q@#D w@#D &, a + b + v + d + eD
Out[245]= 83@1 + b + d + e + vD w@1 + b + d + e + vD,3@2 + b + d + e + vD w@2 + b + d + e + vD, 3@3 + b + d + e + vD w@3 + b + d + e + vD,3@4 + b + d + e + vD w@4 + b + d + e + vD, 3@5 + b + d + e + vD w@5 + b + d + e + vD<
In questo caso particolare, abbiamo definito la funzione pura utilizzando il modo abbreviato; prima
abbiamo definito il corpo della funzione, che è dato dal prodotto delle altre due. Come argomento
abbiamo utilizzato quello delle funzioni pure, che è rappresentato da #. Dopo aver definito il corpo,
Daniele Lupo Appunti di Mathematica
289Printed by Mathematica for Students
abbiamo fatto capire a Mathematica che si tratta di una funzione pura, facendolo seguire dal simbolo
&, che rappresenta la fine della definizione del corpo della funzione. Tuttavia, potevamo anche
utilizzare la forma esplicita:
In[246]:= Map@Function@x, q@xD w@xDD, a + b + v + d + eD
Out[246]= 83@1 + b + d + e + vD w@1 + b + d + e + vD,3@2 + b + d + e + vD w@2 + b + d + e + vD, 3@3 + b + d + e + vD w@3 + b + d + e + vD,3@4 + b + d + e + vD w@4 + b + d + e + vD, 3@5 + b + d + e + vD w@5 + b + d + e + vD<
Ottenendo, in questa maniera, lo stesso risultato. Notate come adesso gli argomenti debbano essere
chiamati (e non siano definiti coma pattern x_, ma solo con il nome x), e che il primo modo di
scriverlo sia più breve.
Function@x, q@xD w@xDD rappresenta soltanto il corpo della funzione, che corrisponderebbe al suo head.
Infatti abbiamo sostituito l'intera espressione dove, normalmente, ci starebbe soltanto l'head. se
vogliamo calcolarla esplicitamente, dobbiamo usare la seguente notazione:
In[247]:= Function@x, q@xD w@xDD@argD
— General::spell1 : Possible spelling error: newsymbol name "arg" is similar to existing symbol "Arg". More…
Out[247]= 3@argD w@argD
Come potete vedere, in contesti di uso 'normale' della funzione questo metodo di scrittura è poco
pratico, ed è sicuramente meglio definirci prima la funzione. Anche se a volte è meglio usare le
funzioni pure anche in questo caso, se la funzione la utilizzeremo soltanto una volta, perchè
altrimenti dovremo scrivere ogni volta tutto quanto, invece di un semplice nome mnemonico.
Inoltre, anche come abbiamo visto per le funzioni normali, possiamo prendere in considerazione gli
argomenti della funzione pura, singoli oppure in sequenza:
# il primo argomento della funzione pura
#n l'argomento n-simo della funzione pura
## la sequenza di tutte le variabili nella funzione pura
##n la sequenza di tutti gli argomento in sequenza apartire dall' n-simo
È importante non sottovalutare la potenza delle funzioni pure, anche se rappresentano operazioni
semplici. Per esempio, possiamo facilmente scrivere qualcosa del tipo:
In[248]:= Clear@yD
Daniele Lupo Appunti di Mathematica
290Printed by Mathematica for Students
In[249]:= Map@# Sin@#^2D &, 8a, v, b, d, r, y<D
Out[249]= 88Sin@1D, 2 Sin@4D, 3 Sin@9D, 4 Sin@16D, 5 Sin@25D<,v Sin@v2D, b Sin@b2D, d Sin@d2D, r Sin@r2D, y Sin@y2D<
Se non avessimo avuto le funzioni pure, avremmpo dovuto prima definire una funzione che facesse
quello che volevamo, dato che, per dire, semplicemente l'espressione di #^2 sarebbe stata difficile da
implementare direttamente in Map, dato che richiede un head, e Power richiede due argomenti.
Notiamo anche che l'operatore & che definsce la funzione pura ha una precedenza piuttosto bassa nel
calcolo, per cui possiamo tranquillamente definire funzioni pure senza l'uso delle parentesi, come nel
caso #1 + #2 &.
Possono essere utili, per esempio, nella costruzione di tavole e di array:
In[250]:= Array@# Log@#D &, 8D
Out[250]= 80, 2 Log@2D, 3 Log@3D, 4 Log@4D, 5 Log@5D, 6 Log@6D, 7 Log@7D, 8 Log@8D<
Ed ecco veloce veloce la tabellina delle elementari...
In[251]:= Array@#1 #2 &, 810, 10<D êê TableForm
Out[251]//TableForm=1 2 3 4 5 6 7 8 9 102 4 6 8 10 12 14 16 18 203 6 9 12 15 18 21 24 27 304 8 12 16 20 24 28 32 36 405 10 15 20 25 30 35 40 45 506 12 18 24 30 36 42 48 54 607 14 21 28 35 42 49 56 63 708 16 24 32 40 48 56 64 72 809 18 27 36 45 54 63 72 81 9010 20 30 40 50 60 70 80 90 100
Vediamo come l'uso permetta, effettivamente, di snellire parecchie operazioni, permettendoci di
scrivere meno codice.
Per esempio, possiamo selezionare in maniera più specifica e potente parti di un'espressione,
utilizzando le funzioni:
Select[list, f] seleziona gli elementi della lista se f restituisce TrueSelect@expr, f , nD si limita a restituire i primi n elementi
della lista che soddisfano la funzione
Con questo comando, e con le funzioni pure, possiamo selezionare velocemente parti della lista o di
un'espressione in generale:
Daniele Lupo Appunti di Mathematica
291Printed by Mathematica for Students
In[252]:= lista = 82, 4, 6, r, h, hj, 47, 2, 46, 1<;
In[253]:= Select@lista, # < 20 &D
Out[253]= 82, 4, 6, 2, 1<
In[254]:= Array@# &, 1000D;
In[255]:= Select@%, PrimeQ@# + Floor@Sqrt@#DDD &D
Out[255]= 81, 2, 5, 10, 14, 19, 26, 32, 37, 41, 47, 52, 54, 60, 65, 71, 75, 88, 92,94, 98, 103, 117, 126, 128, 138, 140, 145, 151, 155, 161, 167, 178,180, 184, 186, 197, 209, 213, 215, 219, 226, 236, 242, 248, 254, 261,265, 267, 277, 290, 294, 296, 300, 314, 320, 329, 331, 335, 341, 349,355, 364, 370, 378, 382, 390, 401, 411, 413, 419, 423, 429, 437, 442,446, 458, 466, 470, 478, 482, 487, 499, 501, 519, 525, 534, 540,546, 548, 554, 564, 570, 577, 583, 589, 593, 595, 607, 617, 619,623, 628, 634, 636, 648, 652, 658, 666, 683, 693, 701, 707, 713,717, 725, 730, 734, 742, 746, 760, 770, 782, 793, 795, 799, 801,811, 825, 829, 831, 835, 848, 852, 854, 858, 878, 882, 890, 907,911, 917, 923, 937, 941, 947, 953, 966, 978, 982, 988, 990, 1000<
In quest'ultimo esempio abbiamo prima, con le funzioni pure, creato un array contenente i primi
1000 numeri interi, e poi con Select abbiamo effettuato il test verificando quali elementi della lista
sono in grado di soddisfare il test (che verifica se una manipolazione di un elemento della lista
risulta essere un numero primo). Notate ancora una volta come abbiamo utilizzato il corpo di una
funzione, nel posto dove a tutti gli effetti dovrebbe starci un head. È questa la potenza principale in
cui risiedono le funzioni pure, permettendovi (ripeto di nuovo per chi si fosse appena collegato) di
scrivere meno codice soprattutto se utilizzate raramente la funzione.
Definizioni di espressioni e funzioni
Vediamo adesso, un poco più in dettaglio, come e cosa fare quando creiamo delle definizioni, siano
esse di funzioni, oppure di variabili.Abbiamo già visto come si creano le definizioni:
In[256]:= x = Binomial@20, 3D
Out[256]= 1140
E che adesso, ogni volta che andremo a scrivere il nome della variabile, userà sempre il valore
memorizzato (anche per l'ordinamento, come abbiamo visto):
In[257]:= Gamma@xD êê Short
Out[257]//Short= 4430884292303290357649371404 2933 0000000000000000000000000000
Daniele Lupo Appunti di Mathematica
292Printed by Mathematica for Students
Abbiamo anche visto che, esattamente come in ogni linguaggio di programmazione, possiamo anche
modificarli, una volra definiti:
In[258]:= x = 4
Out[258]= 4
In[259]:= x
Out[259]= 4
In[260]:= x = x^2 + 1
Out[260]= 17
In[261]:= x
Out[261]= 17
E, se vogliamo che diventino solamente incognite senza nessun contenuto, dobbiamo cancellarlo:
In[262]:= x =.
Oppure
In[263]:= Clear@xD
Clear, in particolar modo, funziona anche con le definizioni delle funzioni.
Possiamo inoltre definire più variabili contemporaneamente, se devono contenere lo stesso valore:
In[264]:= q = w = e = r = 13;
In[265]:= Print@q, " ", w, " ", e, " ", rD
13 13 13 13
Possiamo anche definire con un unico comando più variabili con valori diversi, utilizzando le liste:
In[266]:= 8q, w, e< = 841, 54215, 42<;
In[267]:= Print@q, " ", w, " ", eD
41 54215 42
Daniele Lupo Appunti di Mathematica
293Printed by Mathematica for Students
Come nella maggior parte dei linguaggi di programmazione odierni, possiamo modificare il
contenuto della variabile con una sintassi coincisa, presa direttamente dal C:
x++ incrementa il valore di x di 1
x-- decrementa il valore di x di 1
++x pre-incremento di x
--x pre-decremento di x
x+= dx somma di all'attuale valore di x
x -= dx sottrare dx dall'attuale valore di x
x *= c moltiplica x con c
x /= c divide x con c
Come potete vedere, sono esattamente i comandi che si usano in C per scrivere meno codice.
Supposto:
In[268]:= x = 5;
Possiamo incrementarlo mediande:
In[269]:= x++
Out[269]= 5
In[270]:= x
Out[270]= 6
In[271]:= ++x
Out[271]= 7
In[272]:= x
Out[272]= 7
Come potete vedere, l'incremento lavora in maniera differente, a seconda se consideriamo
l'incremento oppure il pre-incremento, esattamente come succede in C. Nella prima operazione,
infatti, l'incremento viene applicato 'dopo' che viene usata la variabile per l'operazione corrente.
Quindi, prima ha dato in output il contenuto della variabile, e poi l'ha incrementata, come si può
vedere che, dopo il comando, ha valore pari a 6.
Invece, il pre-incremento, 'prima' effettua l'incremento della variabile di un'unità, e dopo esegue
l'operazione assegnata. Infatti, ++x prima incrementa x, e poi lo manda all'output, come abbiamo
Daniele Lupo Appunti di Mathematica
294Printed by Mathematica for Students
potuto vedere. Bisogna fare attenzione a questo diverso modo di procedere di questi comandi, che
altrimenti sarebbero equivalenti:
In[273]:= x = y = 3;
In[274]:= x++ + 5
Out[274]= 8
In[275]:= ++y + 5
Out[275]= 9
Come avete capito, utilizzare l'uno oppure l'altro ha differenti effetti sulle operazioni, di cui bisogna
tenere conto specialmente nella programmazione.
Le altre forme, invece, sono modi abbreviati di scrivere assegnamenti:
In[276]:= x = y = 10;
In[277]:= x += 5
Out[277]= 15
Vediamo che il valore di x viene aggiornato. Questo è equivalente a scrivere:
In[278]:= y = y + 5
Out[278]= 15
L'operazione eseguita è la stessa. Analogamente succede con le altre tre operazioni fondamentali:
In[279]:= x = 6;
In[280]:= x ê= 100
Out[280]=3
50
E così via...
Sappiamo anche come realizzare definizioni delle funzioni:
In[281]:= f@x_D := x^3 Sin@xD
Daniele Lupo Appunti di Mathematica
295Printed by Mathematica for Students
Abbiamo, in questo caso, definito una semplic funzione:
In[282]:= f@tD
Out[282]= 27 Sin@3D
In[283]:= f@7D êê N
Out[283]= 225.346
In[284]:= f@7D = 5
Out[284]= 5
In[285]:= f@7D
Out[285]= 5
Cos'è successo, stavolta? f @7D non restituisce più lo stesso risultato di prima. Questo perchè abbiamo
assegnato ESPLICITAMENTE un valore alla funzione quando è presente l'argomento pari
esattamente a 7:
In[286]:= f@5D := 3
In[287]:= f@5D
Out[287]= 3
Vediamo che possiamo usare in questo caso entrambe le assegnazioni, anche se io preferisco mettere
sempre = . Definire valori espliciti ha particolare significato specialmente per le funzioni ricorsive,
in quanto impongono delle condizioni di terminazione:
In[288]:= g@1D = 1;
In[289]:= g@x_D := 3 Sin@g@x − 1DD
In[290]:= g@5D
Out[290]= 3 Sin@3 Sin@3 Sin@3 Sin@1DDDD
Supponiamo, di dimenticarsi di definire la condizione di terminazione:
In[291]:= gg@x_D := 3 Sin@gg@x − 1DD
Daniele Lupo Appunti di Mathematica
296Printed by Mathematica for Students
In[292]:= gg@5D;
— $RecursionLimit::reclim : Recursion depth of 256 exceeded. More…
Ho deciso di non visualizzare il risultato perchè sarebbe troppo lungo: comunque Mathematica
restituisce un messaggio d'errore, dicendo che la profondità massima della ricorsione è stato
raggiunto, ed il calcolo si è fermato. Può capitare, però, anche se la funzione è chiamata
legittimamente, se la profondità di ricorsione supera quella consentita:
In[293]:= g@300D;
— $RecursionLimit::reclim : Recursion depth of 256 exceeded. More…
In questo caso, occorre aumentare la profondità della ricorsione, modificando il valore originale
nella variabile corrispondente:
In[294]:= $RecursionLimit = 330;
In[295]:= N@g@300D, 23D
— N::meprec : Internal precision limit $MaxExtraPrecision = 49.99999999999999`reached while evaluating 3 Sin@3 Sin@3 Sin@3 Sin@ 1 DDDD. More…
Out[295]= 2.313705137424
Come potete vedere, possiamo alzare facilmente i limiti di calcolo di Mathematica, modificando le
opporune variabili di sistema. Ovviamente, questo va fatto solamente se è strettamente necessario,
mi raccomando!!!
I valori standard valgono anche per funzioni a più variabili. Supponiamo di definire, per esempio:
In[296]:= Clear@qD
In[297]:= q@x_Integer, y_D := Sin@x^2 yD BesselJ@x, yD
In[298]:= q@2, 9.6D
Out[298]= 0.153515
In questo caso, possiamo creare dei valori espliciti che modifichino la definizione della funzione
quando è presente un solo paramentro corrispondente ad un'espressione specificata:
In[299]:= q@2, x_D := x^2
Daniele Lupo Appunti di Mathematica
297Printed by Mathematica for Students
In[300]:= q@2, 9.6D
Out[300]= 92.16
In[301]:= q@2, 3D
Out[301]= 9
Possiamo vedere la definizione della funzione così creata:
In[302]:= ? q
Global`q
q@2, x_D := x2
q@x_Integer, y_D := Sin@x2 yD BesselJ@x, yD
Vediamo che le assegnazioni esplicite compaiono prima, perchè hanno precedenza sulla funzione
generica:
In[303]:= q@2, x_D =.
In[304]:= q@2, 3D
Out[304]= BesselJ@2, 3D Sin@12D
In questo caso, esattamente come per le variabili, abbiamo cancellato la definizione che avevamo
usato in precedenza:
In[305]:= ? q
Global`q
q@x_Integer, y_D := Sin@x2 yD BesselJ@x, yD
Come vediamo, adesso non compare più. Inoltre, quello che abbiamo detto vale anche per pattern
generici, non soltanto per argomenti; per esempio posso avere qualcosa come
In[306]:= Clear@f, gD
In[307]:= f@x_D := Sin@xD + 5
In[308]:= f@g@x_DD := Cos@xD
Daniele Lupo Appunti di Mathematica
298Printed by Mathematica for Students
In[309]:= ? f
Global`f
f@g@x_DD := Cos@xD
f@x_D := Sin@xD + 5
Options@fD = 8option1 → 12, option2 → 3, option3 → 1304<
Vedete come riconosco adesso un pattern generico specificato da me, e che inoltre posso anche
utilizzare l'uguaglianza 'ritardata'. Vedremo fra poco l'utilità di questa definizione esplicita con
quest'altro simbolo. Così, se Mathematica riconosce il pattern, esegue la sostituzione voluta:
In[310]:= f@rD
Out[310]= 5 + Sin@13D
In[311]:= f@g@rDD
Out[311]= Cos@13D
Vediamo come in quest'ultimo caso abbia riconosciuto correttamente il pattern dell'argomento.
Un altro modo per definire valori standard alle funzioni, e, soprattutto, utile quando dobbiamo
velocizzare calcoli ripetutti, è il seguente:
f[x_] := f[x] = rhs definisce una funzione che ricorda i valori che trova
Questo può essere più utile di quanto si pensi: Supponiamo di avere una funzione ricorsiva, scritta in
maniera poco efficiente, come per esempio la funzione per trovare il numero di Fibonacci:
In[312]:= fibo@x_IntegerD := fibo@x − 1D + fibo@x − 2D
Inizializziamo i due valori che terminano la ricorsività:
In[313]:= fibo@0D = fibo@1D = 1;
Vediamo che questi compaiono nella definizione della funzione:
Daniele Lupo Appunti di Mathematica
299Printed by Mathematica for Students
In[314]:= ? fibo
Global`fibo
fibo@0D = 1
fibo@1D = 1
fibo@x_IntegerD := fibo@x − 1D + fibo@x − 2D
Come sappiamo dai nostri studi di fondamenti di informatica (perchè saper programmare un poco è
una base indispensabile per ogni ingegnere, sappiatelo...). questa implementazione è estremamente
inefficiente, perchè il numero di volte che viene richiamata la funzione ricorsiva all'interno della
stessa cresce in maniera esponenziale al crescere dell'argomento:
In[315]:= Timing@fibo@37DD
Out[315]= 8128.609 Second, 39088169<
Supponiamo, adesso, di definire un'altra funzione di Fibonacci, equivalente a quella che abbiamo
appena scritto, ma implementandola nel modo appena visto:
In[316]:= fibo2@x_IntegerD := fibo2@xD = fibo2@x − 1D + fibo2@x − 2D
In[317]:= fibo2@0D = fibo2@1D = 1;
Vediamo la sua definizione:
In[318]:= ? fibo2
Global`fibo2
fibo2@0D = 1
fibo2@1D = 1
fibo2@x_IntegerD := fibo2@xD = fibo2@x − 1D + fibo2@x − 2D
Appare quasi equivalente a quella che abbiamo scritto prima. Tuttavia, adesso, guardate qua cosa
succede:
In[319]:= Timing@fibo2@37DD
Out[319]= 80. Second, 39088169<
Daniele Lupo Appunti di Mathematica
300Printed by Mathematica for Students
Mizzica, quanto abbiamo risparmiato!!! L'algoritmo usato era lo stesso inefficiente di prima, ma qua
addirittura il tempo si è praticamente azzerato!!!
Quello che è successo è semplice, in effetti. Invece di calcolare innumerevoli volte sempre gli stessi
valori della funzione per gli stessi argomenti (compariranno, per esempio, un tot volte
fibo2@3D, fibo2@5D e così via), calcoliamo il valore per un argomento una sola volta, e lo
memorizziamo come valore predefinito. In questo modo il numero di valutazioni della funzione che
dobbiamo fare cala esponenzialmente, valutandola soltanto 37 volte, invece che ay 37, come invece
ha fatto nel caso precedente. Se vediamo la deinizione di fibo2, vediamo che effettivamente
spuntano tutte le definizioni della funzione per tutti i valori preceddenti:
In[320]:= ? fibo2
Global`fibo2
fibo2@0D = 1
fibo2@1D = 1
fibo2@2D = 2
fibo2@3D = 3
fibo2@4D = 5
fibo2@5D = 8
fibo2@6D = 13
fibo2@7D = 21
fibo2@8D = 34
fibo2@9D = 55
fibo2@10D = 89
fibo2@11D = 144
fibo2@12D = 233
fibo2@13D = 377
fibo2@14D = 610
fibo2@15D = 987
fibo2@16D = 1597
fibo2@17D = 2584
fibo2@18D = 4181
Daniele Lupo Appunti di Mathematica
301Printed by Mathematica for Students
fibo2@19D = 6765
fibo2@20D = 10946
fibo2@21D = 17711
fibo2@22D = 28657
fibo2@23D = 46368
fibo2@24D = 75025
fibo2@25D = 121393
fibo2@26D = 196418
fibo2@27D = 317811
fibo2@28D = 514229
fibo2@29D = 832040
fibo2@30D = 1346269
fibo2@31D = 2178309
fibo2@32D = 3524578
fibo2@33D = 5702887
fibo2@34D = 9227465
fibo2@35D = 14930352
fibo2@36D = 24157817
fibo2@37D = 39088169
fibo2@x_IntegerD := fibo2@xD = fibo2@x − 1D + fibo2@x − 2D
Come possiamo vedere, abbiamo aggiunto, appena venivano calcolati per la prima volta, definizioni
per gli argomenti calcolati, in modo da usare risorse computazionali solamente una volta, e salvando
i risultati. Questo ha ovviamente, come abbiamo visto, un notevole vantaggio nel caso di algoritmi
ricorsivi, specialmente se inefficienti come questo, ma dobbiamo comunque ricordare che il tempo
risparmiato ha l'altra faccia della medaglia nella maggior memoria occupata, che per algoritmi e
funzioni più serie può rappresentare un problema. Occorre sempre decidere se spendere più tempo,
oppure se rischiare di bloccare il programma tentando un uso intensivo della memoria. In entrambi i
casi, vi consiglio sempre di salvare una copia di backup del file... Comunque, almeno per calcoli
tutto sommato semplici, e se avete un computer, non per forza dell'ultima generazione, ma almeno
attuale, con 512 MB di memoria almeno, potete sempre tentare questa strada se volete. Non credo
che vi capiteranno molti casi di blocco per mancanza di memoria.
Daniele Lupo Appunti di Mathematica
302Printed by Mathematica for Students
Possiamo applicare casi specifici anche quando, al posto di valori specifici, abbiamo particolari
pattern. Supponiamo, per esempio, di avere una generica funzione g, che però non è definita:
In[321]:= g@xD
Out[321]= gA 350
E
Lavoriamo, per semplificarci le cose, con un solo argomento, anche se quello che diciamo vale
anche per più argomenti della funzione. Così fatta, la nostra g non gode di nessuna proprietà
particolare. Tuttavia, vogliamo che goda della proprietà distributiva rispetto all'addizione. Per far
questo possiamo esplicitare direttamente il pattern da utilizzare:
In[322]:= g@x_ + y_D := g@xD + g@yD
Se andiamo a riscrivere un argomento generico, non cambia ancora niente:
In[323]:= g@f@rDD
Out[323]= g@5D + g@Sin@13DD
Però, se andiamo ad inserire un argomento con il pattern corrispondente, possiamo facilmente vedere
come applichi la proprietà che gli abbiamo imposto:
In[324]:= g@a + b + cD
Out[324]= g@81 + b + c, 2 + b + c, 3 + b + c, 4 + b + c, 5 + b + c<D
Notate come, anche se il pattern è con due addendi, la proprietà distributiva si applica a tutti gli
addendi. Questo perchè ho:
In[325]:= g@a + b + cD g@a + bD + g@cD g@aD + g@bD + g@cD
Out[325]= g@81 + b + c, 2 + b + c, 3 + b + c, 4 + b + c, 5 + b + c<Dg@cD + g@81 + b, 2 + b, 3 + b, 4 + b, 5 + b<D g@bD + g@cD + g@81, 2, 3, 4, 5<D
Come vedete, i tre modi di scrivere l'espressione sono equivalenti. Dal primo si arriva al secondo
caso ma, dato che il primo addendo ha ancora il pattern corrispondente, viene a sua volta riapplicata
la proprietà distributiva. Possiamo, adesso, anche definirla rispetto alla moltiplicazione:
In[326]:= g@x_ y_D := g@xD g@yD
Vediamo adesso:
Daniele Lupo Appunti di Mathematica
303Printed by Mathematica for Students
In[327]:= g@a b + c dD
Out[327]= g@8b + c d, 2 b + c d, 3 b + c d, 4 b + c d, 5 b + c d<D
Le proprietà e le forme particolari che abbiamo scritto vengono memorizzate nella definizione della
funzione, esattamente come per i valori espliciti:
In[328]:= ? g
Global`g
g@x_ + y_D := g@xD + g@yD
g@x_ y_D := g@xD g@yD
A questo punto, potete vedere come, applicando le giuste proprietà, possiamo creare una funzione
generica che si comporti esattamente come vogliamo noi, semplicemente andando ad applicare le
regole invece che una definizione, restituendo sempre il risultato corretto, anche se in forma
simbolica.
Abbiamo anche visto che, pur specificando un parametro, davamo in questo caso sempre una
funzione, per cui abbiamo divuto utilizzare := invece di = .
lhs = rhs rhs viene considerato il valore finale di lhs (e.g.,f[x_] = 1 - x^2)
lhs := rhs rhs restituisce un comando, oppure un programma,che deve essere eseguito quando inserisco un valoreper lhs (e.g., f[x_] := Expand[1 - x^2])
Un esempio utile per poter capire se la funzione è calcolata subito o quando viene chiamato il
programma, consiste nell'usare il comando Random:
In[329]:= a = Random@D; b = Random@D;
Quando chiamiamo i due numeri, otteniamo dei numeri casuali:
In[330]:= 8a, b<
Out[330]= 80.635399, 0.441706<
Se adesso li richiamiamo, riotteniamo gli stessi numeri:
Daniele Lupo Appunti di Mathematica
304Printed by Mathematica for Students
In[331]:= 8a, b<
Out[331]= 80.635399, 0.441706<
Questo perchè in a e b sono memorizzati non Random, ma il loro valore, cioè due numeri casuali
fissi: scriviamo, adesso, la seguente definizione, che usa l'altro simbolo:
In[332]:= a := Random@D; b := Random@D;
In questo caso, non memorizziamo subito un valore, ma la funzione Random viene valutata ogni
volta che a e b sono richiamati:
In[333]:= 8a, b<
Out[333]= 80.535825, 0.450193<
Se adesso li chiamiamo un'altra volta, le funzioni sono rivalutate ancora, dando quindi dei numeri
diversi:
In[334]:= 8a, b<
Out[334]= 80.595409, 0.634603<
Come potete vedere, tutto si è svolto come previsto. Questo è in genere anche vero se, nella
definizione, si vanno ad utilizzare delle funzioni che cambieranno man mano nel notebook: per
esempio:
In[335]:= Clear@f, g, hD
In[336]:= h@x_D := Sin@xD
In[337]:= f@x_D = h@x^2D
Out[337]= SinA 92500
E
In[338]:= g@x_D := h@x^2D
Le definizioni di f e g sembrano uguali:
In[339]:= f@4D
Out[339]= SinA 92500
E
Daniele Lupo Appunti di Mathematica
305Printed by Mathematica for Students
In[340]:= g@4D
Out[340]= Sin@16D
Supponiamo, adesso, di voler ridefinire la funzione h:
In[341]:= Clear@hD; h@x_D := Cos@xD
Vediamo come si comportano adesso le funzioni:
In[342]:= f@4D
Out[342]= SinA 92500
E
In[343]:= g@4D
Out[343]= Cos@16D
Come possiamo vedere, nel caso della f non cambia niente, perchè tutto era stato valutato nella
definizione: nel caso di g, invece, prima di calcolare la funzione nel punto 4, abbiamo valutato
l'espressione della funzione, e, dato che h era cambiato, l'espressione, ricalcolata dopo la modifica di
h risulta pure modificata di conseguenza. Nella maggior parte dei casi conviene utilizzare
l'assegnazione ritardata := anche perchè permette di modificare una funzione semplicemente
andando a modificarne una sua parte, cosa utile se, per esempio, la definizione è un programma con
molte sottofunzioni definite a parte
Regole di trasformazione
Come abbiamo visto anche prima, le regole di trasformazione sono un metodo abbastanza potente e
veloce per poter dotare le nostre funzioni di particolari proprietà, oltre che poter manipolare le
espressioni in maniera avanzata e personalizzata.
Alla luce di quanto imparato finora, tuttavia, come ad esempio i pattern, possiamo vedere nuove
potenzialità delle regole di trasformazione. Un esempio classico di trasformazione è la seguente:
In[344]:= Sin@x yD y xêz + z ê. x → z
Out[344]= z +9 Sin@ 9
10 D10 z
Possiamo anche creare, mediante pattern, altre modifiche, che comportino lo stesso cambiamento a
più parti dell'espressione aventi la stessa struttura:
Daniele Lupo Appunti di Mathematica
306Printed by Mathematica for Students
In[345]:= Sin@x yD y xêz + z ê. Hx » y » zL → Cos@xD
Out[345]= CosA 350
E +9
10SecA 3
50E SinA 9
10E
Le manipolazioni ottenibili sono parecchie.
Dato che tutto quanto possiede un nome, in quanto tutto può essere scritto sotto forma di
espressione, possiamo anche definire variabili che contengano regole di sistituzione:
In[346]:= regola = Sin@x_D → Cos@xD;
In[347]:= Sin@x^2D Sin@x + 1D ê. regola
Out[347]= CosA 350
E2
Inoltre, abbiamo anche visto come fare per effettuare sostituzioni ripetute:
In[348]:= a + b ê. 8a → b, b → c<
Out[348]= 0.409006
In questo caso, si vede che la b non è stata restituita correttamente, perchè applichiamo le definizioni
una volta sola. Se vogliamo che siano ripetute fino a quando l'espressione non varia più, dobbiamo
usare l'altra sintassi:
In[349]:= a + b êê. 8a → b, b → c<
Out[349]= 0.950903
Come potete vedere, in questo caso le sostituzioni vengono effettuate iterativamente.
Tuttavia, ci possono essere casi in cui le iterazioni non portano mai ad un'espressione che rimane
invariata, e questo ne è un esempio banalissimo:
In[350]:= a êê. 8a → b, b → c + a<
Out[350]= 0.852091
Se proviamo ad eseguire questo comando, Mathematica si blocca in un loop infinito. Possiamo usare
la forma completa del comando, aggiungendo un opzione che tenga conto del massimo numero di
iterazioni:
Daniele Lupo Appunti di Mathematica
307Printed by Mathematica for Students
In[351]:= ReplaceRepeated@a, 8a → b, b → c + a<, MaxIterations → 20D
Out[351]= 0.769572
In questo caso, vediamo che il programma ci restituisce un warning, dicendo che non è riuscito a
trovare l'espressione definitiva (quella, cioè, che non cambia più applicando le regole), entro il
numero di iterazioni previste, restituendo il risultato ottenuto con l'ultima iterazione. Questo, però, se
ben usato, può essere un modo per poter effettuare delle trasformazioni cicliche a delle espressioni
senza andare ad usare cicli Do e For, sempre, ovviamente, che si sa quello che si sta facendo, e
fregandosene del warning, che in questo caso non serve a niente.
Questo può essere vero anche quando, per esempio, si ha una lista di regole che trasformano uno
stesso pattern in espressioni diverse. In questo caso Mathematica applica solamente la prima che
trova:
In[352]:= a + b ê. 8x_ + y_ → x^y, _ + _ → c<
Out[352]= 1.5096
Si vede che prima applica la prima regola di sostituzione, poi, non essendo più il pattern una somma,
la seconda regola viene ignorata. Se vogliamo invece avere una lista che comprenda entrambe le
sostituzioni, possiamo usare il seguente comando:
ReplaceList[expr, rules] applica rules in tutti i modi possibili
Vediamo l'effetto di questo comando nell'espressione di prima:
In[353]:= ReplaceList@a + b, 8x_ + y_ → x^y, x_ + y_ → c<D
Out[353]= 8<
Vediamo che ha effettivamente applicato tutti i modi possibili di eseguire la lista di sostituzioni:
prima di tutto ha effettuato la prima regola, sfruttando il fatto che la somma è commutativa, quindi
a + b ã b + a, usando quindi entrambi i modi per scrivere la funzione: dopo ha eseguito nello stesso
modo la seconda regola, dando in entrambi i casi, come risultato, c. Naturalmente questo può essere
utile anche per espressioni più complicate:
In[354]:= espr = x y z + a b c + w e r;
In[355]:= ReplaceList@espr, 8x_ y_ → Sin@x yD, x_ + y_ → Cos@x yD<D
Out[355]= 9CosA 910
E, CosA 910
E, CosA 910
E, CosA 910
E, CosA 910
E, CosA 910
E=
Daniele Lupo Appunti di Mathematica
308Printed by Mathematica for Students
Vediamo che qualcosa non va. Infatti, sebbene applichi la seconda regola correttamente, non lo fa
altrettando per la prima:
In[356]:= TreeForm@esprD
Out[356]//TreeForm=
PlusA29601390, »[email protected], cD
, »TimesA »
Rational@9, 10D, zE
E
Il problema consiste nel fatto che ReplaceList agisce solamente, come Replace, nel primo livello.
Mentre però con Replace possiamo specificare la profondità di livello a cui applicare le sostituzioni,
non si fa altrettanto con ReplaceList, dato che il terzo argomento (opzionale) decide solamente il
massimo numero di elementi di cui deve essere composta la lista (che di default è Infinity). Per
applicare ReplaceList a qualsiasi profondità, dobbiamo inventarci la nostra funzione, che creiamo in
questo modo:
In[357]:= ReplaceAllList@expr_, rules_D := Module@8i<,Join@
ReplaceList@expr, rulesD,If@
AtomQ@exprD, 8<,Join @@ Table@ReplacePart@expr, #, iD & ê@ ReplaceAllList@
expr@@iDD, rulesD
, 8i, Length@exprD<D
DD
D
Module, vedremo più avanti, serve per creare una variabile locale, in questo caso i, che verrà usata
dalle espressioni e comandi successivi. Dopo di che, vediamo il funzionamento della funzione. Join
serve a concatenare liste fra di loro, oppure espressioni con lo stesso head. Il primo argomento di
Join è la lista ottenuta dal comando semplice ReplaceList. Come secondo argomento, invece,
abbiamo un'altra funzione.
L'If serve per vedere se l'espressione ha un solo livello. In caso affermativo, l'operazione è finita, e
restituisce una lista nulla che, unita a quella ottenuta in precedenza, da la lista come avremmo avuto
con ReplaceList. In caso contrario, invece, eseguiamo il terzo argomento del comando If.
Nel terzo argomento, applichiamo Join (@@ rappresenta, vi ricordo, il comando Apply), agli
elementi della lista ottenuta mediante Table. Quest'ultima lista sarà formata dall'espressione, con
l'i-simo elemento (del primo livello), con l'elemento stesso a cui è stata applicata la stessa funzione.
Come possiamo vedere, è una funzione ricorsiva.
Daniele Lupo Appunti di Mathematica
309Printed by Mathematica for Students
Quello che fa, in pratica, è questo: sostituisce il primo livello con ReplaceList; poi prende il primo
elemento, il primo elemento del primo elemento e così via ricorsivamente, fino all'ultimo livello. A
questo punto applica ReplaceList a questo elemento, e sale di un livello, applicando ReplaceList
pure a questo livello, e così via tornando su fino al primo livello. A questo punto ottengo una lista di
espressioni con tutte le sostituzioni del primo elemento, e passo al secondo.
In[358]:= TreeForm@esprD
Out[358]//TreeForm=
PlusA29601390, »[email protected], cD
, »TimesA »
Rational@9, 10D, zE
E
In questo caso, prima applico le regole al primo livello. Poi le applico al primo elemento del secondo
livello, e così via.
Da spiegare, effettivamente, è difficile (come lo sono molte funzioni ricorsive complicate), ma
imparare questo esempio, e capire come funziona serve a darvi un quadro generale su come funziona
Mathematica. Se capite questo esempio, vuol dire che siete già abbastanza bravi col programma.
Meglio non ve lo so spiegare, mi dispiace.
In[359]:= ReplaceAllList@espr, 8x_ y_ → Sin@x yD, x_ + y_ → Cos@x yD<D
Out[359]= 9CosA 910
E, CosA 910
E, CosA 910
E, CosA 910
E, CosA 910
E,
CosA 910
E, 29601390 +9 z10
+ SinA 910
E, 29601390 +9 z10
+ SinA 910
E,
29601390 + 0.214346 c + SinA 910
E, 29601390 + 0.214346 c + SinA 910
E=
Vediamo come ci siano più combinazioni rispetto a prima, anche se ancora non ci sono tutte quelle
disponibili (mancano, per esempio, quelle con Sin e Cos assieme nidificati). Dubito comunque che vi
servirete spesso di queste manipolazioni; per la maggior parte dei casi il primo livello basta e avanza
(altrimenti sicuramente Mathematica avrebbe avuto un comando per far meglio quello che abbiamo
appena fatto...).
Daniele Lupo Appunti di Mathematica
310Printed by Mathematica for Students
Attributi
Mediante gli attributi, siamo in grado di conferire particolari proprietà alle funzioni che andiamo a
definire. Questo è importante quando vogliamo attribuire particolari proprietà matematiche a delle
funzioni che, magari non sono definite, oppure se vogliamo che Mathematica applichi
automaticamente alcune trasformazioni e regole definite dalle proprietà della funzione. Tuttte le
funzioni predefinite di Mathematica hanno una serie di attributi che descrivono alcune delle loro
propietà:
Attributes[f] restituisce una lista contenente gli attributi di f
Attributes[f] = {attr1, attr2,… }
definisce degli attributi per f
Attributes[f] = {} togliamo ad f tutti i suoi attributi
SetAttributes[f, attr] aggiunge attr agli altri attributi della f
ClearAttributes[f, attr] rimuove attr dagli attributi della f
Se vediamo una qualsiasi funzione, vediamo i suoi attrributi:
In[360]:= Attributes@PlusD
Out[360]= 8Flat, Listable, NumericFunction, OneIdentity, Orderless, Protected<
Vediamo che restitusce una lista di attributi. Elenchiamo, adesso, i vari attributi, ed il loro significato:
Ł Ordeless: una funzione i cui argomenti possono scambiarsi di posizione. Saranno ordinati, per il
calcolo, in posizione standard.
Ł Flat: definisce una funzione associativa, passando, quindi, il comando Flatten ai suoi argomenti, se
la funzione viene chiamata come argomento di se stessa
Ł OneIdentity: nel matching dei pattern, f @ f @aDD, e così via, viene visto equivalente ad a
Ł Listable: la funzione viene automaticamente mappata nelle liste che compaiono come argomento;
quindi la funzione applicata ad una lista diventa la lista della funzione applicata ad ognuno degli
argomenti
Ł Constant: tutte le derivate della funzione sono nulle
Ł NumericFunction: si assume che la funzione restituisca un valore numerico, quando i suoi
argomenti sono pure quantità numeriche
Ł Protected: i valori della funzione non possono essere cambiati
Ł Locked: gli attributi della funzione non possono essere cambiati
Daniele Lupo Appunti di Mathematica
311Printed by Mathematica for Students
Ł ReadProtected: i valori della funzione non possono essere letti
Ł HoldFirst: il primo argomento della funzione non viene valutato
Ł HoldRest: tutti gli argomenti, tranne il primo, non vengono valutati
Ł HoldAll: nessuno degli argomenti della funzione vengono valutati
Ł HoldAllComplete: gli argomenti della funzione sono considerati completamente inerti
Ł NHoldFirst: al primo argomeno della funzione non viene applicato il comando N
Ł NHoldRest: a tutti gli argomenti della funzione, tranne che al primo, non viene applicato il comando
N
Ł NHoldAll: N non viene valutato in nessun argomento della funzione
Ł SequenceHold: gli oggetti Sequence che appaiono negli argomenti della funzione non vengono
appiattiti
Ł Temporary: la funzione viene trattata come variabile locare, venendo rimossa quando non è più
usata
Ł Stub: il comando Needs viene automaticamente chiamatato persino se la funzione ha un input
esplicito
Se adesso, andiamo a rivedere gli attributi della funzione Plus, possiamo vedere che è Flat, cioè che
gode della proprietà associativa:
In[361]:= Plus@a, Plus@b, cDD êê FullForm
Out[361]//FullForm= [email protected]`, cD
Vediamo che è Listable, quindi che viene mappata nelle liste:
In[362]:= Plus@8a, b, c<, 8d, e, f<D êê FullForm
Out[362]//FullForm= List@[email protected]`, dD, 42.11352905166384`, Plus@c, fDD
Gode dell'attributo NumericFunction, quindi, se ha quantità numeriche come argomenti, la funzione
viene definita quantità numerica:
In[363]:= NumericQ@Plus@4, 7, 4DD
Out[363]= True
Daniele Lupo Appunti di Mathematica
312Printed by Mathematica for Students
Ha anche l'attributo OneIdentity, cioè gode dell'identità nel pattern matching
In[364]:= Plus@Plus@aDD === a
Out[364]= False
Viene attribuito a questa funzione l'attributo Ordeless, che fa godere alla funzione la proprietà
commutativa:
In[365]:= Plus@n, f, u, aD êê FullForm
Out[365]//FullForm= [email protected]`, f, uD
Notate come, avendo questo attributo, gli argomenti vengono automaticamente riordinati.
Infine, come capita per tutte le funzioni predefinite di Mathematica, gode dell'attributo Protected,
che impedisce di modificare la funzione, a meno che non si specifichi diversamente in maniera
esplicita:
In[366]:= Plus@3, 5, 3D = 5
— Set::write : Tag Plus in 3 + 3 + 5 is Protected. More…
Out[366]= 5
Supponiamo di voler dare delle particolari proprietà ad una funzione, senza definirla per forza; per
esempio, vogliamo che una generica funzione f sia associativa e commutativa:
In[367]:= SetAttributes@f, 8Orderless, Flat<D
Vediamo se funziona:
In[368]:= f@v, d, c, y, tD
Out[368]= f@3, 15, c, d, vD
In[369]:= f@a, f@v, bDD
Out[369]= [email protected], 0.671335, vD
Uao!!!!!!!! E neanche sappiamo cosa sia la f !!!
Come potete vedere, riusciamo in questa maniera a definire particolari proprietà per una funzione
generica, che magari viene difficile oppure impossibile da definire con le corrispondenze fra
Daniele Lupo Appunti di Mathematica
313Printed by Mathematica for Students
argomenti e pattern, che abbiamo visto sopra. Per esempio, in questa maniera è estremamente più
semplice applicare l'attributo per la proprietà commutativa, che andare a creare una regola
complicata (che comunque abbiamo visto prima), per l'ordinamento degli argomenti della funzione.
ü Programmazione avanzata
Introduzione
In questa sezione affrontiamo alcuni aspetti particolari della programmazione, che non abbiamo
ancora visto. Sebbene quello che già sapete dovrebbe bastarvi, per alcuni casi (cresceranno in
numero, man mano che diventerete più bravi), occorre porre particolare attenzione a quello che si fa,
e trovare modi per sbrigarsela e risolvere problemi noti in programmazione classica, come, ad
esempio, quello dello scoping delle variabili definite...
Visibilità di variabili locali
Ogni volta che andiamo a definire qualsiasi espressione, funzione etc, vengono considerati come
variabili globali; cioè, una volta che sono definite potete utilizzarle in qualsiasi punto del vostro
lavoro. Potete anche definire una funzione in un notebook, se volete, ed andarla ad utilizzare in un
altro notebook, senza doverla riscrivere, dato che sarà già in memoria.
Tuttavia, come ogni ragazzo per bene che abbia programmato qualcosa di più del famigerato "Hello
World!" che vi insegnano sempre, non è buona cosa, nei programmi, affidarsi alle variabili locali.
Questo è vero anche in Mathematica, specialmente quando si devono definire dei programmi,
oppure delle funzioni un poco più complicate. Per esempio, supponete di dover utilizzare un ciclo
For all'interno di una funzione. Dovete definire un iteratore ma, se caricate la funzione da qualche
altra parte, niente vi dice che il nome usato per l'iteratore non sia già stato utilizzato, incasinandovi le
cose anche di parecchio. Per questo è importante il concetto di visibilità, sia delle variabili che di
tutto il resto: d'altronde, come avrete capito, in Mathematica 'tutto' è un espressione....
Come tutti sapete, uno degli ambiti principali in cui viene applicata la visibilità consiste nella
definizione delle variabili locali. Supponete di avere qualcosa del genere:
In[370]:= i = 3; i = i^3 + t; i = i^3 + t
Out[370]= 27003
In[371]:= fun@x_D := For@i = 0; y = 0, i < 20, i++, y = y + x^iD
In[372]:= fun@500D
Daniele Lupo Appunti di Mathematica
314Printed by Mathematica for Students
In[373]:= y
Out[373]= 1911170974762024048096192384769539078156312625250501
In[374]:= i
Out[374]= 20
Vediamo che il valore della variabile i, che abbiamo usato all'interno della funzione, ha modificato il
valore della i che se ne stava fuori per i fatti suoi. Effettivamente, dato che parliamo di variabili
globali, per Mathematica sono la stessa identica variabile. Però, probabilmente, non vogliamo che
questo succeda, perchè la i che avevamo definito conteneva un espressione che magari ci serviva per
effettuare vari calcoli, mentre quella della funzione non conteneva informazioni, ma era solamente
un indice per poter effettuare una determinata funzione. Per cui, non vogliamo che siano la stessa
cosa.
Quando però si comincia a creare un notebook che superi il paio di schermate, diventa difficile
ricordarsi ciò che avevamo definito, quello che avevamo cancellato e così via. Inolte, potremmo
voler memorizzare questa funzione in un package personale, da richiamare quando vogliamo, e
potremmo non ricordarci più che all'interno era stata ridefinita la variabile i, complicandoci la
situazione.
La soluzione a questo problema, naturalmente, c'è, ed è data dal seguente comando:
Module[{x, y, … }, body] un blocco contenente le variabili locali x, y, …
Module, in altre parole, definisce una porzione di programma, di funzione o di qualsiasi altra cosa, in
cui si definiscono delle variabili locali. A questo punto, le eventuali variabili globali avente lo stesso
nome di quelle locali vengono preservate e non vengono modificate, ma vengono modificate le
rispettive variabili locali. Inoltre, non appena si esce dal blocco, le variabili sono cancellate.
Ripetiamo l'esempio di prima, utilizzando questa volta le variabili locali:
In[375]:= i = 3; i = i^3 + t; i = i^3 + t
Out[375]= 27003
In[376]:= fun@x_D := Module@8i<,For@i = 0; y = 0, i < 20, i++, y = y + x^iD
D
In[377]:= fun@500D
Daniele Lupo Appunti di Mathematica
315Printed by Mathematica for Students
In[378]:= y
Out[378]= 1911170974762024048096192384769539078156312625250501
In[379]:= i
Out[379]= 27003
Vediamo che abbiamo ottenuto lo stesso risultato, e che, inoltre, il valore della variabile i che si
trova fuori dal blocco non viene modificato. Questo perchè, all'interno del blocco stesso, la i
utilizzata era quella locale, non quella globale. Guardando più attentamente il codice ed il risultato,
notiamo però un'altra cosa: la variabile y continua ad essere vista come variabile globale. Infatti, al
di fuori del blocco ha lo stesso valore di quello che ha all'interno. Questo perchè non l'avevamo
definita esplicitamente come variabile locale, rimanendo quindi, a tutti gli effetti, una variabile
globale. Quindi, se avevamo in precedenza definito già la y, il suo valore verrebbe comunque
riscritto. Bisogna stare attenti, quindi, a definire come locale tutto quello che ci serve, perchè
capiterà di salvare delle funzioni e dei programmi, poi di ricaricarli e riutilizzarli altre volte senza
che ci preoccupiamo di come l'abbiamo fatte, e sapendo solo il risultato che danno.
Vi lascio come esercizietto la modifica alla funzione, che vi permetta di definire anche la y come
variabile locale, ma che, una volta chiamata la funzione, invece di non restituire niente, restituisca
direttamente il valore calcolato. Ormai sapete farlo sicuramente, e fidatevi che è una cavolata!!! Ma
d'altronde, dovete sbatterci almeno una volta la vostra fida testolina, no?
Inotre, all'interno della lista delle variabili locali, potete direttamente porre un valore di
inizializzazione, se vi serve:
In[380]:= Module@8x, i = 0<, x = i + 12; i = x ∗ 234D
Out[380]= 2808
In[381]:= i
Out[381]= 27003
Daniele Lupo Appunti di Mathematica
316Printed by Mathematica for Students
Notate come i sia rimasto ancora invariato....
Inoltre, potete anche definire dei blocchi dove compaiano delle costanti, invece che delle variabili:
With[{x = x0, y = y0, … }, body] definisce delle costanti locali x, y, …
Rispetto ai linguaggi di programmazione normali, però, le costanti non devono essere per forza
associate ad un numero, ma possono essere anche delle espressioni:
In[382]:= With@8q = t + 23<, Sin@qDD
Out[382]= Sin@26D
Visto in un certo modo, possiamo considerare questo comando come l'equivalente di /. quando
andiamo a scrivere dei programmi, che permette di sostituire ad opportune variabili quello che
vogliamo, se presenti nel blocco.
Naturalmente questi blocchi possono anche essere nidificati fra loro; in questo caso le variabili locali
che si useranno saranno quelle definite nello stesso blocco: se non sono definite nello stesso blocco,
saranno le variabili locali del blocco immediatamente superiore e così via:
In[383]:= Module@8i = 5<,Module@8i = 4<,
Module@8i = 3<, Print@iDD;Print@iD
D;Print@iDD
3
4
5
In questo esempio, si procede con ordine. Scorrendo il flusso di programma, il primo comando Print
che incontriamo si trova nel blocco più interno; in questo blocco la variabile locale i è pari a 3, ed è
questo il valore che viene stampato. Dopo, si incontra il secondo Print, che è conenuto nel blocco
Module dove la variabile i è inizializzata a 4, e viene stampato questo valore. Infine, l'ultimo Print si
trova nel blocco dove i vale 5, stampando il corrispondente valore.
Volendo, però, potremmo vedere in un blocco nidificato il valore di una variabile globale, o locale
definita in un blocco superiore, anche se una variabile locale nel nostro blocco ne mina la visibilità.
Infatti, Mathematica, nel risolvere le variabili locali, le rinomina:
Daniele Lupo Appunti di Mathematica
317Printed by Mathematica for Students
In[384]:= Module@8i<,Module@8i<,
Module@8i<, Print@iDD;Print@iD
D;Print@iDD
i$105
i$104
i$103
Come potete vedere, ogni variabile è rinominata in maniera univoca, venendo numerata. possiamo,
quindi, utilizzare questa numerazione per accedere direttamente alle variabili che ci interessano.
Tuttavia non si fa mai (almeno io non l'ho mai fatto), perchè, come potete notare, la numerazione
non parte dall'inizio, ma dipende da quando si è chiamato il blocco etc. Il mio consiglio è quello di
utilizzare nomi diversi per variabili che vi servono in diversi blocchi annidati, anche perchè in questo
caso potrete dargli nomi più sensati, e che non variano a seconda di quando e dove si richiama la
funzione oppure il programma.
E, mentre con Module possiamo trattare i nomi delle variabili come locali, con Block possiamo
trattarne soltanto i valori:
Block[{x, y, … }, body] calcola body usando valori locali per x, y, …
Block[{x = x0, y = y0, …}, body]
assegna valori iniziali ad x, y, …
In apparenza questo blocco si comporta come Module:
In[385]:= x = 20; y = 30;
In[386]:= Block@8x = 4, y = 5<, x + yD
Out[386]= 9
In[387]:= x
Out[387]= 20
In[388]:= y
Out[388]= 30
Daniele Lupo Appunti di Mathematica
318Printed by Mathematica for Students
Tuttavia bisogna notare un'importante differenza concettuale. Module rende univoci i nomi delle
variabili, mentre Block rende univoci i valori.
Abbiamo visto che, all'interno di Module, le variabili sono rinominate, assumento un altro nome.
Questo è importante quando si pensa di utilizzare espressioni definite fuori dai blocchi, che
contengono il nome delle variabili. consideriamo, per esempio, la seguente espressione:
In[389]:= es = a + Cos@bD;
In[390]:= a = 30; b = 50;
Se vogliamo utilizzare questa espressione all'interno di un blocco, dobbiamo stare attenti. Verrebbe
da usare Module, ma ciò sarebbe sbagliato:
In[391]:= Module@8a = 3, b = 4<, esD
Out[391]= 0.627023
Come possiamo vedere, il risultato non viene modificato: ma, in fondo, non deve stupirci più di
tanto, perchè nella valutazione di es non utilizziamo i valori definiti con Module, perchè abbiamo
visto che corrispondono a qualcosa coma x$15. Allora Mathematica, non riconoscendo il nome delle
veriabili di es definite all'interno del blocco, usa quelle globali, che erano state definite prima, per il
calcolo dell'espressione. Per poter utilizzare l'espressione con valori locali, occorre che le variabili
locali definite all'interno del blocco abbiano lo stesso nome di quelle globali, ed a questo pensa
Block:
In[392]:= Block@8a = 3, b = 4<, esD
Out[392]= 0.627023
In questo caso vediamo che i nomi sono rimasti quelli, mentre abbiamo assunto come locali i valori
assunti. Infatti, nonostante il risultato sia corretto, dal punto di vista globale i valori delle variabili
non sono cambiati:
In[393]:= 8a, b<
Out[393]= 830, 50<
Occorre prestare attenzione, nella progettazione dei programmi, quale dei due blocchi è più consono
all'utilizzo che se ne vuole fare, utilizzando di volta in volta quello che semplifica maggiormente le
cose.
Daniele Lupo Appunti di Mathematica
319Printed by Mathematica for Students
PackagesVediamo adesso alcuni packages, predefiniti in Mathematica, che potrebbero essere particolarmente
utili per risolvere particolari problemi (per esempio, disegnare diseguaglianze, o tracciare diagrammi
di Bode, che hanno scale logaritmiche).
Di solito i packages vengono trascurati, e ci si concentra solamente sulle funzioni predefinite in
Mathematica. Questo di certo non è male, per chi ci mette mano per la prima volta, tuttavia
trascurare i package secondo me rappresenta un grave errore; si pensa che si tratti solamente di
comandi aggiuntivi di poca importanza, e che la sostanza è in Mathematica stessa. Questo è vero e
falso allo stesso tempo: vero perchè i packages sono scritti nel linguaggio standard di Mathematica,
e quello che fanno lo potete fare anche voi definendo le vostre funzioni: falso perchè per
implementare una funzione di quelle definite nei packages occorrerebbero pagine e pagine di codice,
che fortunatamente qualcun altro ha già scritto per noi. Non si tratta solamente di orpelli, ma ci sono
molti comandi che possono veramente semplificare la vita di chi utilizza Mathematica. Sono certo
che fra i vari package ce ne saranno almeno un paio che troverete invitanti, e che non abbandonerete.
Capisco che la prima cosa che si deve fare è imparare ad usare il programma ma, una volta imparato,
imparare i comandi dei package (mica tutti: l'help serve anche per trovare quello che cercate in un
dato momento), vi permette di fare cose che altrimenti, diciamocela tutta, non sapreste fare.
Non li elencherò tutti, perchè sono troppi, ma quelli che reputo utili (o che almeno mi sono serviti)
sono tutti qua; considero anche il fatto che, pur essendo solamente alcuni, sono già parecchi, per cui
avrete di che sperimentare ed imparare fino alla laurea ed oltre... Ovviamente appena finito di
leggere queste pagine dovete correre a leggervi l'help per scoprire gli altri!!!!
Comunque, cominciamo:
üAlgebra`AlgebraicInequalities`In[1]:= << Algebra`InequalitySolve`
Questo package contiene una funzione utilizzata per risolvere una disequazione (oppure un sistema
di disequazioni):
InequalitySolve[expr, x] trova i valori di x che soddisfano l'espressionecontenente operatori logici e disuguaglianze algebriche
InequalitySolve[e x p r,{x1, x2, … }]
trova i valori di xi che soddisfano le diseguaglianze
Daniele Lupo Appunti di Mathematica
320Printed by Mathematica for Students
Supponiamo di avere la seguente espressione:
In[2]:= diseguaglianza = x^2êH1 + xL < 5
Out[2]=x2
1 + x< 5
In[3]:= InequalitySolve@diseguaglianza, xD
Out[3]= x < −1 »» 12H5 − 3 è!!!5 L < x <
12H5 + 3 è!!!5 L
Come potete vedere, abbiamo ottenuto la soluzione che volevamo.
Un sistema di diseguaglianze viene scritto come un'unica equazione, dove le varie parti del sistema
sono legate fra di loro dall'operatore AND:
In[4]:= sistema =
yêx > H4 x^3 + yLêHx − yL && x < y^2
Out[4]=yx
>4 x3 + yx − y
&& x < y2
In[5]:= InequalitySolve@sistema, 8x, y<D
Out[5]= Hx < 0 && y < xL »» H0 < x ≤ 1 && y > è!!!x L »» Hx > 1 && y > xL
Abbiamo utilizzato le soluzioni desiderate, sotto forma di condizioni per le incognite.
Come potete vedere, questo comando è molto potente, anche se funziona soltanto con equazioni
polinomiali:
In[6]:= InequalitySolve@Exp@xD < 1 + x, xD
— InequalitySolve::npi : A nonpolynomial equationor inequality encountered. The solution set may be incorrect.
Out[6]= False
Come potete vedere, non possiamo ottenere gli intervalli, in questo caso.
Daniele Lupo Appunti di Mathematica
321Printed by Mathematica for Students
üAlgebra`ReIm`Questo package permette di lavorare meglio con funzioni complesse, estraendone parte reale ed
immaginaria senza dover utilizzare ComplexExpand.
Vediamo, per esempio, questa espressione:
In[7]:= Re@xêyD
Out[7]= ReA xyE
Vediamo che rimane non valutata. Andiamo, adesso, a caricare il package:
In[8]:= << Algebra`ReIm`
In[9]:= Re@xêyD
Out[9]=Im@xD Im@yD
Im@yD2 + Re@yD2 +Re@xD Re@yD
Im@yD2 + Re@yD2
Come si vede, questa volta Mathematica esplicita direttamente la parte reale ed immaginaria dei
simboli, evitando comandi come ComplexExpand. Tuttavia, se specifichiamo un simbolo come reale
o come immaginario, senza dover specificare il simbolo esplicitamente:
In[10]:= y ê: Re@yD = 0;
In[11]:= Re@xêyD
Out[11]=Im@xDIm@yD
Come vedere, con il package abbiamo calcolato il valore considerando l'assunzione che avevamo
fatto.
Daniele Lupo Appunti di Mathematica
322Printed by Mathematica for Students
üAlgebra`RootIsolation`Con questo package possiamo avere funzioni per gestire meglio il conteggio e l'isolamento di
soluzioni di equazioni polinomiali:
CountRoots[poly, {x,m1, m2}]
restituisce il numero delle soluzioni di polynell'intervallo complesso {m1, m2}
RealRootIntervals[poly] restituisce gli intervalli disgiunti che isolano le radicireali di poly
RealRootIntervals[{poly1,poly2, … }]
restituisce gli intervalli disgiunti che isolani le radicireali delle equazioni poly1, poly2, …
ComplexRootIntervals[poly] restituisce gli intervalli disgiunti che isolano lesoluzioni complesse di poly
ComplexRootIntervals[{poly1
, poly2, … }] indovinate cosa fa??? Per i polinomi poly1, poly2, …
ContractInterval[a, n] restituisce un intervallo isolante che circonda il valoredel numero algebrico a fino alla precisione di almeno ncifre significative
Si possono eseguire delle operazioni sui polinomi e scoprire proprietà sulle loro radici senza bisogno
di andare a trovarle esplicitamente. Per esempio:
In[12]:= << Algebra`RootIsolation`
In[13]:= CountRoots@Hx − 4L Hx^4 + 3 x − 6L, 8x, −5, 5<D
Out[13]= 3
Abbiamo visto che nell'intervallo specificato si trovano tre soluzioni, senza averle calcolate:
In[14]:= CountRoots@x^9 + 1, 8x, 0, 1 + I<D
Out[14]= 2
Come vedete, funziona anche per intervalli complessi.
Consideriamo ancora la prima espressione, e fediamo gli intervalli delle soluzioni reali:
In[15]:= RealRootIntervals@H−4 + xL H−6 + 3 x + x4LD
Out[15]= 88−3, 0<, 81, 2<, 82, 6<<
Questi sono, per l'appunto, intervalli disgiunti, ognuno contentente una radice reale del polinomio.
Analogamente possiamo realizzarli per le soluzioni immaginarie:
Daniele Lupo Appunti di Mathematica
323Printed by Mathematica for Students
In[16]:= ComplexRootIntervals@x^9 + 1D
Out[16]= 98−2, 0<, 9−32
−32
, −34=, 9−
32, −
34
+32
=, 9−34
−32
, 0=, 9−34, 3
2=,
9−32
, 34=, 90, 3
4+32
=, 9 34
−32
, 32=, 9 3
4, 3
2+32
==
Possiamo anche specificare un intervallo piccolo a piacere per una soluzione:
In[17]:= ContractInterval@Root@x^9 + 1, 2D, 20D
Out[17]= 9−5652410316521256710973786976294838206464
−189717416474225563087295147905179352825856
,
−452192825321700536871590295810358705651712
−379434832948451126173590295810358705651712
=
In[18]:= N@%, 20D
Out[18]= 8−0.76604444311897803520 − 0.64278760968653932632 ,−0.76604444311897803520 − 0.64278760968653932632 <
Come potete vedere, possiamo ottenere l'approssimazione che vogliamo.
Daniele Lupo Appunti di Mathematica
324Printed by Mathematica for Students
üCalculus`FourierTransform`Questo package contiene alcune funzioni che sono l'equivalente numerico dei comandi per la
trasformata di Fourier predefinite in Mathematica:
NFourierTransform[expr,t, w]
restituisce un approssimazione numerica dellatrasformata di Fourier di expr valutata nel valorenumerico w, mentr expr è considerata funzione di t
NInverseFourierTransform[expr, w, t]
restituisce un approssimazione numerica dellatrasformata inversa di Fourier di expr valutata nel valorenumerico t, mentr expr è considerata funzione di w
NFourierSinTransform[expr,t, w]
restituisce un approssimazione numerica dellatrasformata in seno di Fourier di expr valutata nel valorenumerico w, mentr expr è considerata funzione di t
NInverseFourierSinTransform[expr, w, t]
frestituisce un approssimazione numerica dellatrasformata inversa in seno di Fourier di expr valutata nelvalore numerico t, mentr expr è considerata funzione di
NFourierCosTransform[expr,t, w]
restituisce un approssimazione numerica dellatrasformata in coseno di Fourier di expr valutata nelvalore numerico w, mentr expr è considerata funzione di
NInverseFourierCosTransform[expr, w, t]
restituisce un approssimazione numerica dellatrasformata inversa in cosenodi Fourier di expr valutatanel valore numerico t, mentr expr è considerata funzione
Supponiamo di avere la seguente espressione:
In[19]:= espr = Exp@−Abs@t^3DDêH1 + Abs@tDL;
In[20]:= Timing@FourierTransform@espr, t, wDD
Out[20]= 921.422 Second, FourierTransformA−Abs@tD3
1 + Abs@tD , t, wE=
Come potete vedere, in questo caso non è in grado di calcolare la trasformata di questa funzione, fra
l'altro dopo un tempo neanche breve per il programma. Allora, se ci interessa comunque la
trasformata, per esempio in w = 10, possiamo utilizzare la funzione del packge:
In[21]:= << Calculus`FourierTransform`
In[22]:= Timing@NFourierTransform@espr, t, 10DD
Out[22]= 80.016 Second, 0.00716034 + 0. <
Daniele Lupo Appunti di Mathematica
325Printed by Mathematica for Students
Come potete vedere, non solo abbiamo trovato la soluzione che ci interessava, ma abbiamo anche
risparmiato un sacco di tempo...
In[23]:= Plot@Evaluate@Abs@NFourierTransform@espr, t, ωDDD, 8ω, −8, 8<,PlotStyle → [email protected], [email protected]<,Frame → True,PlotLabel → "Trasformata numerica di Fourier per espr"D
-7.5 -5 -2.5 0 2.5 5 7.50
0.1
0.2
0.3
0.4
0.5Trasformata numerica di Fourier per espr
Out[23]= Graphics
Come potete vedere, non è poi molto importante il non poter calcolare analiticamente la funzione, a
meno che non dobbiate scriverlo sul quaderno, ovvio...
Il vantagigo di questo comando, rispetto alla trasformata numerica predefinita in Mathematica, è
che, mentre quest'ultima lavora solamente con liste di dati, quella definira nel package invece lavora
su funzioni, il che specialmente in calcoli teorici è un bel vantaggio.
Oltre che per la trasformata generale, il pacchetto offre anche funzioni per lavorare con le funzioni
periodiche e con la serie di Fourier:
Daniele Lupo Appunti di Mathematica
326Printed by Mathematica for Students
FourierCoefficient[expr,t, n]
restituisce l' n-simo coefficiente nell'espansione in serieesponenziale della funzione periodica in t uguale adexpr nell'intervallo t=- 1ÅÅÅÅ2 , t= 1ÅÅÅÅ2
FourierSinCoefficient[expr,t, n]
restituisce l' n-simo coefficiente nell'espansione inserie del seno
FourierCosCoefficient[expr,t, n]
restituisce l' n-simo coefficiente nell'espansione inserie del coseno
FourierSeries[expr, t, k] restituisce la serie esponenziale fino all'ordine kdella funzione periodica in t uguale ad exprnell'intervallo t=- 1ÅÅÅÅ2 , t= 1ÅÅÅÅ2
FourierTrigSeries[expr,t, k]
restituisce l'espansione in serie trigonometricafino all'ordine k
Supponiamo di avere la classica onda quadra:
In[24]:= p1 = Plot@Hx − Round@xDLê Abs@x − Round@xDD, 8x, −2, 2<D
-2 -1 1 2
-1
-0.5
0.5
1
Out[24]= Graphics
Sviluppiamo adesso i primi quattro termini della serie di Fourier: dato che l'intervallo preso in
considerazione dal comando è compreso in H- 1ÅÅÅÅ2 , 1ÅÅÅÅ2 L, non abbiamo bisogno di specificare il Round, e
basta scrivere:
In[25]:= FourierTrigSeries@Abs@tDêt, t, 5D
Out[25]=4 Sin@2 π tD
π+4 Sin@6 π tD
3 π+4 Sin@10 π tD
5 π
Vediamo che effettivamente rappresenta quello che volevamo:
Daniele Lupo Appunti di Mathematica
327Printed by Mathematica for Students
In[26]:= Plot@%, 8t, −2, 2<, PlotStyle → [email protected], 0.6, 0.7D<D
-2 -1 1 2
-1
-0.5
0.5
1
Out[26]= Graphics
In[27]:= Show@p1, %D
-2 -1 1 2
-1
-0.5
0.5
1
Out[27]= Graphics
Come potete vedere, l'espansione trigonometrica (troncata) rappresenta effettivamente l'espansione
in serie di Fourier. Possiamo anche trovarci la serie esponenziale, se vogliamo:
In[28]:= FourierSeries@Abs@tDêt, t, 5D
Out[28]=2 −2 π t
π−2 2 π t
π+2 −6 π t
3 π−2 6 π t
3 π+2 −10 π t
5 π−2 10 π t
5 π
Naturalmente, possono capitare casi in cui non è possibile risolvere simbolicamente l'espansione in
serie:
Daniele Lupo Appunti di Mathematica
328Printed by Mathematica for Students
In[29]:= Clear@esprD
In[30]:= espr@t_D := Cos@Cos@tDD
In[31]:= FourierTrigSeries@espr@tD, t, 3D
Out[31]= ‡− 1
2
12
Cos@Cos@tDD t + 2 Cos@2 π tD ‡− 1
2
12
Cos@2 π tD Cos@Cos@tDD t +
2 Cos@4 π tD ‡− 1
2
12
Cos@4 π tD Cos@Cos@tDD t +
2 Cos@6 π tD ‡− 1
2
12
Cos@6 π tD Cos@Cos@tDD t
Possiamo comunque ottenere la serie con coefficienti numerici, se non riusciamo a trovare i
sombolici:
NFourierCoefficient[expr,t, n]
restituisce l'approssimazione numerica dell'n-simo coefficiente nell'espansione in serie
NFourierSinCoefficient[expr, t, n]
restituisce l'approssimazione numerica dell'n-simo coefficiente nell'espansione in serie seno
NFourierCosCoefficient[expr, t, n]
restituisce l' approssimazione numerica dell'n-simo coefficiente nell' espansione in serie coseno
NFourierSeries[expr, t, k] trova l'espansione in serie esponenziale, di ordine k,con coefficienti numerici
NFourierTrigSeries[expr,t, k]
trova l'espansione in serie trigonometrica, di ordine k,con coefficienti numerici
Vediamo di risolvere il problema di poco fa in termini numerici:
In[32]:= NFourierTrigSeries@espr@tD, t, 3D
Out[32]= 0.574072 − 0.0405754 Cos@2 π tD + 0.00954455 Cos@4 π tD −
0.00419166 Cos@6 π tD + 0. Sin@2 π tD + 0. Sin@4 π tD + 0. Sin@6 π tD
Notate anche che, se avete espressioni comunque convertibili, nella stragrande maggioranza dei casi
la soluzione numerica si trova MOLTO più velocemente di quella simbolica, per cui, per espressioni
complicate, usatela solo se vi serve veramente.
Inoltre, potremmo avere funzioni periodiche, ma con un periodo diverso da 1, per cui il periodo non
sarà più contenuto in H- 1ÅÅÅÅ2 , 1ÅÅÅÅ2 L. Per ovviare a ciò, dobbiamo modificare i parametri di Fourier. Per
esempio, se ho:
Daniele Lupo Appunti di Mathematica
329Printed by Mathematica for Students
In[33]:= Hf = 3 + Sqrt@Abs@Sin@xDDD + Cos@3 xD;Plot@f, 8x, −7, 7<DL
-6 -4 -2 2 4 6
2.5
3
3.5
4
4.5
5
Out[33]= Graphics
In[34]:= FindMinimum@f, 8x, −4<D
— FindMinimum::lstol : The line search decreased the step size to within tolerance specified by
AccuracyGoal and PrecisionGoal but was unable to find a sufficientdecrease in the function. You may need more than MachinePrecisiondigits of working precision to meet these tolerances. More…
Out[34]= 82.00009, 8x → −3.14159<<
Possiamo vedere (nonostante il warning, dovuto al fatto che abbiamo un piccolo problema di
convergenza, perchè il minimo è una cuspide), che il periodo è fra -p e p, per cui dobbiamo far
sapere al comando che questi sono i nuovi limiti; per far questo si utilizza l'opzione Fourier-
Parameters, modificando i parametri necessari:
Daniele Lupo Appunti di Mathematica
330Printed by Mathematica for Students
c o m m o n
convention setting d i s c r e t e
F o u r i e rinverse discrete Fourier transform
Mathematicadefault
{0, 1} 1ÅÅÅÅÅÅÅÅÅn1ê2 ‚r=1
nur
e2 p i Hr-1L Hs-1Lên
1ÅÅÅÅÅÅÅÅÅn1ê2 ‚s=1
nvs e-2 p i Hr-1L Hs-1Lên
data analysis {-1, 1} 1ÅÅÅÅn ‚r=1
nur
e2 p i Hr-1L Hs-1Lên⁄s=1
n vs e-2 p i Hr-1L Hs-1Lên
s i g n a lprocessing
{1, -1} ⁄r=1n ur
e-2 p i Hr-1L Hs-1Lên
1ÅÅÅÅn ‚s=1
nvs e2 p i Hr-1L Hs-1Lên
general case {a, b} 1ÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅnH1-aLê2
‚r=1
nur
e2 p i b Hr-1L Hs-1Lên
1ÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅnH1+aLê2 ‚s=1
nvs e-2 p i b Hr-1L Hs-1Lên
setting Fourier coefficient inverse Fourier coefficient
{0, 1} Ÿ-1ê21ê2
f HtL e2 p i n t „t ⁄n=-¶¶ Fn e-2 p i n t
{a, b} †b§H1-aLê2 Ÿ-1êH2 †b§L1êH2 †b§L f
HtL e2 p i b n t „t
†b§H1+aLê2 ⁄n=-¶¶ Fn e-2 p i b n t
Nel nostro caso abbiamo:
In[35]:=
Chop@NFourierTrigSeries@f, x, 5,FourierParameters → 80, 2 Pi<,AccuracyGoal → 8, PrecisionGoal → 8
DD
Out[35]= è!!!!!!!2 π H1.667 − 0.0315571 Cos@4 π2 xD −
0.00730143 Cos@8 π2 xD − 0.00562131 Cos@12 π2 xD −
0.0027441 Cos@16 π2 xD − 0.0025366 Cos@20 π2 xDL
Come potete vedere, abbiamo usato lo stesso comando, specificando però il periodo della funzione
trigonometrica aggiustando i parametri tramite l'opzione apposita.
Inoltre, in questo package sono definite anche funzioni per la trasformata di Fourier di sequenze
numeriche, quindi funzioni definite negli interi, per variabile discretizzata:
Daniele Lupo Appunti di Mathematica
331Printed by Mathematica for Students
DTFourierTransform[expr,n, omega]
restituisce F HwL, una funzione periodica in w, ugualealla sommatoria di Fourier di expr, considerata funzionedegli interi n
InverseDTFourierTransform[expr, omega, n]
restituisce fn, una funzione di interi n definita comeinversa della sommatoria di Fourier F HwL, dove F HwLè uguale ad expr nell'intervallo w= -1ÅÅÅÅÅÅÅÅ2 to w= 1ÅÅÅÅ2
NDTFourierTransform[expr,n, omega]
trova un'approssimazione numerica per F HwL
NInverseDTFourierTransform[expr, omega, n]
trova un'approssimazione numerica per fn
qua otteniamo una trasformata periodica di una sequenza
In[36]:= dtft = DTFourierTransform@Sum@DiscreteDelta@3 n + jD, 8j, −1, 1<D, n, ωD
Out[36]= 1 + − 23 π ω +
2 π ω3
In[37]:= Plot@Abs@dtftD, 8ω, −4, 4<D
-4 -2 2 4
0.5
1
1.5
2
2.5
3
Out[37]= Graphics
Possiamo effettiare la trasformata inversa numerica:
Daniele Lupo Appunti di Mathematica
332Printed by Mathematica for Students
In[38]:= Chop@Table@NInverseDTFourierTransform@dtft, ω, n, AccuracyGoal → 8, PrecisionGoal → 8D,8n, −5, 5<
DD
Out[38]= 80.00738387, −0.0115663, 0.0206748, −0.0472568, 0.206748, 2.65399,0.206748, −0.0472568, 0.0206748, −0.0115663, 0.00738387<
Anche in questo caso, possiamo aggiustare i
parametri:
setting d i s c r e t e - t i m e
Fourier transform inverse discrete-time Fourier coefficient
{0, 1} ⁄n=-¶¶ fn e2 p i n w Ÿ-1ê2
1ê2 F HwL e-2 p i n w „w
{a, b} †b§H1-aLê2
⁄n=-¶¶ fn e2 p i b n w
†b§H1+aLê2 Ÿ-1êH2 †b§L1êH2 †b§L F HwL e-2 p i b n w „w
üCalculus`VectorAnalysis`Questo package è destinato a studiare sistemi e funzioni vettoriali, specialmente nel caso
tridimensionale, permettendo di eseguire complicate analisi con semplici comandi.
Prima di tutto, dobbiamo considerare le funzioni che permettono di definire il tipo di sistemi di
coordinate: oltre a quelle cartesiane, infatti, sono presenti altri tipi di coordinate, come quelle
sferiche, che rappresentano meglio un determinato campo vettoriale perchè, data la sua simmetria, le
equaizioni in quel sistema di coordinate appaiono semplici. Possiamo specificare sia il tipo di
coordinate, sia il nome delle variabili che rappresentano le coordinate nelle tre direzioni (in senso
generale, dato che non si parla più di assi a seconda del sistema di coordinate):
CoordinateSystem restituisce il nome del sistema di coordinate corrente
Coordinates[ ] restitusce le variabili di default che rappresentanol'attuale sistema di coordinate
Coordinates[coordsys] restituisce i simboli per le coordinate di defaultdel sistema di coordinate coordsys
SetCoordinates[coordsys] pone come sistema di coordinate di default coordsyscon le sue variabili di default
SetCoordinates[coordsys[vars]]
pone come sistema di coordinate di default coordsyscon le variabili poste pari a vars
Per poter vedere come funziona questo package, ovviamente dobbiamo prima caricarlo...
Daniele Lupo Appunti di Mathematica
333Printed by Mathematica for Students
In[39]:= << Calculus`VectorAnalysis`
A questo punto, vediamo il sistema di coordinate di default:
In[40]:= CoordinateSystem
Out[40]= Cartesian
In[41]:= Coordinates@D
Out[41]= 8Xx, Yy, Zz<
Come potete vedere, di default il package pone il sistema di coordinate cartesiano. Possiamo
assegnare vari tipi di coordinate:
Bipolar HbipolariL Bispherical HbisfericheLCartesian HcartesianeL ConfocalEllipsoidal Hellissoidali confocaliLConfocalParaboloidalHparaboloidi confocaliL
Conical HconicheL
Cylindrical HcilindricheL EllipticCylindrical Hcilindriche ellitticheLOblateSpheroidal Hsferiche schiacciateL ParabolicCylindrical Hcilindriche paraboloidiLParaboloidal HparaboloidiL ProlateSpheroidal Hsferiche allungateLSpherical HsfericheL Toroidal HtoroidaliL
Come potete vedere, ce n'è veramente per tutti i gusti... vediamo un poco di spiegare cosa
rappresentano:
In[42]:=
ø Cartesian[x, y, z] rappresenta il sistema di coordinate standard rettangolare tridimensionale.
ø Cylindrical[r, theta, z] rappresenta il sistema di coordinate cilindrico, con coordinate
polari r, q per rappresentare il piano x y, e l'asse z a rappresentare l'altezza.
ø Spherical[r, theta, phi] rappresenta il sistema di coordinate sferico, dove r rappresenta la
distanza dall'origine, q rappresenta l'angolo misurato a partire dall'asse z positivo, e f rappresenta
l'angolo misurato nel piano x y, in senso antiorario a partire dall'asse x positivo.
ø ParabolicCylindrical[u, v, z] è un sistema di coordinate dove il piano x y è
rappresentato da u, v: mantenendo costante un parametro e variando l'altro si ottengono due parabole
opposte, dove nel fuoco comune passa l'asse z
Daniele Lupo Appunti di Mathematica
334Printed by Mathematica for Students
ø Paraboloidal[u, v, phi] rappresenta il sistema di coordinate paraboloico: come prima,
variando uno fra u, v si ottengono due parabole opposte con fuoco comune. Inoltre, f rappresenta
l'angolo di rotazione di questo piano rispetto alla bisettrice delle due parabole.
ø EllipticCylindrical[u, v, z, a] è un sistema di coordinate tridimensionale,
parametrizzato da a, e rappresenta un sistema di coordinate simile a quello cilindrico, dove però,
mantenendo costante u, nel piano al variare di v si producono delle ellissi, mentre variando u si
ottengono delle iperboli. In ambeue i casi il fuochi sono distanziati da 2 a, mentre z definisce la
distanza dall'asse dei fuochi comuni. a di default assume valore pari ad 1.
ø ProlateSpheroidal[xi, eta, phi, a] è simile al caso precedente, ma il piano delle ellissi
ruota, rispetto all'asse che connette i due fuochi, di un angolo f. Anche in questo caso il valore di
default per a è pari ad 1.
ø OblateSpheroidal[xi, eta, phi, a] è quasi analogo a prima, soltanto che la rotazione
avviene rispetto all'asse perpendicolare a quello che connette i due fuochi.
ø Bipolar[u, v, z, a] è sempre un sistema di coordinate parametrizzato da a, ed è costruito
attorno a due fuochi distanti 2 a. Con u costante si ottiene un fascio di circonferenze che passa per i
due punti, mentre fissando v si ottengono delle famiglie di ellissi che degenerano in uno dei due
fuochi. z rappresenta la distanza da questo piano. Indovinate qual'è il valore di default per a?
ø Bispherical[u, v, phi, a] differisce da quello precedente soltanto dal fatto che f
rappresenta l'angolo azimutale.
ø Toroidal[u, v, phi, a] rappresenta il sistema di coordinate toroidale, che si ottiene facendo
ruotare le coordinate bipolari attraverso l'asse perpendicolare a quello che unisce i due fuochi, con f
che specifica la rotazione.
ø Conical[lambda, mu, nu, a, b] è un sistema parametrizzato sia da a che da b. Le
superfici che si ottengono per un valore fissato di l sono sfere centrate nell'origine, mentre fissando
m si ottengono dei coni che divergono dall'origine e si prolungano lungo l'asse z, e fissando invece v
si ottengono coni che si aprono lungo l'asse y. I valori di default per i parametri sono a = 1, b = 2.
ø ConfocalEllipsoidal[lambda, mu, nu, a, b, c] contiene tre parametri a, b, c. Le
superfici che si ottengono fissando l sono ellissoidi; fissando m si ottengono degli iperboloidi ad un
foglio, mentre fissando v iperboloidi a due fogli. I valori di default per i paramentri sono
a = 3, b = 2, c = 1.
ø ConfocalParaboloidal[lambda, mu, nu, a, b] è un sistema di coordinate che, tanto
per cambiare, ha a e b come parametri. Fissando la variabile l solo paraboloidi ellittici che si
estendono nella direzione negativa dell'asse z. Fissando la coordinata m si disegnano paraboloidi
Daniele Lupo Appunti di Mathematica
335Printed by Mathematica for Students
iperbolici, ed infine, fissando la coordinata v si ottengono paraboloidi ellittici che si estendono nella
direzione positiva dell'asse z. I valori di default sono a = 2, b = 1.
In[43]:=
Una volta fissato un sistema di coordinate, sono presenti alcune funzioni per poter vedere qualche
informazioni sul range delle variabili e dei parametri, ovvero di quanto possono variare:
CoordinateRanges[ ] restituisce gli intervalli entro cui ognuna dellecoordinate del sistema di coordinate di default può
Parameters[ ] restituisce una lista dei valori dei parametridi default per il sistema di coordinate corrente
ParameterRanges[ ] restituisce gli intervalli entro i quali possono variarei parametri del sistema di coordinate corrente
CoordinateRanges[coordsys],Parameters[c o o r d s y s] ,ParameterRanges[coordsys]
analogo ai tre precedenti, ma invece che usare ilsistema di coordinate di default spiega variabili eparametri del sistema di coordinate coordsys
SetCoordinates[coordsys[vars,param]]
pone come sistema di coordinate di default coordsyscon le variabili vars e valori per i parametri param
Supponiamo di voler cambiare il nostro sistema di coordinate di default in sferico:
In[44]:= SetCoordinates@SphericalD
Out[44]= Spherical@Rr, Ttheta, PphiD
Vediamo gli intervalli in cui si trovano le coordinate;
In[45]:= CoordinateRanges@D
Out[45]= 80 ≤ Rr < ∞, 0 ≤ Ttheta ≤ π, −π < Pphi ≤ π<
Vediamo che il raggio, per esempio, può essere solo positivo ed, in genere, che ci sono le restrizioni
di questo sistema di coordinate.
Vediamo, adesso, il range entro cui possono variare i parametri del sistema ellissoidi confocali, ed i
valori di default:
In[46]:= ParameterRanges@ConfocalEllipsoidalD
Out[46]= 0 < #3 < #2 < #1 < ∞
Daniele Lupo Appunti di Mathematica
336Printed by Mathematica for Students
In[47]:= Parameters@ConfocalEllipsoidalD
Out[47]= 83, 2, 1<
Come potete vedere, abbiamo una restrizione per quanto riguarda i parametri, che non possono
essere scelti a caso. Tuttavia questo sono sicuro che non capiterà perchè, quando si decide di studiare
un problema, si scegli accuratamente il sistema di coordinate, per cui sapreste sicuramente quello che
state per fare, vero?
Per poter semplificarci la vita, ci sono comandi che permettono di passare da coordinate cartesiane a
quelle del sistema di coordinate scelto, e viceversa, sia se quest'ultimo rappresenta il sistema di
default, sia se è un altro:
CoordinatesToCartesian[pt] restituisce le coordinate cartesiane di pt, datonelle coordinate del sistema di coordinate di
CoordinatesToCartesian[pt,coordsys]
restituisce le coordinate cartesiane di pt, datonelle coordinate del sistema di coordinate
CoordinatesFromCartesian[pt]
restituisce le coordinate nel sistema di coordinate didefault di pt, con coordinate date in forma cartesiana
CoordinatesFromCartesian[pt, coordsys]
restituisce le coordinate nel sistema di coordinatecoordsys di pt, con coordinate date in forma cartesiana
Vediamo un esempio di facile comprensione:
In[48]:= CoordinatesToCartesian@81, Piê2, Piê4<, SphericalD
Out[48]= 9 1è!!!2 , 1
è!!!2 , 0=
Tuttavia, questa funzione vale pure per coordinate simboliche, per cui restituisce le formule di
conversione:
In[49]:= CoordinatesToCartesian@8λ, μ, ν<, ConfocalEllipsoidalD
Out[49]= 9è!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!H9 − λL H9 − μL H9 − νL
2 è!!!!!!10,
è!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!−H4 − λL H4 − μL H4 − νLè!!!!!!15
,è!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!H1 − λL H1 − μL H1 − νL
2 è!!!6 =
Sono comandi molto utili, che utlilizzerete abbastanza spesso, se utilizzerete questo package.
Inoltre, ci sono comandi per effettuare operazioni standard sui vettori tridimensionali anche per gli
altri sistemi di coordinate:
Daniele Lupo Appunti di Mathematica
337Printed by Mathematica for Students
DotProduct[v1, v2] calcola il prodotto scalare di v1 e v2 nel sistemadi coordinate di default
CrossProduct[v1, v2] calcola il prodotto vettoriale nel sistema dicoordinate corrente
ScalarTripleProduct[v1,
v2, v3] calcola il triplo prodotto scalare
DotProduct[v1, v2,coordsys], CrossProduct[v1,v2, coordsys], etc.
restituiscono i risultati con i vettori scritti nel sistemadi coordinate coordsys
Vediamo il prodotto scalare nel caso normale:
In[50]:= Clear@a, b, c, d, e, fD
In[51]:= DotProduct@8a, b, c<, 8d, e, f<, CartesianD
Out[51]= a d + b e + c f
Vediamo il prodotto con coordinate date in un altro sistema di coordinate:
In[52]:= DotProduct@8a, b, c<, 8d, e, f<, ProlateSpheroidalD
Out[52]= Cos@bD Cos@eD Cosh@aD Cosh@dD +
Cos@cD Cos@fD Sin@bD Sin@eD Sinh@aD Sinh@dD +
Sin@bD Sin@cD Sin@eD Sin@fD Sinh@aD Sinh@dD
Come vedete, le cose si complicano un pochetto, ma perchè raramente vediamo questo tipo di cose
(almeno io le ho usate davvero poco...)
In[53]:= CrossProduct@8a, b, c<, 8d, e, f<, BipolarD êê FullSimplify êê Timing
Out[53]= 9454.656 Second, 9−2 ImAArcCothA f Sin@aD−Cos@aD + Cosh@bD +
c Sin@dDCos@dD − Cosh@eD + J f Sinh@bD
Cos@aD − Cosh@bD +c Sinh@eD
−Cos@dD + Cosh@eD NEE,
2 ReAArcCothA f Sin@aD−Cos@aD + Cosh@bD +
c Sin@dDCos@dD − Cosh@eD +
J f Sinh@bDCos@aD − Cosh@bD +
c Sinh@eD−Cos@dD + Cosh@eD NEE,
Sin@dD Sinh@bD − Sin@aD Sinh@eDHCos@aD − Cosh@bDL HCos@dD − Cosh@eDL ==
Come vedete, il risultato è tutt'altro che semplice, ma Mathematica digerisce con facilità anche
queste bestialita abnormi...
Un'altro aspetto da considerare, molto importante quando si devono effettuare integrazioni e calcoli
differenziali su campi tridimensionale, è il differenziale che si usa dV. In coordinate cartesiane
Daniele Lupo Appunti di Mathematica
338Printed by Mathematica for Students
questo è dato da Hd x2 + d y2 + d z2L1ê2, che rappresenta la lunghezza d'arco differenziale; ma
ovviamente questa formula cambia al variare del tipo di coordinate che usiamo nel nostro problema:
ArcLengthFactor[{ fx,
fy, fz}, t] restituisce la derivata della lunghezza d'arco lungola curva parametrizzata da t nel sistema dicoordinate di default.
ArcLengthFactor[{ fx,
fy, fz}, t, coordsys] restituisce la stessa cosa di prima, ma nellecoordinate coordsys
consideriamo la seguente funzione parametrica:
In[54]:= param = 8Cos@tD, Sin@tD, t<
Out[54]= 8Cos@tD, Sin@tD, t<
Come avrete capito, in coordinate cartesiane, rappresenta un'elica. La lunghezza d'arco rappresenta
la velocità con cui il punto, al variare di t, descrive la figura. In questo caso abbiamo:
In[55]:= ArcLengthFactor@param, t, CartesianD
Out[55]= "################################################1 + Cos@tD2 + Sin@tD2
In[56]:= % êê Simplify
Out[56]= è!!!2
Come potete vedere, questa rappresenta la 'velocità' del punto che descrive la curva al variare di t.
Tuttavia, se le stesse equazioni le utilizziamo per un altro sistema di coordinate, non rappresentano
più un'elica, e di conseguenza questo valore varia:
In[57]:= ArcLengthFactor@param, t, SphericalD êê FullSimplify
Out[57]= "###############################################################################################Cos@tD4 + Sin@tD2 + Cos@tD2 Sin@Sin@tDD2
Come potete vedere, in questo caso la velocità varia al variare della posizione, cioè del parametro t.
Daniele Lupo Appunti di Mathematica
339Printed by Mathematica for Students
In[58]:= p1 = ParametricPlot3D@param, 8t, 0, 30<,BoxRatios → 81, 1, 2<,PlotPoints → 100D;
SetCoordinates@ConfocalEllipsoidalD;
p2 = ParametricPlot3D@CoordinatesFromCartesian@paramD, 8t, 0, 30<,BoxRatios → 81, 1, 2<,PlotPoints → 1000D;
Show@GraphicsArray@8p1, p2<DD
-1 -0.5 0 0.51
-1-0.5
00.5
1
0
10
20
301-0.5
00.5 -800-600-400-200 0
3.93.925
3.953.975
4
8.8
8.85
8.9
8.95
9.93.925
3.953.975
Out[61]= GraphicsArray
Come potete vedere, la stessa rappresentazione in coordinate diverse cambia di parecchio... Di
conseguenza cambiano anche i valori che abbiamo calcolato prima...
Quello che abbiamo calcolato, in pratica, ci serve per poter calcolare l'integrale di una funzione,
definita nelle tre coordinate, con l'integrale che si estende lungo la curva che abbiamo definito.
Supponiamo di definire la seguente funzione:
In[62]:= f@8x_, y_, z_<D := 3 x^2 Sin@yD z
Daniele Lupo Appunti di Mathematica
340Printed by Mathematica for Students
Notate come abbia scritto come argomento una lista. Questo ci serve per scrivere in modo
semplificato la funzione nelle nostre coordinate: infatti scriveremo:
In[63]:= f@paramD
Out[63]= 3 t Cos@tD2 Sin@Sin@tDD
invece di
In[64]:= f@param@@1DD, param@@2DD, param@@3DDD
Out[64]= f@Cos@tD, Sin@tD, tD
Oppure un altro dei modi con Map e così via...
Per poter ottenere l'integrale lungo la curva, occorre integrare la funzione, avente come argomento le
coordinate della curva parametrica lungo cui vogliamo calcolare l'integrale, per la lunghezza d'arco
definita dal sistema di coordinate che abbiano scelto:
In[65]:= Integrate@f@paramD ArcLengthFactor@param, t, CartesianD,8t, 0, 2 Pi<D
Out[65]= −3 è!!!2 π2 StruveH@1, 1D
MMMMmmmm.... la soluzione è più complicata di quanto sembrasse a prima vista. Comunque
siamo riusciti a calcolarla. Se volessimo avere un'approssimazione numerica basterebbe fare:
In[66]:= N@%D
Out[66]= −8.31004
All'opposto dell'integrale, c'è la derivata, che viene rappresentata nelle sue derivate parziali dalla
matrice Jacobiana, che serve ad aggiustare il volumetto elementare nel cambio di coordinate:
Daniele Lupo Appunti di Mathematica
341Printed by Mathematica for Students
JacobianMatrix[ ] restitusce la matrice delle derivate dellatrasformazione dal sistema di coordinate di default aquello cartesiano, usando le veriabili di default
JacobianMatrix[pt] matrice Jacobiana calcolata nel punto specificato,dato nelle coordinate del sistema di coordinate di
JacobianMatrix[coordsys] restituisce la matrice delle derivate per passaredalle coordinate coordsys a quelle cartesiane
JacobianMatrix[pt, coordsys] come sopra, ma nel punto specificato...
JacobianDeterminant[ ],JacobianDeterminant[pt], etc.
determinante della matrice Jacobiana
ScaleFactors[ ],ScaleFactors[pt], etc.
lista dei fattori di scala
Vediamo la matrice Jacobiana per passare dalle coordinate cartesiani a quelle cartesiani:
In[67]:= JacobianMatrix@CartesianD êê MatrixForm
Out[67]//MatrixForm=
i
k
jjjjjj1 0 00 1 00 0 1
y
{
zzzzzz
Alquanto banale.... Vediamo invece di vedere qualcosa di più serio, per esempio usando il sistema di
coordinate bipolare:
In[68]:= JacobianMatrix@BipolarD êê MatrixForm
Out[68]//MatrixForm=
i
k
jjjjjjjjjjjjj
− Sin@UuD Sinh@VvDH−Cos@UuD+Cosh@VvDL2
Cosh@VvD−Cos@UuD+Cosh@VvD − Sinh@VvD2
H−Cos@UuD+Cosh@VvDL2 0
Cos@UuD−Cos@UuD+Cosh@VvD − Sin@UuD2
H−Cos@UuD+Cosh@VvDL2 − Sin@UuD Sinh@VvDH−Cos@UuD+Cosh@VvDL2 0
0 0 1
y
{
zzzzzzzzzzzzz
L'integrale su una regione tridimensionale si calcola usando lo Jacobiano. per esempio, se cerco di
integrare una funzione descritta in un sistema di coordinate che non sia quello cartesiano, bisogna
utilizzare la trasformazione opportuna: ovviamente, ci serve il determinante dello Jacobiano...
Supponiamo di avere la seguente funzione espressa in coordinate cilindriche:
In[69]:= g@r_, θ_, z_D := Sin@θD^2 z r
L'integrale, calcolato nel cilindro di raggio 3 e di altezza 2 si scrive:
Daniele Lupo Appunti di Mathematica
342Printed by Mathematica for Students
In[70]:= Integrate@g@r, θ, zD JacobianDeterminant@Cylindrical@r, θ, zDD,8r, 0, 3<, 8θ, 0, 2 Pi<, 8z, 0, 2<D
Out[70]= 18 π
Infine, vediamo le funzioni che voi tutti sicuramente aspettate, che sono quelle più comuni quando si
usano funzioni tridimensionali:
Div[f] divergenza del campo vettoriale f nel sistemadi coordinate di default
Curl[f] rotore del campo vettoriale f nel sistema di coordinatedi default
Grad[f] gradiente della funzione scalare f nel sistema dicoordinate di default
Laplacian[f] laplaciano della funzione scalare f nel sistemadi coordinate di default
Biharmonic[f] laplaciano del laplaciano della funzione scalare fnel sistema di coordinate di default
Div[f, coordsys],Curl[f, coordsys], etc.
operatori differenziali che operano nel sistemadi coordinate coordsys
Il campo vettoriale è dato come lista delle tre funzioni che rappresentano le componenti del campo
vettoriale. Ogni funzione, in genere, dipendera da tutte e tre le coordinate. Per esempio, in forma
simbolica possiamo avere:
In[71]:= Clear@f, g, hD
In[72]:= Div@8f@r, θ, φD, g@r, θ, φD, h@r, θ, φD<, Spherical@r, θ, φDD
Out[72]=1r2
HCsc@θD Hr Cos@θD g@r, θ, φD + 2 r f@r, θ, φD Sin@θD + r hH0,0,1L@r, θ, φD +
r Sin@θD gH0,1,0L@r, θ, φD + r2 Sin@θD fH1,0,0L@r, θ, φDLL
Come vedete in questo caso viene dato in forma puramente simbolica. Possiamo fare un caso più
pratico, per farvi vedere meglio:
In[73]:= Grad@r^2 + yθ^3 + Hr θ φL^4, Spherical@r, θ, φDD êê Simplify
Out[73]= 92 Hr + 2 r3 θ4 φ4L, θ2 H3 y + 4 r4 θ φ4Lr
, 4 r3 θ4 φ3 Csc@θD=
Daniele Lupo Appunti di Mathematica
343Printed by Mathematica for Students
üDiscreteMath`Combinatorica`Questo è uno dei packages più corposi di Mathematica, con oltre 450 funzioni avanzate per
permutazioni e combinazioni, sia per disegnare e calcolare con i grafi, orientati e non. Sono funzioni
molto specifiche, con cui personalmente non ho mai avuto a che fare, ma che riporto perchè reputo
comunque il pacchetto importante per chiunque abbia a che fare con calcolo combinatorio.
Le funzioni per le permutazioni sono:
BinarySearch DerangementQ
Derangements DistinctPermutations
EncroachingListSet FromCycles
FromInversionVector HeapSort
Heapify HideCycles
IdentityPermutation Index
InversePermutation InversionPoset
Inversions InvolutionQ
Involutions Josephus
LexicographicPermutations LongestIncreasingSubsequence
MinimumChangePermutations NextPermutation
PermutationQ PermutationType
PermutationWithCycle Permute
RandomHeap RandomPermutation
RankPermutation RevealCycles
Runs SelectionSort
SignaturePermutation ToCycles
ToInversionVector UnrankPermutation
I comandi per i subset sono:
Daniele Lupo Appunti di Mathematica
344Printed by Mathematica for Students
BinarySubsets DeBruijnSequence
GrayCodeKSubsets GrayCodeSubsets
GrayGraph KSubsets
LexicographicSubsets NextBinarySubset
NextGrayCodeSubset NextKSubset
NextLexicographicSubset NextSubset
NthSubset RandomKSubset
RandomSubset RankBinarySubset
RankGrayCodeSubset RankKSubset
RankSubset Strings
Subsets UnrankBinarySubset
UnrankGrayCodeSubset UnrankKSubset
UnrankSubset
E i comandi per la teoria dei gruppi sono:
AlternatingGroup AlternatingGroupIndex
CycleIndex CycleStructure
Cycles Cyclic
CyclicGroup CyclicGroupIndex
Dihedral DihedralGroup
DihedralGroupIndex EquivalenceClasses
KSubsetGroup KSubsetGroupIndex
ListNecklaces MultiplicationTable
NecklacePolynomial OrbitInventory
OrbitRepresentatives Orbits
Ordered PairGroup
PairGroupIndex PermutationGroupQ
SamenessRelation SymmetricGroup
SymmetricGroupIndex
Per le partizioni di interi abbiamo:
Compositions DominatingIntegerPartitionQ
DominationLattice DurfeeSquare
FerrersDiagram NextComposition
NextPartition PartitionQ
ReverseLexicographicPartitions RandomComposition
RandomPartition TransposePartition
Per i set di partizioni abbiamo:
Daniele Lupo Appunti di Mathematica
345Printed by Mathematica for Students
CoarserSetPartitionQ FindSet
InitializeUnionFind KSetPartitions
PartitionLattice RGFQ
RGFToSetPartition RGFs
RandomKSetPartition RandomRGF
RandomSetPartition RankKSetPartition
RankRGF RankSetPartition
SetPartitionListViaRGF SetPartitionQ
SetPartitionToRGF SetPartitions
ToCanonicalSetPartition UnionSet
UnrankKSetPartition UnrankRGF
UnrankSetPartition
Per le tavole di Young abbiamo le seguenti funzioni:
ConstructTableau DeleteFromTableau
FirstLexicographicTableau InsertIntoTableau
LastLexicographicTableau NextTableau
PermutationToTableaux RandomTableau
TableauClasses TableauQ
Tableaux TableauxToPermutation
TransposeTableau
Per conteggi vari abbiamo:
Backtrack BellB
Cofactor Distribution
Element Eulerian
NumberOf2Paths NumberOfCompositions
NumberOfDerangements NumberOfDirectedGraphs
NumberOfGraphs NumberOfInvolutions
NumberOfKPaths NumberOfNecklaces
NumberOfPartitions NumberOfPermutationsByCycles
NumberOfPermutationsByInversions NumberOfPermutationsByType
NumberOfSpanningTrees NumberOfTableaux
StirlingFirst StirlingSecond
Per esempio, se vogliamo vedere tutti i possibili modi per scrivere un numero come somma di un
determinato numero di addendi, possiamo utilizzare il seguente comando:
Daniele Lupo Appunti di Mathematica
346Printed by Mathematica for Students
In[74]:= << DiscreteMath`Combinatorica`
In[75]:= Compositions@9, 3D
Out[75]= 880, 0, 9<, 80, 1, 8<, 80, 2, 7<, 80, 3, 6<, 80, 4, 5<,80, 5, 4<, 80, 6, 3<, 80, 7, 2<, 80, 8, 1<, 80, 9, 0<,81, 0, 8<, 81, 1, 7<, 81, 2, 6<, 81, 3, 5<, 81, 4, 4<,81, 5, 3<, 81, 6, 2<, 81, 7, 1<, 81, 8, 0<, 82, 0, 7<,82, 1, 6<, 82, 2, 5<, 82, 3, 4<, 82, 4, 3<, 82, 5, 2<,82, 6, 1<, 82, 7, 0<, 83, 0, 6<, 83, 1, 5<, 83, 2, 4<, 83, 3, 3<,83, 4, 2<, 83, 5, 1<, 83, 6, 0<, 84, 0, 5<, 84, 1, 4<, 84, 2, 3<,84, 3, 2<, 84, 4, 1<, 84, 5, 0<, 85, 0, 4<, 85, 1, 3<, 85, 2, 2<,85, 3, 1<, 85, 4, 0<, 86, 0, 3<, 86, 1, 2<, 86, 2, 1<, 86, 3, 0<,87, 0, 2<, 87, 1, 1<, 87, 2, 0<, 88, 0, 1<, 88, 1, 0<, 89, 0, 0<<
Notate come siano dati le parti ordinate, per cui 80, 0, 9< ∫ 80, 9, 0<, per esempio. Questo perchè la
funzione dice come dividere in un numero determinato di gruppi, un determinato numero di
elementi, per cui i gruppi sono comunque diversi.
Comunque, sono funzioni avanzate, che conosceranno chi deve utilizzarle. Se le provate a caso
(come me) vi perderete subito. Se cercate qualcosa di particolare perchè sapete che vi serve, qua
siete nel posto giusto.
Invece, trovo più interessante la parte di questo package riguardante la gestione dei grafi.
Daniele Lupo Appunti di Mathematica
347Printed by Mathematica for Students
In[76]:= ShowGraph@CompleteGraph@12DD
Out[76]= Graphics
Come potete vedere, abbiamo realizzato un grafo completo di 12 elementi in men che non si dica...
Se vogliamo mostrare la matrice di adiacenza di un grafo, basta semplicemente utilizzare il comando
designato:
In[77]:= TableForm@ToAdjacencyMatrix@CompleteGraph@12DDD
Out[77]//TableForm=
0 1 1 1 1 1 1 1 1 1 1 11 0 1 1 1 1 1 1 1 1 1 11 1 0 1 1 1 1 1 1 1 1 11 1 1 0 1 1 1 1 1 1 1 11 1 1 1 0 1 1 1 1 1 1 11 1 1 1 1 0 1 1 1 1 1 11 1 1 1 1 1 0 1 1 1 1 11 1 1 1 1 1 1 0 1 1 1 11 1 1 1 1 1 1 1 0 1 1 11 1 1 1 1 1 1 1 1 0 1 11 1 1 1 1 1 1 1 1 1 0 11 1 1 1 1 1 1 1 1 1 1 0
Possiamo anche vedere il numero di vertici di un grafo:
Daniele Lupo Appunti di Mathematica
348Printed by Mathematica for Students
In[78]:= V@CompleteGraph@12DD
Out[78]= 12
Ed il numero di lati:
In[79]:= M@CompleteGraph@12DD
Out[79]= 66
Per chi ancora non l'avesse capito, CompleteGraph crea un grafo in cui ogni elemento è legato
all'altro... Qua sotto sono rappresentate le funzioni usate per creare i particolari tipi di grafi:
Daniele Lupo Appunti di Mathematica
349Printed by Mathematica for Students
BooleanAlgebra ButterflyGraph
CageGraph CartesianProduct
ChvatalGraph CirculantGraph
CodeToLabeledTree CompleteBinaryTree
CompleteGraph CompleteKPartiteGraph
CompleteKaryTree CoxeterGraph
CubeConnectedCycle CubicalGraph
Cycle DeBruijnGraph
DodecahedralGraph EmptyGraph
ExactRandomGraph ExpandGraph
FiniteGraphs FolkmanGraph
FranklinGraph FruchtGraph
FunctionalGraph GeneralizedPetersenGraph
GraphComplement GraphDifference
GraphIntersection GraphJoin
GraphPower GraphProduct
GraphSum GraphUnion
GridGraph GrotztschGraph
Harary HasseDiagram
HeawoodGraph HerschelGraph
Hypercube IcosahedralGraph
IntervalGraph KnightsTourGraph
LabeledTreeToCode LeviGraph
LineGraph ListGraphs
MakeGraph McGeeGraph
MeredithGraph MycielskiGraph
NoPerfectMatchingGraph NonLineGraphs
OctahedralGraph OddGraph
OrientGraph Path
PermutationGraph PetersenGraph
RandomGraph RandomTree
RealizeDegreeSequence RegularGraph
RobertsonGraph ShuffleExchangeGraph
SmallestCyclicGroupGraph Star
TetrahedralGraph ThomassenGraph
TransitiveClosure TransitiveReduction
Turan TutteGraph
Uniquely3ColorableGraph UnitransitiveGraph
VertexConnectivityGraph WaltherGraph
Wheel
Daniele Lupo Appunti di Mathematica
350Printed by Mathematica for Students
Inoltre, possiamo anche creare dei grafi a partire da altre rappresentazioni: per esempio possiamo
creare un grafo se siamo in possesso della matrice di adiacenza, oppure della lista di coppie ordinate
delle connessioni, oppure di ottenere una determinata rappresentazione di un grafo:
Edges FromAdjacencyLists
FromAdjacencyMatrix FromOrderedPairs
FromUnorderedPairs IncidenceMatrix
ToAdjacencyLists ToAdjacencyMatrix
ToOrderedPairs ToUnorderedPairs
Per esempio:
In[80]:= ShowGraph@RobertsonGraphD
Out[80]= Graphics
Se cercate un tipo di grafo in particolare, di certo lo troverete nell'elenco di sopra...
Possiamo anche effettuare delle operazioni sui grafi per modificarli:
Daniele Lupo Appunti di Mathematica
351Printed by Mathematica for Students
AddEdge AddEdges
AddVertex AddVertices
ChangeEdges ChangeVertices
Contract DeleteCycle
DeleteEdge DeleteEdges
DeleteVertex DeleteVertices
InduceSubgraph MakeDirected
MakeSimple MakeUndirected
PermuteSubgraph RemoveMultipleEdges
RemoveSelfLoops ReverseEdges
Per esempio, definiamo un grafo:
In[81]:= grafo = Hypercube@5D
Out[81]= Graph:<80, 32, Undirected>
In[82]:= ShowGraph@grafo, VertexNumber → TrueD
1
23
45
67
8
9
1011
1213
1415
16
17
1819
2021
2223
24
25
2627
2829
3031
32
Out[82]= Graphics
Supponiamo di dover aggiungere una connessione fra il vertice 13 ed il 30:
Daniele Lupo Appunti di Mathematica
352Printed by Mathematica for Students
In[83]:= grafo = AddEdge@grafo, 813, 30<D
Out[83]= Graph:<81, 32, Undirected>
In[84]:= ShowGraph@grafo, VertexNumber → TrueD
1
23
45
67
8
9
1011
1213
1415
16
17
1819
2021
2223
24
25
2627
2829
3031
32
Out[84]= Graphics
Se adesso voglio cancellare il vertice numero 20 basta fare:
In[85]:= grafo = DeleteVertex@grafo, 20D
Out[85]= Graph:<76, 31, Undirected>
Daniele Lupo Appunti di Mathematica
353Printed by Mathematica for Students
In[86]:= ShowGraph@grafoD
Out[86]= Graphics
Come potete vedere, sono scomparse anche le connessioni di quel vertice particolare. Se adesso mi
serve la lista di coppie non ordinate basta fare:
In[87]:= ToUnorderedPairs@grafoD
Out[87]= 881, 2<, 82, 3<, 83, 4<, 81, 4<, 85, 6<, 86, 7<, 87, 8<, 85, 8<,89, 10<, 810, 11<, 811, 12<, 89, 12<, 813, 14<, 814, 15<, 815, 16<,813, 16<, 817, 18<, 818, 19<, 820, 21<, 821, 22<, 822, 23<,820, 23<, 824, 25<, 825, 26<, 826, 27<, 824, 27<, 828, 29<,829, 30<, 830, 31<, 828, 31<, 81, 5<, 82, 6<, 83, 7<, 84, 8<,89, 13<, 810, 14<, 811, 15<, 812, 16<, 817, 20<, 818, 21<, 819, 22<,824, 28<, 825, 29<, 826, 30<, 827, 31<, 81, 9<, 82, 10<, 83, 11<,84, 12<, 85, 13<, 86, 14<, 87, 15<, 88, 16<, 89, 17<, 810, 18<,811, 19<, 813, 20<, 814, 21<, 815, 22<, 816, 23<, 817, 24<, 818, 25<,819, 26<, 820, 28<, 821, 29<, 822, 30<, 823, 31<, 81, 24<, 82, 25<,83, 26<, 84, 27<, 85, 28<, 86, 29<, 87, 30<, 88, 31<, 813, 29<<
Le coppie le ho definite non ordinate perchè non lo era il grafo.
Inoltre, possiamo anche avere delle opzioni che modificano l'aspetto del grafo:
Daniele Lupo Appunti di Mathematica
354Printed by Mathematica for Students
Algorithm Box
Brelaz Center
Circle Directed
Disk EdgeColor
EdgeDirection EdgeLabel
EdgeLabelColor EdgeLabelPosition
EdgeStyle EdgeWeight
Euclidean HighlightedEdgeColors
HighlightedEdgeStyle HighlightedVertexColors
HighlightedVertexStyle Invariants
LNorm Large
LoopPosition LowerLeft
LowerRight NoMultipleEdges
NoSelfLoops Normal
NormalDashed NormalizeVertices
One Optimum
Parent PlotRange
RandomInteger Simple
Small Strong
Thick ThickDashed
Thin ThinDashed
Type Undirected
UpperLeft UpperRight
VertexColor VertexLabel
VertexLabelColor VertexLabelPosition
VertexNumber VertexNumberColor
VertexNumberPosition VertexStyle
VertexWeight Weak
WeightRange WeightingFunction
Zoom
Per esempio, supponiamo di avere questo grafo, che parte dalla seguente matrice di adiacenza:
In[88]:= adiacenza = 880, 1, 1, 1<,80, 1, 0, 1<,81, 0, 0, 1<,80, 1, 1, 1<<;
Daniele Lupo Appunti di Mathematica
355Printed by Mathematica for Students
In[89]:= grafo = FromAdjacencyMatrix@adiacenzaD
Out[89]= Graph:<7, 4, Undirected>
In[90]:= ShowGraph@grafoD
Out[90]= Graphics
Se vogliamo mostrare le direzioni delle connessioni:
Daniele Lupo Appunti di Mathematica
356Printed by Mathematica for Students
In[91]:= ShowGraph@SetGraphOptions@grafo,EdgeDirection → True
DD
Out[91]= Graphics
Se vogliamo anche modificare il punto che rappresenta un vertice del grafo:
Daniele Lupo Appunti di Mathematica
357Printed by Mathematica for Students
In[92]:= ShowGraph@SetGraphOptions@grafo,EdgeDirection → True,VertexColor → Blue
DD
Out[92]= Graphics
Posso anche definire lo stile per particolari parti del grafo, usando le liste:
Daniele Lupo Appunti di Mathematica
358Printed by Mathematica for Students
In[93]:= ShowGraph@SetGraphOptions@grafo,881, 2, VertexColor → Green<,83, 4, VertexColor → Brown<<,EdgeColor → Orange,EdgeDirection → True
DD
Out[93]= Graphics
Come potete vedere, potete creare grafi dall'aspetto che volete, alla faccia, se mi permettete, di
Metapost e PSTricks, che mi hanno fatto impazzire per disegnare solamente una freccia...
Possiamo anche definire pesi ed etichette per i grafi:
GetEdgeLabels GetEdgeWeights
GetVertexLabels GetVertexWeights
SetEdgeLabels SetEdgeWeights
SetGraphOptions SetVertexLabels
SetVertexWeights
Daniele Lupo Appunti di Mathematica
359Printed by Mathematica for Students
Ed altre funzioni per generare i disegni dei grafi:
AnimateGraph CircularEmbedding
DilateVertices GraphOptions
Highlight RadialEmbedding
RandomVertices RankGraph
RankedEmbedding RootedEmbedding
RotateVertices ShakeGraph
ShowGraph ShowGraphArray
ShowLabeledGraph SpringEmbedding
TranslateVertices Vertices
In[94]:= ShowGraphArray@8CompleteGraph@5, 2, 5D, FranklinGraph<D
Out[94]= GraphicsArray
Possiamo fare il prodotto nel senso dei grafi:
Daniele Lupo Appunti di Mathematica
360Printed by Mathematica for Students
In[95]:= ShowGraph@GraphProduct@CompleteGraph@5, 2, 5D, FranklinGraphDD
Out[95]= Graphics
Non è che sia effettivamente molto chiara... Abbiamo preso il primo grafo, e l'abbiamo sostituito ad
ogni vertice del secondo grafo, connettendo inoltre i corrispondenti punti del vari sotto-grafi.
Possiamo anche creare grafi personalizzati, dove i vertici sono connessi se soddisfano espressioni
specificate da noi: bisogna specificare il numero di vertici del grafo, e la relazione booleana che dice
se due vertici sono connessi. Per esempio, questa rappresentazione connette due vertici se la loro
somma è minore del doppio del più piccolo dei due sommato a 4:
In[96]:= grafo = MakeGraph@Range@16D,H#1 + #2 < 2 Min@8#1, #2<D + 4L &
D
Out[96]= Graph:<100, 16, Directed>
Daniele Lupo Appunti di Mathematica
361Printed by Mathematica for Students
In[97]:= ShowGraph@grafo, VertexNumber → TrueD
1
2
34
5
6
7
8
9
10
1112
13
14
15
16
Out[97]= Graphics
Come potete vedere, quello che possiamo con i grafi è veramente un casino. Ci sono libri interi che
sono dedicati soltanto a questo package!!!!! Quindi come posso andare oltre la punta della punta
della punta dell'iceberg??? Sperimentate e scoprirete sempre cose nuove. Vi posso assicurare che
imparare questo package è come imparare un programma a parte!!!
Daniele Lupo Appunti di Mathematica
362Printed by Mathematica for Students
In[98]:= ShowGraph@ShortestPathSpanningTree@GridGraph@5, 5D, 1DD
Out[98]= Graphics
üDiscreteMath`GraphPlotQuesto package contiene altre funzioni specifiche per il plottaggio di grafi. Supporta i grafi di
Combinatoria e le sue funzioni sono ottimizzate per funzionare con grandi grafi. Il comando
principale è quello che permette di disegnare i grafici sullo schermo:
GraphPlot@g, optionsD calcola un layout bidimensionale del grafo usando
delle regole predefinite
GraphPlot3D@g, optionsD calcola il layout di un grafo tridimensionale
A differenza del packege di prima, in questo il disegno viene automaticamente riarrangiato: mentre
prima i vertici avevano posizioni definite, qua vengono automaticamente spostati in modo da dare il
layout migliore predefinito.
Vediamo un esempio, disegnando un grafo definito da una lista di regole:
In[99]:= << DiscreteMath`GraphPlot`;
Daniele Lupo Appunti di Mathematica
363Printed by Mathematica for Students
In[100]:= lista = 81 → 2, 2 → 3, 3 → 4, 4 → 5, 5 → 1<;
In[101]:= GraphPlot@listaD
Out[101]= Graphics
Aggiungiamo un altro vertice:
In[102]:= lista = Flatten@Append@lista, 86 → 1, 6 → 3<DD;
In[103]:= GraphPlot@listaD
Out[103]= Graphics
Daniele Lupo Appunti di Mathematica
364Printed by Mathematica for Students
Come potete vedere, il layout dello stesos grafo è cambiato aggiungendo un vertice:
In[104]:= GraphPlot@lista, EdgeStyleFunction → HArrow@8#1, #2<D &L,VertexStyleFunction → AutomaticD
12
3 4
5
6
Out[104]= Graphics
option name default value
Method Automatic metodo usato per disegnare il grafo"VertexStyleFunction" None definisce come sono disegnati i vertici"EdgeStyleFunction" None descrive come disegnare i ramiPlotStyle Automatic definisce lo stile di disegno del grafo
RandomSeed Automatic definisce il posizionamento iniziale deivertici per la funzione di disegno del grafo
"VertexCoordinates" None coordinate di vertici definite
Definiamo quest'altro grafo:
In[105]:= grafo2 = 81 → 2, 2 → 3, 3 → 4, 4 → 5, 5 → 6, 6 → 7, 7 → 5, 1 → 4<;
In[106]:= GraphPlot@grafo2,PlotStyle → 8Green, [email protected]<D
Out[106]= Graphics
Come vedete, ho disegnato il grafo. Possiamo selezionare il metodo di disegno:
Daniele Lupo Appunti di Mathematica
365Printed by Mathematica for Students
In[107]:= GraphPlot@grafo2,PlotStyle → 8Green, [email protected]<,Method −> "LayeredDrawing"
D
Out[107]= Graphics
Daniele Lupo Appunti di Mathematica
366Printed by Mathematica for Students
In[108]:= GraphPlot@grafo2,PlotStyle → 8Green, [email protected]<,Method −> "RadialDrawing"
D
Out[108]= Graphics
E così via...
Possiamo anche disegnare facilemte degli alberi:
TreePlot@g, optionsD genera un grafo ad albero
TreePlot@g, r, optionsD genera un grafo ad albero, con radice r
Vediamo:
In[109]:= grafo3 = 81 → 2, 2 → 3, 2 → 8, 1 → 4, 4 → 5, 4 → 6, 4 → 7<;
Daniele Lupo Appunti di Mathematica
367Printed by Mathematica for Students
In[110]:= TreePlot@grafo3D
Out[110]= Graphics
option name default value
AspectRatio Automatic rapporto larghezza-altezza"RootPosition" Top posizione della radice"TreeSizeFunction" H1&L altezza di ogni livello dell' albero
Possiamo mettere, per esempio, la radice al centro:
Daniele Lupo Appunti di Mathematica
368Printed by Mathematica for Students
In[111]:= TreePlot@grafo3, "RootPosition" → CenterD
Out[111]= Graphics
Questo package aggiunge anche due utili funzioni:
GraphDistance@g, i, jD calcola la distanza del grafo fra i due vertici i e j
PseudoDiameter@gD restituisce lo pseudodiametro del grafo non direzionale
Considerando il penultimo grafo, possiamo vedere la distanza fra due suoi punti:
In[112]:= GraphDistance@grafo2, 1, 5D
Out[112]= 2
Questo package contiene altri comandi minori, come il conteggio dei numeri di vertici oppure la loro
lista, quindi andate a vedervi i comandi che vi servono. In fondo, questa è solo un appendice!!!
Daniele Lupo Appunti di Mathematica
369Printed by Mathematica for Students
üGraphics`Animation`Questo package definisce comandi specifici per la creazione delle animazioni in Mathematica:
definiscono in pratica un insieme di immagini che poi vengono usati come frame per l'animazione,
che poi può essere esportata con il comando Export, come ben sappiamo:
Animate@ grcom, 8 t, tmin, tmax, dt < D
esegue il comandio grafico grcom per il range specificato di t
ShowAnimation@
8 p1, p2, p3, … < D
anima la sequenza di immagini "\!\H\*Cell@BoxData@FormBox@SubscriptBox@StyleBox@\"\\<\\\"p\\\"\\>\",\"TI\"D,StyleBox@\"\\<\\\"i\\\"\\>\",\"TI\"DD, TraditionalFormDD, \"InlineFormula\"D\L
Questi due comandi sono abbastanza semplici ed esplicativi. Vediamo un esempio del primo
comando:
In[113]:= << Graphics`Animation`
In[114]:= Animate@Plot@n x, 8x, −4, 4<, PlotRange → 88−4, 4<, 8−4, 4<<D, 8n, −5, 5<D
-4 -3 -2 -1 1 2 3 4
-4
-3
-2
-1
1
2
3
4
Qua vi mostro solamente i due frame per risparmiare spazio. Se adesso volete creare l'animazione,
basta fare doppio clic su di un frame, e partirà l'animazione ciclica; cliccando di nuovo l'animazione
si fermerà. Notate anche come in basso a sinistra nel notebook compaiano pulsanti per il controllo
dell'animazione.
A proposito, dovete farlo voi, naturalmente: cliccare sul PDF non funziona...
Daniele Lupo Appunti di Mathematica
370Printed by Mathematica for Students
La potenza di questo comando, però, consiste nel fatto che la parametrizzazione non è limitata alla
funzione, ma anche ai parametri della funzione Plot (o di qualsiasi altra funzione che restituisca un
grafico utilizzata nell'argomento del comando): possiamo per esempio creare un animazione dove
cambiano i colori:
In[115]:= Animate@Plot3D@Cos@x yD, 8x, −4, 4<, 8y, −4, 4<,LightSources → 8881, 1, 1<, Hue@tD<<, PlotPoints → 50, Mesh → False
D,8t, 0, 1, .1<D
-4
-2
0
2
4 -4
-2
0
2
4
-1-0.5
0
0.5
1
-4
-2
0
2
Notate come questa volta siamo stati in grado di lavorare sui parametri, oltre al fatto che abbiamo
utilizzato un altra funzione grafica diversa da Plot.
Il secondo comando, ShowAnimation, è simile al primo, con la differenza che questa volta, invece di
creare i frame con un parametro, richiediamo esplicitamente la lista dei frame creati
precedentemente. Quindi possiamo per esempio creare varie animazioni e fonderle in una soltanto,
eseguire stacchi etc, con un minimo di pre-processing. Tenete sempre conto, però, che le animazioni
(a meno che non sia un requisito del vostro studio) devono restare semplici, per far focalizzare
l'attenzione sulla funzione e sul concetto, invece che sulla magnifica combinazione di colori che siete
riusciti a fare.
Inoltre, ci sono comandi specifici per i vari tipi di grafico presenti in Mathematica:
Daniele Lupo Appunti di Mathematica
371Printed by Mathematica for Students
MoviePlot@ f @ x, t D, 8 x, xmin, xmax <, 8 t, tmin, tmax < D
anima Plot@ f @ x, t D, 8 x, xmin, xmax < D per il range definito del parametro t
MoviePlot3D@ f @ x, y, t D, 8 x, xmin, xmax <, 8 y, ymin, ymax <, 8 t, tmin, tmax < D
anima grafici tridimensionali
MovieDensityPlot@ f @ x, y, t D, 8 x, xmin, xmax <, 8 y, ymin, ymax <, 8 t, tmin, tmax < D
anima grafici di densità
MovieContourPlot@ f @ x, y, t D, 8 x, xmin, xmax <, 8 y, ymin, ymax <, 8 t, tmin, tmax < D
anima grafici di curve di livello
MovieParametricPlot@ 8 f @ s, t D, g @ s, t D <, 8 s, smin, smax <, 8 t, tmin, tmax < D
anima grafici parametrici
SpinShow@graphicsD ruota oggetti tridimensionali
Il funzionamento è analogo per tutte le funzioni specificate qua sopra (a parte l'ultima, che vedremo
subito dopo).
In[116]:= MovieContourPlot@Sqrt@Hx − Sin@tDL^2 + Hy − Cos@3 tDL^2D,8x, −2, 2<, 8y, −2, 2<, 8t, 0, 2 Pi − Piê7, Piê7<D
-2 -1 0 1 2-2
-1
0
1
2
Come vedete, è abbastanza semplice creare animazioni in questo modo. Inoltre, queste funzioni
accettano anche gli argomenti corrispondenti alle funzioni che animano.
SpinShow, invece, crea una rotazione dell'oggetto tridimensionale; in realtà fa ruotare il punto di
Daniele Lupo Appunti di Mathematica
372Printed by Mathematica for Students
vista. Le opzioni sono le seguenti:
option name default value SpinOrigin 80, 0, 1.5< usato con SpinDistance
per determinare ViewPoint
SpinDistance 2 usato con SpinOrigin
per determinare ViewPoint
SpinTilt 80,0< specifica gli angoli di Eulero a e gSpinRange 8 0 Degree,
360 Degree < specifica il raggiodegli angoli entro cui varia a
RotateLights False specifica se le luci debbano omeno ruotare assieme all'oggetto
Il comando crea l'animazione creando un punto di vista che ruota attorno ad una sfera di raggio
SpinDistance, e traslando il risultato di SpinOrigin. La rotazione usa il primo angolo di Eulero a con
le condizione di SpinRange. Inoltre possiamo specificare anche gli angoli b, g per ottenere altri
effetti di rotazione:
Supponiamo di avere la seguente superfice:
In[117]:= superfice = ParametricPlot3D@8a b Cos@bD, a b Sin@bD, b<, 8a, 0, 2<, 8b, 0, 7 Pi<,Axes → False, Boxed → False, BoxRatios → 81, 1, 2<,PlotPoints → 84, 70<, LightSources → 8883, 3, 3<, Hue@5D<<D;
Daniele Lupo Appunti di Mathematica
373Printed by Mathematica for Students
In[118]:= SpinShow@superfice, Frames → 20, SpinRange → 80, 4 Pi<D
Toh, una vite che si avvita da sola... Certo che sono proprio un simpaticone ed un mostro di
simpatia....
üGraphics`ComplexMap`Questo package permette di rappresentare in maniera classica le funzioni complesse di variabile
complessa, vedendo come viene trasformata una griglia di linee nel piano bidimensionale dal
dominio al codominio.
C a r t e s i a n M a p [f ,{xmin, xmax}, {ymin,
disegna l'immagine in coordinate cartesiane, nelrange specificato, della funzione f
PolarMap[f, {rmin,rmax}, {thetamin,
restituisce l'immagine con le linee in coordinate polari f
Vediamo le griglie formate da questa funzione, senza deformazione:
In[119]:= << Graphics`ComplexMap`
Daniele Lupo Appunti di Mathematica
374Printed by Mathematica for Students
In[120]:= CartesianMap@Identity, 8−5, 5<, 8−5, 5<D
-4 -2 2 4
-4
-2
2
4
Out[120]= Graphics
Daniele Lupo Appunti di Mathematica
375Printed by Mathematica for Students
In[121]:= PolarMap@Identity, 80, 2<, 80, 2 Pi<D
-2 -1 1 2
-2
-1
1
2
Out[121]= Graphics
Se vogliamo adesso applicare la funzione, sostituiamo ad Identity la funzione di nostro interesse:
In[122]:= CartesianMap@Cos, 80, 2<, 80, 2 Pi<D
-100 -50 50 100 150 200 250
-250
-200
-150
-100
-50
Out[122]= Graphics
Notate come sia necessario solamente l'head per creare la funzione. Questo, da un lato, permette di
scrivere di meno. Tuttavia se dobbiamo inserire delle funzioni personalizzate dobbiamo o definirle
prima, oppure andare ad usare le funzioni pure. Per esempio, potrei voler mappare qualcosa del tipo:
Daniele Lupo Appunti di Mathematica
376Printed by Mathematica for Students
In[123]:= mappa@x_D := Sqrt@ Cos@xDD
In[124]:= PolarMap@mappa, 80, 10<, 80, 2 Pi<D
20 40 60 80 100
-75
-50
-25
25
50
75
Out[124]= Graphics
Potevamo anche utilizzare, naturalmente, una funzione pura, per ottenere lo stesso risultato, evitando
di andare a definire prima la funzione; vediamolo con il seno, stavolta:
Daniele Lupo Appunti di Mathematica
377Printed by Mathematica for Students
In[125]:= PolarMap@Sqrt@Sin@#DD &, 80, 10<, 80, 2 Pi<D
20 40 60 80 100
-100
-50
50
100
Out[125]= Graphics
Come potete vedere la rappresentazione è semplice, invece di andare a creare una lista di funzioni
come sarebbe stato necessario se avessimo utilizzato solamente il comando Plot.
üGraphics`FilledPlot`Con questo package non si crea della matematica od altre cose importanti, ma a mio avviso permette
di creare grafici bidimensionali con un aspetto più accattivante senza dover andare a giocherellare
con le opzioni, riempendendoli (cosa che le opzioni di Plot non fanno):
FilledPlot[f, {x,xmin, xmax}]
disegna f nella variabile x, riempendo lo spazio frala funzione e l'asse delle ascisse
FilledPlot[{ f1, f2, …
}, {x, xmin, xmax}] disegna fi, riempendo lo spazio fra due successivecoppie di curve con colori differenti
Il funzionamento è molto semplice:
In[126]:= << Graphics`FilledPlot`
Daniele Lupo Appunti di Mathematica
378Printed by Mathematica for Students
In[127]:= FilledPlot@BesselJ@3, xD, 8x, 0, 30<D
5 10 15 20 25 30
-0.3
-0.2
-0.1
0.1
0.2
0.3
0.4
5 10 15 20 25 30
-0.3
-0.2
-0.1
0.1
0.2
0.3
0.4
Out[127]= Graphics
Possiamo anche riempire gli spazi di funzioni successive:
In[128]:= FilledPlot@Evaluate@Table@BesselJ@n, xD, 8n, 7<D
D,8x, 0, 30<D
5 10 15 20 25 30
-0.2
0.2
0.4
0.6
5 10 15 20 25 30
-0.2
0.2
0.4
0.6
Out[128]= Graphics
I colori, di default, sono scelti automaticamente. Tuttavia ci sono opzioni che permettono di
modificare il tipo di colori utilizzati per il riempimento dello spazio fr ale funzioni:
Daniele Lupo Appunti di Mathematica
379Printed by Mathematica for Students
option name default value
Fills Automatic curve e stili usate per il riempimento
Curves Back il modo in cuivengono visualizzate le curve
Fills lavora in diversi modi: possiamo specificare direttamente i colori utilizzati, in maniera che fra la
prima funzione e la seconda ci sia un colore, fra la seconda e la terza un altro e così via, scrivendo
qualcosa come Fills -> {color1, color2, … }. Se, invece, vogliamo specificare il colore che
riempe lo spazio fra due curve specifiche della lista possiamo utilizzare Fills -> {{{curve11,
curve21}, color1}, … }, dove {curve11, curve21} sono due numeri che rappresentano le
posizioni, nella lista, delle funzioni che prendiamo in considerazione, e riempiamo lo spazio fra di
loro con il colore specificato. Se vogliamo indicare l'asse delle ascisse utilizziamo, al posto del
numero, la parola Axis. Invece, il parametro Curve determina se dobbiamo disegnare le curve delle
funzioni dietro i colori, davanti oppure non dobbiamo disegnarle.
Consideriamo la seguente lista di funzioni:
In[129]:= lista = 8Cos@xD, Sin@xD, Cos@5 xD, Sin@5 xD<;
In[130]:= Plot@Evaluate@listaD, 8x, 0, 2 Pi<D
1 2 3 4 5 6
-1
-0.5
0.5
1
Out[130]= Graphics
Supponiamo di voler riempire lo spazio fra la prima e la terza funzione della lista, ed anche fra la
terza e la quarta, rispettivamente con il rosso e con il verde:
Daniele Lupo Appunti di Mathematica
380Printed by Mathematica for Students
In[131]:= FilledPlot@Evaluate@listaD, 8x, 0, 2 Pi<,Fills → 8881, 3<, Red<, 883, 4<, Green<<D
1 2 3 4 5 6
-1
-0.5
0.5
1
1 2 3 4 5 6
-1
-0.5
0.5
1
Out[131]= Graphics
Abbiamo riempito solamente quello che ci serviva. Vedete anche come le linee dei grafici siano
nascosti dal colore. Se vogliamo mostrarli dobbiamo specificarlo con l'altra opzione:
In[132]:= FilledPlot@Evaluate@listaD, 8x, 0, 2 Pi<,Fills → 8881, 3<, Red<, 883, 4<, Green<<, Curves → FrontD
1 2 3 4 5 6
-1
-0.5
0.5
1
1 2 3 4 5 6
-1
-0.5
0.5
1
Out[132]= Graphics
Ed in questo modo abbiamo specificato di voler vedere le linee dei grafici.
Abbiamo anche analoghi comando per le liste di dati, non solo per le funzioni:
Daniele Lupo Appunti di Mathematica
381Printed by Mathematica for Students
FilledListPlot[{y1, y2,… }]
genera dei grafici di dati dati da {1, y1}, {2, y2},… colorando lo spazio fra il grafico e l'asse delle
FilledListPlot[{{x1,y1}, {x2, y2}, … }]
genera un grafico, riempendo lo spazio fra la curvedei dati e l'asse x delle ascisse
F i l l e d L i s t P l o t [data1 ,
data2, … ] genera un grafico con colori fra le curve specificatedai dati specificati datai
Le opzioni in questo caso sono analoghe a quelle viste prima:
In[133]:= lista = 83, 5, 5, 6, 5, 5, 4, 3, 3, 7<;
In[134]:= FilledListPlot@lista, Fills → YellowD
2 4 6 8 10
1
2
3
4
5
6
7
2 4 6 8 10
1
2
3
4
5
6
7
Out[134]= Graphics
In[135]:= lista2 = 86, 8, 2, 2, 9, 1, 7, 3, 7, 2<;
Daniele Lupo Appunti di Mathematica
382Printed by Mathematica for Students
In[136]:= FilledListPlot@lista, lista2D
2 4 6 8 10
2
4
6
8
2 4 6 8 10
2
4
6
8
Out[136]= Graphics
Un package piccolo ma simpatico, non trovate?
Daniele Lupo Appunti di Mathematica
383Printed by Mathematica for Students
üGraphics`Graphics`Questo package aggiunge nuovi comandi che permettono di disegnare particolari tipi di grafici, che
sarebbe difficoltoso da fare con i comandi predefiniti di Mathematica: per esempio, i grafici
logaritmici, oppure quelli polari:
LogPlot[f, {x, xmin, xmax}] genera un grafico lineare-logaritmico di f in funzione dix da xmin a xmax
LogLinearPlot[f, {x,xmin, xmax}]
genera un grafico logaritmico-lineare di f
LogLogPlot[f, {x,xmin, xmax}]
genera un grafico logaritmico-logaritmico di f
LogListPlot[{{x1 ,y1}, {x2, y2}, … }]
genera un grafico lineare logaritmico dei dati Hx1,y1L, …
LogLinearListPlot[{{x1,y1}, {x2, y2}, … }]
genera un grafico logaritmico-lineare dei dati Hx1,y1L, …
LogLogListPlot[{{x1,y1}, {x2, y2}, … }]
genera un grafico logaritmico-logaritmico dei datiHx1,y1L, …
LogListPlot[{y1, y2, … }],LogLinearListPlot[{y1, y2,… }],
LogLogListPlot[{y1, y2,… }]
grafici dei punti y1, y2, … con valori di x 1, 2, …
Questo package è utile, per esempio, per il tracciamento dei diagrammi di Bode oppure di Nyquist,
dato che permette di lavorare con grafici logaritmici e polari:
In[137]:= << Graphics`Graphics`
In[138]:= tf@ωD := 3 HI ω − 2L HI ω − 15LêHHω^2 + 4 I ω + 2L HI ω − 10L^5L
Daniele Lupo Appunti di Mathematica
384Printed by Mathematica for Students
In[139]:= LogLogPlot@Abs@tf@ωDD, 8ω, 1, 100<D
— ParametricPlot::pptr : 9 Log@ωDLog@10D ,
Log@Abs@tf@ωDDDLog@10D = does not
evaluate to a pair of real numbers at ω = 1.000004125`. More…
— ParametricPlot::pptr :
9 Log@ωDLog@10D ,
Log@Abs@tf@ωDDDLog@10D = does not evaluate to a pair of
real numbers at ω = 5.0161321657186635 .̀ More…
— ParametricPlot::pptr :
9 Log@ωDLog@10D ,
Log@Abs@tf@ωDDDLog@10D = does not evaluate to a pair of
real numbers at ω = 9.396071186077995 .̀ More…
— General::stop : Further output ofParametricPlot::pptr will be suppressed during this calculation. More…
1 1.5 2 3 5 7 101
1.5
2
3
5
7
10
Out[139]= Graphics
Daniele Lupo Appunti di Mathematica
385Printed by Mathematica for Students
In[140]:= PolarPlot@1 − Cos@ωD, 8ω, 0, 2 π<, Frame → True,PlotStyle → [email protected], [email protected]<<D
-2 -1.5 -1 -0.5 0
-1
-0.5
0
0.5
1
Out[140]= Graphics
Come potete vedere, le opzioni sono simili a quelle che si hanno per i comandi standard.
Inoltre, Mathematica con questo package è anche in grado di eseguire diversi tipi di grafico utili per
la rappresentazione dei dati, come quelli che si vedono, per esempio, in Excel: grafici a torta, a barre
e così via.
BarChart[datalist1, datalist2,… ]
genera un grafico a barre a partire dai set di dati
GeneralizedBarChart[datalist1, datalist2, … ]
genera un grafico a barre dei seti di dati ,dove i dati specificano la posizione,l' altezza e la larghezza delle barre
StackedBarChart[datalist1,datalist2, … ]
genera un grafico a barre impilate
PercentileBarChart[datalist1,datalist2, … ]
genera un grafico a barre impilate dei dati, dove i datidi ogni grupo di barre sono scalati in modo che ilvalore assoluto della somma si auguale ad 1
Supponiamo di avere le tre seguenti liste di dati:
Daniele Lupo Appunti di Mathematica
386Printed by Mathematica for Students
In[141]:= dati1 = 81, 2, 3, 5, 6, 3, 5, 1, 3<;
In[142]:= dati2 = 85, 7, 6, 0, 9, 7, 1, 3, 6<;
In[143]:= dati3 = 85, 6, 6, 7, 3, 1, 2, 1, 4<;
Vediamo la differenza fra i tipi di grafico ottenibili:
In[144]:= BarChart@dati1, dati2, dati3D
1 2 3 4 5 6 7 8 9
2
4
6
8
Out[144]= Graphics
In[145]:= StackedBarChart@dati1, dati2, dati3D
1 2 3 4 5 6 7 8 9
2.5
5
7.5
10
12.5
15
17.5
Out[145]= Graphics
Daniele Lupo Appunti di Mathematica
387Printed by Mathematica for Students
In[146]:= PercentileBarChart@dati1, dati2, dati3D
1 2 3 4 5 6 7 8 9
10%
20%
30%
40%
50%
60%
70%
80%
90%
100%
Out[146]= Graphics
Nel caso del comando GeneralizedBarChart, ogni elemento della lista dei dati è a sua volta una lista
di tre elementi, dove il primo elemento rappresenta la posizione della barra nell'asse delle ascisse, il
secondo elemento rappresenta l'altezza della barra, ed il terzo la larghezza:
In[147]:= dati = 881, 2, 3<, 810, 5, 1<, 85, 3, 2<<;
In[148]:= GeneralizedBarChart@datiD
2 4 6 8 10
1
2
3
4
5
Out[148]= Graphics
Naturalmente abbiamo delle opzioni che ci permettono di poter formattare i grafici a
barre:
Daniele Lupo Appunti di Mathematica
388Printed by Mathematica for Students
option name default value
BarOrientation Vertical determina l'orientamento dellebarre: Vertical oppure
BarStyle Automatic determina lo stile delle barre; per unsingolo set di dati determina l'aspetto diogni barra. Per più set di dati determinalo stile di ogni singolo set
BarLabels Automatic determina le etichette da applicarenei marker della posizione
BarEdges True specifica se bisogna disegnare ilcontorno delle barre
BarEdgeStyle Automatic detrermina lo stile per il contornodelle barre
Oltre a queste opzioni, i comandi accettano anche la maggior parte delle opzioni utilizzate dai
comandi di grafica standard. Vediamo di ridisegnare, per esempio, il secondo grafico che abbiamo
fatto, con qualche opzione in più...
In[149]:= PercentileBarChart@dati1, dati2, dati3,BarStyle → [email protected], [email protected], [email protected]<,BarOrientation → Horizontal,Axes → False,Frame → TrueD
0% 10% 20% 30% 40% 50% 60% 70% 80% 90%100%
1
2
3
4
5
6
7
8
9
0% 10% 20% 30% 40% 50% 60% 70% 80% 90%100%
1
2
3
4
5
6
7
8
9
Out[149]= Graphics
Vediamo un altro esempio:
Daniele Lupo Appunti di Mathematica
389Printed by Mathematica for Students
In[150]:= BarChart@dati1, dati2,BarStyle → [email protected], [email protected]<,BarEdgeStyle → 88Red, [email protected], [email protected], 0.03<D<,8Red, [email protected]<<
D
1 2 3 4 5 6 7 8 9
2
4
6
8
Out[150]= Graphics
Ci sono alche altre opzioni per una formattazione
migliore
BarValues -> True etichetta ogni barra con il suo valore
BarStyle -> function colora ogni barra applicando la funzionedefinita all'altezza della barra stessa
BarSpacing −> Automatic Specifica lo spazio che intercorre fra le barre,come frazione della larghezza di una singola barra
BarGroupSpacing −>
AutomaticSpecifica lo spazio che intercorre fra ogni gruppo di barre,
come frazione della larghezza di una singola barra
Ovviamente l'ultima opzione vale solamente per il comando BarChart, dato che negli altri non ci
sono gruppi, ma le barre sono impilate fra di loro:
Daniele Lupo Appunti di Mathematica
390Printed by Mathematica for Students
In[151]:= BarChart@dati1,BarValues → True,BarStyle → HIf@# > 3, Blue, RedD &L,Frame → True,Axes → False
D
1 2 3 4 5 6 7 8 90
1
2
3
4
5
61 2 3 4 5 6 7 8 9
1
2
3
5
3
5
1
3
Out[151]= Graphics
Un altro tipo di grafico molto utilizzato per la presentazione dei dati è il grafico a
torta:
PieChart[data] genera un grafico a torta dei dati
Consideriamo questa volta i seguenti dati:
In[152]:= listatorta = 82, 3, 4, 5, 5<;
Daniele Lupo Appunti di Mathematica
391Printed by Mathematica for Students
In[153]:= PieChart@listatortaD
1
2
3
45
Out[153]= Graphics
Anche in questo caso sono presenti varie opzioni per personalizzare il grafico
ottenuto:
PieStyle -> stylelist specifica gli stili che devono essere usati (in manieraciclica) per la sequenza delle parti del grafico a tortache rappresentano i singoli dati
PieLineStyle -> linestyle specifica lo stile che deve essere utilizzato per le lineedi bordo del grafico
PieLabels -> lablelist specifica le etichette che verranno applicate(ciclicamente), alle 'fette' della torta del graficoche rappresentano i singoli dati
PieExploded -> All genera un grafico a torta esploso
PieExploded ->{wedge1, wedge2, … }
esplode solamente le fette corrispondenti agliindici wedge1, wedge2, …
Sempre per i dati di prima, possiamo mostrare il grafico a torta con delle specifiche fette esplose:
Daniele Lupo Appunti di Mathematica
392Printed by Mathematica for Students
In[154]:= PieChart@listatorta,PieExploded → 882, .3<, 84, .1<<,PieLineStyle → [email protected], Gray<,PieLabels → H# &LD
1
2
3
4 5
Out[154]= Graphics
Abbiamo fatto parecchie cosette: prima di tutto, abbiamo notato come nell'opzione PieExploded,
oltre a specificare quale fetta debba essere esplosa, abbiamo anche visto che possiamo specificare di
quanto debba essere staccata. Poi, invece di indicare le fette con un indice generico, ho creato una
funzione pura che restituisce il valore del dato, per cui questo stesso valore è rappresentato
all'interno della fetta; meglio sicuramente di avere un indice generico, a mio avviso, ma poi si può
creare quello che si vuole, naturalmente. Infine ho anche aggiustato le linee di contorno. Non sarà il
massimo dell'estetica, ma è per farvi vedere come funziona...
Un altro aspetto interessante è quando decidiamo di mostrare più diagrammi assieme; il modo
convenzionale che si utilizza è quello di realizzare i singoli grafici considerando l'opzione Display
Function -> Identity , e poi mostrarli assieme mediante Show. Tuttavia, per evitare di dover
disegnare i grafici prima uno ad uno, questo package include dei comandic he automatizzano questo
lavoro:
Daniele Lupo Appunti di Mathematica
393Printed by Mathematica for Students
DisplayTogether[plot1,plot2, … , opts]
combina i grafici ottenuto dai comandi di grafica cheha come argomento, restituendo un unico oggetto
DisplayTogetherArray[plotarray, opts]
combina i grafici definiti da plotarray (una lista digrafici annidata a matrice) in un oggetto Graphics
Questi comandi accettano le opzioni di Graphics e di GraphicsArray:
In[155]:= DisplayTogether@Plot@Sin@xD, 8x, 0, 5<, PlotStyle → [email protected], 0.02<D, Red<D,Plot@Cos@x^2D, 8x, 0, 5<,PlotStyle → [email protected], Blue<
D,Frame → TrueD
0 1 2 3 4 5-1
-0.5
0
0.5
1
Out[155]= Graphics
Il package contiene anche comandi per creare tipi di grafico meno usati, ed alcuni anche meno
'ortodossi':
Daniele Lupo Appunti di Mathematica
394Printed by Mathematica for Students
TextListPlot[{y1, y2, … }] disegna il grafico con i dati y1, y2, … per valori di xpari a 1, 2, … , mostrando, al posto dei punti, le etichette1, 2, …
TextListPlot[{{x1 ,y1}, {x2, y2}, … }]
disegna i punti Hx1 , y1L, Hx2 , y2L, … ,renderizzandoli come 1, 2, …
TextListPlot[{{x1, y1,expr1}, {x2, y2, expr2}, … }]
disegna i punti Hx1 , y1L, Hx2 , y2L, … renderizzandolicon il testo expr1, expr2, …
LabeledListPlot[{y1, y2,… }]
disegna y1, y2, … per valori di x pari a 1, 2,… , etichettando i punti con 1, 2, …
LabeledListPlot[{{x1,y1}, {x2, y2}, … }]
disegna i punti Hx1 , y1L, Hx2 , y2L, … , etichettandoli coni valori 1, 2, …
LabeledListPlot[{{x1, y1,expr1}, {x2, y2, expr2}, … }]
disegna i punti Hx1 , y1L, Hx2 , y2L, … , etichettandolicon expr1, expr2, …
ErrorListPlot[{{y1 ,d1}, {y2, d2}, … }]
genera un grafico di dati con le barre di errore
Consideriamo una lista di dati numerici, come al solito:
In[156]:= data = 82, 4, 5, 6, 4, 3, 6, 7, 7, 3, 1, 3, 4, 6, 7<;
— General::spell1 : Possible spelling error: newsymbol name "data" is similar to existing symbol "dati". More…
In[157]:= TextListPlot@dataD
2 4 6 8 10 12 14
1
2
3
4
5
6
7
1
2
3
4
5
6
7
8 9
10
11
12
13
14
15
Out[157]= Graphics
Tuttavia questo tipo di grafico a me personalmente non piace; trovo più utile il seguente, che è anche
più chiaro:
Daniele Lupo Appunti di Mathematica
395Printed by Mathematica for Students
In[158]:= LabeledListPlot@dataD
2 4 6 8 10 12 14
1
2
3
4
5
6
7
1
2
3
4
5
6
7
8 9
10
11
12
13
14
1
Out[158]= Graphics
Per risultati sperimentali, è estremamente utile il grafico con i corrispondenti errori, che devono
essere comunque misurati a parte:
In[159]:= data = Table@8n + Sin@nê6D + Random@Real, 81, 3<D, Random@Real, 82, 4<D<, 8n, 30<D;
In[160]:= ErrorListPlot@dataD
5 10 15 20 25 30
5
10
15
20
25
30
Out[160]= Graphics
Naturalmente, questo grafico è molto più utile se i dati hanno un senso...
Un altro grafico utile nella rappresentazione di dati sperimentali è dato dall'istogramma:
Daniele Lupo Appunti di Mathematica
396Printed by Mathematica for Students
Histogram[{x1, x2, … }] genera un istogramma dei dati grezzi
Histogram[{ f1, f2, …}, FrequencyData ->
genera un istogramma dei dati di frequenza, doce, sei valori di taglio sono dati da c0,c1,c2,..., allora firappresenta il numeri di dati in c j-1<=x<c j
Gli istogrammi sono utilizzati per mostrare quanti dati rientrano entro un determinato range di valori,
dando una visione maggiormente d'insieme, e più sintetica. Vediamo un esempio con una serie di
dati sperimentali:
In[331]:= esperimento = Random@D & ê@ Range@0, 1000D;
In[332]:= Histogram@esperimentoD
0.2 0.4 0.6 0.8 1
5
10
15
20
25
30
35
Out[332]= Graphics
Di default Mathematica sceglie intervalli formati da numeri semplici:
Daniele Lupo Appunti di Mathematica
397Printed by Mathematica for Students
In[334]:= Histogram@esperimento,HistogramCategories → 80, .2, .5, 1<D
0.2 0.4 0.6 0.8 1
200
400
600
800
1000
Out[334]= Graphics
In questo caso abbiamo definito degli intervalli definiti da noi, personalizzando in questa maniera il
grafico. Ci sono alcune opzioni importanti per questo tipo di grafico:
option name default value
ApproximateIntervals Automatic specifica se i limiti degli intervallidebbano essere o meno approssimati adei numeri semplici; può assumerevalore True, False, o Automatic
FrequencyData False specifica se i dati debbano essereconsiderati grezzi, per i quali le categoriedi frequenze devono essere trovati,oppure se i dati debbano essereconsiderati già dati di frequenza per gliintervalli specificati con HistogramCategories
HistogramCategories Automatic specifica gli intervalli dell'istogramma
HistogramRange Automatic specifica il range dei dati chedevono essere inclusi
HistogramScale Automatic specifica se le altezze delle barre debbanoessere scalate in modo che le misure dellasomma delle altezze debba essere unitaria
Ticks -> None non disegna marker
Ticks -> Automatic posiziona automaticamente i marker
Ticks -> IntervalBoundaries
posiziona i marker ai limiti degli intervalle
Ticks -> IntervalCenters posizione i marker ai centri degli intervalli
Ticks -> {xticks, yticks} specifica i marker per gli assi
Daniele Lupo Appunti di Mathematica
398Printed by Mathematica for Students
Supponiamo, per esempio, di avere dei dati sperimentali, che dicono che 30 risultati stanno
nell'intervallo fra 0 e 10, 43 risultati fra 10 e 20, 69 risultati fra 20 e 30, e 44 risultati fra 30 e 40:
In[164]:= dati = 830, 43, 69, 44<;
In[165]:= intervalli = 80, 10, 20, 30, 40<;
In[166]:= Histogram@dati,FrequencyData → True,HistogramCategories → intervalli,BarStyle → HHue@Random@DD &L,Frame → True,FrameTicks → None,GridLines → Automatic,Ticks → IntervalBoundariesD
10 20 30 40
10
20
30
40
50
60
70
Out[166]= Graphics
Potete vedere come, oltre alle opzioni proprie di questo comando, abbia aggiunto anche qualche
opzione standard, per fare panza e presenza, e soprattutto per rendere più piacevole l'aspetto del
grafico e più efficace
Daniele Lupo Appunti di Mathematica
399Printed by Mathematica for Students
üGraphics`Graphics3D`Questo package è analogo a quello visto a prima, per i grafici tridimensionali. Estende il numero di
comandi possibili creando nuove tipologie di grafici e nuovi modi per rappresentarli.
Prim di tutto, sono presenti comandi per poter creare un grafico a barre tridimensionale:
BarChart3D[{{z11, z12, …}, {z21, z22, … }, … }]
crea un grafico a barre tridimensionale usando unarray bidimensionale delle altezze zx y
B a r C h a r t 3 D [ { { {z11 ,style11}, {z12, style12}, …
crea un grafico a barre specificando lo stile dellesingole barre
Vediamo il funzionamento, che è abbastanza semplice:
In[167]:= << Graphics`Graphics3D`
In[168]:= dati = 881, 1, 2<, 82, 3, 1<<;
In[169]:= BarChart3D@datiD
0.51
1.5
2
2.5
1
2
3
0
1
2
3
0.51
1.5
2
1
2
3
Out[169]= Graphics3D
Daniele Lupo Appunti di Mathematica
400Printed by Mathematica for Students
Come potete vedere il comando usa la grafica standard tridimensionale (si riconosce dalle opzioni
standard), quindi possiamo anche andare a modificarle come facciamo per i comandi predefiiti:
In[170]:= Show@%, LightSources → 8885, 4, 6<, [email protected]<<, Boxed → FalseD
0.51
1.5
2
2.5
1
2
3
0
1
2
3
0.51
1.5
2
1
2
3
Out[170]= Graphics3D
Oltre a queste opzioni, ci sono anche quelle specifiche per questo comando, che permettono di
personalizzare il modo in cui vengono visualizzate le barre:
option name default value
XSpacing 0 spazio fra le barre nella direzione x
YSpacing 0 spazio fra le barre nella direzione y
SolidBarEdges True specifica se disegnare gli spigolidelle barre
SolidBarEdgeStyle GrayLevel[0] specifica lo stile degli spigoli
SolidBarStyle GrayLevel[0.
5] specifica lo stile per le facce delle barre
Possiamo utilizzare anche questi comandi per poter disegnare meglio le barre:
Daniele Lupo Appunti di Mathematica
401Printed by Mathematica for Students
In[171]:= massimo = Max@datiD
Out[171]= 3
3
In[172]:= BarChart3D@dati,XSpacing → .12,YSpacing → .12,SolidBarStyle → [email protected],Boxed → False,Lighting → False,FaceGrids → 880, 1, 0<, 8−1, 0, 0<<D
1
1.5
2
1
2
3
0
1
2
3
1
1.5
2
1
2
3
Out[172]= Graphics3D
Come abbiamo visto, è abbastanza facile personalizzarlo. Un difetto che ho personalmente
incontrato in questo comando è che l'opzione SolidBarStyle non accetta funzioni pure, come
Hue[#]&, per poter selezionare individualmente il colore di una singola barra; non so se questo si
possa fare oppure no, ma non ci sono riuscito... Se qualcuno riesce a farlo, sarebbe molto gentile a
farmi sapere come c@##o ha fatto, che io non ci sono riuscito in nessun modo!!!! Lo citerò nella
prossima edizione di questi appunti ringranziandolo pubblicamente, naturalmente!
Un altro comando che da questo package riguarda i grafici scatter, cioè a punti, che possiamo
Daniele Lupo Appunti di Mathematica
402Printed by Mathematica for Students
eseguire anche in tre dimensioni (sarebbe l'analogo di ListPlot):
ScatterPlot3D[{{x1,y1, z1}, {x2, y2, z2},
genera un grafico scatter nelle tre dimensioni
ScatterPlot3D[{{x1,y1, z1}, {x2, y2, z2},… }, PlotJoined ->
collega assieme i punti con una linea
ListSurfacePlot3D[{{{x11,y11, z11}, {x12, y12, z12},… }, … }]
usa la lista di punti per generare una meshtridimensionale avente i dati come vertici
Notate come, mentre per il caso bidimensionale ListPlot bastava solamente una coordinata del dato,
dato che la x era assegnata automaticamente con 1, 2..., in questo caso invece dobbiamo esplicitare
per forza tutte e tre le coordinate di ogni singolo punto:
In[173]:= << Graphics`Graphics`
In[174]:= punti = Table@8Sin@x^.6D, Cos@x^.6D, x<, 8x, 0, 50, 1<D;
In[175]:= DisplayTogetherArray@8ScatterPlot3D@punti, BoxRatios → 81, 1, 2<D,ScatterPlot3D@punti, BoxRatios → 81, 1, 2<, PlotJoined → TrueD
<D
-1-0.5 0 0.5 1
-1-0.5
00.5
1
0
20
40
1-0.5
00.5
-1-0.5 0 0.5 1
-1-0.5
00.5
1
0
20
40
1-0.5
00.5
Out[175]= GraphicsArray
Ho anche usato un comando che abbiamo visto prima... Vedete come apprendere bene i songoli
comandi permetta di saperli combinare assieme per raggiungere il risultato ottenuto. Saper utilizzare
Daniele Lupo Appunti di Mathematica
403Printed by Mathematica for Students
tutti i comandi e saperli combinare nella maniera giusta è particolarmente importante, e potete
impararlo soltanto con la pratica, perchè solo così saprete che esistono comandi che fanno
istantaneamente quello che invece volete fare scrivendo righe e righe di codice...
Possiamo anche rappresentare delle superfici date da liste di punti. Per esempio, potremmo importare
dei punti che rappresentano la triangolazione di un territorio, oppure delle serie di misure in cui varia
un parametro dell'esperimento, e così via... ogni dato deve contenere le tre coordinate
In[176]:= dati = 8880, 0, 1<, 80, 1, 1<, 80, 2, 1<<,881, 0, 1<, 81, 1, 2<, 81, 2, 0<<,882, 0, 0<, 82, 1, 1<, 82, 2, 1<<<;
In[177]:= ListSurfacePlot3D@dati, ViewPoint −> 80.675, 1.246, 3.073<D
Out[177]= Graphics3D
Come potete vedere, occorre che i punti siano spazialmente omogeneri, per ottenere una mesh
adeguata: i punti devono essere ordinati in modo da poter rappresentare la prima riga le coordinate
della prima riga della mesh, la seconda riga le coordinate della seconda riga della mesh e cos' via. Se
utilizziamo punti che si sovrappongono, accadrà lo stesso nel grafico. Per esempio, supponiamo di
spostare il punto centrare della lista in modo che si trovi prima della prima riga della mesh. Facciamo
un esempio con questa mesh:
Daniele Lupo Appunti di Mathematica
404Printed by Mathematica for Students
In[178]:= dati2 = Table@8n, m, Exp@−5 Hn^2 + m^2LD<,8n, −1, 1, .1<,8m, −1, 1, .1<D;
In[179]:= ListSurfacePlot3D@dati2, PlotRange → AllD
Out[179]= Graphics3D
Andiamo a modificare il punto centrale della mesh, in modi che le sue coordinate x ed y varino,
sovrapponendosi a qualche altro punto della mesh:
In[180]:= dati2@@10, 10DD = 8−.5, −.2, 1<;
Daniele Lupo Appunti di Mathematica
405Printed by Mathematica for Students
In[181]:= ListSurfacePlot3D@dati2, PlotRange → AllD
Out[181]= Graphics3D
Come vedete, il processo di generazione della mesh ha preso quel punto come appartenente sempre a
quella posizione della griglia, deformandola di conseguenza. Questo può essere o meno utile per
quello che volete fare, ma in entrambi i casi, state attenti a come impostate l'ordine dei dati nella
creazione della matrice.
Un altro comando, a mio avviso molto interessante per la presentazione di un grafico, è il seguente:
ShadowPlot3D[f, {x,xmin, xmax}, {y, ymin,
crea un grafico tridimensionale della funzione, edisegna la proiezione nel piano x-y
ListShadowPlot3D[{{z11,z12, … }, {z21, z22, … },… }]
come prima, ma per liste di punti
Shadow[g] crea delle proiezioni dell'oggetto grafico nei pianidegli assi
I comandi sono simili a quelli standard, come pure le opzioni generiche:
Daniele Lupo Appunti di Mathematica
406Printed by Mathematica for Students
In[182]:= ShadowPlot3D@x^2 + y^2 + 3 Sin@x yD, 8x, −5, 5<, 8y, −5, 5<,PlotPoints → 50,Lighting → False,ShadowMesh → FalseD
Out[182]= Graphics3D
Notate come, con le opzioni di default per il colore della mesh e delle luci, bisogna disabilitare
queste ultime affinchè l'ombra sia effettivamente disegnata: in caso contrario, avremmo non il colore
della funzione, ma del piano con la luce, quindi un piano uniforme. Notate come varino alcune
opzioni di default: per esempio, in Plot3D di default il colore della mesh è uniforme, mentre in
questo caso è dato dalla funzione Hue. Inoltre ci sono parametri distinti per personalizzare sia la
mesh che la sua proiezione: per esempio, in Plot3D ho l'opzione Mesh, mentre qua ne ho due,
SurfaceMesh e ShadowMesh, per personalizzarle in maniera indipendente. Le opzioni specifiche
sono:
Daniele Lupo Appunti di Mathematica
407Printed by Mathematica for Students
option name default value
ColorFunction Hue funzione per determinare il coloredella superfice in base all'altezza
SurfaceMesh True specifia se disegnare le linee dellamesh della superfice
SurfaceMeshStyle RGBColor[0,0, 0]
direttive grafiche per disegnare lamesh della superfice
ShadowMesh True specifica se disegnare la mesgdella proiezione
ShadowMeshStyle RGBColor[0,0, 0]
direttive grafiche per disegnare lamesh della proiezione
ShadowPosition -1 specifica se la mesh debba esseredisegnata nella superfice inferioreo superiore
Se vogliamo proiettarlo in altri piani, dobbiaom utilizzare il comando Shadow, il che significa che
prima dobbiamo creare il grafico e poi utilizzarlo con Shadow:
In[183]:= grafico = Plot3D@x^2 + y^2 + 3 Sin@x yD, 8x, −5, 5<, 8y, −5, 5<,PlotPoints → 30,Lighting → False,ColorFunction → Hue
D
-4-2
02
4-4
-2
0
2
4
0
20
40
-4-2
02
4
Out[183]= SurfaceGraphics
Daniele Lupo Appunti di Mathematica
408Printed by Mathematica for Students
In[184]:= Shadow@grafico, BoxRatios → 81, 1, 1<,Lighting → False, ShadowMesh → False,XShadowPosition → 1D
Out[184]= Graphics3D
Come potete vedere qua già ci avviciniamo alla qualità dei grafici pubblicati nelle riviste (senza
bisogno di andare ad usare programmi come Origin), e ciò sarà ancora più vero quando, più avanti,
spiegherò il package per fare le legende.
Se non ci piacciono le direzioni standard di proiezione, perchè magari ci interessano piani inclinati
(chi studia cristallografia mi capisce bene...), allora può essere utile quest'altro comando, che esegue
proiezioni in qualsiasi piano dello spazio:
Project[g, pt] proietta l'oggetto tridimensionale g nel piano, la cuinormale è rappresentata da un vettore che unisce ilcentro dell'oggetto con il punto pt
Project[g, {e1, e2}, pt] proietta l'oggetto g nel piano che include i vettorivectors {e1, e2} basati su pt
Project[g, {e1, e2},pt, origin]
proietta nella direzione determinata dal vettore pt e origin
Consideriamo il seguente oggetto grafico tridimensionale:
Daniele Lupo Appunti di Mathematica
409Printed by Mathematica for Students
In[185]:= spirale = ParametricPlot3D@8t u Sin@uD, t u Cos@uD, t^3êHu + 9L<, 8t, 0, 5<, 8u, 0, 9 Pi<,PlotPoints → 813, 90<,PlotRange → All,ViewPoint −> 80.675, −1.246, 1.5<,BoxRatios → 81, 1, 1<
D
-1000
100
-100
0
100
0
5
10
-100
0
100
Out[185]= Graphics3D
Daniele Lupo Appunti di Mathematica
410Printed by Mathematica for Students
In[186]:= Show@Project@spirale, 880, .1, 1<, 80, 1, 0<<, 80, 1, 1<, 80, 0, 0<D,ViewPoint −> 8−3.878, 1.362, 0.000<D
-1-0.500.51
-1000100
-10
0
10
0.500.51
Out[186]= Graphics3D
Un altro comando che può essere utile è il
seguente:
StackGraphics[{g1, g2,… }]
restituisce un'immagine tridimensionale a partiredagli oggetti tridimensionali g1,g2,…
Può essere una maniera diversa di rappresentare un grafico bidimensionale al variare di un
parametro; a volte è meno chiaro di una tabella, ma di certo fa più effetto. A parte il fatto che lo
potete usare pure se vi serve per creare un particolare grafico.
Supponiamo di avere le seguenti figure:
In[187]:= figure = Table@Graphics@8Hue@nê10D, Disk@80, 0<, 8n, 1ên<D<D, 8n, .7, 6<
D
Out[187]= 8 Graphics , Graphics , Graphics , Graphics , Graphics , Graphics <
Daniele Lupo Appunti di Mathematica
411Printed by Mathematica for Students
In[188]:= Show@figureD
Out[188]= Graphics
In[189]:= Show@StackGraphics@figure, Lighting → FalseD, PlotRange → AllD
-5-2.5
02.5
5
-1
0
1
-5-2.5
02.5
5
Out[189]= Graphics3D
Come potete vedere, quello che fa questo comando è mettere le figure bidimensionali in fila fra di
loro in un grafico tridimensionale. Notate come questo comando crea solo il l'oggetto grafico, e
come dobbiate utilizzare Show per poterlo anche mostrare.
Daniele Lupo Appunti di Mathematica
412Printed by Mathematica for Students
L'ultimo comando che andiamo a vedere per questo package, è quello riguardante il disegno di
istogrammi tridimensionali:
Histogram3D[{{x1 ,y1}, {x2, y2}, … }]
genera un istogramma dei dati grezzi
Histogram3D[{{{ f11, f12,f13, … }, { f21, f22, f23},… }, … }, FrequencyData-> True]
genera un diagramma delle frequenze relative, dove gliestremi degli intervalli per l'asse x sono dati dac0,c1,c2,..., mentre per l'asse y sono dati da d0,d1,d2,..., equindi fi j rappresenta il numero di dati nell'intervallobidimensionale c j-1<=x<c j e d j-1<=y<d j
Creiamo un esempio di dati bidimensionali con distribuzione Gaussiana:
In[190]:= Table@Exp@HRandom@D^2 + Random@D^2Lê3D, 8n, 4000<, 8m, 2<D;
In[191]:= Histogram3D@%,ViewPoint −> 82.667, 1.154, 2.906<,FaceGrids → 880, −1, 0<, 8−1, 0, 0<<,Boxed → FalseD
1
1.2
1.4
1.6
1.8
11.2
1.41.6
1.8
0
20
40
60
1.21.4
1.61.8
0
20
0
Out[191]= Graphics3D
Come potete vedere, in questo caso ho la rappresentazione dei dati "sperimentali", grezzi. Si ragiona
in maniera analoga al caso bidimensionale, se abbiamo direttamente i dati relativi alle frequenze
Daniele Lupo Appunti di Mathematica
413Printed by Mathematica for Students
relative, specificando il numero di elementi per ogni intervallo, dai dati sperimentali, e anche gli
intervalli:
option name default value
ApproximateIntervals Automatic specifica se gli intervalli debbanoessere approssimati con numerisemplici; può assumere valori True,False, or Automatic
FrequencyData False specifica se i dati debbano essereconsiderati dati grezzi, opure serappresentano direttemente lefrequenze relative, nel qual caso sidevono specificare gli intervalli inHistogramCategories
HistogramCategories Automatic specifica le categorie (intervalli)del diagramma
HistogramRange Automatic specifica il range dei dati chedevono essere inclusi nell' istogramma
HistogramScale Automatic specifica se le altezze delle barredebbano essere scalate in modo che lemisure dell'altezza delle densità dellefrequenze relative o il volume delle barredebba avere una somma unitaria
Anche qua possiamo sia utilizzare opzioni standard per gli oggetti tridimensionali, sia le opzioni per
i marker degli intervalli, che in questo caso sono i seguenti:
Ticks -> None non disegna i marker
Ticks -> Automatic disegna automaticamente i marker
Ticks -> IntervalBoundaries
posizione i marker ai limiti degli intervalli
Ticks -> IntervalCenters posiziona i marker al centro degli intervalli
Ticks -> {xticks,yticks, zticks}
specifica i marker per ogni asse
Vediamo, quindi, un esempio che racchiuda quello che sappiamo fare con questo comando:
In[192]:= dati = 8812, 34, 25, 17<,84, 45, 51, 33<,814, 55, 48, 32<,812, 26, 32, 10<<;
Daniele Lupo Appunti di Mathematica
414Printed by Mathematica for Students
In[193]:= intervalli = 880, 4, 7, 10, 13<,80, 3, 7, 8, 9<<;
In[194]:= Histogram3D@dati,FrequencyData → True,HistogramCategories → intervalli,SolidBarStyle → [email protected],LightSources → 8884, −4, 7<, [email protected]<<,Boxed → False,AxesEdge → 88−1, −1<, 81, −1<, 81, 1<<,Ticks → IntervalBoundaries,FaceGrids → 880, 1, 0<, 8−1, 0, 0<<D
0
47
10
130
3
7890
5
10
15
0
47
10
0
5
1
Out[194]= Graphics3D
Anche in questo caso, non sono riuscito a trovare il modo per colorare in modo indipendente le
barre... :-( Evidentemente ho ancora molto da imparare...
Daniele Lupo Appunti di Mathematica
415Printed by Mathematica for Students
üGraphics`ImplicitPlot`Questo package definisce un comando che permette di disegnare grafici di funzioni implicite, cioè
che non possono essere scritte esplicitamente nella forma y = f @xD , come capita per moltissime
famiglie di curve: per esempio le coniche, definendo il luogo dei punti che rappresentano le
soluzioni dell'equazione:
ImplicitPlot[eqn, {x,xmin, xmax}]
disegna la soluzione di eqn usando il metodo Solve,con x che varia da xmin a xmax
ImplicitPlot[eqn, {x,xmin, m1, m2, … , xmax}]
disegna la soluzione, evitando i punti mi
ImplicitPlot[eqn, {x,xmin, xmax}, {y, ymin,
disegna il grafico utilizzando il metodo usatoda ContourPlot
ImplicitPlot[{eqn1, eqn2,… }, ranges, options]
disegna le soluzioni delle equazioni eqni
Notiamo come il comando può essere utilizzato in due modi: al suo interno può utilizzare sia il
comando Solve, sia un ContourPlot: nel primo caso, definito il range della variabile x, trova le
soluzioni dell'equazione per vari punti di x utilizzando Solve, e poi lo disegna; nel secondo caso,
invece, si viene a creare una rappresentazione bidimensionale, creando un grafico di contorno e
disegnando solamente la curva di livello corrispondente al valore di z pari a 0. Questo metodo è
iterativo e crea curve approssimate, dovendo lavorare con l'opzione PlotPoints per poter creare delle
curve più morbide. Il primo metodo, invece, crea grafici migliori, ma pone i limiti di Solve, quali ad
esempio quelli riguardanti funzioni periodiche ed impossibilità di risolvere determinati tipi di
equazioni. Vediamo adesso entrambi i casi:
In[195]:= << Graphics`ImplicitPlot`
In[196]:= ImplicitPlot@x^2 − 3 y^2 2, 8x, −5, 5<D
-4 -2 2 4
-2
-1
1
2
Out[196]= Graphics
Daniele Lupo Appunti di Mathematica
416Printed by Mathematica for Students
Vediamo che questo è un grafico che non può essere realizzato con Plot, a meno di scindere
l'equazione, disegnare i singoli pezzi ed unirli con Show o con DisplayTogether.
In questo caso Solve funziona, e restituisce il grafico corretto. Vediamo, invece, il seguente disegno:
In[197]:= ImplicitPlot@Sin@x yD 0, 8x, −6, 6<D
— Solve::incnst : Inconsistent or redundant transcendental equation.After reduction, the bad equation is ArcSin@Sin@x yDD == 0. More…
— Solve::ifun : Inverse functions are being used by Solve, so some solutions may not
be found; use Reduce for complete solution information. More…
— Solve::svars : Equations may not give solutions for all "solve" variables. More…
— Solve::ifun : Inverse functions are being used by Solve, so some solutions may not
be found; use Reduce for complete solution information. More…
— Solve::ifun : Inverse functions are being used by Solve, so some solutions may not
be found; use Reduce for complete solution information. More…
— General::stop : Further output of Solve::ifun will be suppressed during this calculation. More…
-6 -4 -2 2 4 6-1
-0.5
0.51
Out[197]= Graphics
Come possiamo vedere, il comando Solve genera degli errori, e avverte che esistono possibilità che
tutte le soluzioni non vengano trovate, restituendo un risultato sbagliato. Se, invece, specifichiamo
pure i limiti per l'asse y, Mathematica cambia metodo di disegno, utilizzando quello di ContourPlot:
Daniele Lupo Appunti di Mathematica
417Printed by Mathematica for Students
In[198]:= ImplicitPlot@Sin@x yD 0, 8x, −6, 6<, 8y, −6, 6<D
-6 -4 -2 0 2 4 6-6
-4
-2
0
2
4
6
Out[198]= ContourGraphics
Come possiamo vedere, in questo caso viene riportato il giusto grafico implicito. Notiamo anche
come le curve siano meno definite rispetto al primo caso: per ovviare a questo nella maggior parte
dei casi, basta aumentare il numero di punti:
Daniele Lupo Appunti di Mathematica
418Printed by Mathematica for Students
In[199]:= ImplicitPlot@Sin@x yD 0, 8x, −6, 6<, 8y, −6, 6<, PlotPoints → 100D
-6 -4 -2 0 2 4 6-6
-4
-2
0
2
4
6
Out[199]= ContourGraphics
Già le cose vanno meglio...
In generale, trovo questo package abbastanza utile, permettendovi di disegnare questi grafici, che
almeno io ho usato parecchio nei miei studi... Provatelo, e non lo abbandonerete facilmente...
üGraphics`InequalityGraphics`Il package contiene dei comandi per visualizzare, in maniera grafica, delle diseguaglianze, sia che si
tratti di numeri reali, che di numeri complessi. Per i numeri reali abbiamo i seguenti comandi:
InequalityPlot[ ineqs,{x, xmin, xmax}, {y,ymin, ymax}]
rappresenta graficamente il set di diseguaglianze ineqsin 2D
I n e q u a l i t y P l o t 3 D [
ineqs, {x, xmin, xmax},{y, ymin, ymax}, {z,
rappresenta graficamente il set di diseguaglianze ineqsin 3D
Nel primo caso si lavora con due variabili, mentre nel secondo caso con tre. Il funzionamento è
abbastanza semplice:
Daniele Lupo Appunti di Mathematica
419Printed by Mathematica for Students
In[200]:= << Graphics`InequalityGraphics`
In[201]:= diseguaglianza = 3 < Abs@x yD < 6;
In[202]:= InequalityPlot@diseguaglianza, 8x, −5, 5<, 8y, −5, 5<D
-4 -2 2 4
-4
-2
2
4
-4 -2 2 4
-4
-2
2
4
Out[202]= Graphics
Come potete vedere, viene colorata automaticamente la regione che soddisfa la diseguaglianza.
Nel caso in cui la regione della diseguaglianza è limitata nel piano, cioè sia confinata entro un
intervallo finito, Mathematica è in grado di disegnarlo interamente, senza la necessità di dover
applicare i limiti per le variabili:
In[203]:= diseguaglianza2 = Hx^2 − y < 1L fl Hx^2 + y^2 < 2L;
Daniele Lupo Appunti di Mathematica
420Printed by Mathematica for Students
In[204]:= InequalityPlot@diseguaglianza2, 8x<, 8y<,Fills → YellowD
-1 -0.5 0.5 1
-1
-0.5
0.5
1
-1 -0.5 0.5 1
-1
-0.5
0.5
1
Out[204]= Graphics
Come potete vedere, essendo in questo caso la regione limitata, non è stato necessario definire
esplicitamente i limiti, anche se ovviamente potevamo farlo, magari perchè ci interessava solamente
una regione del piano. Notate anche come sia possibile introdurre disequazioni con la notazione
standard matematica: per esempio, fl si può scrivere come Esc-and-Esc. Andate a rivedervi la parte
riguardante le abbreviazioni, perchè sono molto utili per scrivere notazioni in matematica standard.
Oltre ai casi bidimensionali, possiamo creare anche grafici tridimensionali rappresentani
diseguaglianze:
In[205]:= dis3D = Abs@x y^5 z^2D < 2 fl x^2 + y^2 + z^2 < 60;
Daniele Lupo Appunti di Mathematica
421Printed by Mathematica for Students
In[206]:= InequalityPlot3D@dis3D, 8x<, 8y<, 8z<, PlotRange → AllD
-5
0
5
-5
0
5
-5
0
5
-5
0
5
-5
0
5
Out[206]= Graphics3D
Tuttavia, ho scoperto alcuni problemucci, quando si tratta di gestire piani perfettamente paralleli ad
uno dei piani verticali. Nell'esempio seguente, infatti, non riesco a disegnare le basi del cilindro, che
rimangono aperte:
In[207]:= dis3D2 = x^2 + y^2 + z^2 ≤ 3 fl Hx + 1L^2 + Hy + 1L^2 + Hz − 1L^2 ≤ 2 fix^2 + z ^2 ≤ .6 fl Abs@yD ≤ .6;
Daniele Lupo Appunti di Mathematica
422Printed by Mathematica for Students
In[208]:= InequalityPlot3D@dis3D2, 8x<, 8y<,8z<, ViewPoint −> 8−1.207, 3.619, 1.528<D
-10
-1.5
-1
-0.5
0
0.5
0
1
-10
Out[208]= Graphics3D
Come potete vedere ci sono aluni problemi nel gestire porzioni di regioni perfettamente parallere ai
piani verticali, e non sono riuscito a trovare un modo per evitarlo, neanche andando a spulciare i
metodi nascosti andando ad aprire il file del package... Mi sa che è un difetto intrinseco del
comando. Comunque, per tutto il resto funziona alla grande.
Comunque, andiamo avanti. Probabilmente esiste un metodo per risolvere questo problema ed io
sono troppo stupido per trovarlo...
Dicevamo, che oltre che con numeri reali, il package ci permette di definire regioni di numeri
complessi:
ComplexInequalityPlot[ineqs, {z, zmin, zmax}]
genera una rappresentazione grafica del set didisequazioni ineqs nella variabile complessa z nellaregione di piano complesso definita da zmin and zmax.
Anche in questo caso, come nel precedente, possiamo evitare di usare i limiti del piano, se la regione
che soddisfa la disequazione è limitata:
Daniele Lupo Appunti di Mathematica
423Printed by Mathematica for Students
In[209]:= ComplexInequalityPlot@−3 < Re@zD < 3 && −3 < Im@zD < 3 && Abs@zD > 1, 8z<D
-3 -2 -1 1 2 3
-3
-2
-1
1
2
3
-3 -2 -1 1 2 3
-3
-2
-1
1
2
3
Out[209]= Graphics
Ohhh, che bel buchino!!! Il procedimento di tracciamento del grafico è analogo a quello del primo
comando, ma la possibilità di gestire parametri complessi permette di gestire con maggior facilità
questi numeri, invece di dover esplicitare sempre parte reale e parte immaginaria:
Daniele Lupo Appunti di Mathematica
424Printed by Mathematica for Students
In[210]:= ComplexInequalityPlot@Abs@z^3 − z^2 − zD > .4, 8z, −1 − 1 I, 2 + 1 I<D
-1 -0.5 0.5 1 1.5 2
-1
-0.5
0.5
1
-1 -0.5 0.5 1 1.5 2
-1
-0.5
0.5
1
Out[210]= Graphics
Daniele Lupo Appunti di Mathematica
425Printed by Mathematica for Students
üGraphics`Legend`Questo package permette di creare delle legende da usare per i grafici. Sebbene non sia importante
per quanto riguarda lo studio vero e proprio (si presume che sappiate cosa state disegnando...),
tuttavia è molto utile quando si decide di esportare i grafici, magari per utilizzarli in un articolo
oppure se dovete stamparli in una slide... Insomma, in tutti quei casi dove una maggiore leggibilità è
d'aiuto.
Il package aggiunge un opzione per il comando Plot, che ci permette di creare legende direttamente
da esso, ed un comando che ci permette di prendere un oggetto grafico ed andare a sovrapporre la
legenda:
PlotLegend -> {text1,text2, … }
opzione per Plot per inserire una legenda delle curve
S h o w L e g e n d [g r a p h i c,legend1, legend2, … ]
posizione le legende legendi sopra l'oggetto grafico
{{{box1, text1}, … }, opts} specifica una legenda, con colori od oggetti graficiin genere per boxi ed espressioni sfruttabili per ilposizionamenti della primitiva Text in texti
{colorfunction, n,minstring, maxstring, opts}
specifica una legenda con n riquadri, ognuno coloratocon colorfunction; anche con stringhe opzionaliper la fine dei riquadri
Vediamo un esempio semplice, che permette di creare una legenda veloce con l'opzione per il
comando Plot. Notate come bisogna specificare con PlotStyle lo stule delle varie curve, perchè
PlotLegend crea solamente le etichette: se non specifichiamo gli stili la legenda sarà leggermente
inutile
In[211]:= << Graphics`Legend`
Daniele Lupo Appunti di Mathematica
426Printed by Mathematica for Students
In[212]:= Plot@8HermiteH@4, xD, HermiteH@6, xD<, 8x, −2, 2<,PlotRange → 8Automatic, 8−200, 200<<,PlotStyle →
[email protected], [email protected]<D<, [email protected], [email protected], .02<D<<,PlotLegend → 8"Grado 3", "Grado 6"<D
-2 -1 1 2
-200
-150
-100
-50
50
100
150
200
Grado 6
Grado 3
Out[212]= Graphics
Naturalmente, ci sono anche delle opzioni che permettono di personalizzare l'aspetto della legenda
all'interno del grafico:
option name default value
LegendPosition {-1, -1} specifica la posizione della legenda inrelazione all'oggetto grafico, dove ilcentro del grafico corrisponde a {0, 0}
LegendSize Automatic determina la lunghezza, oppurele dimensioni in {x, y} nellestesse coordinate di sistemadell'opzione LegendPosition
LegendShadow Automatic None non crea nessun'ombra per ilriquadro, mentre {x, y}restituisce l'offset per l'ombra della
LegendOrientation Vertical Horizontal o Vertical,determina l'orientamento della legenda
LegendLabel None etichetta per la legenda
LegendTextDirection Automatic le direzione del testo viene ruotatacome avviene per la primitiva grafica
LegendTextOffset Automatic offset del testo, come per laprimitiva grafica Text
Daniele Lupo Appunti di Mathematica
427Printed by Mathematica for Students
Se andiamo ad utilizzare altri tipi di grafico, dobbiamo utilizzare il comando ShowLegend. Vediamo
l'esempio e, siccome sarà complesso, lo commenterò come si fa con ognu buon programma:
In[213]:= ShowLegend@H∗
∗ Creazione del grafico didensità. L' opzione DisplayFunction→True,
∗ è necessaria, per evitare di disegnaredue grafici invece di uno.∗ Altrimenti dovrei prima creare il graficomemorizzandolo in una variabile,
∗ e dopo usarla nel comando,anche se anche in questo caso otterrei due grafici.∗L
DensityPlot@Exp@−Hr2Lê9D + [email protected] Hr2LDêSqrt@Hr2 + 1LD Cos@9 Arg@Hx + .1 + I yLDD ê.r2 → x^2 + y^2,8x, −5, 5<, 8y, −5, 5<,PlotPoints → 200,DisplayFunction → Identity,ColorFunction → Hue,Mesh → False,PlotRange → All
D,H∗
Definizione delle opzioni della legenda∗L
8H∗ Funzione di colore della legenda,che combacia con quella della funzione ∗LHue@1 − #D &,H∗ Numero di valori della legenda: più piccolo è il numero,più scalettata è la legenda ∗L
20,H∗ Etichette della Legenda ∗L"2", "−0.13",H∗ Posizione della Legenda ∗LLegendPosition → 81.1, −.65<,H∗ Dimensioni della Legenda ∗LLegendSize → 8.6, 1<,H∗ Spazio attorno la legenda ∗LLegendBorderSpace → .4
<D
Daniele Lupo Appunti di Mathematica
428Printed by Mathematica for Students
-4 -2 0 2 4
-4
-2
0
2
4
−0.13
2
Out[213]= Graphics
In[214]:= ,
— Syntax::sntxi : Incomplete expression; more input is needed. More…
— ,
Sembra lungo e complicato, ma, se levate i commenti, ed il disegno della funzione (che
effettivamente ho scelto abbastanza complicata, ma che da un risultato grafico niente male...), le
righe sono veramente poche, con poche battute per ogni opzione della legenda.
Inoltre, il package definisce le funzioni per poter disegnare l'ombra, oltre che il comando per
restituire l'oggetto grafico che rappresenta la legenda, per utilizzarlo magari in altri contesti:
Legend[legendargs, opts] restituisce la primitiva grafica che descrive la legenda
ShadowBox[pos, size, opts] restituisce un rettangolo con un'ombra definitadalle dimensioni e dalle opzioni
Vediamo come viene rappresentata la legenda sotto forma di primitive grafiche:
Daniele Lupo Appunti di Mathematica
429Printed by Mathematica for Students
In[214]:= Legend@Hue@1 − #D &, 20, "2", "−0.13", LegendPosition → 81.1, −.65<,LegendSize → 8.6, 1<,LegendBorderSpace → .4D
Out[214]= 8GrayLevel@0D, [email protected], −0.7<, 81.75, 0.3<D,GrayLevel@1D, [email protected], −0.65<, 81.7, 0.35<D,[email protected], GrayLevel@0D, [email protected], −0.65<, 81.7, −0.65<, 81.7, 0.35<, 81.1, 0.35<, 81.1, −0.65<<D,
[email protected], −0.65<, 81.7, 0.35<, Graphics D<
In[215]:= Show@Graphics@%DD
−0.13
2
Out[215]= Graphics
Vediamo come creare un rettangolo con l'ombreggiatura:
In[216]:= ShadowBox@80, 0<, 81, 1<, ShadowBackground → [email protected];
Daniele Lupo Appunti di Mathematica
430Printed by Mathematica for Students
In[217]:= Show@Graphics@%DD
Out[217]= Graphics
üGraphics`PlotField`Questo package permette di disegnare campivettoriali bidimensionali, che vengono rappresentati
come un insieme di vettori nel piano con direzione e modulo concordi al valore del campo vettoriale
in quel punto:
PlotVectorField[{ fx ,
fy}, {x, xmin, xmax}, {y,ymin, ymax}]
disegna il campo vettoriale definito dalla lista delledue funzioni componenti, nel range di valori
PlotGradientField[f,{x, xmin, xmax}, {y,ymin, ymax}]
disegna il gradiente della funzione scalare f
PlotHamiltonianField[f,{x, xmin, xmax}, {y,ymin, ymax}]
disegna il campo vettoriale hamiltoniano dellafunzione scalare f
Vediamo subito come funziona:
In[218]:= << Graphics`PlotField`
In[219]:= campovet = 8Hx + yL, x y<;
Daniele Lupo Appunti di Mathematica
431Printed by Mathematica for Students
In[220]:= PlotVectorField@campovet, 8x, −7, 7<, 8y, −7, 7<D
Out[220]= Graphics
Ovviamente, anche in questi casi è possibile determinare il numero di punti (quindi di frecce) che
definiscono il grafico:
Daniele Lupo Appunti di Mathematica
432Printed by Mathematica for Students
In[221]:= PlotVectorField@campovet, 8x, −7, 7<, 8y, −7, 7<, PlotPoints → 30D
Out[221]= Graphics
Per questi comandi sono presenti delle opzioni
specifiche:
option name default value
ScaleFactor Automatic scala linearmente i vettori in manierache quello più lungo abbia lunghezzadeterminata da questo valore;Automatic scala il vettoreautomaticamente per farlo stare nellamesh, None non riscala
ScaleFunction None la funzione utilizzata per scalare ilmodulo dei vettori
MaxArrowLength None lunghezza massima del vettore che verràdisegnato, applicato dopo ScaleFunction ma prima di ScaleFactor
ColorFunction None funzione utilizzata per colorare i vettoria seconda del loro modulo
PlotPoints 15 numero di punti in cui vengono calcolatii vettori in ogni direzione.
Daniele Lupo Appunti di Mathematica
433Printed by Mathematica for Students
Rivediamo il primo grafico, in due diverse salse, usando due diversi set di opzioni, in modo da
rappresentare in maniera diversa la stessa cosa:
In[222]:= << Graphics`Graphics`
In[223]:= DisplayTogetherArray@88PlotVectorField@campovet,8x, −7, 7<, 8y, −7, 7<, ColorFunction → HHue@#D &LD,
PlotVectorField@campovet, 8x, −7, 7<,8y, −7, 7<, ScaleFactor → NoneD
<<D
Out[223]= GraphicsArray
Come possiamo vedere, la rappresentazione cambia; prima avevamo scalato il tutto in modo da far
apparire tutte le frecce all'interno del grafico, e sembravano tutte di modulo simile. Adesso, invece,
abbiamo visto (prima con i colori, dopo con l'eliminazione della scalatura automatica), che i moduli
dei vettori effettivamente cambiano molto, ed il campo è in realtà diverso da come sembrava a prima
vista.
Daniele Lupo Appunti di Mathematica
434Printed by Mathematica for Students
In[224]:= PlotVectorField@8Cos@xD, Sin@yD<, 8x, −10, 10<, 8y, −10, 10<,PlotPoints → 40,ColorFunction → HRGBColor@#, #^2, #^3D &L,ScaleFactor → NoneD
Out[224]= Graphics
Le altre funzioni richiedono invece una funzione scalare, restituendo il gradiente oppure
l'hamiltoniana:
Daniele Lupo Appunti di Mathematica
435Printed by Mathematica for Students
In[225]:= DisplayTogetherArray@88PlotGradientField@x^2 + y, 8x, −7, 7<, 8y, −7, 7<, ScaleFactor → 1D,PlotHamiltonianField@x^2 + y, 8x, −7, 7<, 8y, −7, 7<, ScaleFactor → 1D
<<D
Out[225]= GraphicsArray
Un altro modo di usare i campi vettoriali consiste nella rappresentazioni di funzioni complesse:
infatti, ad un numero complesso ne corrisponde un altro. Allora è possibile creare un campo
vettoriale dove, ad ogni punto del campo complesso, corrisponde un vettore rappresentate il
corrispondente punto complesso nel codominio. Questa rappresentazione è detta di Polya:
PlotPolyaField[f,{x, xmin, xmax}, {y,ymin, ymax}]
disegna la funzione complessautilizzando la rappresentazione di Polya
Daniele Lupo Appunti di Mathematica
436Printed by Mathematica for Students
In[226]:= PlotPolyaField@Sin@x + I yD, 8x, −8, 8<,8y, −8, 8<, PlotPoints → 20, ColorFunction → HueD
Out[226]= Graphics
Inoltre, sono presenti delle funzioni analoghe, che lavorano con liste di dati: il comando accetta due
diversi tipi di dati: nel primo caso l'elemento della lista contiene solamente un vettore, e quindi
saranno rappresentati in un array bidimensionale; nel secondo caso, invece, in ogni elemento della
lista è presente sia le componenti del vettore, che il punto in cui esso compare:
ListPlotVectorField[{{vect11
, vect12, … }, {vect21, vect22,
… }, … }]
crea un grafico vettoriale della matrice di vettori v e c tx y
ListPlotVectorField[{{pt1,vect1}, {pt2, vect2}, … }]
restituisce il grafico vettoriale dei vettori datinei determinati punti
Vediamo il primo caso:
In[227]:= listavettori = Table@8Sin@Sqrt@n^2 + m^2DD, Cos@Sqrt@n^2 + m^2DD<,8n, −4 Pi, 4 Pi, .3 Pi<, 8m, −4 Pi, 4 Pi, .3 Pi<D;
Daniele Lupo Appunti di Mathematica
437Printed by Mathematica for Students
In[228]:= ListPlotVectorField@listavettori, HeadWidth → 0.3D
Out[228]= Graphics
Notate come abbia utilizzato un opzione che permette di modificare l'aspetto delle frecce:
In[229]:= Options@ListPlotVectorFieldD
Out[229]= 9ScaleFactor → Automatic, ScaleFunction → None,
MaxArrowLength → None, ColorFunction → None, AspectRatio → Automatic,HeadScaling → Automatic, HeadLength → 0.02, HeadCenter → 1,HeadWidth → 0.5, HeadShape → Automatic, ZeroShape → Automatic,
AspectRatio →1
GoldenRatio, Axes → False, AxesLabel → None,
AxesOrigin → Automatic, AxesStyle → Automatic, Background → Automatic,ColorOutput → Automatic, DefaultColor → Automatic,DefaultFont $DefaultFont, DisplayFunction $DisplayFunction,Epilog → 8<, FormatType $FormatType, Frame → False, FrameLabel → None,FrameStyle → Automatic, FrameTicks → Automatic, GridLines → None,ImageSize → Automatic, PlotLabel → None, PlotRange → All,PlotRegion → Automatic, Prolog → 8<, RotateLabel → True,TextStyle $TextStyle, Ticks → Automatic, AxesFront → False=
Come vedete, ci sono opzioni come HeadScaling ed HeadLength. Non ho lo spazio di spiegarvi
tutto, però date sempre un'occhiata alle opzioni di una funzione che utilizzate, perchè potreste
trovarne qualcuna nascosta veramente utile, come in questo caso.
Daniele Lupo Appunti di Mathematica
438Printed by Mathematica for Students
Vediamo, adesso, un esempio di come possiamo creare una lista con posizioni e vettori assieme, e la
differenza nel visualizzarlo:
In[230]:= listavettori2 = Table@88n, Sqrt @nD<, 84 Sin@ nD, nê2<<, 8n, 0, 8 Pi, .05 Pi<D;
In[231]:= ListPlotVectorField@listavettori2,ColorFunction → Hue,HeadWidth → 1,HeadLength → .05,HeadScaling → RelativeD
Out[231]= Graphics
Come potete vedere, in questo caso il campo vettoriale non viene disegnato più in un array
bidimensionale, ma vengono semplicemente disegnati i vettori nei punti indicati nella lista
Daniele Lupo Appunti di Mathematica
439Printed by Mathematica for Students
üGraphics`PlotField3D`Questo package è l'analogo tridimensionale di quello precedente, permettendo di creare grafici
vettoriali nelle tre dimensioni:
PlotVectorField3D[{ fx, fy,
fz}, {x, xmin, xmax}, {y,ymin, ymax}, {z, zmin, zmax}]
disegna il campo vettoriale dao dalla funzionevettoriale, nel range specificato
PlotGradientField3D[f,{x, xmin, xmax}, {y, ymin,ymax}, {z, zmin, zmax}]
disegna il campo gradiente della funzione scalare f
I comandi lavorano in maniera quasi identica a quelli del caso bidimensionale, con l'ovvia aggiunta
della terza dimensione:
In[232]:= << Graphics`PlotField3D`
In[233]:= PlotVectorField3D@8x, y, z<,8x, −4, 4<, 8y, −4, 4<, 8z, 0, 5<D
Out[233]= Graphics3D
Come potete vedere, in questo caso si disegnano soltanto delle linee, senza le teste delle frecce. Se
vogliamo inserirle, dobbiamo esplicitarlo con l'opzione esatta:
Daniele Lupo Appunti di Mathematica
440Printed by Mathematica for Students
In[234]:= PlotVectorField3D@8x, y, z<,8x, −4, 4<, 8y, −4, 4<, 8z, 0, 5<,VectorHeads → True,ColorFunction → Hue,Boxed → False,Axes → True,FaceGrids → 880, 1, 0<, 8−1, 0, 0<<D
-4-2
0
2
4-4
-2
0
2
4
0
2
4
-4-2
0
2
4
Out[234]= Graphics3D
Possiamo anche disegnare i gradienti:
Daniele Lupo Appunti di Mathematica
441Printed by Mathematica for Students
In[235]:= PlotGradientField3D@Sin@x y zD, 8x, −4, 4<, 8y, −4, 4<, 8z, 0, 5<,ScaleFactor → 2, VectorHeads → TrueD
Out[235]= Graphics3D
Inoltre, possiamo anche rappresentare liste di
vettori:
ListPlotVectorField3D[{{pt1, vect1}, {pt2, vect2}, … }]
disegna una lista di vettori nei punti specificati
Vediamo l'ultimo esempio di questo package (e me ne vado a dormire, che sono le 12.30 e domani
devo alzarmi presto):
In[236]:= vettori3D = Flatten@Table@88n, m, Sqrt@n^2 + m^2D<,8Sin@nD, Sin@mD, Sin@m nD<<,8n, 0, 6 Pi<, 8m, 0, 6 Pi<
D,1D;
Daniele Lupo Appunti di Mathematica
442Printed by Mathematica for Students
In[237]:= ListPlotVectorField3D@vettori3D, BoxRatios → 81, 1, 1<D
Out[237]= Graphics3D
Ed ora, con il vostro permesso, me ne andrei a dormire, dato che il sonno avanza e non riesco più ad
inventarmi niente di interessante.
Buonanotte.
Daniele Lupo Appunti di Mathematica
443Printed by Mathematica for Students
üGraphics`SurfaceOfRevolution`Non è bello smettere perchè si ha sonno, e ricominciare il giorno dopo a mezzanotte passata... Devo
gestire meglio i miei impegni, ma d'altronde è periodo d'esame...
Ma torniamo a noi.
Questo package serve principalmente per generare delle figure tridimensionali facendo ruotare una
curva attorno ad un asse. La curva può essere sia ad una sola variabile, a due oppure a tre, in questii
due ultimi casi descritta parametricamente e dipendente da un parametro (d'altronde, ci serve una
curva, non una superficie...):
SurfaceOfRevolution[f,{x, xmin, xmax}]
disegna la superfice di rotazione ottenendo facendoruotare la curca definita da f nel piano x-z fra xmin e xmax
SurfaceOfRevolution[{ fx,fz}, {t, tmin, tmax}]
disegna la superfice di rivolusione ottenuta ruotandola curva descritta parametricamente nel piano x-z nelparametro t
SurfaceOfRevolution[{ fx,fy, fz}, {t, tmin, tmax}]
analogo a sopra,ma per una curva parametrica a tre componenti
Vediamo subito un esempio:
In[238]:= << Graphics`SurfaceOfRevolution`
Daniele Lupo Appunti di Mathematica
444Printed by Mathematica for Students
In[239]:= SurfaceOfRevolution@−x^1.5 + Sin@4 xD, 8x, 0, 6<,Axes → False,LightSources → 8882, −2, 2<, [email protected], 0.6, 0.8D<,88−2, −1, 1<, [email protected]<<
D
Out[239]= Graphics3D
Per poter essere esguito, il comando utilizza ParametricPlot3D, per cui valgono tutte le opzioni
valide per quest'ultimo comando.
L'esempio riportatao sotto, invece, defiinisce una superfice di rivoluzione ottenuta da una curva
parametrica bidimensionale. Inoltre, se si aggiunge un secondo parametro, possiamo specificare
l'angolo di rivoluzione:
In[240]:= << Graphics`Graphics`
In[241]:= curva = 83 Cos@tD, Tan@tD<;
Daniele Lupo Appunti di Mathematica
445Printed by Mathematica for Students
In[242]:= DisplayTogetherArray@88SurfaceOfRevolution@curva, 8t, 0, Pi<D,SurfaceOfRevolution@curva, 8t, 0, Pi<, 8u, 0, 3 Piê2<D<<D
-20
2
-2
02
-5
-2.5
0
2.5
5
-2
02 -2
02
-2
02
-5
-2.5
0
2.5
5
-2
02
Out[242]= GraphicsArray
L'asse di rotazione, comunque sia definita la curva, è sempre dato dall'asse z. Se vogliamo
cambiarlo, dobbiamo specificare il nuovo asse con la giusta opzione:
RevolutionAxis -> {x, z} ruota la curva intorno all'asse di rotazione che connettel'origine degli assi con il punto specificato nel piano x-z
RevolutionAxis -> {x,y, z}
ruota la curva intorno all'asse che passa per l'origine eper il punto specificato
Pur mantenendo lo stesso angolo, la direzione dell'asse fa variare la superficie, perchè la curva è
sempre definita nel piano x-z:
Daniele Lupo Appunti di Mathematica
446Printed by Mathematica for Students
In[243]:= DisplayTogetherArray@88SurfaceOfRevolution@curva, 8t, 0, Pi<D,SurfaceOfRevolution@curva, 8t, 0, Pi<, RevolutionAxis → 82, 3, 8<D<<D
-20
2
-2
0
2
-5
-2.5
0
2.5
5
-2
0
2
-50
5
-5
0
5
-5
0
5
-50
5
-5
0
5
Out[243]= GraphicsArray
Per finire con questo package, vediamo il comando per effettuare la superfice di rivoluzione a partire
da una curva definita da dei dati, invece che da una funzione:
ListSurfaceOfRevolution[{point1, point2, … }]
genera una superfice di rivoluzione a partire dallacurva specificata per punti
ListSurfaceOfRevolution[{point1, point2, … }, {theta,thetamin, thetamax}]
genra una superfice di rivoluzione con undeterminato range per l'angolo di rivoluzione
Vediamo come funziona il comando:
In[244]:= dati = Table@8BesselJ@0, 7 nD, n<, 8n, 0, 4, .07<D;
Daniele Lupo Appunti di Mathematica
447Printed by Mathematica for Students
In[245]:= ListSurfaceOfRevolution@dati, 8t, 0, 2 Pi<,RevolutionAxis → 83, 0<,PlotRange → All,ViewVertical → 81, 0, 0<,PlotPoints → 30,Boxed → False,FaceGrids → 880, 1, 0<, 8−1, 0, 0<, 80, 0, −1<<D
00.51
-4
-2
0
2
4-4
-2
0
2
4
-2
0
2
4
Out[245]= Graphics3D
E con questo package ho finito (credo, spero...) di descrivere quelli riguardanti comandi grafici
avanzati...
Vediamo il resto, adesso...
ü LinearAlgebra`FourierTrig`Il package contiene le varianti reali della trasformata di Fourier, vedendola come le parti in seno e
coseno:
FourierCos[{a1, a2, …, an+1}]
trasformata discreta del coseno
FourierSin[{a1, a2, …
, an+1}] trasformata discreta del seno
In[246]:= << LinearAlgebra`FourierTrig`
Daniele Lupo Appunti di Mathematica
448Printed by Mathematica for Students
In[247]:= Table@1 − 2 ChebyshevT@2, xD, 8x, .1, .9, .03<D
Out[247]= 82.96, 2.9324, 2.8976, 2.8556, 2.8064, 2.75, 2.6864, 2.6156, 2.5376,2.4524, 2.36, 2.2604, 2.1536, 2.0396, 1.9184, 1.79, 1.6544, 1.5116,1.3616, 1.2044, 1.04, 0.8684, 0.6896, 0.5036, 0.3104, 0.11, −0.0976<
In[248]:= Chop@FourierCos@%DD
Out[248]= 813.241, 4.47343, −0.893379, 0.501916, −0.226638, 0.184256,−0.103225, 0.0968197, −0.0601015, 0.0609337, −0.0402234,0.0428777, −0.029518, 0.0326164, −0.0231674, 0.026318, −0.0191642,0.0222679, −0.0165554, 0.0196115, −0.0148469, 0.0178917,−0.0137685, 0.0168559, −0.0131714, 0.0163679, −0.01298<
In[249]:= FourierCos@%D
Out[249]= 82.96, 2.9324, 2.8976, 2.8556, 2.8064, 2.75, 2.6864, 2.6156, 2.5376,2.4524, 2.36, 2.2604, 2.1536, 2.0396, 1.9184, 1.79, 1.6544, 1.5116,1.3616, 1.2044, 1.04, 0.8684, 0.6896, 0.5036, 0.3104, 0.11, −0.0976<
Come potete vedere, si deve eseguire il calcolo su una lista di dati, ed inoltre i comandi sono
normalizzati, nel senso che fare la trasformata della trasformata restituisce la lista principale.
ü LinearAlgebra`MatrixManipulation`Questo package contiene varie funzioni per una manipolazione più agevole ed avanzata delle
matrici, ed anche se la maggior parte di loro sono implementabili attraverso semplici funzioni che
possiamo definire, la loro completezza, il loro numero permettono di cominciare subito a lavorare
con le matrici senza perdere tempo iniziale a dover definire le nostre funzioni.
Le prime funzioni che andiamo a vedere sono quelle che ci permettono di ottenere una matrice
unendo delle sottomatrici:
AppendColumns[m1, m2, … ] unisce le colonne delle matrici m1, m2, …
AppendRows[m1, m2, … ] unisce le righe delle matrici m1, m2, …
BlockMatrix[blocks] unisce le righe e le colonne delle matrici definitenella lista blocks per formare una nuova matrice
Questi comandi ci permettono, in altre parole, di creare delle matrici a blocchi:
In[250]:= << LinearAlgebra`MatrixManipulation`
Definiamo due matrici:
Daniele Lupo Appunti di Mathematica
449Printed by Mathematica for Students
In[251]:= mat1 = 88a, b<, 8c, d<<; mat2 = 881, 2<, 83, 4<<;
Vediamo adesso la matrice che si ottinene unendo queste due:
In[252]:= AppendRows@mat1, mat2D êê MatrixForm
Out[252]//MatrixForm=
J a b 1 2c d 3 4
N
In[253]:= AppendColumns@mat1, mat2D êê MatrixForm
Out[253]//MatrixForm=
i
k
jjjjjjjjjjj
a bc d1 23 4
y
{
zzzzzzzzzzz
In[254]:= [email protected], mat2.mat1<, 8mat1, mat2<<D êê MatrixForm
Out[254]//MatrixForm=
i
k
jjjjjjjjjjj
a + 3 b 2 a + 4 b a + 2 c b + 2 dc + 3 d 2 c + 4 d 3 a + 4 c 3 b + 4 da b 1 2c d 3 4
y
{
zzzzzzzzzzz
Questi comandi permettono di creare facilmente delle matrici a partire dai loro blocchi, evitando di
dover scrivere cicli e quant'altro per eseguire gli stessi comandi senza usare il package.
Dopo aver visto questi comandi, andiamo a vedere quelli che ci permettono di estrarre parti di una
matrice definita:
TakeRows[mat, n] restituisce le prime n righe presenti in mat
TakeRows[mat, -n] restituisce le ultime n righe presenti in mat
TakeRows[mat, {m, n}] restituisce le righe dalla m alla n della matrice mat
TakeColumns[mat, n] restituisce le prime n colonne in mat
TakeColumns[mat, -n] restituisce le ultime n colonne in mat
TakeColumns[mat, {m, n}] restituisce le colonne dalla m alla n della matrice mat
TakeMatrix[mat, pos1, pos2] restituisce la sottomatrice limitata dagli elementi chesi trovano nella posizione pos1 e pos2
SubMatrix[mat, pos, dim] restituisce la sottomatrice mat di dimensione dimche parte dalla posizione pos
Creiamo una matrice 5x4:
Daniele Lupo Appunti di Mathematica
450Printed by Mathematica for Students
In[255]:= mat = ToExpression@Table@"a" <> ToString@mD <> ToString@nD, 8m, 5<, 8n, 4<DD;
mat êê MatrixForm
Out[256]//MatrixForm=
i
k
jjjjjjjjjjjjjjjj
a11 a12 a13 a14a21 a22 a23 a24a31 a32 a33 a34a41 a42 a43 a44a51 a52 a53 a54
y
{
zzzzzzzzzzzzzzzz
Per creare gli elementi della matrice, prima li ho creati come stringhe, e poi li ho convertriti in
simboli di nuovo, per non aver a che fare con delle stringhe come elementi; a questo punto,
possiamo cominciare a manipolare la nostra matrice come più ci piace. Per esempio, possiamo
prendere le prime due righe, oppure le ultime due:
In[257]:= TakeRows@mat, 2D êê MatrixForm
Out[257]//MatrixForm=
J a11 a12 a13 a14a21 a22 a23 a24
N
In[258]:= TakeRows@mat, −2D êê MatrixForm
Out[258]//MatrixForm=
J a41 a42 a43 a44a51 a52 a53 a54
N
Analogamente possiamo fare per le colonne:
In[259]:= TakeColumns@mat, 2D êê MatrixForm
Out[259]//MatrixForm=
i
k
jjjjjjjjjjjjjjjj
a11 a12a21 a22a31 a32a41 a42a51 a52
y
{
zzzzzzzzzzzzzzzz
In[260]:= TakeColumns@mat, −2D êê MatrixForm
Out[260]//MatrixForm=
i
k
jjjjjjjjjjjjjjjj
a13 a14a23 a24a33 a34a43 a44a53 a54
y
{
zzzzzzzzzzzzzzzz
Daniele Lupo Appunti di Mathematica
451Printed by Mathematica for Students
Vediamo di prendere, adesso, la sottomatrice centrale. Possiamo farlo in due modi: specificando le
dimensioni ed il primo elemento della sottomatrice, oppure specificandp il primo e l'ultimo elemento:
In[261]:= TakeMatrix@mat, 82, 2<, 84, 3<D êê MatrixForm
Out[261]//MatrixForm=
i
k
jjjjjja22 a23a32 a33a42 a43
y
{
zzzzzz
In[262]:= SubMatrix@mat, 82, 2<, 83, 2<D êê MatrixForm
Out[262]//MatrixForm=
i
k
jjjjjja22 a23a32 a33a42 a43
y
{
zzzzzz
Nel primo caso abbiamu utlizzato gli indici del primo e dell'ultimo elemento, mentre nel secondo
abbiamo sfruttato le dimensioni.
Oltre a questi semplici comandi di manipolazione, il package contiene anche comandi per creare dei
particolari tipi di matrici:
UpperDiagonalMatrix[f, n] crea una matrice diagonale superiore nän conglielementi non nulli pari a f[i, j]
LowerDiagonalMatrix[f, n] crea una matrice diagonale inferiore nän conglielementi non nulli pari a f[i, j]
TridiagonalMatrix[f, n] crea una matrice tridiagonale nän con gli elementidella tridiagonale pari a f[i, j]
ZeroMatrix[n] crea una matrice nulla nän
ZeroMatrix[m, n] crea una matrice nulla män
HilbertMatrix[n] crea una matrice di Hilbert nän, i cui elementi sonodati da 1êHi+ j-1L
HilbertMatrix[m, n] crea una matrice di Hilbert män
HankelMatrix[n] crea una matrice di Hankel nän con gli elementi dellaprima colonna pari a 1, 2, …, n la seconda da 2, 3, …,n ,0 e così via
HankelMatrix[list] crea una matrice di Hankel con la prima colonnadefinita da list e che segue il ragionamento di sopra
HankelMatrix[col, row] crea una matrice di Hankel con la prima colonnadata dalla lista col e dall'ultima riga data dalla lista
Il funzionamento di questi comandi non è complicato:
Daniele Lupo Appunti di Mathematica
452Printed by Mathematica for Students
In[263]:= UpperDiagonalMatrix@Sin@2 #1 + a #2D &, 4D êê MatrixForm
Out[263]//MatrixForm=
i
k
jjjjjjjjjjj
Sin@2 + aD Sin@2 + 2 aD Sin@2 + 3 aD Sin@2 + 4 aD0 Sin@4 + 2 aD Sin@4 + 3 aD Sin@4 + 4 aD0 0 Sin@6 + 3 aD Sin@6 + 4 aD0 0 0 Sin@8 + 4 aD
y
{
zzzzzzzzzzz
Notate come il comando richieda solamente l'head della funzione oppure, in modo alternativo, la
corrispondente funzione pura:
In[264]:= LowerDiagonalMatrix@Plus, 5D êê MatrixForm
Out[264]//MatrixForm=
i
k
jjjjjjjjjjjjjjjj
2 0 0 0 03 4 0 0 04 5 6 0 05 6 7 8 06 7 8 9 10
y
{
zzzzzzzzzzzzzzzz
Funziona anche con gli head classici...
Per la matrice di Hilbert, invece, occorrono solamente le dimensioni:
In[265]:= HilbertMatrix@4D êê MatrixForm
Out[265]//MatrixForm=
i
k
jjjjjjjjjjjjjjjj
1 12
13
14
12
13
14
15
13
14
15
16
14
15
16
17
y
{
zzzzzzzzzzzzzzzz
Le matrici tridiagonali, invece, sono particolari tipi di matrici, in cui sono diversi da zero gli
elementi della diagonale principale, della sovradiagonale e della sottodiagonale:
In[266]:= TridiagonalMatrix@f, 5D êê MatrixForm
Out[266]//MatrixForm=
i
k
jjjjjjjjjjjjjjjj
f@1, 1D f@1, 2D 0 0 0f@2, 1D f@2, 2D f@2, 3D 0 00 f@3, 2D f@3, 3D f@3, 4D 00 0 f@4, 3D f@4, 4D f@4, 5D0 0 0 f@5, 4D f@5, 5D
y
{
zzzzzzzzzzzzzzzz
Le matrici di Hankel, invece, sono delle matrici che si ottengono scrivendo la prima colonna; la
colonna generica si ottiene shiftando di un posto verso l'alto la colonna precedente, e riempendo
l'ultimo elemento con uno zero:
Daniele Lupo Appunti di Mathematica
453Printed by Mathematica for Students
In[267]:= HankelMatrix@5D êê MatrixForm
Out[267]//MatrixForm=
i
k
jjjjjjjjjjjjjjjj
1 2 3 4 52 3 4 5 03 4 5 0 04 5 0 0 05 0 0 0 0
y
{
zzzzzzzzzzzzzzzz
Possiamo anche definire da soli la nostra prima colonna:
In[268]:= HankelMatrix@8a, b, c, d, e<D êê MatrixForm
Out[268]//MatrixForm=
i
k
jjjjjjjjjjjjjjjj
a b c d eb c d e 0c d e 0 0d e 0 0 0e 0 0 0 0
y
{
zzzzzzzzzzzzzzzz
Inoltre, possiamo riempire anche la parte sottostante, definendo l'ultima riga, che sarà shiftata in
maniera equivalente:
In[269]:= HankelMatrix@8a, b, c, d, e<, 8e, 2, 3, 4, 5, 6<D êê MatrixForm
Out[269]//MatrixForm=
i
k
jjjjjjjjjjjjjjjj
a b c d e 2b c d e 2 3c d e 2 3 4d e 2 3 4 5e 2 3 4 5 6
y
{
zzzzzzzzzzzzzzzz
Naturalmente, se si costruisce in questa maniera, l'ultimo elemento della prima lista deve essere
uguale al primo elemento della seconda lista, dato che l'ultimo elemento della prima colonna ed il
primo elemento dell'ultima riga coincidono: se si specifica diversamente il comando non funziona:
In[270]:= HankelMatrix@81, 2, 3<, 8a, b, c<D
Out[270]= HankelMatrix@81, 2, 3<, 8a, b, c<D
In questo caso non siamo in grado di costruire la matrice.
Un altro comando molto iutile è quello che permette, dato un sistema lineare scritto sotto forma di
equazioni, di ricavarne la matrice dei coefficienti e quella dei termini noti:
LinearEquationsToMatrices[eqns, vars]
restituisce una lista del tipo {mat, vec}, dove matrappresenta la matrice dei coefficienti del sistemalineare nelle variabili specificate, e vec rappresenta ilvettore dei termini noti
Daniele Lupo Appunti di Mathematica
454Printed by Mathematica for Students
Supponiamo di avere il seguente sistema:
In[271]:= sistema = 8a x + b y 4 + t,5 t + p == 4 x + p y,x − y == t<;
Se adesso voglio andare a trovarmi la forma matriciale basta scrivere:
In[272]:= LinearEquationsToMatrices@sistema, 8x, y, t<D
Out[272]= 888a, b, −1<, 8−4, −p, 5<, 81, −1, −1<<, 84, −p, 0<<
Sono date in un'unica lista, ma ovviamente noi sappiamo come estrarre gli elementi, vero?
In[273]:= coeff = %@@1DD; termnoti = %@@2DD;
In[274]:= coeff êê MatrixForm
Out[274]//MatrixForm=
i
k
jjjjjja b −1−4 −p 51 −1 −1
y
{
zzzzzz
In[275]:= termnoti êê MatrixForm
Out[275]//MatrixForm=
i
k
jjjjjj4−p0
y
{
zzzzzz
Notate come, dato che ho concatenato due operazioni in un unico Input, % faccia riferimento
all'output precedente, che corrisponde all'ultimo Out creato prima della riga, e come nel secondo
comando concatenato, di conseguenza, uso % e non %%. Si impara sempre qualcosa di nuovo,
vero???
Sono anche presenti due comandi per la fattorizzazione di una matrice:
Daniele Lupo Appunti di Mathematica
455Printed by Mathematica for Students
PolarDecomposition[mat] restituisce una lisa nella forma {u, s}, dove srappresenta una matrice definita positiva, mentre u.u*
è uguale alla matrice identità, e u.s=m a tLUMatrices@luD restituisce una lista nella forma 8l, u<,
dove l ed u rappresentano le matrici diagonali inferiori,e diagonale superiore di una fattorizzazione LU diuna matrice, ed lu rappresenta il primo elementodella decomposizione LUDecomposition@matD
Ovviamente, dovete sapere cosa rappresenta una decomposizione polare, ed usarla quando vi serve.
Un consiglio: utilizzate questo comando soltanto con valori numerici; utilizzare numeri esatti oppure
costanti di solito da luogo a risultati estremamente lunghi ed inutili. Provate con la solita matrice
88a, b<, 8c, d<<, e mi darete ragione:
In[276]:= mat = 883., 5., 4.<,87., −6., −2.<,84., 4., 7.<<;
In[277]:= PolarDecomposition@matD
Out[277]= 8880.529976, 0.83848, −0.126798<, 80.815019, −0.544932, −0.196962<,80.234245, −0.00104205, 0.972177<<, 888.23204, −1.30325, 2.12958<,8−1.30325, 7.45782, 4.43649<, 82.12958, 4.43649, 6.69197<<<
In[278]:= MatrixForm@%@@1DDD
Out[278]//MatrixForm=
i
k
jjjjjj0.529976 0.83848 −0.1267980.815019 −0.544932 −0.1969620.234245 −0.00104205 0.972177
y
{
zzzzzz
In[279]:= GridBox@88MatrixForm@%@@1DDD,MatrixForm@%@@2DDD
<<
D êê DisplayForm
Out[279]//DisplayForm=
i
k
jjjjjj0.5299760.83848−0.126798
y
{
zzzzzzi
k
jjjjjj0.815019−0.544932−0.196962
y
{
zzzzzz
Daniele Lupo Appunti di Mathematica
456Printed by Mathematica for Students
Come potete vedere ho usato il comando GridBox, che serve per creare delle tabelle. Andate a
vedervi i comandi di formattazione... Comunque, lo scopo era farvi vedere più chiaramente le due
matrici così ottenute.
In[280]:= %%@@1DD.%%@@2DD
Out[280]= −1.953×10−16
Come potete vedere, il prodotto di queste due matrici è effettivamente la matrice originale.
Vediamo invece l'utilità del secondo comando, LUMatrices. Effettuiamo prima di tutto la
decomposizione LU di una matrice, con il comando predefinito di Mathematica:
In[281]:= LUDecomposition@matD
Out[281]= 8887., 0.428571, 0.571429<, 8−6., 7.57143, 0.981132<,8−2., 4.85714, 3.37736<<, 82, 1, 3<, 9.46927<
In[282]:= %@@1DD êê MatrixForm
Out[282]//MatrixForm=
i
k
jjjjjj7. 0.428571 0.571429−6. 7.57143 0.981132−2. 4.85714 3.37736
y
{
zzzzzz
Il comando restituisce una lista di tre elementi: il primo è rappresentato dalla matrice ottenuta
combinando la matrice diagonale inferiore e superiore: il secondo elemento è il vettore delle
permutazioni dei pivot, ed il terzo un numero rappresenta il numero L¶. Se vogliamo adesso estrarre
dal primo elemento di questo risultato le due matrici, invece di averne una singola, possiamo creare
un programmino, oppure utilizzare il comando definito da questo package:
In[283]:= ris = LUMatrices@%%@@1DDD; GridBox@88MatrixForm@ris@@1DDD,MatrixForm@ris@@2DDD
<<
D êê DisplayForm
Out[283]//DisplayForm=
i
k
jjjjjj1. 0. 0.0.428571 1. 0.0.571429 0.981132 1.
y
{
zzzzzzi
k
jjjjjj7. −6. −2.0 7.57143 4.857140 0 3.37736
y
{
zzzzzz
Come poete vedere adesso ris contiene le due matrici correttamente suddivise nella triangolare
inferiore e superiore:
Daniele Lupo Appunti di Mathematica
457Printed by Mathematica for Students
In[284]:= ris@@1DD.ris@@2DD
Out[284]= 887., −6., −2.<, 83., 5., 4.<, 84., 4., 7.<<
Di nuovo la matrice di partenza...
Un altro comando utile, specialmente quando si ha a che fare con matrici di grandi dimensioni, è il
seguente:
MatrixPlot[mat] mostra graficamente la struttura di mat
MatrixPlot[mat, cen] mostra graficamente la struttura di mat con valorecentrale cen
In pratica, crea qualcosa di simile ad un grafico di densità; tuttavia non è la stessa cosa, perchè
questo comando mostra solamente la struttura: una cella bianca per un elemento nullo, ed una nera
per un elemento non nullo:
In[285]:= MatrixPlot@Table@Random@IntegerD, 8100<, 8100<DD
1 20 40 60 80 100
1
20
40
60
80
100
1 20 40 60 80 100
1
20
40
60
80
100
Out[285]= Graphics
Ci sono un paio di cosette da aggiungere riguardo questo comando: prima di tutto, bisogna notare
come possiamo definire comunque una funzione per il colore della matrice, passando dal semplice
bianco e nero ad una scala rappresentante i valori della matrice, con la solita opzione ColorFunction:
Daniele Lupo Appunti di Mathematica
458Printed by Mathematica for Students
In[286]:= mat2 = HankelMatrix@100D;
In[287]:= MatrixPlot@mat2, ColorFunction → HHue@#ê1.03D &LD
1 20 40 60 80 100
1
20
40
60
80
100
1 20 40 60 80 100
1
20
40
60
80
100
Out[287]= Graphics
Come potete vedere, in questo caso abbiamo utilizzato una funzione per evidenziare con il colore la
quantità numerica contenuta nella matrice. Tuttavia, questo vale solamente per matrici numeriche. Se
la matrice contiene anche elementi simbolici. Per rendercene conto guardiamo il seguente esempio:
In[288]:= << Graphics`Graphics`
Daniele Lupo Appunti di Mathematica
459Printed by Mathematica for Students
In[289]:= DisplayTogetherArray@88MatrixPlot@88a, 1<, 8.6, 0<<, ColorFunction → HHue@#ê1.3D &LD,MatrixPlot@88a, 1<, 8.6, 0<<D
<<D
1 2
1
2
1 2
1
2
1 2
1
2
1 2
1
2
Out[289]= GraphicsArray
Come possiamo vedere, la struttura della matrice contiene solamente un elemento nullo. Questo
viene riprodotto correttamente nella seconda matrice. Nella prima, invece, il comando non è in grado
di valutare un colore per il simbolo, per cui viene colorato nella stessa maniera in cui viene colorato
l'elemento nullo, portando ad una errata interpretazione della struttura della matrice.
L'altra opzione è la seguente:
MaxMatrixSize -> n massima dimensione della per la visualizzazionedella matrice
Prima di disengare la matrice, il comando effettua un downsampling per poterla visualizzare sullo
schermo. Per fare questo, raggruppa gruppi di elementi in un unica cella quadrata. Se almento un
elemento del gruppo di elemento della cella è non nullo, allora la cella corrispondente risulterà non
vuota. Supponiamo, per esempio, di avere la seguente matrice sparsa, dove solamente il primo e
l'ultimo elemeno sono non nulli:
In[290]:= mat3 = SparseArray@881, 1< → 1, 8200, 200< → 1<D
Out[290]= SparseArray@<2>, 8200, 200<D
Daniele Lupo Appunti di Mathematica
460Printed by Mathematica for Students
In[291]:= MatrixPlot@mat3D
1 50 100 150 200
1
50
100
150
200
1 50 100 150 200
1
50
100
150
200
Out[291]= Graphics
Come potete vedere, il grafico è vuoto, eccezion fatta per i due angolini che si fanno pure fatica a
distinguerli. Veriamo di effettuare un downsampling;
Daniele Lupo Appunti di Mathematica
461Printed by Mathematica for Students
In[292]:= MatrixPlot@mat3, MaxMatrixSize → 5D
1 50 100 150 200
1
50
100
150
200
1 50 100 150 200
1
50
100
150
200
Out[292]= Graphics
Come possiamo vedere, abbiamo effettuato un downsampling, visualizzando una matrice 5 x 5 .
Siccome il primo ed ultimo elemento di questa matrice contengono elemento non nulli della matrice
principale, sono considerati anch'essi non nulli. Questo può agevolare la visualizzazione di matrici
grandi, ma notate come si vengano a perdere, in questo modo, informazioni sulla struttura,
apparendo più grossolana.
Daniele Lupo Appunti di Mathematica
462Printed by Mathematica for Students
ü LinearAlgebra`Orthogonalization`Questo package contiene alcuni comandi utili per gestirvi le basi dei vettori, andandovi a trovare le
basi ortonormali a partire da una qualsiasi, a proiettare un vettore su di un altro e così via.
Il comando che tutti conoscerete (almeno quelli che hanno fatto Teoria dei Segnali), riguarda la
procedura di Gram-Schmidt. Il comando corrispondente effettua l'ortonormalizzazione in maniera
simbolica. Tutttavia a volte può dare problemi, e verrà dato un altro comando che lavora
esclusivamente su dati numerici, risultando più stabile.
Vediamo i comandi principali:
GramSchmidt[{v1, v2, … }] genera una base ortonormale a partire dalla lista divettori reali
Normalize[vect] normalizza il vettore vect
Projection[vect1, vect2] restituisce la proiezione ortognale di vect1 su vect2
Vediamo un esempio pratico:
In[293]:= << LinearAlgebra`Orthogonalization`
In[294]:= vettori = 881, 3, 4, 6<, 8−3, 6, −3, 2<, 80, 3, 3, 1<, 81, 4, 4, 4<<;
In[295]:= 8b1, b2, b3, b4< = GramSchmidt@vettoriD
Out[295]= 99 1è!!!!!!62
, 3è!!!!!!62
, 2$%%%%%%%%%231
, 3$%%%%%%%%%231
=,
9−201
è!!!!!!!!!!!!!!!!209002, 327
è!!!!!!!!!!!!!!!!209002, −123$%%%%%%%%%%%%%%%%%%%2
104501, 17$%%%%%%%%%%%%%%%%%%%2
104501=,
9−38
è!!!!!!!!!!!!!!!!347213, 1416
5 è!!!!!!!!!!!!!!!!347213, 356
è!!!!!!!!!!!!!!!!347213, −
18635 è!!!!!!!!!!!!!!!!347213
=,
9 9è!!!!!!!!!103
, 175 è!!!!!!!!!103
, −3
è!!!!!!!!!103, −
65 è!!!!!!!!!103
==
Come potete vedere, abbiamo ottenuto la normalizazione in maniera simbolica.
Inoltre, possimamo lavorare con le opzioni di questo comando per poter comandare
l'ortonormalizzazione:
Daniele Lupo Appunti di Mathematica
463Printed by Mathematica for Students
GramSchmidt[{v1, v2, …}, InnerProduct -> func]
genera un set ortonormale, utilizzando comeprodotto interno dello spazio la funzione func
Normalize[vect, InnerProduct -> func]
normalizza vect utilizzando il prodotto internodello spazio func
P r o j e c t i o n [vect1 ,vect2, InnerProduct
restitusce la proiezione ortogonale di vect1 suvect2 utilizzando il prodotto interno dello spazio
GramSchmidt@8v1, v2, … <,Normalized −> FalseD
Crea una base ortogonale, senza andarla a normalizzare
Ripetiamo lo stesso procedimento di prima, ma stavolta evitando di normalizzare i vettori della base:
In[296]:= 8b1, b2, b3, b4< = GramSchmidt@vettori, Normalized → FalseD
Out[296]= 981, 3, 4, 6<, 9−20162
, 32762
, −12331
, 1731
=,
9−5703371
, 42483371
, 53403371
, −55893371
=, 9 261515
, 4932575
, −87515
, −1742575
==
Abbiamo ottenuto la base di poco fa, evitando di normalizzare i vettori. Se li andiamo a
normalizzare, riotteniamo la base di poco fa:
In[297]:= Normalize ê@ %
Out[297]= 99 1è!!!!!!62
, 3è!!!!!!62
, 2$%%%%%%%%%231
, 3$%%%%%%%%%231
=,
9−201
è!!!!!!!!!!!!!!!!209002, 327
è!!!!!!!!!!!!!!!!209002, −123$%%%%%%%%%%%%%%%%%%%2
104501, 17$%%%%%%%%%%%%%%%%%%%2
104501=,
9−38
è!!!!!!!!!!!!!!!!347213, 1416
5 è!!!!!!!!!!!!!!!!347213, 356
è!!!!!!!!!!!!!!!!347213, −
18635 è!!!!!!!!!!!!!!!!347213
=,
9 9è!!!!!!!!!103
, 175 è!!!!!!!!!103
, −3
è!!!!!!!!!103, −
65 è!!!!!!!!!103
==
Ho applicato la funzione Normalize ad ogni elemento della lista, tramite /@ che è il modo abbreviato
di utilizzare Map. Ma questo ve lo ricordavate, vero???
Possiamo anche lavorare con spazi funzionali, dove un elemento è costituito da una combinazione
lineare di funzioni (qualcuno ha detto Fourier?): in questo caso bisogna specificare, al posto dei
vettori, le funzioni, ed inoltre bisogna specificare il prodotto interno dello spazio. Nel caso delle
funzioni, di solito si utilizza l'integrale. Vediamo adesso la base per uno spazio i cui elementi si
possono scrivere come a Cos@xD + b x Sin@xD + c x2, e il prodotto interno è dato da Ÿ-p
p v2 v1 „ x:
In[298]:= base = 8Cos@xD, x Sin@xD, x^2<;
Daniele Lupo Appunti di Mathematica
464Printed by Mathematica for Students
In[299]:= GramSchmidt@base, InnerProduct → HIntegrate@#1 #2, 8x, −π, π<D &LD êêFullSimplify
Out[299]= 9 Cos@xDè!!!π , $%%%%%%%%%%%%%%%%%%%%%%%%%%3
−9 π + 4 π3HCos@xD + 2 x Sin@xDL,
$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%−45 + 20 π2
−11040 π + 3040 π3 − 258 π5 + 8 π7
Jx2 + 4 Cos@xD −12 H−7 + π2L HCos@xD + 2 x Sin@xDL
−9 + 4 π2N=
Questa rappresenta la nostra base ortonormale per lo spazio definito da quelle funzioni.
Consideriamo adesso una gaussiana:
In[300]:= gaussiana@x_D := Exp@−x^2êH2 σ^2LD
Come possiamo vedere, manca in questo caso il coefficiente di normalizzazione. Possiamo calcolare
la funzione normalizzata o facendo l'integrale e dividendo la funzione per il risultato, oppure usare
Normalize, definendo il prodotto interno dello spazio, cioè come si calcola il modulo:
In[301]:= Normalize@gaussiana@xD,InnerProduct → HIntegrate@#1 #2, 8x, −∞, ∞<D &LD
Out[301]= − x2
2 σ2 ìi
k
jjjjjjj-IfAIm@σD2 < Re@σD2,è!!!π"#######1
σ2
,
IntegrateA − x2
σ2 , 8x, −∞, ∞<, Assumptions → Im@σD2 ≥ Re@σD2EEy
{
zzzzzzz
MMMMmmmmm.... si vede che in questo caso dobbiamo specificare un paio di cosette... Infatti,
non avendo fatto nessuna assunzione per s, viene trattata come caso generale, anche se in questo è
incluso il caso che ci interessa. Specifichiamo che la variabile deve essere reale positiva:
In[302]:= Assuming@σ > 0,Normalize@gaussiana@xD,InnerProduct → HIntegrate@#1 #2, 8x, −∞, ∞<D &LD
D
Out[302]=− x2
2 σ2
π1ê4 è!!!!σ
Comep possiamo vedere, avendo fatto la giusta assunzione per la deviazione standard, il risultato è
corretto ed è quello che ci aspettavamo...
Daniele Lupo Appunti di Mathematica
465Printed by Mathematica for Students
Vediamo adesso un esempio di Projection, prioiettando un vettore su di un altro:
In[303]:= Projection@81, 1, 1<, 81, 5, 9<D
Out[303]= 9 15107
, 75107
, 135107
=
In questo caso ho ottenuto la proiezione del vettore sull'altro...
In[304]:= Projection@81, 0, 0<, 80, a, 0<D
Out[304]= 80, 0, 0<
In questo caso i due vettori sono ortogonali fra di loro, e la proiezione di consegenza è nulla.
Consideriamo adesso questo esempio:
In[305]:= basenum = 880, 0, 1.<, 81., 0, 0<,8−0.12988785514152842, 0.3997814966837186, 0.5468181006215335<,81.013982920708332, −0.02721531177817664, −0.18567966396292607<<;
Effettuiamo l'ortonormalizzazione:
In[306]:= GramSchmidt@basenumD
Out[306]= 880, 0, 1.<, 81., 0, 0.<, 80., 1., 0.<, 80., −1., 0.<<
C'è un problema... Risultano quattro vettori, mentre la base è di tre vettori, in questo caso. Questo è
uno dei (rarissimi) casi in cui l'algoritmo di Gram-Schmidt non funziona, e dobbiamo utilizzare
l'altro comando:
In[307]:= Householder@basenumD
Out[307]= 880., 0., −1.<, 8−1., 0., 0.<, 80., 1., 0.<, 80., 0., 0.<<
In questo caso si riconosce il vettore nullo, e di conseguenza la base restituita è di soli tre vettori,
com'è giusto che sia.
Daniele Lupo Appunti di Mathematica
466Printed by Mathematica for Students
üMiscellaneous`Units`Questo package è utile soprattutto negli esercizi dove conta la fisica, ed il risultato è pesantemente
influenzato dalle unità di misura, cosa che in ingegneria capita abbastanza spesso, direi...
Il comando principale è quello che ci permette di effettuare la conversione fra due unità di misura:
Convert[old, newunits] converte old in una forma che coinvolgeuna combinazione di newunits
Vediamo come sia facile utilizzare le unità di misura con questo package:
In[308]:= << Miscellaneous`Units`
In[309]:= Convert@2314 MeterêSecond, Kilo MeterêHourD
Out[309]=41652 Kilo Meter
5 Hour
Inoltre, sono definite anche i prefissi per le unità di misura; anche nel caso di sopra, il chilometro è
stato definito come metro per Kilo, che rapresenta 10^3, come tutti sappiamo.
Un comando a parte merita la temperatura, perchè non è una conversione semplicemente
moltiplicativa:
In[310]:= ConvertTemperature@37, Celsius, FahrenheitD
Out[310]=4935
Inoltre, possiamo prendere una grandezza, ed espromerla sotto forma delle unità di misura
standard:
SI[expr] converte expr nel sistema SI (International System)
MKS[expr] converte expr nel sistema MKS (meter/kilogram/second)
CGS[expr] converte expr nel sistema CGS (centimeter/gram/second)
Per esempio:
In[311]:= SI@13 MileD
Out[311]=2615184 Meter
125
Daniele Lupo Appunti di Mathematica
467Printed by Mathematica for Students
Qua sotto sono rappresentate le tabelle delle varie unità di misuta incluse in questo package:
PrefissiYocto 10-24 Deca 101
Zepto 10-21 Hecto 102
Atto 10-18 Kilo 103
Femto 10-15 Mega 106
Pico 10-12 Giga 109
Nano 10-9 Tera 1012
Micro 10-6 Peta 1015
Milli 10-3 Exa 1018
Centi 10-2 Zetta 1021
Deci 10-1 Yotta 1024
Unità elettricheAbampere Abcoulomb
Abfarad Abhenry
Abmho Abohm
Abvolt Amp
Biot Coulomb
Farad Gilbert
Henry Mho
Ohm Siemens
Statampere Statcoulomb
Statfarad Stathenry
Statohm Statvolt
Volt
Unità di lunghezza:
Daniele Lupo Appunti di Mathematica
468Printed by Mathematica for Students
AU Bolt
Cable Caliber
Centimeter Chain
Cicero Cubit
Didot DidotPoint
Ell Fathom
Feet Fermi
Foot Furlong
Hand Inch
League LightYear
Link Meter
Micron Mil
Mile NauticalMile
Parsec Perch
Pica Point
Pole PrintersPoint
Rod Rope
Skein Span
Stadion Stadium
StatuteMile SurveyMile
XUnit Yard
Unità di informazione:Baud Bit
Byte Nibble
Unità di tempo:Century Day
Decade Fortnight
Hour Millennium
Minute Month
Second SiderealSecond
SiderealYear TropicalYear
Week Year
Unità di massa:AMU AtomicMassUnit
Dalton Geepound
Gram Kilogram
MetricTon Quintal
Slug SolarMass
Tonne
Daniele Lupo Appunti di Mathematica
469Printed by Mathematica for Students
Unità di peso:AssayTon AvoirdupoisOunce
AvoirdupoisPound Bale
Carat Cental
Drachma Grain
GrossHundredweight Hundredweight
Libra Mina
NetHundredweight Obolos
Ounce Pennyweight
Pondus Pound
Shekel ShortHundredweight
ShortTon Stone
Talent Ton
TroyOunce Wey
Unità di forza:Dyne GramWeight
KilogramForce KilogramWeight
Newton Poundal
PoundForce PoundWeight
TonForce
Unità di lunghezza inversa:Diopter Kayser
Unità di volume:
Daniele Lupo Appunti di Mathematica
470Printed by Mathematica for Students
Bag Barrel
BoardFoot Bucket
Bushel Butt
Cord Cup
Drop Ephah
Fifth Firkin
FluidDram FluidOunce
Gallon Gill
Hogshead Jeroboam
Jigger Last
Liter Magnum
Minim Noggin
Omer Pint
Pony Puncheon
Quart RegisterTon
Seam Shot
Stere Tablespoon
Teaspoon Tun
UKGallon UKPint
WineBottle
Unità di viscosità:Poise Reyn
Rhes Stokes
Unità di energia luminosa:Apostilb Candela
Candle FootCandle
Hefner Lambert
Lumen Lumerg
Lux Nit
Phot Stilb
Talbot
Unità di radiazione:Becquerel Curie
GrayDose Rad
Roentgen Rontgen
Rutherford
Unità di angolo:
Daniele Lupo Appunti di Mathematica
471Printed by Mathematica for Students
ArcMinute ArcSecond
Circle Degree
Grade Quadrant
Radian RightAngle
Steradian
Unità di potenza:ChevalVapeur Horsepower
Watt
Unità di area:Acre Are
Barn Hectare
Rood Section
Township
Unità di quantità di sostanza:Dozen Gross
Mole
Unità di accelerazione di gravità:Gal Gravity
Unità di forza magnetica:BohrMagneton Gauss
Gamma Maxwell
NuclearMagneton Oersted
Tesla Weber
Moltiplicatori di unità:ArcSecond BakersDozen
Circle Degree
Dozen Grade
Gross Percent
Quadrant RightAngle
Unità di pressione:Atmosphere Bar
Barye InchMercury
MillimeterMercury Pascal
Torr
Daniele Lupo Appunti di Mathematica
472Printed by Mathematica for Students
Unità di energia:BritishThermalUnit BTU
Calorie ElectronVolt
Erg Joule
Rydberg Therm
Unità di frequenza:Hertz
Come vedete, ce n'è davvero per tutti i gusti...
üNumberTheory`Recognize`Questo package permette di definire dei polinomi, a partire dalle loro radici
conosciute:
Recognize[x, n, t] crea un polinomio di grado massimo n nella variabile tin modo che x sia uno zero approssimato del polinomio
Recognize[x, n, t, k] ficrea un polinomio di grado massimo n nella variabile tin modo che x sia uno zero approssimato del polinomio,e con un coefficiente di penalità k per i polinomi digrado superiore
Supponiamo di volere una retta che passi per un determinato punto, per esempio 3.45:
In[312]:= << NumberTheory`Recognize`
In[313]:= [email protected], 1, xD
Out[313]= 69 − 20 x
In genere, se trova un polinomio soddisfacente per gradi inferiori, allora si blocca, evitando il
calcolo di polinomi di grado superiore:
In[314]:= [email protected], 4, xD
Out[314]= 69 − 20 x
Questo accade perchè il package crea dei polinomi con coefficienti interi, e non reali. Di
conseguenza vengono soddisfatte le condizioni già per un polinomio di tal grado... Possiamo avere
soluzioni per la quale questo non è valido. Per esempio:
In[315]:= sol = 1.462624652;
Daniele Lupo Appunti di Mathematica
473Printed by Mathematica for Students
In questo caso ho:
In[316]:= Recognize@sol, 1, xD
Out[316]= −44723006 + 30577227 x
Tuttavia, aumentando il grado, possiamo avere polinomi con coefficienti più piccoli:
In[317]:= Recognize@sol, 4, xD
Out[317]= −512 − 209 x − 370 x2 − 511 x3 + 701 x4
Che è già più fattibile come numeri:
In[318]:= sol = N@Sqrt@3DD;
In[319]:= Recognize@sol, 1, xD
Out[319]= −50843527 + 29354524 x
In[320]:= Recognize@sol, 2, xD
Out[320]= −3 + x2
In[321]:= Recognize@sol, 3, xD
Out[321]= −3 + x2
Come vedete, anche in questo caso la soluzione più efficace è quella riguardante il polinomio di
secondo grado: d'altronde, era scontato, dato che la nostra soluzione era una radice quadrata...
Se vogliamo comunque evitare di scrivere equazioni di grado troppo elevato, possiao utilizzare un
coefficiente che limita l'uso dei polinomi di grado massimo:
In[322]:= sol = N@4^H1ê7LD
Out[322]= 1.21901
In[323]:= Recognize@sol, 10, xD
Out[323]= −4 + 8 x − 4 x2 + x7 − 2 x8 + x9
Daniele Lupo Appunti di Mathematica
474Printed by Mathematica for Students
In[324]:= Roots@% 0, xD êê N
Out[324]= x 0.760043 + 0.953063 »»x −0.271256 + 1.18845 »» x −1.09829 + 0.52891 »»x −1.09829 − 0.52891 »» x −0.271256 − 1.18845 »»x 0.760043 − 0.953063 »» x 1.21901 »» x 1. »» x 1.
Come vedete, abbiamo le soluzioni contengono quella iniziale. Se vogliamo limitare il grado,
possiamo utilizzare il coefficiente di peso:
In[325]:= Recognize@sol, 10, x, 7D
Out[325]= −1952 + 1927 x − 327 x2 + 32 x3 + 14 x4
In[326]:= Roots@% 0, xD êê N
Out[326]= x 2.15641 − 3.15924 »»x 2.15641 + 3.15924 »» x −7.81756 »» x 1.21901
In questo caso abbiamo detto a Mathematica che, se la differenza di soluzione fra un grado e quello
inferiore non è così grande (così grande dipende dal coefficiente), allora ci accontentiamo della
soluzione del grado inferiore, anche se non è precisa come quella di grado superiore. Notate come le
soluzioni paiano uguali, ma tenete sempre conto che il dato non viene rappresentato, di default, con
tutte le cifre decimali, e che Mathematica lavora comunque, volendo, con precisione arbitraria, per
cui l'approssimazione si fa sentire man mano che aumentiamo la precisione. Bisogna quindi scegliere
il giusto compromesso fra precisione e semplicità del polinomio.
Daniele Lupo Appunti di Mathematica
475Printed by Mathematica for Students
Eq differenzialiPrima di cominciare inizializziamo caricando il package per visualizzare i grafici:
Needs@"Graphics`Graphics`"D;Needs@"Graphics`Colors`"D;Needs@"Graphics`Animation`"D;Needs@"DifferentialEquations`NDSolveProblems`"D;Needs@"DifferentialEquations`NDSolveUtilities`"D;
ü Introduzione
In quest'appendice vedremo meglio uno degli aspetti migliori (a mio avviso) di Mathematica, ossia i
suoi comandi e le sue opzioni per la risoluzione di equazioni differenziali, sia in forma simbolica,
che in forma numerica. Per esempio, possiamo trattare con estrema semplicità sia le equazioni, che i
sistemi di equazioni, anche di tipo misto, dove alcune equazioni del sistema sono differenziali,
mentre altre sono algebriche. Inoltre, possiamo trattare anche le equazioni differenziali alle derivate
parziali. Insomma, possiamo fare veramente di tutto. Tuttavia, se le equazioni differenziali che
trattiamo sono alquanto complicate, dobbiamo cominciare a cercare di capire meglio come
funzionano questi comandi, vedendoli in maniera più dettagliata. Il fatto che risolvano da soli la
maggior parte dei problemi è sicuramente una grande cosa, ma dobbiamo comunque tener conto del
fatto che mettere mano alle opzioni permette di avere un controllo maggiore su quello che si fa, e
permette di capire anche il funzionamento di certi algoritmi: inoltre potremmo anche essere in grado
di selezionare manualmente le opzioni e gli algoritmi migliori per il problema che ci serve.
ü Tipi di equazioni
Il comanid DSolve è in grado di risolvere sia singole equazioni differenziali, che sistemi di equazioni.
Ł Equazioni differenziali ordinarie ODE: sono i tipi di equazioni in cui la variabile indipendente è
una sola, mentre quelle dipendenti yiHxL possono essere una soltanto, nel caso di una sola equazione
differenziale, oppure più di una, nel caso in cui abbiamo a che fare con dei sistemi di equazioni
differenziali.
Ł Equazioni differenziali alle derivate parziali PDE: questo tipo di equazioni differenziali si
distinguono dalle prime per il fatto che la loro funzione (o variabile dipendente) dipende da più di
una variabile indipendente yHt1, t2, ...L. Questi casi sono più difficili da risolvere simbolicamente
rispetto alle ODE: Mathematica non è oggettivamente in grado di poter trovare soluzioni a qualsiasi
equazione PDE, per il semplice fatto che non esiste una teoria che permetta di calcolarle in maniera
esatta. Il problema è talmente difficile che ci sono, per fare un esempio, dei casi in cui ci sono premi
per chi riesce a trovare soluzioni esatte per questo tipo di equazioni differenziali; un esempio è dato
dal milione di dollari messo in palio (da chi adesso non ricordo, sinceramente), per chi riesca a
Daniele Lupo Appunti di Mathematica
476Printed by Mathematica for Students
trovare soluzioni in forma simbolica delle equazioni di Navier-Stokes, per la particolare importanza
che rivestono in moltissimi campi dell'ingegneria.
Mathematica è in grado di risolvere PDE in maniera simbolica nella maggior parte dei casi in cui
l'equazione è del primo ordine, ed in un minor numero di casi quando la PDE è di ordine superiore.
Ł Equazioni algebrico-differenziali DAE: si tratta in particolar modo di sistemi, in cui compaiono sia
equazioni differenziali, che equazioni algebriche, in cui non compaiono le derivate. Per questo tipo
di sistemi valgono gli stessi problemi delle PDE, cioè che non esiste una teoria tanto robusta da poter
trovare in tutti i casi le soluzioni in maniera simbolica; anche in questo caso Mathematica non è in
grado di trovare le soluzioni per casi difficili, ma molti problemi sono comunque alla portata di
questo programma.
Risoluzione Simbolica
Adesso vedremo meglio, più in dettaglio, e con un maggior numero di esempi, il funzionamento del
comando DSolve. La soluzione simbolica, è sempre da preferire, quando è possibile averla, perchè
naturalmente non abbiamo in questo caso problemi tipici del calcolo numerico, come errori di
approssimazione, necessità di specificare sempre le condizioni iniziali, la scelta dell'intervallo di
risoluzione e così via. In casi avanzati le soluzioni possono occupare anche diverse pagine, ma fin
quando lasciamo tutto il lavoro di elaborazione a Mathematica, non dobbiamo preoccuparcene più di
tanto, lasciando al programma il compito di elaborare le funzioni ottenute.
ü DSolve
Come ben sappiamo, è questo il comando che dobbiamo utilizzare quando vogliamo trovare la
soluzione di un'equazione differenziale in forma simbolica. Data la natura, appunto, simbolica della
soluzione, se si omettono le condizioni iniziali, Mathematica darà il risultato in forma generale, con
le opportune costanti, che di default sono date nella forma C[n]. Per poter scrivere la derivata, basta
utilizzare il carattere ' (quello che vi trovate accanto lo zero nella parte superiore della tastiera, per
capirci), come se si trattasse del simbolo che si usa nei libri; per poter creare derivate di ordine
superiore basta mettere tanti ' per quanto è necessario. Vediamo questo esempio:
DSolve@y''@xD + x y@xD 0, y@xD, xD
88y@xD → AiryAi@H−1L1ê3 xD C@1D + AiryBi@H−1L1ê3 xD C@2D<<
Possiamo vedere due cose, che in fondo già sapevamo (ma ricordare non fa mai male, vero, cari miei
folletti che volano sulle favole dell'ingegneria? Ehm....).
Prima di tutto, occorre notare come viene data la soluzione, cioè sotto forma di regola, invece che
direttamente come funzione. Questo permette di andare a sostituire la funzione dove serve. Inoltre,
come caso più generale, permette anche di andare a sostituire più funzioni in una volta sola, nel caso
Daniele Lupo Appunti di Mathematica
477Printed by Mathematica for Students
avessimo più soluzioni. per andare a sostituirla basta usare ReplaceAll, che come sapete si può
scrivere anche come /.
y@xD ê. %
8AiryAi@H−1L1ê3 xD C@1D + AiryBi@H−1L1ê3 xD C@2D<
Viene restituita come lista, anche se è formata da un solo elemento, per manterene la generalità della
soluzione: infatti, dato che le soluzioni possono essere più di una, si racchiudono in una lista, e
questa è semplicemente il caso particolare in cui abbiamo un solo elemento.
La seconda cosa da notare è come abbiamo introdotto le costanti, che Mathematica ha aggiunto
automaticamente, in mancanza delle opportune condizioni iniziali. Se le avessimo imposte, avremmo
anche ottenuto la soluzione particolare:
DSolve@8y''@xD + x y@xD 0, y@0D 3, y@3D 0<, y@xD, xD êê FullSimplify
99y@xD →
J3 32ê3 H−AiryAi@−xD AiryBi@−3D + AiryAi@−3D AiryBi@−xDL GammaA 23EN í
J2 BesselJA 13, 2 è!!!3 EN==
In questo caso abbiamo posto le condizioni iniziali, ed abbiamo ottenuto la soluzione particolare:
Plot@y@xD ê. %, 8x, 0, 12<, PlotStyle → 8Orange<,Epilog → 88Blue, [email protected], Point@80, y@xD êê. 8%@@1, 1DD, x → 0<<D<,8Red, [email protected], Point@83, y@xD êê. 8%@@1, 1DD, x → 3<<D<<
D
2 4 6 8 10 12
-3
-2
-1
1
2
3
Graphics
Daniele Lupo Appunti di Mathematica
478Printed by Mathematica for Students
Come possiamo vedere, abbiamo aggiunto al grafico dei punti che rappresentano la funzione
calcolata nelle condizioni iniziali, e possiamo vedere come coindidano con quelle che avevamo
imposto in partenza, cosa che effettivamente era naturale. Guai ad non essere così. Potevo anche
semplicemente utilizzare le coordinate 83, 0< e 80, 3< per rappresentare direttamente i punti, ma in
questa maniera vi ho fatto vedere come ottenere lo stesso risultato lavorando con le funzioni e con le
regole di sostituzione.
Potete anche vedere come abbiamo imposto le condizioni iniziali nel comando DSolve, cioè creando
sintatticamente un sistema di equazioni simile al DAE, dove però c'è l'importante differenza che,
invece di equaioni delle variabili dipendenti generiche, compaiono equazioni per valori particolari
della funzione. Ovviamente, le condizioni iniziali devono essere compatibili con il problema.
Sempre nell'esempio fatto, infatti, abbiamo bisogno di due condizioni iniziali per avere la soluzione
esatta; un numero maggiore porta a generare un errore:
DSolve@8y''@xD + x y@xD 0, y@0D 3, y@3D 0, y'@0D 3<, y@xD, xD
— DSolve::bvnul : For some branches of the general solution,the given boundary conditions lead to an empty solution. More…
8<
Questo perchè le condizioni iniziali sono inconsistenti con li problema. Ovviamente, in questo caso,
l'errore non è del programma, ma è vostro, ed è un modo per dirvi di andare a studiare...
Un'importante aspetto del comando DSolve, specialmente dalla versione 5 di Mathematica, è la sua
capacità di lavorare con funzioni definite a tratti, che quindi possono presentare delle discontinuità,
come la funzione UnitStep:
DSolve@8y@tD UnitStep@t − 1D + t^2 UnitStep@t − 2D y'@tD, y@0D 3<, y@tD, tD
99y@tD → −2 2 − 10 t − 3 1+t + 2 2 t + 2 t2
2 +
J3 −1+t +2 2 − 10 t − 3 1+t + 2 2 t + 2 t2
2 N UnitStep@2 − tD +
UnitStep@1 − tD H3 − 3 −1+t UnitStep@2 − tDL==
Daniele Lupo Appunti di Mathematica
479Printed by Mathematica for Students
Plot@y@tD ê. %@@1DD, 8t, 0, 3<, PlotStyle → 8Blue<D
0.5 1 1.5 2 2.5 3
5
10
15
20
25
30
Graphics
Potete notare i punti di discontinuità che si hanno per t = 1, t = 2, che sono i punti dove iniziano i
gradini nella nostra equazione differenziale.
Le funzioni definite a tratti possono essere anche utilizzate nei sistemi, come in questo caso:
sistema = 8UnitStep@t − 3D y'@tD − x@tD t + UnitStep@−t + 3D x'@tD t^2 x@tD,y'@tD t x'@tD,x'@1D 4,y@0D 4<;
Per comodità, oltre al sistema, ho specificato anche le condizioni iniziali nel sistema stesso: adesso
posso andare a risolverlo normalmente, utilizzando sempre DSolve:
DSolve@sistema, 8x@tD, y@tD<, tD êê FullSimplify
99x@tD → 21+
Ø≤≤∞±≤≤
− 1t +Log@tD t≤3
− 103 +t+Log@tD True,
y@tD →Ø≤≤∞±≤≤4 − 2 2ê3 + 2 − 7
3 +t H1 + H−1 + tL tL + ExpIntegralEi@− 13 D t > 3
4 + 1− 1t t H1 + tL + ExpIntegralEi@− 1
t D True==
Notate la potenza del comando, che risulta in grado di definire funzioni a tratti anche nell'argomento
dell'esponenziale, e come la soluzione includa funzioni avanzate come ExpIntegralEi
Daniele Lupo Appunti di Mathematica
480Printed by Mathematica for Students
Plot@8x@tD ê. %, y@tD ê. %<, 8t, −7, 7<,PlotStyle → 88Orange<, [email protected], 0.015<D, Green<<D
-6 -4 -2 2 4 6
-150
-100
-50
50
100
150
200
Graphics
In maniera analoga, possiamo risolvere anche equazioni differenziali alle derivate parziali, andando
a specificare sempre quali sono le variabili indipendenti. Considerando la seguente equazione
differenziale
eqn = x y^2 D@u@x, yD, xD + y^2 x^2 D@u@x, yD, yD − x y u@x, yD
−x y u@x, yD + x2 y2 uH0,1L@x, yD + x y2 uH1,0L@x, yD
sol = DSolve@eqn 0, u@x, yD, 8x, y<D
99u@x, yD →2 ArcTanA xè!!!!!!!!!!!!!!!!!!!!!
−x2+2 yE
è!!!!!!!!!!!!!!!!!!!!−x2+2 y C@1DA 1
2H−x2 + 2 yLE==
Da questa scrittura possiamo notare subito un paio di cose importanti. Prima di tutto, possiamo
notare il diverso tipo di notazione, quando dobbiamo scrivere delle PDE. infatti, scrivendo qualcosa
come u '@x, tD, Mathematica (e neanche noi, a dire il vero), non è in grado di distinguere la variabile
rispetto alla quale stiamo derivando; per questo motivo, dobbiamo per forza di cose andare ad
esplicitare tramite il comando D il tipo di derivata parziale che andiamo ad utilizzare. Comparirà in
maniera corretta nell'output, come possiamo andare a vedere.
Inoltre, i coefficienti C[i], in questo caso, non rappresentano più delle costanti, ma sono a tutti gli
effetti delle funzioni. Si può notare considerando che C[1], nel nostro caso, è una funzione, avente
come argomento 1ÅÅÅÅ2 H-x2 + 2 yL, come possiamo vedere dalla soluzione che abbiamo ottenuto. Dalla
soluzione generale, quindi, se vogliamo arrivare ad una particolare, dobbiamo andare a sostituire a
C[i] delle funzioni (che naturalmente, a seconda delle condizioni al contorno, possono essere anche
Daniele Lupo Appunti di Mathematica
481Printed by Mathematica for Students
delle costanti...). Possiamo trovare una soluzione particolare del nostro problema, ipotizzando per
esempio, di mettere come caso particolare il seno:
solpar = u@x, yD ê. %@@1DD ê. 8C@1D@t_D → Sin@tD<
2 ArcTanA xè!!!!!!!!!!!!!!!!!!!!!−x2+2 y
Eè!!!!!!!!!!!!!!!!!!!!
−x2+2 y SinA 12H−x2 + 2 yLE
Notiamo come sia stato necessario preservare la struttura dell'argomento della costante C[i], in
quanto è quello necessario per la risoluzione del problema. Adesso possiamo andare a visualizzare la
funzione, notando che ottengo una soluzione reale soltanto quando -x2 + 2 y ¥ 0, cioè quando è
reale il radicale, considerato che non ho limiti per quanto riguarda l'argomente del seno e dell'Arc-
Tan, sempre che siano ovviamente numeri reali :-). Per cui otterremmo degli errori nel caso in cui
specifichiamo durante il plottaggio, dei punti al di fuori questo dominio. Per risolvere il problema
allora andiamo a plottare una funzione Piecewise, che facciamo corrispondere alla nostra funzione se
rientra nel dominio, e la poniamo uguale a 0 se invece cade fuori i nostri limiti permessi:
dominio = Reduce@−x^2 + 2 y > 0, 8x, y<D
x ∈ Reals && y >x2
2
Daniele Lupo Appunti di Mathematica
482Printed by Mathematica for Students
DisplayTogetherArray@88
DensityPlot@Piecewise@88solpar, dominio<, 80, True<<D,8x, −4, 4<, 8y, −.1, 10<,PlotPoints → 200,Mesh → False,ColorFunctionScaling → False,ColorFunction → HHue@Sqrt@#DD &LD,
Plot3D@Piecewise@88solpar, dominio<, 80, True<<D,8x, −4, 4<, 8y, −.1, 10<,PlotPoints → 130,Mesh → False,PlotRange → 8Automatic, Automatic, 80, 5<<,ViewPoint −> 8−2.004, −1.853, 2.000<D
<<D
-4 -2 0 2 40
2
4
6
8
10
-4
-2
0
24
0
2.5
57.5
10012345
-2
0
240
12
GraphicsArray
Abbiamo visto come possiamo risolvere sia le ODE che le PDE. Naturalmente, possiamo risolvere
anche le DAE, sempre nei casi in cui è permesso. Possiamo considerare il seguente sistema:
dae = 8f'@xD 5 g''@xD,f@xD + g@xD 3 Cos@xD,f@PiD 0, f'@0D 0<;
Daniele Lupo Appunti di Mathematica
483Printed by Mathematica for Students
soluzione = DSolve@dae, 8f, g<, xD
99f → FunctionA8x<,1526
− π5 − x
5 H−5 πê5 + 5π5 + x
5 + 5 xê5 + 5π5 + x
5 Cos@xD −π5 + x
5 Sin@xDLE,
g → FunctionA8x<, 326
− π5 − x
5
H25 πê5 − 25π5 + x
5 − 25 xê5 +π5 + x
5 Cos@xD + 5π5 + x
5 Sin@xDLE==
Plot@Evaluate@8f@xD, g@xD, f@xD + g@xD< ê. soluzioneD, 8x, −9, 9<,PlotStyle → 88Blue<, 8Green<, 8Orange<<,Background → [email protected]
-7.5 -5 -2.5 2.5 5 7.5
-15
-10
-5
5
10
Graphics
Possiamo notare come la loro somma dia effettivamente 3 cosHxL, come avevamo scritto nel sistema
misto.
Il modo di lavorare di DSolve è abbastanza complicato ed oscuro per la maggior parte degli esseri
umani (diciamo tutti apparte la ventina di persone che l'hanno programmato). Tuttavia imparare ad
usarlo bene, permette di inserire l'input in una maniera che può anche agevolare il comando a
lavorare.
Quello che faremo adesso è quello di andare ad analizzare un tantino più in dettaglio quello che
possiamo ottenere con DSolve, e capire un pochino meglio le equazioni differenziali.
ODE
Sono le equazioni che si incontrano per la prima volta, perchè corrispondono a quelle più semplici
da risolvere. Il caso più diretto è un'equazione differenziale di questo tipo:
Daniele Lupo Appunti di Mathematica
484Printed by Mathematica for Students
y¢HtL f HtL
Questo tipo di equazione differenziale si risolve semplicemente integrando la parte destra
dell'equazione stessa:
DSolve@y'@tD Sin@tD^2, y@tD, tD
99y@tD →t2
+ C@1D −14Sin@2 tD==
La soluzione è semplice e diretta. Dato la natura di questo tipo di equazione, potevamo risolverla
anche in questa maniera:
Integrate@Sin@tD^2, tD
t2
−14Sin@2 tD
Ottenendo esattamente lo stesso risultato; l'unica differenza risiede nel fatto che Integrate non mette
direttamente la costante C (tutti gli integrali indefiniti dovrebbero essere in teoria come C + FHtL),mentre l'equazione differenziale l'aggiunge, perchè varia al variare delle condizioni al contorno della
soluzione generica
DSolveAy @xD x Sin@xD y@xD^2è!!!!!!!!!!!
3 − x, y, xE
88y → Function@8x<, H4 3 + xLëH−2 3 è!!!!!!!!!!!3 − x − 2 3 +2 x è!!!!!!!!!!!3 − x −
4 3 + x C@1D − H1 + 6 L H−1L3ê4 x è!!!π Erfi@H−1L1ê4 è!!!!!!!!!!!3 − x D −
H1 − 6 L H−1L1ê4 6 + x è!!!π Erfi@H−1L3ê4 è!!!!!!!!!!!3 − x DLD<<
Adesso abbiamo invece un esempio di equazione omogenea:
omo = y'@xD −Hx^4 − 3 y@xD^3L∗Hx ∗ y@xDL;
sol = DSolve@omo, y, xD êê FullSimplify
99y → FunctionA8x<, −H−2L1ê3 Hx6L1ê9
I2 x62 Hx6L1ê3 C@1D + 3 21ê3
x62 x2 Gamma@ 1
3 ,x62 DM1ê3
E=,
9y → FunctionA8x<, 21ê3 Hx6L1ê9
I2 x62 Hx6L1ê3 C@1D + 3 21ê3
x62 x2 Gamma@ 1
3 ,x62 DM1ê3
E=,
9y → FunctionA8x<, H−1L2ê3 21ê3 Hx6L1ê9
I2 x62 Hx6L1ê3 C@1D + 3 21ê3
x62 x2 Gamma@ 1
3 ,x62 DM1ê3
E==
Daniele Lupo Appunti di Mathematica
485Printed by Mathematica for Students
Come vediamo, abbiamo tre funzioni che risolvono questa equazione differenziale. Effettivamente,
però, le tre funzioni coincidono:
f1 = Table@Abs@y@xDD ê. sol@@1DD ê. C@1D → p, 8p, −5, 5, .5<D;
f2 = Table@Abs@y@xDD ê. sol@@2DD ê. C@1D → p, 8p, −5, 5, .5<D;
f3 = Table@Abs@y@xDD ê. sol@@3DD ê. C@1D → p, 8p, −5, 5, .5<D;
f1 f2 f3
True
Abbiamo visto che sono uguali, indipendentemente dal parametro, e basta quindi plottare soltanto
una famiglia di equazioni, diciamo f1:
colori = PlotStyle → Table@8Hue@Random@DD<, 8p, 0, 20<D;
Plot@Evaluate@f1, 8x, 0, 2<, coloriDD;
0.5 1 1.5 2
0.5
1
1.5
2
2.5
3
Piccola particolarità: non è necessatio che PlotStyle definisca un numero di stili uguale al numeri di
funzioni, perchè viene ripetuto ciclicamente.
Detto questo, abbiamo visto come ottenere le soluzioni generali. Questo può essere più utile di
quanto sembri. Infatti, possiamo avere vari rami della soluzione generale. Per qualcuno di essi, può
non valere la condizione iniziale che vogliamo. Ipotizziamo di avere questa equazione differenziale:
rami = y'@xD −Hx − 3 y@xD^2LêHx^2 ∗ y@xDL;
Daniele Lupo Appunti di Mathematica
486Printed by Mathematica for Students
sol = DSolve@rami, y, xD
99y → FunctionA8x<, −$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%−6êx JC@1D + 2 ExpIntegralEiA 6xEN E=,
9y → FunctionA8x<, $%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%−6êx JC@1D + 2 ExpIntegralEiA 6xEN E==
r1 = Table@y@xD ê. sol@@1DD ê. C@1D → p, 8p, −5, 5, .5<D;
r2 = Table@y@xD ê. sol@@2DD ê. C@1D → p, 8p, −5, 5, .5<D;
DisplayTogetherArray@8Plot@Evaluate@r1, 8x, 0, 4.5<, coloriDD,Plot@Evaluate@r2, 8x, 0, 4.5<, coloriDD
<D
1 2 3 4
-1.5-1.25
-1-0.75-0.5
-0.25
1 2 3 4
0.250.50.75
11.251.5
GraphicsArray
In questo esempio abbiamo evidenziato come, ad un'equazione differenziale, possano corrispondere
più rami della soluzione, definite da due (o più, a seconda dei casi) funzioni. Vediamo quello che
succede adesso:
DSolve@8rami, y@2D 2<, y, xD
— DSolve::bvnul : For some branches of the general solution,the given boundary conditions lead to an empty solution. More…
99y → FunctionA8x<,
è!!!2 $%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%−6êx J2 3 − ExpIntegralEi@3D + ExpIntegralEiA 6xEN E==
In questo caso abbiamo avuto un warning... La soluzione generale, infatti. è formata da due rami ma,
dal comportamento che abbiamo visto nei grafici, vediamo come solamente uno dei due rami sia in
grado di soddisfare la condizione al contorno che abbiamo imposto. Il warning sta appunto a dirci
che, nonostante Mathematica abbia trovato due soluzioni indipendenti per l'equazione differenziale,
Daniele Lupo Appunti di Mathematica
487Printed by Mathematica for Students
soltanto una viene utilizzata per trovare quella particolare.
In altre occasioni, invece, Mathematica riesce a trovare la soluzione, per così dire, in maniera
parziale; questo può capitare perchè, ad esempio, durante i calcoli si ritrova un integrale che non
riesce a risolvere in maniera analitica, come nell'esempio seguente:
integ = x y'@xD Sin@xD^4 y@xD Cos@xD;
DSolve@integ, y, xD
99y → FunctionA8x<, Ÿ1x− 8 Cos@K$101533D
K$101533 H−3+4 Cos@2 K$101533D−Cos@4 K$101533DL K$101533 C@1DE==
Come possiamo vedere, nella soluzione compare un integrale. Questo succede perchè Mathematica
se lo è ritrovato davanti, senza essere in grado di risolverlo. La variabile utilizzata per l'integrale è
una variabile locale, di quelle che il programma si crea da solo. Se vogliamo, possiamo andarlo a
sostituire con un'altra variabile, per rendere la soluzione un tantinello più leggibile:
% ê. K$101533 → t
99y → FunctionA8x<, Ÿ1x− 8 Cos@tD
t H−3+4 Cos@2 tD−Cos@4 tDL t C@1DE==
Naturalmente, la soluzione non è stata calcolata completamente. Per avere il valore della funzione in
un punto, occorre sempre valutare numericamente l'integrale, quindi l'intera espressione
y@3D ê. % ê. C@1D → 1 êê N
83.39381×10−18<
Oltre agli integrali, nel comando DSolve occorre anche risolvere delle equazioni, in maniera
simbolica, mediante il comando Solve. Quando quest'ultimo non è in grado di lavorare al meglio,
Mathematica ce lo segnala:
errSolve = Sin@y'@xDD x y@xD;
Daniele Lupo Appunti di Mathematica
488Printed by Mathematica for Students
DSolve@errSolve, y, xD
— Solve::ifun : Inverse functions are being used by Solve, so some solutions may not
be found; use Reduce for complete solution information. More…
— Solve::tdep : The equations appear to involve the variablesto be solved for in an essentially non−algebraic way. More…
— Solve::tdep : The equations appear to involve the variablesto be solved for in an essentially non−algebraic way. More…
— Solve::tdep : The equations appear to involve the variablesto be solved for in an essentially non−algebraic way. More…
— General::stop : Further output of Solve::tdep will be suppressed during this calculation. More…
SolveA‡1
y@xDx 1
K$112646 − ArcSin@K$112646D K$112646 C@1D − Log@xD, y@xDE
In questo caso, non viene dato il risultato completo, ma neanche quello che avevamo in partenza.
Quello che abbiamo ottenuto è un'espressione che coinvolge il comando Solve, perchè non è stato in
grado di dare la soluzione cercata, restituendocelo così com'è. Anche in questo caso, come nel
precedente, per avere soluzioni occorrono altre manipolazioni, e risoluzioni per via numerica, dato
che non si possono trovare soluzioni in forma chiusa (dubito che possa risultare utile un risultato
dove comare Solve ed un integrale non calcolabile simbolicamente). A questo punto conviene usare
NDSolve, ma ne parleremo nell'opportuna sezione.
Un altro tipo di equazioni differenziali che Mathematica è in grado di risolvere sono quelle di
Bernoulli:
bern = y'@xD + 3 x y@xD x^4 y@xD^4;
solbern = DSolve@bern, y, xD
99y → FunctionA8x<, −3 H−2L1ê3
I6 x + 18 x3 + 549 x22 C@1D −
9 x22
è!!!!!!!2 π ErfA 3 xè!!!!2 EM1ê3E=,
9y → FunctionA8x<, 3 21ê3
I6 x + 18 x3 + 549 x22 C@1D −
9 x22
è!!!!!!!2 π ErfA 3 xè!!!!2 EM1ê3E=,
9y → FunctionA8x<, 3 H−1L2ê3 21ê3
I6 x + 18 x3 + 549 x22 C@1D −
9 x22
è!!!!!!!2 π ErfA 3 xè!!!!2 EM1ê3E==
Naturalmente, avendole trovate, sono le soluzioni dell'equazione differenziale, e possiamo
verificarlo facilmente:
Daniele Lupo Appunti di Mathematica
489Printed by Mathematica for Students
bern ê. solbern êê Simplify
8True, True, True<
Un altro tipo di equazoni differenziali, particolarmente difficili da risolvere, sono le equazioni di
Riccati, che sono nella forma y£ HxL f HxL + gHxL yHxL + hHxL yHxL2. Qua sotto potete vederne un
esempio:
riccati = y'@xD + 1êx^3 − 3 x^3 y@xD^2 0;
DSolve@riccati, y, xD
99y → FunctionA8x<,−J2 x BesselY@2, − è!!!3 xD −
12
è!!!3 x2 HBesselY@1, − è!!!3 xD −
BesselY@3, − è!!!3 xDL + J2 x BesselJ@2, − è!!!3 xD −12
è!!!3
x2 HBesselJ@1, − è!!!3 xD − BesselJ@3, − è!!!3 xDLN C@1DN íH3 x3 Hx2 BesselY@2, − è!!!3 xD + x2 BesselJ@2, − è!!!3 xD C@1DLLE==
Un altro tipo di equazioni differenziali difficili da risolvere sono quelle di Abel, che vengono poste
nella seguente forma: y£ HxL f HxL + gHxL yHxL + hHxL yHxL2 + kHxL yHxL3
abel = y @xD y@xD3 −x y@xD2
x − 1;
DSolve@abel, y, xD
— InverseFunction::ifun : Inverse functions arebeing used. Values may be lost for multivalued inverses. More…
— InverseFunction::ifun : Inverse functions arebeing used. Values may be lost for multivalued inverses. More…
— Solve::tdep : The equations appear to involve the variablesto be solved for in an essentially non−algebraic way. More…
SolveA1−x+ 1
y@xD
−1 + x+ C@1D + ExpIntegralEiA1 − x +
1y@xD E 0, y@xDE
In questo caso abbiamo diversi warning: questi sono dovuti al fatto che, durante la ricerca della
soluzione esatta di questo tipo di equazioni, vengono utilizzati inverse di ODE, per cui compaiono
delle funzioni inverse, di cui Mathematica non conosce direttamente la struttura, e se in questo modo
si perdono alcuni valori durante l'inversione. Nel caso seguente, invece, tutto quanto va a buon fine:
abel2 = y @xD y@xDx
− 3 y@xD2 + x y@xD3;
Daniele Lupo Appunti di Mathematica
490Printed by Mathematica for Students
sol = DSolve@abel2, y, xD
99y → FunctionA8x<, 1x
−1
x2 "######################1x2 + C@1D
E=,
9y → FunctionA8x<, 1x
+1
x2 "######################1x2 + C@1D
E==
a1 = Table@y@xD ê. sol@@1DD ê. C@1D → p, 8p, 0, 1000, 20<D;
a2 = Table@y@xD ê. sol@@2DD ê. C@1D → p, 8p, 0, 1000, 20<D;
DisplayTogetherArray@8Plot@Evaluate@a1, 8x, −2, 2<, coloriD,
PlotRange → 8Automatic, 8−10, 10<<D,Plot@Evaluate@a2, 8x, −2, 2<, coloriD,
PlotRange → 8Automatic, 8−10, 10<<D<D
-2 -1 1 2
-10-7.5-5
-2.5
2.55
7.510
-2 -1 1 2
-10-7.5-5
-2.5
2.55
7.510
GraphicsArray
Come possiamo vedere, anche in questo caso abbiamo due rami distinti per la soluzione
dell'equazione differenziale.
Finora abbiamo considerato solamente alcuni esempi di equazioni ODE di primo grado.
Naturalmente, però, possiamo considerare anche ordini superiori: possiamo prendere un esempio di
ODE a coefficienti costanti, che sono il caso sempre più semplice:
ode2 = y''@xD − y@xD 0;
DSolve@ode2, y, xD
88y → Function@8x<, x C@1D + −x C@2DD<<
Naturalmente, in questo casi abbiamo due costanti di indeterminazione C[1] e C[2]. Vediamo come
varia la soluzione al variare di quesi valori:
Daniele Lupo Appunti di Mathematica
491Printed by Mathematica for Students
funz = FlattenATableA9y@xD ê. %@@1DD ê. 8C@1D → a, C@2D → b<,
RGBColorA a + 3
6,
b + 3
6, .1E=, 8a, −3, 3, .4<, 8b, −3, 3, .4<E, 1E;
Ho creato in questa maniera una lista di elementi, in cui il primo rappresenta la funzione, mentre il
secondo il colore della funzione, che varia al variare dei parametri:
Plot@Evaluate@funz@@All, 1DDD, 8x, −5, 5<, PlotStyle → funz@@All, 2DDD
-4 -2 2 4
-75
-50
-25
25
50
75
Graphics
Per questo tipo di equazioni, la soluzione è data come combinazione lineare di esponenziali. Dato
che abbiamo in questo esempio il secondo ordine, il risultato è combinazione lineare di due
esponenziali. Per questo tipo di equazioni, come ben saprete, si può ottenere il risultato, a partire
dall'equazione caratteristica, dalla quale si ricavano poi gli esponenti degli esponenziali che formano
la base per lo spazio delle soluzioni. Prendiamo quest'altra equazione:
car = y'''@xD + 4 y''@xD − 11 y'@xD − 30 y@xD 0;
A questo punto, possiamo ricavarci l'equazione caratteristica:
car ê. 8Derivative@n_D@yD@xD → λ^n, y@xD → 1<
−30 − 11 λ + 4 λ2 + λ3 0
Dato che tutto è rappresentato come espressioni, in Mathematica, lo è anche la forma y '' HxL, che
viene descritta da Derivative@nD@yD@xD, dove n rappresenta il grado di derivazione, y rappresenta la
funzione ed x la variabile indipendente. Abbiamo utilizzato quindi Derivative nella regola di
sostituzione, per andare a sostituire tutte le derivate con la variabile l, elevata al corrispettivo
esponente. Questa regola permette di ricavarci direttamente l'equazione caratteristica, senza bisogno
di doverla ricopiare. Una volta ottenuta, possiamo risolverla:
Daniele Lupo Appunti di Mathematica
492Printed by Mathematica for Students
Solve@%, λD
88λ → −5<, 8λ → −2<, 8λ → 3<<
Ed, arrivati a questo punto, possiamo creare la funzione che è soluzione dell'equazione differenziale,
andando a mapparci le soluzioni in una combinazione lineare. Il comando seguente prende le
soluzioni che abbiamo trovato, e le trasforma da regole a valori. A questo punto, applichiamo
MapIndexed alla lista delle soluzioni, in maniera tale da creare una lista dove ogni elemento è
formato dall'esponenziale dove compare la soluzione, e dal coefficiente di ogni elemento, con
opportuno indice. A questo punto, applico Plus alla lista trovata, in modo da sommare tutti gli
elementi presenti:
Plus @@ HMapIndexed@a#2@@1DD Exp@x #1D &, λ ê. %DL
−5 x a1 + −2 x a2 + 3 x a3
Notate come i comandi che ho utilizzato siano generici, il che mi permette di utilizzarli senza
nessuna modifica per ODE a coefficienti costanti di qualsiasi ordine. L'unica accortezza è che, per
equazioni di livello elevato, potrebbe essere necessario sostituire Solve con NSolve. Naturalmente,
potevamo fare tutto direttamente tramite DSolve:
DSolve@car, y, xD
88y → Function@8x<, −5 x C@1D + −2 x C@2D + 3 x C@3DD<<
D'altronde, spiegare la risoluzione classica credo che abbia giovato a molti di voi, impratichendovi
un pochino con le manipolazioni. D'altronde, qua ormai si parla seriamente...
Possiamo eseguire lo stesso procedimento mediante un'altra equazione:
car2 = y''''@xD − 10 ∗ y'''@xD + 54 ∗ y''@xD − 130 ∗ y'@xD + 125 ∗ y@xD 0;
car2 ê. 8Derivative@n_D@yD@xD → λ^n, y@xD → 1<
125 − 130 λ + 54 λ2 − 10 λ3 + λ4 0
Solve@%, λD
88λ → 2 − <, 8λ → 2 + <, 8λ → 3 − 4 <, 8λ → 3 + 4 <<
Plus @@ HMapIndexed@a#2@@1DD Exp@x #1D &, λ ê. %DL
H2− L x a1 + H2+ L x a2 + H3−4 L x a3 + H3+4 L x a4
Daniele Lupo Appunti di Mathematica
493Printed by Mathematica for Students
In questo caso abbiamo coefficienti immaginari, per cui possiamo trasformare l'espressione ottenuta
in maniera da far comparire seni e tett... ehm, coseni:
Con il comando DSolve avremmo ottenuto direttamente:
DSolve@car2, y@xD, xD
88y@xD →2 x C@2D Cos@xD + 3 x C@4D Cos@4 xD + 2 x C@1D Sin@xD + 3 x C@3D Sin@4 xD<<
Lascio a voi il compito di mostrare l'equivalenza di queste due espressioni, tenendo conto del fatto
che non è così immediato come possa sembrare a prima vista... Dovrete lavorarci un po', cari miei
discepoli.
Vediamo adesso di trattare l'equazione di Eulero, che ha la seguente forma:
x2 y££HxL + a x y£HxL + b yHxL 0. Possiamo vederne un esempio:
eulero = x^2 ∗ y''@xD + 5 ∗ x ∗ y'@xD + 9 ∗ y@xD 0;
DSolve@eulero, y@xD, xD
99y@xD →C@2D Cos@è!!!5 Log@xDD
x2+C@1D Sin@è!!!5 Log@xDD
x2==
In questo caso non abbiamo nente di particolarmente complicato, come soluzione. Possiamo invece
considerare una generalizzazione, data dall'equazione lineare di Legendre, che sono equazioni nella
forma Hc x + dL2 y££HxL + a Hc x + dL y£HxL + b yHxL 0:
legendre = H9 x + 1L^2 ∗ y''@xD + 5 ∗H3 x − 1L∗ y'@xD + 6 ∗ y@xD 0;
DSolve@legendre, y@xD, xD
99y@xD →
H−5L 127 I−11−è!!!!!!!67 M 2
227 I−11−è!!!!!!!67 M 3
19 I11+è!!!!!!!67 M J 1
1 + 18 x + 81 x2N
154 I−11−è!!!!!!!67 M
C@1D
Hypergeometric1F1A−1127
−è!!!!!!6727
, 1 −2 è!!!!!!6727
, 2027
$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%11 + 18 x + 81 x2
E +
H−5L 127 I−11+è!!!!!!!67 M 2
227 I−11+è!!!!!!!67 M 3
19 I11−è!!!!!!!67 M J 1
1 + 18 x + 81 x2N
154 I−11+è!!!!!!!67 M
C@2D
Hypergeometric1F1A−1127
+è!!!!!!6727
, 1 +2 è!!!!!!6727
, 2027
$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%11 + 18 x + 81 x2
E==
Sebbene sia lunga, il ramo della soluzione è unico anche in questo caso.
Daniele Lupo Appunti di Mathematica
494Printed by Mathematica for Students
Come avete visto, Mathematica è in grado di risolvere equazioni differenziali che coinvolgono
funzioni speciali, come quelle di Bessel:
bes = x^2 ∗ y''@xD + x ∗ y'@xD + Hx^2 − 5L∗ y@xD 0;
DSolve@8bes, y@1D 0, y'@1D 3<, y@xD, xD êê FullSimplify
99y@xD →32
π H−BesselJ@è!!!5 , xD BesselY@è!!!5 , 1D +
BesselJ@è!!!5 , 1D BesselY@è!!!5 , xDL==
Plot@y@xD ê. %, 8x, 0, 15<, PlotStyle → 88Red, [email protected]<<D
2 4 6 8 10 12 14
-12.5
-10
-7.5
-5
-2.5
2.5
5
Graphics
Una leggera modifica all'equazione di sopra comporta soluzioni con più funzioni speciali:
bes2 = x^2 ∗ y''@xD + x y'@xD + Hx − 5L^2 ∗ y@xD 0;
DSolve@bes2, y@xD, xD êê FullSimplify
99y@xD → − x x5 JC@1D HypergeometricUA 12, 1 + 10 , 2 xE +
C@2D LaguerreLA−12, 10 , 2 xEN==
Possiamo utilizzare anche altri tipi di coefficienti, che non siano semplicemente polunomi:
DSolve@ y''@xD − Hk^2 + 2 ∗ Sech@xD^2L y@xD == 0, y@xD, xD
99y@xD → C@1D LegendrePA 12
H + è!!!7 L, k, Tanh@xDE +
C@2D LegendreQA 12
H + è!!!7 L, k, Tanh@xDE==
Daniele Lupo Appunti di Mathematica
495Printed by Mathematica for Students
Le equazioni che DSolve è in grado di calcolare possono essere sia omogenee, come abbiamo visto
negli esempi precedenti, che inomogenee, come nel caso che segue:
trig = DSolve@x^2 y''@xD + y@xD x^4 + Log@xD, y@xD, xD
99y@xD → è!!!x C@1D CosA 12è!!!3 Log@xDE + è!!!x C@2D SinA 1
2è!!!3 Log@xDE +
113
ikjjj13 CosA 1
2è!!!3 Log@xDE
2+ x4 CosA 1
2è!!!3 Log@xDE
2+
13 CosA 12è!!!3 Log@xDE
2Log@xD + 13 SinA 1
2è!!!3 Log@xDE
2+
x4 SinA 12è!!!3 Log@xDE
2+ 13 Log@xD SinA 1
2è!!!3 Log@xDE
2y{zzz==
Analogamente a quanto abbiamo fatto precedentemente, possiamo particolareggiare le soluzioni,
disegnandone alcune con costanti definite mediante il comando Table:
sol = Flatten@Table@8y@xD ê. trig ê. 8C@1D → i, C@2D → j<, 8Hue@i + jD<<,8i, 0, 10, 2<, 8j, 1, 6, .3<D, 1D;
Plot@Evaluate@sol@@All, 1DDD, 8x, 0, 2<,PlotStyle → sol@@All, 2DD , PlotRange → 8Automatic, 8−7, 20<<D
0.5 1 1.5 2
-5
5
10
15
20
Graphics
Mathematica è in grado di risolvere equazioni non lineari, anche se ci sono casi in cui non è
possibile neanche al programma trovare la soluzione in forma chiusa in nessuna maniera conosciuta
fino ad oggi. Un esempio può essere il seguente:
eqn = y''@xD 4 x ∗ y'@xD^2 + y'@xD^2;
Daniele Lupo Appunti di Mathematica
496Printed by Mathematica for Students
DSolve@eqn, y, xD
99y → FunctionA8x<, −2 ArcTanA 1+4 xè!!!!!!!!!!!!!!!!!!!!!!!!!−1+8 C@1D E
è!!!!!!!!!!!!!!!!!!!!!!!!!−1 + 8 C@1D + C@2DE==
Plot@Evaluate@y@xD ê. % ê. 8C@1D → −2, C@2D → 1<D,8x, −1, .7<, PlotStyle → 8Blue<D;
-1 -0.75 -0.5 -0.25 0.25 0.5
0.6
0.8
1.2
1.4
1.6
1.8
Possiamo avere a che fare, in alcuni casi, con equazioni differenziali che non dipendono
esplicitamente da x, y ' HxL, come in questo caso:
DSolve@y''@xD == 2 Exp@3 ∗ y@xDD, y@xD, xD
— Solve::ifun : Inverse functions are being used by Solve, so some solutions may not
be found; use Reduce for complete solution information. More…
99y@xD → LogA−H−3L1ê3 J−C@1D + C@1D TanhA 3
2è!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!C@1D Hx + C@2DL2 E2N
1ê3
22ê3E=,
9y@xD → LogA31ê3 J−C@1D + C@1D TanhA 3
2è!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!C@1D Hx + C@2DL2 E2N
1ê3
22ê3E=,
9y@xD → LogAH−1L2ê3 31ê3 J−C@1D + C@1D TanhA 3
2è!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!C@1D Hx + C@2DL2 E2N
1ê3
22ê3E==
Data la difficoltà intrinseca nel risolvere equazioi differenziali di ordine superiore, e considerando
che DSolve utilzza Solve nella sua pancia, può capitare che le soluzioni coinvolgano la funzione
Root, dato che è il modo di dare soluzioni per un'equazione di grado elevato, quando non è possibile
trovarla in forma chiusa:
Daniele Lupo Appunti di Mathematica
497Printed by Mathematica for Students
DSolve@x^5 y'''''@xD + 6 x^4 ∗ y''''@xD −
2 ∗ x^3 ∗ y'''@xD − x^2 ∗ y''@xD + 5 ∗ x ∗ y'@xD + y@xD 0, y@xD, xD
99y@xD → xRoot@1−7 #1−#12+#13&,1D C@1D + xRoot@1−7 #1−#12+#13&,2D C@2D +
xRoot@1−7 #1−#12+#13&,3D C@3D + x32 −
è!!!!52 C@4D + x
32 +
è!!!!52 C@5D==
In questo caso non possiamo trovarci una soluzione simbolica, ma comunque possiamo averla in
maniera numerica. Inoltre, consideranto che abbiamo ottenuto una formula sì in maniera non chiusa,
ma sempre senza coefficienti numerici, possiamo avere facilmente risultati numerici con precisione
arbitraria:
f@x_D = y@xD ê. %@@1DD;
Notate come abbia utilizzato = invece di := perchè altrimenti avrei sempre la valutazione di % ad
ogni nuovo comando, che non rappresenterebbe più la soluzione di DSolve. Se andiamo a mettere un
valore alla soluzione in maniera esatta, otteniamo:
f@3D
3Root@1−7 #1−#12+#13&,1D C@1D + 3Root@1−7 #1−#12+#13&,2D C@2D +
3Root@1−7 #1−#12+#13&,3D C@3D + 332 −
è!!!!52 C@4D + 3
32 +
è!!!!52 C@5D
Il risultato è restituito sempre in forma simbolica, come nel caso generale. Andiamo invece a
sostituire un valore numerico:
0.082313 C@1D + 1.16682 C@2D + 31.2355 C@3D + 1.5214 C@4D + 17.7468 C@5D
Questa volta abbiamo visto come vengano restituiti i numeri, anche se rimangono i coefficienti C
che ovviamente non erano calcolati. Possiamo utilizzare una precisione maggiore, se ci serve:
N@f@3D, 50D
0.082313036603068456357530701934319583558912006682794C@1D +
1.1668222437039807891665184590870851804424075884110C@2D +
31.235461826749516230168482745226269524617450019969C@3D +
1.5214024193806499467234230586261890237812609816579C@4D +
17.746783925183628648066945795420638758100659851792C@5D
Ah, la potenza di Mathematica!!!!
In altri casi possiamo avere soluzioni esatte date in maniera simbolica, come questa sottostante che
restituisce la soluzione con le funzioni di Airy che compaiono all'interno di integrali
Daniele Lupo Appunti di Mathematica
498Printed by Mathematica for Students
ai = y'''@xD − y''@xD + 5 x y'@xD + 5 y@xD 0;
DSolve@ai, y@xD, xD êê FullSimplify
99y@xD → xê2 ikjjjjjAiryAiA
H−1L1ê3 H−1 + 20 xL4 52ê3
E C@2D +
AiryBiA H−1L1ê3 H−1 + 20 xL4 52ê3
E C@3D + AiryBiA H−1L1ê3 H−1 + 20 xL4 52ê3
E
‡1
x
−1
51ê3 ikjjjH−1L2ê3 −K$4755ê2 π AiryAiA H−1L1ê3 H−1 + 20 K$4755L
4 52ê3E C@1Dy
{zzz
K$4755 + AiryAiA H−1L1ê3 H−1 + 20 xL4 52ê3
E
‡1
x H−1L2ê3 −K$4051ê2 π AiryBiA H−1L1ê3 H−1+20 K$4051L4 52ê3 E C@1D
51ê3 K$4051
y{zzzzz==
Sistemi ODE
Abbiamo visto finora come lavorare con equazioni differenziali, ma possiamo trattare alla stessa
maniera i sistemi di equazioni differenziali, che sono sistemi del tipo:
FHY HnLHxL, Y Hn-1LHxL, ..., Y ' HxL, Y HxLL ã 0
dove Y HxL rappresenta un vettore di funzioni incognite: il caso più semplice di sistema, naturalmente,
è il caso di sistema lineare, che può essere espresso, per il caso di sistema lineare del primo ordine,
nella seguente forma:
Y £HxL AHxL Y HxL +BHxL
Dove è presente il vettore delle derivate prime Y ' HxL, quello delle funzioni non derivate Y HxL, ed
inoltre è presente la matrice dei coefficienti AHxL, ed il vettore dei termini noti BHxL. Naturalmente il
caso si semplifica ulteriormente se la matrice A è a termini costanti, invece che dipendenti dalla
variabile x.
Il comando DSolve, tuttavia, si aspetta come argomento una lista di equazioni, quindi, se abbiamo la
matrice A ed il vettore B, dobbiamo comunque trasformarli nelle rispettive equazioni, prima di dare
il sistema in pancia a DSolve. Supponiamo che la nostra matrica A sia la seguente, assieme al vettore
B:
A = 88−3, 3, 0<,85, 0, −2<,84, −3, −1<<;
Daniele Lupo Appunti di Mathematica
499Printed by Mathematica for Students
Adesso occorre creare il vettore delle incognite, che nel nostro caso sono delle funzioni:
Y@x_D := 8y1@xD, y2@xD, y3@xD<;
Arrivati a questo punto, possiamo crearci il sistema;
sisdiff = H#1 #2L &∼ MapThread∼8Y'@xD, A.Y@xD<
8y1 @xD −3 y1@xD + 3 y2@xD,y2 @xD 5 y1@xD − 2 y3@xD, y3 @xD 4 y1@xD − 3 y2@xD − y3@xD<
Una volta creato il sistema, possiamo risolverlo:
solsis = DSolve@sisdiff, Y@xD, xD êê FullSimplify
99y1@xD →1
814− 1
2 I7+è!!!!!!!37 M x
II333 + 15 è!!!!!!37 + H333 − 15 è!!!!!!37 L è!!!!!!!37 x + 14812 I13+
è!!!!!!!37 M xM C@1D −
2 H74 + 7 è!!!!!!37 L C@2D + 14812 I13+
è!!!!!!!37 M x H2 C@2D − C@3DL + H74 − 26 è!!!!!!37 LC@3D + 2
è!!!!!!!37 x HH−74 + 7 è!!!!!!37 L C@2D + H37 + 13 è!!!!!!37 L C@3DLM,y2@xD →
1814
− 12 I7+è!!!!!!!37 M x I2 I−74 − 29 è!!!!!!37 + H−74 + 29 è!!!!!!37 L è!!!!!!!37 x +
14812 I13+
è!!!!!!!37 M xM C@1D + 3 H37 + 9 è!!!!!!37 L C@2D +
29612 I13+
è!!!!!!!37 M x H2 C@2D − C@3DL + 4 H37 − 2 è!!!!!!37 L C@3D +è!!!!!!!37 x H3 H37 − 9 è!!!!!!37 L C@2D + 4 H37 + 2 è!!!!!!37 L C@3DLM, y3@xD →
1814
− 12 I7+è!!!!!!!37 M x II37 − 101 è!!!!!!37 + H37 + 101 è!!!!!!37 L è!!!!!!!37 x − 74
12 I13+è!!!!!!!37 M xM C@1D +
H74 + 40 è!!!!!!37 L C@2D − 7412 I13+è!!!!!!!37 M x H2 C@2D − C@3DL + H370 − 42 è!!!!!!37 L
C@3D +è!!!!!!!37 x HH74 − 40 è!!!!!!37 L C@2D + H370 + 42 è!!!!!!37 L C@3DLM==
Vediamo di disegnare queste soluzioni per alcuni valori delle costanti; visualizziamo in tre grafici
distinti y1, y2, y3:
funz = Flatten@Table@# ê. solsis ê. 8C@1D → a, C@2D → b, C@3D → c<,8a, 0, 1, .3<, 8b, 0, 1, .3<, 8c, 0, 1, .3<DD & ê@
8y1@xD, y2@xD, y3@xD<;
colori = PlotStyle → Flatten@Table@RGBColor@a, b, cD,8a, 0, 1, .3<, 8b, 0, 1, .3<, 8c, 0, 1, .3<DD;
Daniele Lupo Appunti di Mathematica
500Printed by Mathematica for Students
DisplayTogetherArray@Plot@Evaluate@#, 8x, −1, 1.3<, colori,
AspectRatio → 1, PlotRange → 8−3, 6<DD & ê@ funzD
-1 -0.5 0.5 1
-2
2
4
6
-1 -0.5 0.5 1
-2
2
4
6
-1 -0.5 0.5 1
-2
2
4
6
GraphicsArray
Mamma mia, quante soluzioni...
Proviamo adesso a fare qualcosa di più semplice, invocando soltanto due equazioni, e tracciando la
traiettoria che si ottiene utilizzando come coordinate parametriche le due funzioni ottenute:
A = 887, −80<, 85, −5<<;
Y@t_D := 8x@tD, y@tD<
sisT = H#1 #2L &∼ MapThread∼8Y'@tD, A.Y@tD<
8x @tD 7 x@tD − 80 y@tD, y @tD 5 x@tD − 5 y@tD<
solT = DSolve@sisT, Y@tD, tD êê FullSimplify
99x@tD → t C@1D Cos@2 è!!!!!!91 tD +t H3 C@1D − 40 C@2DL Sin@2 è!!!!!!91 tD
è!!!!!!91,
y@tD → t C@2D Cos@2 è!!!!!!91 tD +t H5 C@1D − 6 C@2DL Sin@2 è!!!!!!91 tD
2 è!!!!!!91==
Arrivati a questo punto, possiamo utilizzare ParametricPlot per disegnare la traiettoria; tuttavia
creerò qualcosa di più attraente, colorando la curva a con un gradiente che dipende dal parametro:
traiettoria@t_D =
Evaluate@8x@tD, y@tD< ê. solT ê. 8C@1D → 2, C@2D → 4<D@@1DD;
Daniele Lupo Appunti di Mathematica
501Printed by Mathematica for Students
Module@
H∗ Parametri del disegno ∗L
8inizio = 0, fine = 3, passo = 1ê300<,
H∗ Creazione della curva ∗L
Show@Graphics@
H∗ Creazione delle linee colorate che compongono il grafico ∗L
8Table@[email protected], Hue@tê6D,Line@8traiettoria@t − passoD, traiettoria@tD<D<,
8t, inizio, fine, passo<D<,
H∗ Opzioni del disegno ∗L
AspectRatio → 1, Axes → True, Background → RGBColor@1, 1, .8DDDD
-200 -100 100 200 300
-60
-40
-20
20
40
60
80
Graphics
Possiamo anche vedere come varia la spirale al variare di un singolo parametro: vediamo i due
grafici distinti, dove prima variamo C[1], e dopo C[2]:
Daniele Lupo Appunti di Mathematica
502Printed by Mathematica for Students
traiettoriamultiplaC1 =
Table@8x@tD, y@tD< ê. solT@@1DD ê. 8C@1D → a, C@2D → 4<, 8a, 0, 20, 4<D;
traiettoriamultiplaC2 = Table@8x@tD, y@tD< ê. solT@@1DD ê. 8C@1D → 10, C@2D → a<, 8a, 0, 20, 4<D;
DisplayTogetherArray@8ParametricPlot@Evaluate@#D, 8t, 0, 3<,
PlotRange → All, PlotStyle → 8Red, Green, Orange, Blue, Cyan<D &ê@ 8traiettoriamultiplaC1, traiettoriamultiplaC2<
<D
-200 200 400
-100
-50
50
100
-1000 -500 500 1000 1500
-300-200-100
100200300400
GraphicsArray
I coefficienti del sistema lineare, comunque, possono anche essere non costanti, cioè dipendere dalla
variabile indipendente anch'essi, come in questo caso, in cui le due funzioni i vettori della matrice
sono ortogonali fra di loro:
A = 88t, Cos@tD<, 8− Cos@tD, t<<;
Y@t_D := 8x@tD, y@tD<
noncostante = MapThread@#1 #2 &, 8Y'@tD, A.Y@tD<D
8x @tD t x@tD + Cos@tD y@tD, y @tD −Cos@tD x@tD + t y@tD<
DSolve@noncostante, Y@tD, tD
99x@tD →t22 C@1D Cos@Sin@tDD +
t22 C@2D Sin@Sin@tDD,
y@tD →t22 C@2D Cos@Sin@tDD −
t22 C@1D Sin@Sin@tDD==
Anche nel caso dei sistemi di equazioni differenziali possiamo avere casi che non sono omogenei,
come abbiamo trattato finora, cioè casi in cui il vettore B non è nullo:
Daniele Lupo Appunti di Mathematica
503Printed by Mathematica for Students
A = 887, −8<, 81, −1<<;B = 8t, Gamma@tê5D<;X@t_D = 8x@tD, y@tD<;inomogeneo = MapThread@#1 #2 &, 8X'@tD, A.X@tD + B<D
9x @tD t + 7 x@tD − 8 y@tD, y @tD GammaA t5E + x@tD − y@tD=
DSolve@inomogeneo, 8x, y<, tD êê FullSimplify
99x → FunctionA8t<,12I I3−2 è!!!!2 M t − è!!!2 I3−2 è!!!!2 M t + I3+2 è!!!!2 M t + è!!!2 I3+2 è!!!!2 M tM C@1D +
è!!!2 I I3−2 è!!!!2 M t − I3+2 è!!!!2 M tM C@2D +
12I I3−2 è!!!!2 M t − è!!!2 I3−2 è!!!!2 M t + I3+2 è!!!!2 M t + è!!!2 I3+2 è!!!!2 M tM
‡1
t
J 12I −I3−2 è!!!!2 M K$1025371 − è!!!2 −I3−2 è!!!!2 M K$1025371 +
−I3+2 è!!!!2 M K$1025371 + è!!!2 −I3+2 è!!!!2 M K$1025371M K$1025371 +
è!!!2 I −I3−2 è!!!!2 M K$1025371 − −I3+2 è!!!!2 M K$1025371M GammaA K$10253715
EN
K$1025371 + è!!!2 I I3−2 è!!!!2 M t − I3+2 è!!!!2 M tM
‡1
ti
kjjjjjj−
I −I3−2 è!!!!2 M K$1029249 − −I3+2 è!!!!2 M K$1029249M K$10292494 è!!!2 +
12I −I3−2 è!!!!2 M K$1029249 + è!!!2 −I3−2 è!!!!2 M K$1029249 + −I3+2 è!!!!2 M K$1029249 −
è!!!2 −I3+2 è!!!!2 M K$1029249M GammaA K$10292495
Ey
{zzzzzz K$1029249E,
y → FunctionA8t<, −I I3−2 è!!!!2 M t − I3+2 è!!!!2 M tM C@1D
4 è!!!2 +
12I I3−2 è!!!!2 M t + è!!!2 I3−2 è!!!!2 M t + I3+2 è!!!!2 M t − è!!!2 I3+2 è!!!!2 M tM C@2D −
14 è!!!2
ikjjjjI I3−2 è!!!!2 M t − I3+2 è!!!!2 M tM
‡1
t
J 12I −I3−2 è!!!!2 M K$1025371 − è!!!2 −I3−2 è!!!!2 M K$1025371 + −I3+2 è!!!!2 M K$1025371 +
è!!!2 −I3+2 è!!!!2 M K$1025371M K$1025371 + è!!!2 I −I3−2 è!!!!2 M K$1025371 −
−I3+2 è!!!!2 M K$1025371M GammaA K$10253715
EN K$1025371y{zzzz +
12I I3−2 è!!!!2 M t + è!!!2 I3−2 è!!!!2 M t + I3+2 è!!!!2 M t − è!!!2 I3+2 è!!!!2 M tM
‡1
ti
kjjjjjj−
I −I3−2 è!!!!2 M K$1029249 − −I3+2 è!!!!2 M K$1029249M K$10292494 è!!!2 +
12I −I3−2 è!!!!2 M K$1029249 + è!!!2 −I3−2 è!!!!2 M K$1029249 + −I3+2 è!!!!2 M K$1029249 −
è!!!2 −I3+2 è!!!!2 M K$1029249M GammaA K$10292495
Ey
{zzzzzz K$1029249E==
Daniele Lupo Appunti di Mathematica
504Printed by Mathematica for Students
Anche in questo caso possiamo visualizzare soluzioni partcolari nel solito modo. Dato che però la
soluzione non è data in forma chiusa, il calcolo del grafico è computazionalmente intensivo, e
potrebbe impiegarci parecchio prima di completare il disegno. Oltre al grafico è mostrato il tempo
impiegato sul mio AthlonXP64 3200, con sistema operativo WinXP Pro a 32 bit:
particularsol = 8x@tD, y@tD< ê. %@@1DD ê. 8C@1D → 1, C@2D → 2<;
Plot@Evaluate@particularsolD, 8t, 0, Pi<,PlotStyle → 88Blue<, [email protected]<D, Orange<<D êê Timing
0.5 1 1.5 2 2.5 3
-2× 106
-1.5× 106
-1× 106
-500000
8599.25 Second, Graphics <
Cavolo!!! Dopo aver aspettato tutto questo tempo, poteva almeno uscire qualcosa di più carino... Ma
non ho intenzione di rifare i calcoli un'altra volta. Accontentatevi di questo. Adesso, comunque,
dopo questo 'grande' finale, possiamo passare alla sezione successiva.
PDE
La caratteristica che differenzia le PDE dalle ODE è il fatto che in questo caso abbiamo più variabili
indipendenti, invece di una soltanto. Questo complica parecchio la risoluzione, specialmente nei casi
non lineari dove, a parte pochi casi, possiamo tranquillamente metterci le mani in testa e passare alla
sezione successiva dove si parla della risoluzione numerica. Ma per ora tralasciamola...
Vediamo subito un esempio, come il seguente:
pde = D@u@x, yD, xD + y D@u@x, yD, yD y Sin@xD
y uH0,1L@x, yD + uH1,0L@x, yD y Sin@xD
Daniele Lupo Appunti di Mathematica
505Printed by Mathematica for Students
pdesol = DSolve@pde, u, 8x, y<D
99u → FunctionA8x, y<, 12H−y Cos@xD + y Sin@xD + 2 C@1D@ −x yDLE==
Vediamo come sia stato necessario definire mediante l'operatore D la derivata perchè, come
avevamo detto all'inizio, in questo caso dobbiamo specificare rispetto a quale variabile è calcolata la
derivata, specialmente nelle derivate miste. Anche in questo caso, come nel caso unidimensionale,
Mathematica lo interpreta tramite il comando Derivative:
InputForm@pdeD
y*Derivative[0, 1][u][x, y] + Derivative[1, 0][u][x, y] == y*Sin[x]
Ricordate? L'abbiamo visto a proposito della risoluzione manuale delle ODE a coefficienti costanti,
quando siamo andati a trovarci l'equazione caratteristica...
Vi ricordo anche che, in questo caso, abbiamo le C[n] che adesso diventano delle funzioni arbitrarie,
anche se l'argomento è specificato. Nel nostro caso abbiamo 2 C@1D@‰-x yD, dove l'argomento è unico,
ma è dato come funzione delle due variabili indimententi x, y. Se vogliamo trovarci una soluzione
particolare, dobbiamo sostituire a C@nD al posto di un valore, l'head di una funzione:
pdeparticolare@x_, y_D := u@x, yD ê. pdesol@@1DD ê. C@1D → Cos
In questo modo abbiamo creato la funzione. Notate come il coseno abbia lo stesso argomento di
C@1D, cosa che fra l'altro era scontata. Adesso, tanto per farvi contenti, plottiamo questqa funzione:
Daniele Lupo Appunti di Mathematica
506Printed by Mathematica for Students
DisplayTogetherArray@8Plot3D@pdeparticolare@x, yD, 8x, −3, 3<, 8y, −5, 5<,
PlotPoints → 100, Mesh → False,ViewPoint −> 83.252, −1.028, 2.732<D,
DensityPlot@pdeparticolare@x, yD, 8x, −3, 3<, 8y, −7, 7<,PlotPoints → 100, Mesh → FalseD
<D
-2
0
2
-4-2
02 4
-4-20242
0
2
--0
-3 -2 -1 0 1 2 3
-6
-4
-2
0
2
4
6
GraphicsArray
Le equazioni PDE sono di solito classificate in tre tipi: lineati, quasilineari e non lineari. Per
cominciare, vediamo un esempio di equazione omogenea a coefficienti costanti;
omo = 2 ∗ D@u@x, yD, xD + 9 ∗ D@u@x, yD, yD + u@x, yD 0
u@x, yD + 9 uH0,1L@x, yD + 2 uH1,0L@x, yD 0
sol = DSolve@omo, u, 8x, y<D
99u → FunctionA8x, y<, −xê2 C@1DA 12H−9 x + 2 yLEE==
Non è veramente una delle equazioni più complicate che abbiamo visto finora... Vediamo delle
soluzioni che si ottengono andando a sostituire alla funzione arbitraria C@1D delle funzioni specifiche:
omop = u@x, yD ê. sol@@1DD ê.88C@1D → Sin<, 8C@1D → ArcTan<, 8C@1D → H# &L<<
9 −xê2 SinA 12H−9 x + 2 yLE, −xê2 ArcTanA 1
2H−9 x + 2 yLE, 1
2−xê2 H−9 x + 2 yL=
Andiamo a plottare adesso queste funzioni:
Daniele Lupo Appunti di Mathematica
507Printed by Mathematica for Students
DisplayTogetherArray@Plot3D@#, 8x, −4, 4<, 8y, −4, 4<, PlotPoints → 40D & ê@ omopD
-4-2
02
4-4-2024
-4-2024
4-2
02
-4-2
02
4-4-2024
05
10
4-2
02
-4-2
02
4-4-2024
050
100150
4-2
02
GraphicsArray
Come potete vedere la funzione arbitrarià da una maggiore libertà alla funzione, rispetto a dei
coefficienti indeterminati...
Un esempio interessante di PDE è l'equazione di trasporto:
∑uÅÅÅÅÅÅÅ∑x + k ∑uÅÅÅÅÅÅÅ∑y 0
dove k rappresenta una quantità costante. Come potete vedere è un'equazione lineare, ed è una delle
più semplici PDE che si possano incontrare (forse la più semplice?).
trasporto = DSolve@D@u@x, yD, xD + κ D@u@x, yD, yD 0, u@x, yD, 8x, y<D
88u@x, yD → C@1D@y − x κD<<
Come potete vedere è una soluzione abbastanza semplice, ed è praticamente data da qualsiasi
funzione avente l'argomento specificato:
trabel = u@x, yD ê. trasporto@@1DD ê. C@1D → HBesselJ@3, #D &L
BesselJ@3, y − x κD
Daniele Lupo Appunti di Mathematica
508Printed by Mathematica for Students
DisplayTogetherArray@8DensityPlot@trabel ê. κ → 8, 8x, 0, 8<,8y, 0, 8<, PlotPoints → 100, Mesh → FalseD,
Plot3D@trabel ê. κ → 8, 8x, 0, 8<, 8y, 0, 8<, PlotPoints → 870, 40<D<D
0 2 4 6 80
2
4
6
8
02
46
8 0
2
4
6
8
-0.4-0.2
00.20.4
02
46
GraphicsArray
Adesso andiamo a vedere un semplice esempio di equazione differenziale PDE inomogenea, con
l'aggiunta di coefficienti non costanti, data dalla seguente equazione:
inom = D@u@x, yD, xD + x D@u@x, yD, yD Sin@xD + x
x uH0,1L@x, yD + uH1,0L@x, yD x + Sin@xD
solino = DSolve@inom, u, 8x, y<D
99u → FunctionA8x, y<, 12Jx2 − 2 Cos@xD + 2 C@1DA 1
2H−x2 + 2 yLENE==
Anche in questo caso la soluzione è abbastanza semplice, seppure possa essere resa complicata a
piacere scegliendo la funzione C@1D:
inopar = u@x, yD ê. solino@@1DD ê.88C@1D → Sin<, 8C@1D → ArcTan<, 8C@1D → H# &L<<
9 12Jx2 − 2 Cos@xD + 2 SinA 1
2H−x2 + 2 yLEN,
12Jx2 + 2 ArcTanA 1
2H−x2 + 2 yLE − 2 Cos@xDN, 1
2H2 y − 2 Cos@xDL=
Daniele Lupo Appunti di Mathematica
509Printed by Mathematica for Students
DisplayTogetherArray@8ContourPlot@#, 8x, −6, 6<, 8y, −6, 6<, PlotPoints → 50D & ê@ inopar,Plot3D@#, 8x, −8, 8<, 8y, −8, 8<, PlotPoints → 30D & ê@ inopar
<D
-50
5-5
050
102030
-50
5
-50
5-5
050
102030
-50
5
-50
5-5
05-5
05
-50
5
-6 -4 -2 0 2 4 6-6
-4
-2
0
2
4
6
-6 -4 -2 0 2 4 6-6
-4
-2
0
2
4
6
-6 -4 -2 0 2 4 6-6
-4
-2
0
2
4
6
GraphicsArray
I gradi di liberta, nelle PDE, è generalmene maggiore, come possiamo vedere da questi esempi.
La caterogira successiva è data dalle equazioni quasi lineari, che ha termini lineari nelle derivate
prime rispetto ad x ed ad y, ma che possono contenere termini non lineari dati da queste derivate e
della funzione non derivata, come in questo esempio:
ql = D@u@x, yD, xD + x^3 D@u@x, yD, yD u@x, yD^2 + x
x3 uH0,1L@x, yD + uH1,0L@x, yD x + u@x, yD2
solql = DSolve@ql, u, 8x, y<D êê FullSimplify
99u → FunctionA8x, y<,
J−2 x3ê2 BesselJA−23, 2 x3ê2
3E + 2 x3ê2 BesselJA 2
3, 2 x3ê2
3E
C@1DA 14H−x4 + 4 yLEN í J2 Jx BesselJA 1
3, 2 x3ê2
3E +
x BesselJA−13, 2 x3ê2
3E C@1DA 1
4H−x4 + 4 yLENNE==
Daniele Lupo Appunti di Mathematica
510Printed by Mathematica for Students
Possiamo vedere come anche in questo caso cambia radicalmente la funzione se andiamo a sostituire
nel nostro caso due funzioni distinte, ad esempio il seno e l'identità:
DisplayTogetherArray@DensityPlot@#, 8x, 0.1, 4<,
8y, −15, 20<, PlotPoints → 400, Mesh → FalseD & ê@
Evaluate@u@x, yD ê. solql@@1DD ê. 88C@1D → Sin<, 8C@1D → H# &L<<DD êêTiming
1 2 3 4-15
-10
-5
0
5
10
15
20
1 2 3 4-15
-10
-5
0
5
10
15
20
833.797 Second, GraphicsArray <
Quello che possiamo notare, come principale differenza dalle lineari alle quasilineari, è la presenza
di discontinuità nella soluzione, che si possono vedere come passaggi bruschi dal bianco al nero, che
sono caratteristiche di quest'ultimo tipo di equazioni, sebbene il metodo risolutivo sia per certi versi
simile al caso lineare.
Le cose diventano decisamente più toste quando abbiamo a che fare con equazioni PDE non lineari,
nel senso che la funzione
F(u,p,q) 0
Dove p, q rappresentano le derivate prime rispetto alle due variabili (sempre considerando equazioni
differenziali del primo ordine ed a due variabili), ed F in questo caso non è lineare.
Possiamo definire per semplicità, le nostre derivate, e la funzione, in questa maniera:
z := u@x, yD; p := D@u@x, yD, xD; q := D@u@x, yD, yD;
Daniele Lupo Appunti di Mathematica
511Printed by Mathematica for Students
In questa maniera non dobbiamo per forza riscrivere tutto quanto quando abbiamo bisogno di usare
le derivate nelle nostre equazioni. Effettivamente potevamo farlo dall'inizio, ma ci ho pensato
solamente adesso... :-( Spero che voi l'abbiate fatto e che siate stati più intelligenti di me!!!
Comunque, vediamo subito un veloce esempio:
nonlin = p q z^2
uH0,1L@x, yD uH1,0L@x, yD u@x, yD2
DSolve@nonlin, u, 8x, y<D
— DSolve::nlpde : Solution requested to nonlinear partialdifferential equation. Trying to build a complete integral.
99u → FunctionA8x, y<, − yè!!!!!!!!!!!!!C@1D −x è!!!!!!!!!!!!C@1D − C@2D
è!!!!!!!!!!!!!C@1D E==
In questo caso Mathematica ci avverte con gentilezza e garbo che abbiamo a che fare con PDE non
lineari, prima di creare l'integrale completo, che serve per calcolare simbolicamente la PDE, quando
obbiamente ci riesce. In questo caso, inoltre, abbiamo ottenuto dei valori di C@1D, C@2D che non sono
delle funzioni, ma delle costanti. Possiamo anche parametrizzare il tutto, in questo esempio, ponendo
una costante in funzione dell'altra. In questo modo si ottiengono delle superfici dipendenti da un
parametro, ovvero una famiglia di superfici, il cui inviluppo è pure soluzione della PDE, che è dato
dall'integrale completo. Quest'ultimo include qualsiasi elemento della famiglia di curve ottenuta
variando arbitrariamente i paramentri, l'inviluppo che abbiamo appenda detto, l'inviluppo dell'intera
famiglia (integrale singolare), e altri integrali completi della PDE si possono dal processo di
formazione degli inviluppi.
Come potete vedere, quindi, la teoria delle PDE è alquanto corposa e cummattusa (i siciliani mi
capiranno). Tuttavia ci possono essere casi in cui possono essere comunque risolte. Un caso utile si
ha quando possiamo applicare la separazione delle variabili, in modo da integrare in maniera
indipendente le due parti dell'equazione ottenuta:
sepa = DSolve@Hy p − x qL^2 + Hx p + y qL 6, z, 8x, y<D
— DSolve::nlpde : Solution requested to nonlinear partialdifferential equation. Trying to build a complete integral.
99u@x, yD →
− ArcTanA yxE è!!!!!!!!!!!C@1D + C@2D + 6 LogAè!!!!!!!!!!!!!!!x2 + y2 E + C@1D LogAè!!!!!!!!!!!!!!!x2 + y2 E==
Daniele Lupo Appunti di Mathematica
512Printed by Mathematica for Students
Dato che la funzione che abbiamo ottenuto è complessa, andiamo a visualizzare la parte reale e
quella immaginaria, rispettivamente, fissando dei parametri per permetterci di avere una risoluzione
numerica
DisplayTogetherArray@Plot3D@#, 8x, −4, 4<, 8y, −4, 4<D & ê@ HH8Re@#D, Im@#D< &L ê@
Evaluate@u@x, yD ê. sepa@@1DD ê. 8C@1D → 1, C@2D → 2<DLD
-4-2
02
4 -4
-2
0
2
4
05
10
4-2
02
-4-2
02
4 -4
-2
0
2
4
-101
4-2
02
GraphicsArray
Notate la discontinuità tipica dell' ArcTan nel grafico della fase...
Il passo successivo, adesso, è quello delle PDE del secondo ordine. Come prima, partiamo dal caso
più semplice, che è dato da quello lineare. In questo caso, essendo la funzione a più variabili (nel
nostro caso due), dovranno comparire anche le derivate miste:
a ∑2uÅÅÅÅÅÅÅÅÅ∑x2 + b ∑2uÅÅÅÅÅÅÅÅÅÅÅÅÅ∑x ∑y + c ∑2uÅÅÅÅÅÅÅÅÅ∑y2 + d ∑uÅÅÅÅÅÅÅ∑x + e ∑uÅÅÅÅÅÅÅ∑y + f u g
Possiamo distunguere, qua come in tutti li altri casi, le equazioni omogenee da quelle inomogenee, a
seconda se g è uguale o diverso da zero. Richiamando velocemente le proprietà delle PDE lineari del
secondo ordine, possiamo dividerle in tre categorie principali, che dipendono dalle derivate di ordine
due, in particolar modo dai loro coefficienti.
Se abbiamo b2 - 4 a c < 0, allora l'integrale è detto ellittico. Come caso particolare abbiamo
l'equazione di Laplace, che si ottiene per a = 1, b = 0, c = 1. Poi abbiamo le equazioni parabolice,
nel caso in cui b2 - 4 a c = 0, l'equazione è detta parabolica, come l'equazione per la diffuzione del
calore. Infine, per b2 - 4 a c > 0 l'equazione viene chiamata iperbolica, come l'equazione d'onda.
Come potete vedere, nelle PDE del secondo ordine, anche solo fermandoci alle lineari, sorgono
molti casi importanti. La soluzione simbolica può essere trovata in non tutti i casi, per esempio si
possono trovare nei casi in cui l'equazione è omogenea, e i coefficienti delle derivate prime è nullo,
Daniele Lupo Appunti di Mathematica
513Printed by Mathematica for Students
come appunto l'equazione di Laplace; in questo caso la soluzione è quella generica, dato che manca
ogni condizione al contorno:
laplace = D@u@x, yD, 8x, 2<D + D@u@x, yD, 8y, 2<D 0;
DSolve@laplace, u, 8x, y<D
88u → Function@8x, y<, C@1D@ x + yD + C@2D@− x + yDD<<
Possiamo vedere un altro esempio di PDE dove compaiono solamente le derivate di ordine 2:
pde2 = 8 D@u@x, yD, 8x, 2<D + 9 D@u@x, yD, x, yD + 9 D@u@x, yD, 8y, 2<D 0
9 uH0,2L@x, yD + 9 uH1,1L@x, yD + 8 uH2,0L@x, yD 0
solpde2 = DSolve@pde2, u, 8x, y<D
99u → FunctionA8x, y<,C@1DA 1
16H−9 + 3 è!!!!!!23 L x + yE + C@2DA 1
16H−9 − 3 è!!!!!!23 L x + yEE==
pde2 ê. solpde2 êê Simplify
8True<
Come possiamo vedere, le soluzioni sono rispettate. Anche in questo caso la funzione che abbiamo
ottenuto ha valori sia reali che immaginari:
Daniele Lupo Appunti di Mathematica
514Printed by Mathematica for Students
DisplayTogetherArray@Plot3D@#, 8x, −6, 6<, 8y, −6, 6<, PlotPoints → 45, PlotRange → AllD & ê@
HH8Re@#D, Im@#D< &L ê@
Evaluate@u@x, yD ê. solpde2@@1DD ê. 8C@1D → Sin, C@2D → Log<DLD
-5-2.5
02.5
5-5
-2.5
02.55
-100-500
50100
-5-2.5
02.5
5
-5-2.5
02.5
5-5
-2.5
02.55
-100-500
50100
-5-2.5
02.5
5
GraphicsArray
Daniele Lupo Appunti di Mathematica
515Printed by Mathematica for Students
DAE
Molti sistemi naturali possono essere modellati tramite un insieme di equazioni che sono sia
differenziali che algebriche: come non citare i circuiti elettronici, per chi fa ingegneria elettronica
come me? Dalle leggi di Kirkoff, che sono algebriche, alle cariche e scariche dei condensatori ed
induttori, che sono equazioni differenziali, ottenendo una bellissima ed affascinante DAE...
......................
Meglio se me ne vado a letto, per stasera.......
.....zzzzzzzzzzzzzzzzzzzzzzzz......
.......................
Arieccoci, qua, per cominciare di nuovo. Di cosa parlavamo? delle letterine?!?!? Ah, ora ricordo...
Bene, rientiramo nel nostro mondo fatto di matematica e di tante figurine colorate, che non sono
quelle dei calciatori...
Abbiamo appena definito le DAE, facendo un piccolo esempio su un sistema che le sfruttasse. Come
problema analitico sono abbastanza complicate, specialmente se andiamo a considerare i casi non
lineari, che possono essere veramente delle bruttissime bestie.
Un caso in cui le DAE possono essere risolte è il caso dei sistemi lineari, scritti nella seguente
maniera:
A.x£HtL + B.xHtL F
Le matrici sono funzioni del parametro t, come pure il vettore F. Si distguono anche qua, tanto per
cambiare, le equazioni omogenee da quelle inomogenee. Se A e B sono costanti, DSolve può essere
in grado di trovare la soluzione. Inoltre, in questo tipo di problema bisogna porre particolare
attenzione alle condizioni iniziali del problema, per assicurarci la soluzione.
Possiamo vedere qua un semplicissimo esempio di DAE:
dae = 8x'@tD − 3 y@tD 0,x@tD − y@tD 0<;
Daniele Lupo Appunti di Mathematica
516Printed by Mathematica for Students
daesol = DSolve@dae, 8x, y<, tD
99x → FunctionA8t<, 14
3 t C@1DE, y → FunctionA8t<, 14
3 t C@1DE==
Possiamo scrivere la corrispondente soluzione equazione in foma non omogenea, per compilcarci un
tantinello la vita:
inodae = 8x'@tD + y@tD t,x@tD − y@tD Cos@tD<;
inodaesol = DSolve@inodae, 8x, y<, tD
99x → FunctionA8t<, 14H −t C@1D + 2 H−2 + 2 t + Cos@tD + Sin@tDLLE, y →
FunctionA8t<, −Cos@tD +14H −t C@1D + 2 H−2 + 2 t + Cos@tD + Sin@tDLLE==
Come possiamo vedere il risultato è dato dalla soluzione omogenea, più una soluzione particolare di
quella inomogenea, come dice la teoria delle equazioni differenziali riguardo, appunto, alle eq.
inomogenee. Possiamo anche imporre delle opportune condizioni iniziali per le nostre funzioni:
inodaesolpar =
DSolve@Flatten@8inodae, x@3D 0<D, 8x, y<, tD êê FullSimplify
99x → FunctionA8t<, 12
−t
H−4 3 − 2 t + 2 t t − 3 Cos@3D + t Cos@tD − 3 Sin@3D + t Sin@tDLE,y → FunctionA8t<, −
12
−t H4 3 + 2 t − 2 t t + 3 Cos@3D +
t Cos@tD + 3 Sin@3D − t Sin@tDLE==
In questo modo possiamo plottare le funzioni ottenute:
Daniele Lupo Appunti di Mathematica
517Printed by Mathematica for Students
Plot@Evaluate@8x@tD, y@tD, x@tD − y@tD< ê. inodaesolparD,8t, 0, 5 Pi<, PlotRange → 8−5, 15<,PlotStyle −> 88Red<, 8Blue<, [email protected], Green<<D
2.5 5 7.5 10 12.5 15
-5
-2.5
2.5
5
7.5
10
12.5
15
Graphics
Possiamo vedere come la differenza delle due funzioni sia effettivamente il coseno che avevamo
imposto nell'equazione algebrica della DAE.
Possiamo trattare le DAE anche in generale, volendo. Per esempio, potremmo volere che la funzione
della parte inomogenea sia indefinita, come nel caso che segue:
indef = 8x''@tD + y@tD == f@tD,2 x@tD == h@tD
<;
DSolve@indef, 8x, y<, tD
99x → FunctionA8t<, h@tD2
E, y → FunctionA8t<, f@tD −h @tD2
E==
In questo caso possiamo vedere che nella soluzione compaiono le funzioni arbitrarie. Possiamo
notare anche un'altra cosa, però, cioè la mancanza di costanti arbitrarie, il che ci fa capire che nella
soluzione del nostro problema non abbiamo gradi di libertà. Possiamo tentare di risolvere il caso in
cui le funzioni diventano particolari:
def = 8x''@tD + y@tD == Cos@tD,2 x@tD == BesselJ@3, tD
<;
Daniele Lupo Appunti di Mathematica
518Printed by Mathematica for Students
sol = DSolve@def, 8x, y<, tD
99x → FunctionA8t<, 12BesselJ@3, tDE,
y → FunctionA8t<, 14J 12H−BesselJ@1, tD + BesselJ@3, tDL +
12HBesselJ@3, tD − BesselJ@5, tDLN + Cos@tDE==
Possiamo notare la corrispondenza fra le fue soluzioni che abbiamo ottenuto, nel caso generale ed in
quello particolare. Possiamo plottare il grafico parametrico nello stesso modo di come abbiamo fatto
prima
tr@t_D = Evaluate@8x@tD, y@tD< ê. solD@@1DD;
Module@8inizio = 0, fine = 100, passo = 1ê300, scalahue = 200<,Show@Graphics@8Table@[email protected],
Hue@têscalahueD, Line@8tr@t − passoD, tr@tD<D<,8t, inizio + passo, fine, passo<D<,
AspectRatio → 1, Axes → True, Background → RGBColor@1, 1, .8DDDD
-0.15 -0.1 -0.05 0.05 0.1 0.15 0.2
-1
-0.5
0.5
1
Graphics
Daniele Lupo Appunti di Mathematica
519Printed by Mathematica for Students
Possiamo fare adesso un passetto avanti, ed andare a considerare, per esempio, un problema DAE
del terzo ordine, imponendo pure le condizioni iniziali, date sulla x:
Clear @x, y, zD
terzo = 8x'''@tD − y@tD + z@tD 0,x'@tD + z@tD − t 0,z@tD − y@tD 0,x@0D 1,x'@0D 4,x''@0D 2<;
solterzo = DSolve@terzo, 8x, y, z<, tD
88x → Function@8t<, 1 + 4 t + t2D,y → Function@8t<, −4 − tD, z → Function@8t<, −4 − tD<<
Daniele Lupo Appunti di Mathematica
520Printed by Mathematica for Students
ParametricPlot3D@Evaluate@8x@tD, y@tD, x@tD − y@tD, 8BlueViolet, [email protected]<< ê. solterzoD,
8t, −5, 5 Pi<, BoxRatios → 81, 1, 1<,ViewPoint −> 80.279, −3.548, 2.851<D
0 100 200 300
-20
-15
-10
-5
0
0
100
200
300
0 100
5
-10
-5
0
Graphics3D
Il problema diventa invece di più difficile soluzione, diciamo impossibilile nella maggior parte dei
casi, quando i coefficienti non sono costanti. In questo caso si rendono necessari metodi di
risoluzione numerica.
Daniele Lupo Appunti di Mathematica
521Printed by Mathematica for Students
Problema del valore al contorno
Fino ad adesso abbiamo cercato, in generale, soluzioni generiche per le nostre equazioni
differenziali. Queste danno idea della struttura della soluzione, ma in pratica si è interessati ad una
particolare soluzione, che soddisfi la condizione al contorno specifica per il nostro problema.
Possiamo imporre due tipi di condizioni: le condizioni iniziali e le condizioni al contorno. Per il
primo tipo imponiamo che ad un determinato valore iniziale del parametro t (consideriamo ad
esempio l'istante iniziale dell'evoluzione di un sistema), siano date delle specifiche condizioni sul
valore della funzione, e sulle due derivate. Invece, per le condizioni al contorno, specifichiamo il
valore che deve assumere la funzione in particolari punti del dominio della funzione stessa, per
esempio il valore che deve assumere all'inizio ed alla fine dell'intervallo di spazio che prendiamo in
considerazione. Analiticamente possiamo trattare allo stesso modo entrambi i tipi di restrizioni della
soluzione, che chiamiamo quindi valori al contorno.
La soluzione nei casi lineari è abbastanza semplice, mentre non lo è altrettanto nei casi non lineari,
per i quali possono comparire più rami, per i quali soltanto alcuni sono in grado di soddisfare precise
condizioni al contorno che andiamo a specificare nel nostro problema.
Prendendo come sempio un caso lineare, possiamo avere un'equazione del seguente tipo:
lineare = y'@tD + t^2 y@tD t
t2 y@tD + y @tD t
La soluzione generale sarà data dal risultato dato da DSolve, senza specificare nessuna condizione al
contorno:
generale = DSolve@lineare, y, tD
99y → FunctionA8t<, − t33 C@1D −
− t33 t2 GammaA 2
3 , − t33 E
31ê3 H−t3L2ê3E==
Possiamo notare come, essendo del primo ordine, compaia soltanto un coefficiente di
indeterminazione. Supponiamo, adesso, di volere una precisa condizione al contorno, per esempio
specifichiamo il valore che deve assumere la funzione quando si ha t = 0, per esempio 3:
Daniele Lupo Appunti di Mathematica
522Printed by Mathematica for Students
particolare = DSolve@8lineare, y@1D 3<, y, tD
99y → FunctionA8t<,16 t
J − t33 J18 1ê3 t − 3 31ê6 t GammaA 2
3, −
13E − 32ê3 t GammaA 2
3, −
13E +
2 32ê3 H−t3L1ê3 GammaA 23, −
t3
3ENNE==
y@1D ê. particolare@@1DD êê Simplify
3
Abbiamo trovato il caso particolare. Tuttavia, possiamo anche creare delle condizioni al contorno
simboliche; possiamo ad esempio supporre che per t = 0 la la funzione assuma un generico valore a:
particolareα = DSolve@8lineare, y@1D α<, y, tD
99y → FunctionA8t<,16 t
J − t33 J6 1ê3 t α − 3 31ê6 t GammaA 2
3, −
13E − 32ê3 t GammaA 2
3, −
13E +
2 32ê3 H−t3L1ê3 GammaA 23, −
t3
3ENNE==
Possiamo notare che, non essendo il coefficiente semplicemente additivo, non basta andare a
sostituire la condizione iniziale al coefficiente per ottenere il risultato, ma abbiamo bisogno di
ulteriori elaborazioni:
f@t_D = y@tD ê. particolareα@@1DD
16 t
J − t33 J6 1ê3 t α − 3 31ê6 t GammaA 2
3, −
13E −
32ê3 t GammaA 23, −
13E + 2 32ê3 H−t3L1ê3 GammaA 2
3, −
t3
3ENN
f@1D êê Simplify
α
Come vedete, tutto persegue il grande cerchio della vita...
Daniele Lupo Appunti di Mathematica
523Printed by Mathematica for Students
Plot@Evaluate@Table@f@tD ê. α → αvalue, 8αvalue, −1, 5<DD, 8t, 0, 5<,PlotStyle → 8Blue, Red, Green, Cerulean, Coral, BlueViolet, Banana<,Background → LightBeigeD
1 2 3 4 5
-2
2
4
6
Graphics
Possiamo vedere un altro esempio, questa volta con un'equazione del secondo oridine; in questa
maniera compariranno due costanti di indeterminazione:
lineare2 = y''@tD + 3 y'@tD − y@tD t
−y@tD + 3 y @tD + y @tD t
generale = DSolve@lineare2, y, tD
99y → FunctionA8t<, −3 − t + I− 32 −
è!!!!!!!132 M t C@1D + I− 3
2 +è!!!!!!!132 M t C@2DE==
Come possiamo vedere sono spuntati, in questo caso, sia C@1D che C@2D; di conseguenza abbiamo
bisogno di due condizioni al contorno per poter risolvere questa equazione differenziale per un caso
particolare. Possiamo dare le due condizioni nei due modi citati: possiamo specificare il valore che
deve assumere la funzione in due punti distinti, oppure specificare il valore che deve assumere in un
punto, ed il valore della derivata in un punto, che possono pure coincidere. Un esempio del primo
caso può essere:
Daniele Lupo Appunti di Mathematica
524Printed by Mathematica for Students
DSolve@8lineare2, y@0D 0, y@2D 3<, y, tD
99y →
FunctionA8t<, 1−1 + 2 è!!!!!!!13
J3 − 3 2 è!!!!!!!13 − 3 I− 32 +
è!!!!!!!132 M t − 8 3+
è!!!!!!!13 +I− 32 −
è!!!!!!!132 M t +
3 2 è!!!!!!!13 +I− 32 −
è!!!!!!!132 M t + 8 3+è!!!!!!!13 +I− 3
2 +è!!!!!!!132 M t + t − 2 è!!!!!!!13 tNE==
Mentre per il secondo caso possiamo avere, ad esempio:
DSolve@8lineare2, y@0D 0, y'@0D 2<, y, tD
99y → FunctionA8t<, 126
J−78 + 39 I− 32 −
è!!!!!!!132 M t −
15 è!!!!!!13 I− 32 −
è!!!!!!!132 M t + 39 I− 3
2 +è!!!!!!!132 M t + 15 è!!!!!!13 I− 3
2 +è!!!!!!!132 M t − 26 tNE==
Il punto dove specifichiamo la derivata può essere anche diverso dal primo:
DSolve@8lineare2, y@0D 0, y'@4D 2<, y, tD
99y → FunctionA8t<,J−9 − 3 è!!!!!!13 + 9 4 è!!!!!!!13 − 3 è!!!!!!13 4 è!!!!!!!13 + 9 I− 3
2 +è!!!!!!!132 M t + 3 è!!!!!!13 I− 3
2 +è!!!!!!!132 M t −
6 6+2 è!!!!!!!13 +I− 32 −
è!!!!!!!132 M t − 9 4 è!!!!!!!13 +I− 3
2 −è!!!!!!!132 M t + 3 è!!!!!!13 4 è!!!!!!!13 +I− 3
2 −è!!!!!!!132 M t +
6 6+2 è!!!!!!!13 +I− 32 +
è!!!!!!!132 M t − 3 t − è!!!!!!13 t + 3 4 è!!!!!!!13 t − è!!!!!!13 4 è!!!!!!!13 tN í
I3 + è!!!!!!13 − 3 4 è!!!!!!!13 + è!!!!!!13 4 è!!!!!!!13 ME==
Daniele Lupo Appunti di Mathematica
525Printed by Mathematica for Students
Plot@Evaluate@y@tD ê. 88%%%@@1DD<, 8%%@@1DD<, 8%@@1DD<<D,8t, −6, 6<,PlotStyle → 8Gainsboro, Firebrick, IvoryBlack<,Background → Linen, PlotRange → 8−20, 20<D
-6 -4 -2 2 4 6
-20
-15
-10
-5
5
10
15
20
Graphics
Come possiamo vedere tutte e tre le soluzioni passano per l'origine, come specificato dalle nostre
condizioni al contorno.
Possiamo risolvere un altro tipo di equazione differenziale:
problemacontorno = y''@xD + y@xD E^x
y@xD + y @xD x
prgen = DSolve@problemacontorno, y, xD
99y → FunctionA8x<, C@1D Cos@xD + C@2D Sin@xD +12
x HCos@xD2 + Sin@xD2LE==
Proprio non riuscite a capire perchè l'ho chiamata così questa equazione, vero? Vedete un poco
adesso quello che succede. In generale, posso porre delle condizioni al contorno per avere il risultato
voluto, come in questo caso:
DSolve@8problemacontorno, y@0D 1, y@1D 1ê2<, y, xD
99y → FunctionA8x<, 12HCos@xD + x Cos@xD2 − Cot@1D Sin@xD +
Csc@1D Sin@xD − Csc@1D Sin@xD + x Sin@xD2LE==
Daniele Lupo Appunti di Mathematica
526Printed by Mathematica for Students
Guardate con più attenzione il risultato, e noterete che in effetti non possiamo trovare tutte le
soluzioni che vogliamo.
y@0D ê. prgen
9 12
+ C@1D=
Se imponiamo y@0D ã 1, allora per forza di cose C@1D deve essere uguale ad 1 ê2. In questo caso nel
resto possiamo giostrarci solamente con C@2D. Se però ci mettiamo a calcolare la funzione in p:
y@πD ê. prgen
9π
2− C@1D=
Notiamo come in questo caso il valore dipenda anch'esso esclusivamente da C@1D. In questo caso,
fissato y@0D, non possiamo fissare con altrettanta arbitrarietà il valore della funzione in p, perchè
avrei delle condizioni inconsistenti. Abbiamo la soluzione se imponiamo i valori che abbiamo
trovato:
DSolve@8problemacontorno, y@0D 1, y@πD E^π ê2 − 1ê2<, y, xD
99y → FunctionA8x<, 12HCos@xD + x Cos@xD2 + 2 C@2D Sin@xD + x Sin@xD2LE==
Se invece andiamo a inserire un valore diverso nel punto p otteniamo un errore, perchè non è
obiettivamente possibile andare a trovare un valore di C@1D che soddisfi entrambe le condizioni:
DSolve@8problemacontorno, y@0D 1, y@πD 1<, y, xD
— DSolve::bvnul : For some branches of the general solution,the given boundary conditions lead to an empty solution. More…
8<
In questo caso otteniamo un errore, e non viene restituita nessuna soluzione, per il semplice fatto che
non esistono: nell'ultimo caso C@2D dovrebbe essere pari ad 1 ê 2 nel punto x = 0, mentre dovrebbe
essere pari a 1 - ‰p ê 2 nel punto x = p, cosa che ovviamente non è possibile in quanto C@1Drappresenta una quantità costante.
Naturalmente, con le opportune condizioni al contorno, possiamo trovare soluzioni al contorno di
equazioni non lineari, di grado più elevato e così via, a patto comunque, come abbiamo appena visto,
che le condizioni siano consistenti:
Daniele Lupo Appunti di Mathematica
527Printed by Mathematica for Students
quarto = y''''@xD + 2 y''@xD − 2 y@xD Cos@xD
−2 y@xD + 2 y @xD + yH4L@xD Cos@xD
DSolve@quarto, y, xD
99y → FunctionA8x<, "##################−1+è!!!!3 x C@3D + −
"##################−1+è!!!!3 x C@4D + C@1D CosA"###############1 + è!!!3 xE +
C@2D SinA"###############1 + è!!!3 xE +112
ikjjjj−
"################################################2 H−1 + è!!!3 L H1 + è!!!3 L Cos@xD −
"################################################2 H−1 + è!!!3 L H1 + è!!!3 L Cos@xD CosA"###############1 + è!!!3 xE2
−
"################################################2 H−1 + è!!!3 L H1 + è!!!3 L Cos@xD SinA"###############1 + è!!!3 xE2y{zzzzE==
Un caso particolare si ha per:
DSolve@8quarto, y@0D 0, y'@0D −3, y''@0D 0, y'''@0D 9<, y, xD
99y → FunctionA8x<,
1
24"###############1 + è!!!3 i
kjjjjjj
−"##################
−1+è!!!!3 xi
kjjjjjj−9 è!!!2 + 3 è!!!6 + 2"###############1 + è!!!3 + 9 è!!!2 2"##################
−1+è!!!!3 x −
3 è!!!6 2"##################−1+
è!!!!3 x + 2"###############1 + è!!!3 2"##################−1+
è!!!!3 x −
4"###############1 + è!!!3 "##################−1+è!!!!3 x Cos@xD + 4"###############1 + è!!!3 "##################
−1+è!!!!3 x CosA"###############1 + è!!!3 xE −
4"###############1 + è!!!3 "##################−1+è!!!!3 x Cos@xD CosA"###############1 + è!!!3 xE
2
−
72"##################
−1+è!!!!3 x SinA"###############1 + è!!!3 xE − 18$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%2 H−1 + è!!!3 L
1 + è!!!3"##################
−1+è!!!!3 x
SinA"###############1 + è!!!3 xE + 6$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%6 H−1 + è!!!3 L1 + è!!!3
"##################−1+è!!!!3 x SinA"###############1 + è!!!3 xE −
4"###############1 + è!!!3 "##################−1+è!!!!3 x Cos@xD SinA"###############1 + è!!!3 xE
2y
{zzzzzzy
{zzzzzzE==
Daniele Lupo Appunti di Mathematica
528Printed by Mathematica for Students
Plot@Evaluate@y@xD ê. %D, 8x, −7, 7<,PlotStyle → DarkKhaki, Background → AzureD
-6 -4 -2 2 4 6
-10
-5
5
10
Graphics
Analogamente alle equazioni possiamo trattare anche i sistemi. A volte è conveniente scrivere
separatamente equazioni e condizioni iniziali, e congiungerli nel comando DSolve:
A = 880, −2, 0<,82, 1, 0<,81, 0, 1<<;
Y@t_D := 8x@tD, y@tD, z@tD<;
sislin = H#1 #2L &∼ MapThread∼8Y'@tD, A.Y@tD<
8x @tD −2 y@tD, y @tD 2 x@tD + y@tD, z @tD x@tD + z@tD<
valiniziali = 8x@0D 0, y@0D 3, z@0D −3<;
DSolve@Join@sislin, valinizialiD, 8x, y, z<, tD
99x → FunctionA8t<, −4$%%%%%%35
tê2 SinAè!!!!!!15 t
2EE,
y → FunctionA8t<, 15
tê2 ikjjj15 CosA
è!!!!!!15 t2
E + è!!!!!!15 SinAè!!!!!!15 t
2Ey{zzzE, z →
FunctionA8t<, −110
tê2 ikjjj45 tê2 − 15 CosA
è!!!!!!15 t2
E − è!!!!!!15 SinAè!!!!!!15 t
2Ey{zzzE==
Visualizziamo separatemente, prima, e con un grafico parametrico dopo:
Daniele Lupo Appunti di Mathematica
529Printed by Mathematica for Students
DisplayTogetherArray@8Plot@#, 8t, −3, 3<, PlotStyle → 8Green, Blue, BurntUmber<D,ParametricPlot3D@Join@#, 88Red, [email protected]<<D,8t, 0, 5<, BoxRatios −> 81, 1, .5<D< & @@
88x@tD, y@tD, z@tD< ê. %@@1DD<,Background −> LinenD
-3 -2 -1 1 2 3
-15
-10
-5
5
10
-20-10
010
-20
0-600-400-200
0
-20-10
0
GraphicsArray
Molte volte abbiamo a che fare con equazioni non lineari, invece che lineari, che sono utili in
parecchi casi reali. Un esempio è l'equazione logistica y£HtL r I1 - yHtLÅÅÅÅÅÅÅÅÅK M yHtL , detta anche di
Verhlust, che altro non è se un'equazione di Riccati:
eqlog = y'@tD r H1 − Hy@tDêKLL∗ y@tD
y @tD r y@tD J1 −y@tDK
N
DSolve@eqlog, y, tD
99y → FunctionA8t<,r t+K C@1D K
−1 + r t+K C@1D E==
Quest'equazione serve per descrivere l'andamento di una popolazione. Il tasso di crescita è dato da r,
mentre K rappresenta la saturazione della popolazione: avremo una crestica più o meno veloce, a
seconda della popolazione iniziale, che viene definita nelle condizioni iniziali:
andamento = DSolve@8eqlog, y@0D α<, y, tD
— Solve::ifun : Inverse functions are being used by Solve, so some solutions may not
be found; use Reduce for complete solution information. More…
99y → FunctionA8t<,r t K α
K − α + r t αE==
Il warning ottenuto è dato dall'inversione dell'esponenziale, ma siccoma sappiamo essere nel nostro
caso una funzione monotona, possiamo ignorarlo. In questo modo possiamo plottare il grafico per
Daniele Lupo Appunti di Mathematica
530Printed by Mathematica for Students
diversi valori iniziali della popolazione. Se normalizziamo il tutto, quindi ponendo K = 1, allora
possiamo disegnare diversi grafici, che rappresentano l'andamento della popolazione che varia a
seconda del tasso di crescita e della popolazione iniziale. Ho dovuto lavorare un poco per ottenere un
array bidimensionale, ma è sempre meglio di dover scrivere i vari plot singolarmente:
DisplayTogetherArray@8Take@#, 3D, Take@#, −3D< &@
HDisplayTogether ê@
Table@Plot@
Evaluate@y@tD ê. andamento@@1DD ê. 8α → a, r → b, K → 1<D,8t, 0, 5<, PlotRange → 80, 1<, PlotStyle → Hue@aD,PlotLabel −> "Tasso crescita r = " <> ToString@bD
D,8b, −2, 3<, 8a, 0, 1, .03<DL
D
1 2 3 4 5
0.20.40.60.81
Tasso crescita r = 1
1 2 3 4 5
0.20.40.60.81
Tasso crescita r = 2
1 2 3 4 5
0.20.40.60.81
Tasso crescita r = 3
1 2 3 4 5
0.20.40.60.81
Tasso crescita r = −2
1 2 3 4 5
0.20.40.60.81
Tasso crescita r = −1
1 2 3 4 5
0.20.40.60.81
Tasso crescita r = 0
GraphicsArray
Possiamo vedere che all'aumentare oppure al diminuire del tasso di crescita, il raggiungimento della
saturazione (o l'estinzione, nel caso di tasso di crescita negativo), sia più o meno rapido.
Nelle nostre condizioni al contorno, possiamo anche specificare l'infinito, come nel caso seguente di
un'equazione non lineare del secondo ordine:
nonlinord2 = y''@xDê3 y@xD^3 − y@xD
y @xD3
−y@xD + y@xD3
Daniele Lupo Appunti di Mathematica
531Printed by Mathematica for Students
DSolve@nonlinord2, y, xD
— Solve::ifun : Inverse functions are being used by Solve, so some solutions may not
be found; use Reduce for complete solution information. More…
99y → FunctionA8x<, è!!!3 $%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%1−3 + è!!!3 è!!!!!!!!!!!!!!!!!!!!!!3 − 2 C@1D JacobiSNA
−1è!!!2 I,H3 x2 + è!!!3 x2 è!!!!!!!!!!!!!!!!!!!!!!3 − 2 C@1D + 6 x C@2D + 2 è!!!3 x è!!!!!!!!!!!!!!!!!!!!!!3 − 2 C@1D C@2D +
3 C@2D2 + è!!!3 è!!!!!!!!!!!!!!!!!!!!!!3 − 2 C@1D C@2D2LM, 3 − è!!!!!!!!!!!!!!!!!!!!!!9 − 6 C@1D3 + è!!!!!!!!!!!!!!!!!!!!!!9 − 6 C@1D E −
$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%1−3 + è!!!3 è!!!!!!!!!!!!!!!!!!!!!!3 − 2 C@1D
è!!!!!!!!!!!!!!!!!!!!!!3 − 2 C@1D JacobiSNA
−1è!!!2 I,H3 x2 + è!!!3 x2 è!!!!!!!!!!!!!!!!!!!!!!3 − 2 C@1D + 6 x C@2D + 2 è!!!3 x è!!!!!!!!!!!!!!!!!!!!!!3 − 2 C@1D C@2D +
3 C@2D2 + è!!!3 è!!!!!!!!!!!!!!!!!!!!!!3 − 2 C@1D C@2D2LM, 3 − è!!!!!!!!!!!!!!!!!!!!!!9 − 6 C@1D3 + è!!!!!!!!!!!!!!!!!!!!!!9 − 6 C@1D EE=,
9y → FunctionA8x<, è!!!3 $%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%1−3 + è!!!3 è!!!!!!!!!!!!!!!!!!!!!!3 − 2 C@1D JacobiSNA
1è!!!2 I,H3 x2 + è!!!3 x2 è!!!!!!!!!!!!!!!!!!!!!!3 − 2 C@1D + 6 x C@2D + 2 è!!!3 x è!!!!!!!!!!!!!!!!!!!!!!3 − 2 C@1D C@2D +
3 C@2D2 + è!!!3 è!!!!!!!!!!!!!!!!!!!!!!3 − 2 C@1D C@2D2LM, 3 − è!!!!!!!!!!!!!!!!!!!!!!9 − 6 C@1D3 + è!!!!!!!!!!!!!!!!!!!!!!9 − 6 C@1D E −
$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%1−3 + è!!!3 è!!!!!!!!!!!!!!!!!!!!!!3 − 2 C@1D
è!!!!!!!!!!!!!!!!!!!!!!3 − 2 C@1D JacobiSNA
1è!!!2 I,H3 x2 + è!!!3 x2 è!!!!!!!!!!!!!!!!!!!!!!3 − 2 C@1D + 6 x C@2D + 2 è!!!3 x è!!!!!!!!!!!!!!!!!!!!!!3 − 2 C@1D C@2D +
3 C@2D2 + è!!!3 è!!!!!!!!!!!!!!!!!!!!!!3 − 2 C@1D C@2D2LM, 3 − è!!!!!!!!!!!!!!!!!!!!!!9 − 6 C@1D3 + è!!!!!!!!!!!!!!!!!!!!!!9 − 6 C@1D EE==
Possiamo andare a trovarci una soluzione particolare, andando ad invocare la derivata calcolata
all'infinito, il che permette di dire che la funzione deve avere un asintoto orizzontale:
Daniele Lupo Appunti di Mathematica
532Printed by Mathematica for Students
DSolve@8nonlinord2, y@0D 0, y'@∞D 0<, y, xD
— Solve::ifun : Inverse functions are being used by Solve, so some solutions may not
be found; use Reduce for complete solution information. More…
— DSolve::bvlim : For some branches of the general solution, unable to compute the limit
at the given points. Some of the solutions may be lost. More…
— DSolve::bvlim : For some branches of the general solution, unable to compute the limit
at the given points. Some of the solutions may be lost. More…
99y → FunctionA8x<, −TanhA$%%%%%%32
è!!!!!!x2 EE=,
9y → FunctionA8x<, TanhA$%%%%%%32
è!!!!!!x2 EE==
Nonostante i warning, che avvertono che non possiamo trovare soluzioni per tutti i rami, abbiamo
ottenuto due soluzioni che soddisfano la nostra condizione al contorno
Plot@8y@xD ê. %@@1DD, y@xD ê. %@@2DD, 1, −1<,8x, −2, 2<, PlotRange → All, PlotStyle → 88Red<, 8Green<,[email protected]<D, Blue<, [email protected]<D, Violet<<D
-2 -1 1 2
-1
-0.5
0.5
1
Graphics
Una caratteristica molto importante, spuntata dalla versione 5.0 di Mathematica, è la caratteristica di
poter utilizzare come coefficienti non costanti funzioni definite a tratti, tramite Piecewise. Possiamo
quindi definire delle funzioni definite a tratti, come la seguente:
Daniele Lupo Appunti di Mathematica
533Printed by Mathematica for Students
tratto = PiecewiseExpand@UnitStep@xD − UnitStep@x − 2D + Max@x, Sin@xDDD
Ø≤≤≤≤≤∞±≤≤≤≤≤
x Hx ≥ 2 && x − Sin@xD ≥ 0L »» Hx < 0 && x − Sin@xD ≥ 0L1 + x 0 ≤ x < 2 && x − Sin@xD ≥ 0Sin@xD Hx ≥ 2 && x − Sin@xD < 0L »» Hx < 0 && x − Sin@xD < 0L1 + Sin@xD True
Come possiamovedere otteniamo una funzione definita a tratti.
Plot@tratto, 8x, −4, 5<,PlotStyle → 8Red, [email protected]<, Background → GainsboroD
-4 -2 2 4
-1
1
2
3
4
5
Graphics
Possiamo utilizzare quindi anche questi coefficienti. Visualizziamo il risultato generico (stavolta in
forma tradizionale. Troppa Mathematica d'estate mi fa male...):
eqtratto = y'@xD Max@x, x^2D == y@xD + x;
DSolve@eqtratto, y, xD êê TraditionalForm
::y Ø FunctionB8x<, ‰
Ø≤≤≤≤≤≤∞±≤≤≤≤≤≤
- 1ÅÅÅÅx x§0logHxL 0<x§1
1- 1ÅÅÅÅx True c1 + ‰
Ø≤≤≤≤≤≤∞±≤≤≤≤≤≤
- 1ÅÅÅÅx x§0logHxL 0<x§1
1- 1ÅÅÅÅx True
i
k
jjjjjjjjjjjj
Ø≤≤≤≤≤≤∞±≤≤≤≤≤≤
-EiH 1ÅÅÅÅx L x § 0logHxL 0 < x § 1EiH1LÅÅÅÅÅÅÅÅÅÅÅʼn -
EiI 1ÅÅÅÅx MÅÅÅÅÅÅÅÅÅÅÅÅÅʼn True
y
{
zzzzzzzzzzzzF>>
Anche in questo caso possiamo imporre delle condizioni iniziali opportune per il nostro problema:
Daniele Lupo Appunti di Mathematica
534Printed by Mathematica for Students
DSolve@8eqtratto, y@1D 0<, y, xD
99y → FunctionA8x<,Ø≤≤≤≤≤∞±≤≤≤≤≤
− 1x x≤0
Log@xD 0<x≤1
1− 1x True
i
k
jjjjjjjjjj
Ø≤≤≤≤≤∞±≤≤≤≤≤
−ExpIntegralEi@ 1x D x ≤ 0
Log@xD 0 < x ≤ 1ExpIntegralEi@1D − ExpIntegralEi@ 1
x D True
y
{
zzzzzzzzzzE==
Possiamo plottare adesso la funzione, assieme alla sua derivata, per far vedere meglio dove sono
presenti le discontinuità nella derivata, che diventano cuspidi nella funzione
Plot@Evaluate@8y@xD, D@y@xD, xD< ê. %D, 8x, −3, 3<,PlotStyle → 88Blue, [email protected]<,8Red, [email protected], [email protected]<D<<,
Background → LinenD
— Power::infy : Infinite expression10
encountered. More…
— Power::infy : Infinite expression10
encountered. More…
-3 -2 -1 1 2 3
-2
-1
1
Graphics
Come abbiamo visto, abbiamo il plottaggio della soluzione, a parte i warning dovuti alla singolarità
nel punto 0.
Con questo, credo di aver concluso la panoramica sulla risoluzione simbolica delle equazioni
differenziali. Credo che adesso possiamo passare alla risoluzione numerica, che dal punto di vista
teorico è più difficile, dato che fino ad adesso ha fatto tutto DSolve...
Daniele Lupo Appunti di Mathematica
535Printed by Mathematica for Students
Risoluzione numerica
Quando non possiamo trovare la soluzione esatta di un'equazione differenziale, magari perchè non si
riesce a trovarla, l'equazione è troppo difficile da risolvere etc etc etc, allora si rende necessaria la
risoluzione numerica.
ü NDSolve
Il comando di Mathematica dedito a questo fine è NDSolve. Il suo utilizzo per equazioni abbastanza
elementari è abbastanza semplice. Basta infatti specificare l'equazione differenziale (oppure il
sistema), come abbiamo fatto per DSolve, con un paio di modifiche: prima di tutto, siccome la
soluzione è numerica e non simbolica, NDSolve non utilizza i parametri indeterminati C@nD, per cui
abbiamo sempre bisogno di specificare le condizioni al contorno del nostro problema, per trovare
una soluzione esclusivamente numerica. Inoltre, è necessario anche specificare il range entro cui
vogliamo calcolare la funzione. Infatti Mathematica crea una funzione interpolata all'interno
dell'intervallo definito: al di fuori dell'intervallo dobbiamo utilizzare delle estrapolazioni, che
rendono impreciso il risultato all'aumentare della distanza dal punto.
In teoria basterebbe estendere il range ad un intervallo più grande di quello che ci interessa, per
evitarci problemi. Tuttavia questo può essere eccessivamente dispendioso in termini di tempo di
calcolo della nostra funzione interpolata, oltre che eccessivo in termini di memoria e di pesantezza di
gestione della funzione. Occorre sempre studiarsi prima il problema per cercare l'intervallo che ci
interessa, senza sprecare tempo prezioso. Se questo appare abbastanza superfluo per problemi
semplici, può diventare determinante quando i calcoli si fanno pesanti, come per esempio si ha nelle
equazioi di Navier-Stokes.
Inoltre, a seconda della natura delle equazioni, sono adatti certi algoritmi di risoluzione rispetto ad
altri. Trovare il giusto algoritmo è sempre stato un problema; NDSolve effettua ogni volta un
pre-processing della nostra equazione, cercando di scoprire quale algoritmo meglio si presta alla
risoluzione del nostro problema. Comunque in casi particolarmente ostici, oppure quando
semplicemente vogliamo maggior controllo su quello che facciamo, possiamo selezionare
manualmente le varie opzioni, per rendere più specifico il risultato e forzare NDSolve a lavorare
come vogliamo noi.
Data l'estrema generalizzazione della risoluzione numerica, possiamo trovare soluzioni per tutti i tipi
di equazioni differenziali, tempo di calcolo permettendo; quindi lavora tranquillamente anche con
tutti i tipi di equazioni differenziali finora elencate nella risoluzione simbolica: ODE, PDE, DAE.
Vediamo un esempio per capire il funzionamento base di NDSolve:
Daniele Lupo Appunti di Mathematica
536Printed by Mathematica for Students
esnum = NDSolve@8x'@tD Sin@x@tD + Cos@t^2DD, x@0D 3<, x, 8t, 0, 3 Pi<D
88x → InterpolatingFunction@880., 9.42478<<, <>D<<
Possiamo notare come abbiamo utilizzato per forza anche le condizioni iniziali, e come assieme alla
variabile indipendente sia stato specificato l'intervallo di integrazione dell'equazione differenziale.
Mathematica naturalmante restituisce un errore se mettiamo un numero insufficiente di condizioni
iniziali, oppure se non specifichiamo l'intervallo:
NDSolve@x'@tD Sin@x@tD + Cos@t^2DD, x, 8t, 0, 3 Pi<D
— NDSolve::ndnco : The number of constraints H0L Hinitial conditionsL is not equal to
the total differential order of the system H1L. More…
NDSolve@x @tD Sin@Cos@t2D + x@tDD, x, 8t, 0, 3 π<D
NDSolve@8x'@tD Sin@x@tD + Cos@t^2DD, x@0D 3<, x, tD
— NDSolve::ndlim : Range specification t is not of the form 8x, xend< or 8x, xmin, xmax<. More…
NDSolve@8x @tD Sin@Cos@t2D + x@tDD, x@0D 3<, x, tD
Una volta ottenuta la soluzione, possiamo utilizzarla come abbiamo fatto per il risultato di DSolve.
Inatti anche in questo caso il risultato è formito come regola di sostituzione da utilizzare dove serve:
x@4D ê. esnum
83.13899<
Possiamo utilizzarla ovunque possiamo mettere una regola, ergo anche nel plottaggio, naturalmente:
Daniele Lupo Appunti di Mathematica
537Printed by Mathematica for Students
Plot@x@tD ê. esnum, 8t, 0, 3 Pi<,PlotRange → All, PlotStyle → Green, Background → LinenD
2 4 6 8
2.6
2.7
2.8
2.9
3.1
3.2
Graphics
Come potete notare la funzione viene smorzata, fino a stabilizzarsi attorno ad un valore limite.
Tuttavia, se proviamo a calcolare la funzione in punti che cadono al di fuori dell'intervallo di
definizione, viene utilizzata l'estrapolazione, che porta ad un grande errore, che cresce, in generale,
man mano che ci si allontana dagli estremi dell'intervallo. Mathematica segna questo problema con
un warning, da prendere abbastanza seriamente, anche se esegue comunque l'estrapolazione:
Daniele Lupo Appunti di Mathematica
538Printed by Mathematica for Students
Plot@x@tD ê. esnum, 8t, 0, 4 Pi<,PlotRange → All, PlotStyle → Green, Background → LinenD
— InterpolatingFunction::dmval : Input value 89.47541< lies outside the range of data in
the interpolating function. Extrapolation will be used. More…
— InterpolatingFunction::dmval : Input value 89.99568< lies outside the range of data in
the interpolating function. Extrapolation will be used. More…
— InterpolatingFunction::dmval : Input value 89.72325< lies outside the range of data in
the interpolating function. Extrapolation will be used. More…
— General::stop : Further output of InterpolatingFunction::dmval willbe suppressed during this calculation. More…
2 4 6 8 10 12
250
500
750
1000
1250
1500
Graphics
Come potete vedere, al di fuori dell'intervallo praticamente la funzione interpolata non serve a
niente; questo è vero in particolar modo per le funzioni oscillanti come questa.
Analogamente a questo, possiamo anche risolvere sistemi di equazioni differenziali, come in questo
esempio:
sol = NDSolve@8x''@tD y'@tDêx@tD,y'@tD x@tDêHy@tD + 30 x@tD^Sin@tDL,x@0D 1,x'@0D .1,y@0D 4
<, 8x, y<, 8t, 0, 40<D
88x → InterpolatingFunction@880., 40.<<, <>D,y → InterpolatingFunction@880., 40.<<, <>D<<
Daniele Lupo Appunti di Mathematica
539Printed by Mathematica for Students
Plot@Evaluate@8x@tD, y@tD< ê. %D, 8t, 0, 40<,PlotRange → All, PlotPoints → 200, PlotStyle → 8Red, Blue<D;
10 20 30 40
5
10
15
20
25
30
Il sistema può contenere un numero arbitrario di incognite, ovviamente. L'esempio serve solo per
farvi capire come funziona il tutto.
Possiamo risolvere numericamente anche delle PDE, come nel caso seguente, dove consideriamo
l'evoluzione di un'equazione differenziale che dipende da due coordinate spaziali e da una temporale;
questo esempio può prendere un po' di tempo in più rispetto alle equazioni banali. Potremmo dire
che è un esempio quasi serio...
sol = NDSolve@8D@u@t, x, yD, t, tD
D@u@t, x, yD, x, xD + D@u@t, x, yD, y, yD − Sin@u@t, x, yDD,u@0, x, yD Exp@−Hx2 + y2LD, Derivative@1, 0, 0D@uD@0, x, yD 0,u@t, −5, yD u@t, 5, yD Sin@t yê2Dê2,u@t, x, −5D u@t, x, 5D 0<,u, 8t, 0, 25<, 8x, −5, 5<, 8y, −5, 5<D
— NDSolve::ibcinc : Warning: Boundary and initial conditions are inconsistent. More…
— NDSolve::eerr : Warning: Scaled local spatial error estimate of 508.4402959177667`
at t = 25.` in the direction of independent variable x is muchgreater than prescribed error tolerance. Grid spacing with 91 pointsmay be too large to achieve the desired accuracy or precision. Asingularity may have formed or you may want to specify a smallergrid spacing using the MaxStepSize or MinPoints options. More…
88u → InterpolatingFunction@880., 25.<, 8−5., 5.<, 8−5., 5.<<, <>D<<
Adesso possiamo vedere il risultato tramite un'animazione che mostra l'evoluzione temporale della
soluzione:
Daniele Lupo Appunti di Mathematica
540Printed by Mathematica for Students
animazione = MoviePlot3D@First@u@t, x, yD ê. solD,8x, −5, 5<, 8y, −5, 5<, 8t, 0, 25<,PlotRange → 8−1, 1<, PlotPoints → 40, Frames → 110, Mesh → False,LightSources → 8882, 2, 2<, White<, 88−2, 2, 2<, Blue<<D
-4-2
02
4-4
-2
0
2
4
-1
-0.5
0
0.5
1
-4-2
02
4
Se procedete con l'animazione, vedrete nel vostro schermo una simpatica cosuccia...
Quello che fa NDSolve è considerare ina sequenza di passi nella variabile indipendente t, e cercare il
metodo migliore per la risoluzione dell'equazione differenziale. Inoltre, adatta automaticamente lo
step size della variabile, in maniera da rispettare la precisione voluta da PrecisionGoal, che
rappreseta l'errore relativo, ed AccuracyGoal, che rappresenta quello assoluto. Nel nostro caso
abbiamo una discontinuità ai vertici della regione d'integrazione, perchè in due lati la condizione al
contorno è 0, mentre negli altri 2 è Sin@tD: allora ai vertici ho contemporaneamente 0 e Sin@tD, e
Mathematica ci avvisa di questo, non riuscendo fra l'altro ad imporre un giusto step size per
l'algoritmo, in quanto le discontinuità non sono ben digerite. In ogni caso otteniamo un risultato che
giudico personalmente più che soddisfacente, almeno per poter fare un esempio pratico. In altri casi
si arriva alla produzione di artefatti, che possono falsare il risultato. Possiamo anche aumentare la
precisione della soluzione numerica, quando ci serve:
Daniele Lupo Appunti di Mathematica
541Printed by Mathematica for Students
NDSolve@8x''@tD x@tD,x@0D 1,x'@0D 0
<,x, 8t, 3<,AccuracyGoal → 20, PrecisionGoal → 20, WorkingPrecision → 25
D
88x → InterpolatingFunction@880, 3.000000000000000000000000<<, <>D<<
Una volta ottenuta la soluzione con la precisione voluta, possiamo calcolare i risultati:
x@2D ê. %
83.76219569108363660919707<
Come possiamo vedere, abbiamo ottenuto una precisione superiore a quella di macchina, che
avremmo ottenuto sfruttando le impostazioni di default.
Moltissimo c'è da dire ancora sulla risoluzione numerica delle equazioni differenziali, ma purtroppo
il tempo mi manca.... Se avete dubbi leggete il manuale, sperimentate e non esistate a cercare nuove
vie e nuovi comandi!!!!!
Daniele Lupo Appunti di Mathematica
542Printed by Mathematica for Students