Octave – matrici

elefante

Octave è decisamente grosso, a me viene in mente la storiella bantu:

D: Come si mangia l’elefante?
R: Un po’ per volta.

OK, la traduzione non rende, d’altronde io quando l’ho sentita me la sono fatta tradurre, e quella sopra è la traduzione della traduzione.
Ma sono già OT! Torno a Octave prima di subito, anche perché ho visto che interessa. E lo faccio in funzione delle mie curiosità, per esempio oggi esamino le matrici. Quando l’informatica era giovane e i programmatori erano veri programmatori usavano il Fortran le matrici erano una brutta gatta da pelare, il codice risultava sempre troppo lento. Vero che c’erano le librerie, non sempre disponibili però. Adesso invece, una pacchia! Ah! utilizzo ancora il quadrato magico di lato 4 ma solo per comodità; oltretutto è immediato verificare i risultati delle elaborazioni.

Un’avvertenza: il post l’ho scritto in tempi diversi, con ripensamenti (sono lento di comprendonio), la versione definitiva è alla fine, e non è nello script (yup! sono pasticcione!).

Il mio linguaggio di scripting preferito è Python. OK, ce ne sarebbero altri ma questo è condivisibile, anche se non è il preferito da tutti. Esiste in due versioni principali la 2.x e la 3.x, per oggi uso la due, i cambiamenti sarebbero minimi (magari ne parlerò in futuro).
Ecco come dire a Octave di scrivere la matrice per verificarla con Python.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
#!/usr/bin/octave -qf

QM4 = magic(4);
stmat = sprintf("    [%2d, %2d, %2d, %2d],\n", QM4);
L = length(stmat) - 2;
f = fopen("qm4.py", "w");
fprintf(f, "qm = [\n");
fprintf(f, "%s", stmat(1 : L));
fprintf(f, "\n]")
fclose(f);

qm4

Semplice vero? La chiamata a magic() della riga 3 produce la matrice che verrà scritta nel file qm4.py usando fprintf(), simile a quella del C. Per i vecchi: notare niente cicli (for o do, visto Massimo?). E tutto in 10 righe che potrebbero essere anche molto meno se non fosse un esempio didascalico e non ci fosse la necessità di essere prêt-à-porter per Python, ecco il risultato:

qm = [
    [16,  5,  9,  4],
    [ 2, 11,  7, 14],
    [ 3, 10,  6, 15],
    [13,  8, 12,  1]
]

Questo è un modulo (OK, piccolino ma tutto quello che serve per il test), ecco lo script Python (testqm.py):

#!/usr/bin/python
# -*- coding: utf-8 -*-

from qm4 import *

print "Matrice:"
print "["
for r in range(4):
	print "  ", qm[r]
print "]"

L = 4
Cc = (1 + L**2) * L / 2
print "\nValore atteso:", Cc

print "\nRighe:"
for r in range(4):
	s = 0
	for c in range(4):
		print qm[r][c],
		s += qm[r][c]
	print "->", s

print "\nColonne:"
for c in range(4):
	s = 0
	for r in range(4):
		print qm[r][c],
		s += qm[r][c]
	print "->", s

print "\nDiagonale principale:"
s = 0
for c in range(4):
	print qm[c][c],
	s += qm[c][c]
print "->", s

print "\nDiagonale secondaria:"
s = 0
for c in range(4):
	print qm[3 - c][c],
	s += qm[3 - c][c]
print "->", s

testqm

Beh, tutto OK, inoltre con Python torno a gestire gli indici come facevo una volta (posso vero?), mi sembra di essere tornato giovane. Una cosa: invece di i e j per gli indici uso r e c per riga e colonna, il nuovo che avanza!

Ma le stesse verifiche si possono fare dentro Octave, ecco t-oct.m:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#!/usr/bin/octave -qf

QM = magic(4);
disp(QM);

#somma righe
disp("");
disp("Righe:");
c = sum(QM)(1, :);
disp(c);

#somma colonne
disp("");
disp("Colonne:");
disp(QM');
disp("");
r = sum(QM')(1, :);
disp(r);

I = eye(4);
disp("");
disp("diagonale principale:");
disp(QM .* I);
disp(sum(sum(QM .* I)));

disp("");
disp("diagonale secondaria:");
disp(QM .* rot90(I));
disp(sum(sum(QM .* rot90(I))));

t-oct

Non so se sono stato tanto bravo. Ho qualche dubbio per la somma delle colonne, ho dovuto usare la matrice trasposta QM', quella cosa che in Fortran (e nei linguaggi normali) richiede un ciclo doppio e possibili errori se non stai attento con gli indici.

Trasporre la matrice è/era l’operazione dispendiosa, non so se sia possibile scrivere l’istruzione della riga 17 senza usare un ciclo. Difatti, ecco interattivamente cosa ottengo:

colint

Hmmm, ci devo pensare ancora, mi sa 😳
O forse no, è solo un problema di visualizzazione, se scrivo:

colint2

generalizzando ho:

colint3

È solo un problema di scrittura dei risultati intermedi (righe 12-18).
Per cui la riga 17 dello script van sostituita con questa:

r = sum(QM)(:, :);

Quindi niente matrice trasposta 😀
Adesso non mi resta che sperare nella comprensione dei lettori del post 🙄

Posta un commento o usa questo indirizzo per il trackback.

Commenti

  • Massimo Ortolano  Il 24 ottobre 2013 alle 13:23

    Bravo! Due note. La somma puoi decidere se farla per righe o per colonne: se X è una matrice sum(X) o sum(X,1) somma le righe; sum(X,2) somma le colonne. La cosa si generalizza poi a matrici multidimensionali. Per estrarre la diagonale principale puoi usare diag(X) e per le altre diagonali diag(X,m).

    • juhan  Il 24 ottobre 2013 alle 13:28

      Grazie Massimo 😉
      Sì lo so che ci sono un sacco di funzioni belle, ne parlerò in futuro. Siccome il post era già lungo ho trascurato anche il lollismo eye() per la matrice identità.
      E comincio a capire il perché di Octave/Matlab.

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: