Maxima: panoramica iniziale

(Questo post potrebbe essere il primo di una serie, ispirato da questo commento; ma il futuro è sempre incerto, il tempo scarso e troppe le cose che sarebbe bello fare o sperimentare.)

Esploriamo “brevemente” Maxima, un CAS, cioè Computer Algebra System. Secondo Wikipedía un CAS è

un software che permette il calcolo di espressioni matematiche in un modo simile al calcolo manuale che farebbero matematici e scienziati.

Poniamo il caso che ci venga chiesto di calcolare la frazione risultante dal prodotto di altre frazioni. Per esempio 4/7 × 7/3. Ci hanno insegnato a semplificare per arrivare a 4/3, un bel numero razionale la cui rappresentazione decimale non è finita. Per poter arrivare a scrivere la frazione 4/3 ci basta sapere un paio di regolette ed applicarle: “manipoliamo” simboli e il fatto che quei simboli siano dei numeri è irrilevante, a questo livello. Tanto che saremmo giunti allo stesso risultato anche se ci avessero chiesto di calcolare 4/a × a/3 (specificando che a≠0).

Proviamo a farlo in C:

printf("%lf\n", (4.0/7)*(7.0/3));

Un approccio del tutto diverso: il C non manipola simboli ma calcola numeri, quindi svolge le moltiplicazioni e le divisioni e produce un numero. Il numero restituito è chiaramente un razionale e dunque esprimibile come frazione, che però non è la nostra frazione (4/3), bensì qualcosa di “abbastanza vicino”. Se prendiamo quel risultato e lo moltiplichiamo per 3 (a mano), non otteniamo 4. Dunque il risultato è un’approssimazione, per forza di cose.

La frazione 4/3 può essere scritta come 1.\overline{3}. Sapete dire al volo quanto fa 1.\overline{3} × 1.5? Fa quanto fa 4/3 × 3/2, cioè 2. Questo dà l’idea di almeno un buon motivo per tenersi il 4/3 nella formula del volume di una sfera, per dirne una.

Quindi teniamoci le frazioni, almeno finché non sia necessario produrre un numero “esatto” come 1.33: sappiamo che è solo un’approssimazione del “numero vero”, ma forse per gli usi pratici che abbiamo in mente può andare benissimo e persino 1.33333 potrebbe avere una precisione inutilmente alta per i nostri scopi. Il meglio che possiamo fare è dire che il “numero vero” è compreso tra due numeri esprimibili in modo finito: per esempio il “vero π” è certamente compreso tra 3.140 e 3.142. Queste approssimazioni si ripercuotono su tutti i conti e…

Torniamo ai computer e facciamo degli esperimenti. I pythonisti nei paraggi con il loro REPL sempre pronto possono provare:

pythonscr

Se pensiamo a 1.3333333333333333 come risultato di 4.0/3, ci pare normale e anzi necessario che 1.3333333333333333*3 faccia 4. Tuttavia dovremmo rimanere un po’ perplessi: matematicamente 1.3333333333333333×3 fa 3.9999999999999999 e 3.9999999999999999 è 3.9999999999999999, non 4. Sappiamo che 3.(9) (tre punto nove periodico) è matematicamente uguale a 4, ma quello che abbiano noi è un numero finito di 9… 1.3333333333333333×3 ≠ 4, e sarà sempre così, anche se aggiungessimo tantissimi 3 (ma sempre in numero finito). Possiamo dire che 3.9999999999999999 è sufficientemente vicino a 4 da poterlo sostituire proprio con 4… A titolo esemplificativo ho anche mostrato altri casi borderline.

Ci stiamo solo confrontando con l’IEEE 754 binary64 e i suoi limiti, che a volte è necessario tenere a mente.

Finché si tratta di conti con delle frazioni in cui numeratore e denominatore sono numeri interi, poco male: possiamo risolvere in tutti i linguaggi, scrivendo a mano quanto ci serve o usando una libreria. Per esempio vedi Arithmetic/Rational su RosettaCode. (In alternativa per il C possiamo usare la GNU multiprecision library, in particolare le Rational Number Functions.)

Tutto molto bello ma di qualcosa come 4/a × a/3 (a≠0) non sappiamo che farne. Né Smalltalk, né C++, né Python e loro affini possono fare nulla al cospetto di quella variabile incognita — a meno di non salvarla dal suo stato incognito assegnandole un valore arbitrario (p.es. ponendo a=7…)… in questo caso funzionerebbe, ma ci vuole poco a classificarlo come espediente: b/a × a/3.

Maxima

Era tutto per convincervi della superiorità dell’approccio umano, fondamentalmente simbolico, al calcolo. Stiamo però da tempo provando a far fare alle macchine alcune cose a mo’ d’umano (the human way); con gli scacchi è stato un po’ un fallimento e, affinché la macchina batta l’uomo, sono necessarie forza bruta e grande memoria “infallibile” (ma non sono aggiornatissimo sugli ultimi sviluppi).

Sul versante dei calcoli e della manipolazione simbolica invece andiamo meglio.

A Maxima possiamo dire di calcolare b/a × a/3! Maxima fa quello che fareste voi: non sa cosa siano a e b, però sa la regoletta per semplificare il prodotto di due frazioni. (Da qualche parte qualcuno terrà a mente che a ≠ 0…)

Faccio una panoramica di alcune funzionalità base di Maxima (nella modalità interattiva).

Per questa (ipotetica) serie userò il frontend wxmaxima: maxima ha di base un’interfaccia testuale, però offre la possibilità di “parlare” con un frontend che lo pilota e pensa lui alla visualizzazione. Inoltre è possibile chiedere l’output (La)TeX… Insomma un fronted può mostrare i risultati in modo più accattivante.

Parto dalla mia risposta alla questione dell’arcotangente iperbolica di -2.

maxima1

Abbiamo il numero complesso espresso in forma polare in modo analitico invece che numerico, perché Maxima preferisce tenersi frazioni e simboli invece di dare numeri che, per forza di cose, sono approssimazioni.

Esercizi: derivate, razionalizzazioni e semplificazioni

Online ho trovato questo PDF di esercizi. Facciamo svolgere qualche esercizio a Maxima…

maxex1

Invece di derivative possiamo usare diff. L’esempio mostra come calcolare la derivata prima rispetto ad una variabile. Il ; segnala la fine dell’input. Maxima lo valuta e ci mostra il risultato della valutazione. Naturalmente l’espressione di cui stiamo calcolando la derivata può contenere anche altri parametri/variabili, oltre alla variabile su cui stiamo derivando.

maxex1b

Possiamo far riferimento all’ultimo risultato tramite %, oppure a un risultato specifico scrivendo per esempio %o20. Il % precede anche alcune costanti, come %pi, %e e %i (nell’output con wxmaxima non le vedete, e %pi diventa π).

Tornando al primo esercizio di derivazione, lo ripetiamo e poi chiediamo di applicare la ratsimp, razionalizzazione e semplificazione.

maxex2

Proviamo con l’esercizio 3.

maxex3

Ho usato fullratsimp, che «applies ratsimp followed by non-rational simplification to an expression until no further change occurs». In questo caso non fa molta differenza.

Esercizi: formule/funzioni e integrali

Calcoliamo il volume di una sfera di un certo raggio.

maxex4

Usiamo := per definire una funzione; il $ è come ; ma sopprime l’output: lo usiamo se siamo interessati solo agli effetti della valutazione ma non vogliamo che l’espressione sia visualizzata, oppure se è un risultato intermedio che non ci interessa “vedere”. Con il ; Maxima avrebbe mostrato la funzione:

maxex5

Vediamo se riusciamo a ricavare le formule per l’area di un cerchio e per il volume di una sfera. Partiamo dalla circonferenza, 2πr. Come forse sapete, “basta” integrare 2πr×dr. In Maxima è un attimo:

maxex6

Per il volume possiamo lavorare a fette (dischi)… (I dettagli li trovate altrove, per esempio su Wikipedía.)

maxex8

Nell’esempio vedete pure un’altra cosa: se mettete un ', state dicendo a Maxima di non calcolare l’espressione, ma di tenerla così com’è. In questo modo viene visualizzata l’espressione con l’integrale (però come vedete ha “capito” che il π può stare fuori e l’ha messo fuori). Un altro caso d’uso dell’apostrofo è per definire le equazioni differenziali.

Per arrivare alla formula del volume di una sfera possiamo usare le coordinate sferiche per calcolare un elemento di volume e poi integrare. Vediamo come se la cava Maxima…

maxex7

Esercizi: sistemi di equazioni lineari

Un classico degli esercizi della scuola secondaria sono i sistemi di equazioni. Prendo spunto da questo PDF. Vediamo l’esercizio 6 a pagina 6:

syseq1

Ho “definito” le due equazioni (a e b) per comodità; poi ad algsys (cfr. algsys) ho dato un array delle equazioni e uno delle incognite. I : sono usati per assegnare a un simbolo una certa espressione; p.es. x:5$ assegna a x il numero 5, e a:x=y$ assegna ad a l’equazione x=y. L’= in Maxima ha il significato matematico, per cui x = x + 1 è proprio l’equazione che ci porta a dire che 0 è uguale a 1…

Vediamo che succede con l’esercizio 9 a pagina 7.

syseq2

Il libro dice “indeterminato”, ma Maxima invece ci fornisce un risultato. Che vuol dire? Il sistema è indeterminato nel senso che non possiamo determinare dei valori unici per le incognite. Però le soluzioni esistono. Maxima ci dà le formule (con il parametro %r1) per avere dei valori di x e y che soddisfano le equazioni; al variare di %r1 avremo tutte le coppie (x,y) che soddisfano il sistema.

Vediamo l’esercizio 13, a pagina 7, per il quale non ci sono soluzioni.

syseq3

Maxima ci ritorna una lista vuota, [].

Restano comunque casi che richiedono l’intervento di un po’ più di cervello e conoscenza. Per esempio nell’esercizio 62 a pagina 13, Maxima fornisce la soluzione parametrizzata (con %r…, come prima), ma non ci dà indicazioni sui valori di x da evitare. Si vede ad occhio che -1 e -5 portano ad una divisione per zero. Per quanto riguarda 6x+x²+5, possiamo usare solve.

solve1

In caso di N equazioni in M incognite, basta aggiungere elementi alle rispettive liste passate a algsys. Inoltre, come dovrebbe essere ormai chiaro, non è affatto necessario che nelle equazioni ci siano solo le incognite e dei numeri: possiamo metterci dei parametri.

L’algsys «solves the simultaneous polynomials […] or polynomial equations […]». La “funzione” solve, quando chiamata con delle liste come argomento, a sua volta usa algsys oppure linsolve, che «solves the list of simultaneous linear equations for the list of variables».

Morale: algsys può risolvere anche sistemi di grado superiore al primo e quando abbiamo il dubbio se usare linsolve o algsys, usiamo solve e dovrebbe andare “sempre” bene. Proviamo con il sistema proposto qui

eq2g

(Avevo già inserito le due equazioni in un ordine non adatto per fare lo screenshot, sicché ho digitato a; e b; solo per rivisualizzarle prima di invocare solve.)

Esercizi: sistemi di disequazioni lineari

Un po’ diverse e un po’ più complicate le cose con le disequazioni. Proviamo, a scopo illustrativo, fourier_elim, che non è precaricato, per cui lo carichiamo; dopodiché procediamo. Prendo gli esempi da questo PDF.

ineq1

Ok. Ora vediamo l’esercizio 19:

ineq2

Il risultato non è proprio quello dato nel PDF: occurerà approfondire…

Voglio il numero!

L’output di Maxima, come abbiamo visto, preferisce i numeri razionali (rappresentati tramite frazioni); inoltre, se ci sono irrazionali di mezzo, mantiene la forma simbolica. Se ci serve il numero, anche se approssimato, della radice quadrata di 2, possiamo dirgli di fornircelo.

sqrt2

Possiamo tenere l’impostazione fissa scrivendo numer:true$; da questo momento calcoli come sqrt(2) o anche il nostro 4/3 daranno lo stesso risultato che darebbe per esempio il Python.

numer

Ma Maxima può fare calcoli a precisione arbitraria. Impostiamo fpprec a quanto vogliamo, per esempio fpprec:30$, e usiamo bfloat(espressione) per avere il numerello.

prec30

Equazioni differenziali

Come ultimo esempio prendiamo la classica equazione differenziale del moto armonico. Maxima ci chiede se il coefficiente omega è diverso da zero. Dopodiché, ci dà il risultato atteso.

ode2

Possiamo risparmiarci la domanda dando un’informazione in più: assume(omega>0)$. Un’ultima cosa: usiamo bc2 per avere il risultato una volta fissate le condizioni al contorno.

ode2p1

Alla prossima

Come primissima panoramica penso che possa bastare. Preciso che il mio uso di Maxima è sempre stato molto pragmatico e limitato (per cose un pochetto più complicate degli esempi fatti, ma nemmeno poi troppo).

Posta un commento o usa questo indirizzo per il trackback.

Commenti

  • Man from Mars  Il 30 ottobre 2015 alle 10:20

    Bellissimo! Peccato ci siano solo gli .rpm disponibili per Linux, toccherà compilare…
    Aspetto le prossime puntate con impazienza.

    • shintakezou  Il 30 ottobre 2015 alle 19:15

      su debian (e credo pure su ubuntu) ci dovrebbe essere il pacchetto pronto.

      • Man from Mars  Il 1 novembre 2015 alle 10:19

        Vado subito a controllare, grazie. Una parte di me spera che non ci siano per evitare di cadere in un baratro!

  • juhan  Il 30 ottobre 2015 alle 10:31

    Bello; un paio di note pistine ma sapete com’è 🙄
    Maxima è l’evoluzione di Macsima, roba Lisp. Attualmente è in Common Lisp ma i numeri razionali nel Lisp ci sono da sempre, p.es.:

    Welcome to Racket v6.2.
    -> (* 4/7 7/3)
    4/3

    Volendo stare più sulla programmazione tradizionale con Python c’è SymPy e SciPy/NumPy dove trovi il calcolo simbolico, credo di averne parlato anticamente, p.es.:

    https://okpanico.wordpress.com/2013/01/19/sympy/
    https://okpanico.wordpress.com/2013/02/16/sympy-un-esempio-anzi-la-soluzione/

    Maxima mi attira, messo nella lista cose urgenti davvero da fare 😀

Rispondi

Inserisci i tuoi dati qui sotto o clicca su un'icona per effettuare l'accesso:

Logo di WordPress.com

Stai commentando usando il tuo account WordPress.com. Chiudi sessione /  Modifica )

Google photo

Stai commentando usando il tuo account Google. Chiudi sessione /  Modifica )

Foto Twitter

Stai commentando usando il tuo account Twitter. Chiudi sessione /  Modifica )

Foto di Facebook

Stai commentando usando il tuo account Facebook. Chiudi sessione /  Modifica )

Connessione a %s...

Questo sito utilizza Akismet per ridurre lo spam. Scopri come vengono elaborati i dati derivati dai commenti.

%d blogger hanno fatto clic su Mi Piace per questo: