You are on page 1of 42

6.

MATRICE RARE


6.1 Concepte de baz

Matricele rare i gsesc aplicabilitatea n modelarea unor procese de
natur industrial, economic, tehnic, social etc. Capitolul de fa i
propune s trateze modalitile de reprezentare n structuri de date a
matricelor rare, precum i principalele operaii matriceale implementate ntr-un
limbaj orientat pe obiecte. n final este prezentat o aplicaie concret
estimarea parametrilor unei regresii statistice.
n rezolvarea multor probleme de natur economic, tehnic, social, a
diverselor probleme de optimizare, precum i n modelarea unor procese
industriale i tehnologice este necesar s se determine modelul matematic care
descrie funcionarea procesului respectiv. Descrierea acestor sisteme fizice
conduce la obinerea unor modele matematice care fie n mod direct, prin
modelare, fie prin metoda de rezolvare implic sisteme de ecuaii algebrice
liniare sau probleme de programare liniar a cror matrice a coeficienilor este
rar (sparse), n sensul c ponderea elementelor nenule n totalul elementelor
matricei este mic.
Din punct de vedere practic trebuie remarcat faptul c analiza sistemelor
mai sus amintite conduce la obinerea unor modele matematice de mari
dimensiuni care implic sisteme de ecuaii algebrice liniare de mii de ecuaii,
pentru a cror rezolvare sunt necesare resurse mari de memorie i timp de
calcul. n multe cazuri practice, cum sunt sistemele n timp real, timpul de
calcul este o resurs critic, nefiind permis s depeasc o valoare limit.
Modelele matematice ale proceselor reale implic un numr foarte mare
de variabile i restricii care prezint fenomenul de raritate ,sparsity, adic o
slab interconectare a elementelor sale. Luarea n consideraie a fenomenului
de raritate furnizeaz un nou mod de abordare foarte eficient, ce implic n
dezvoltarea aplicaiilor informatice folosirea unor structuri de date speciale,
care s conduc la reducerea resurselor de memorie i a timpului de calcul.
n general, o matrice - dimensional este rar atunci cnd conine
un numr mic de elemente nenule
) , ( n n
t , adic . Cantitativ, matricele rare
sunt caracterizate de ponderea numrului de elemente nenule n totalul de
elemente, pondere ce definete gradul de umplere al matricei. n aplicaiile
curente se ntlnesc matrice rare cu grade de umplere ntre 0,15% i 3%.
2
n << t


6.2 Memorarea matricelor rare

Se consider matricea:

|
|
|
|
|
.
|

\
|

=
0 0 0 1 0
0 0 0 0 0
4 0 2 0 0
0 0 0 0 1
A (6.1)

Matricea A este un exemplu de matrice rar, ea coninnd 16 elemente
nule din totalul de 20.
Se definete gradul de umplere, densitatea, unei matrice prin raportul
dintre numrul elementelor nenule i numrul total al elementelor sale:

100(%)

=
m n
p
G (6.2)

unde:
p numrul de elemente nenule;
n numrul de linii;
m numrul de coloane.
n general se accept c o matrice este rar dac densitatea sa este de
cel mult 3%. Densitatea matricei A este % 20 ) ( = A G , ea fiind prezentat aici n
scopul ilustrrii conceptului de matrice rar.
Structura de date clasic folosit pentru manipularea matricelor, tabloul
de dimensiune (n, m) alocat la compilare, se dovedete a fi ineficient n cazul
n care matricea este rar. Un prim avantaj este legat de folosirea
neeconomic a spaiului de memorie prin alocarea de zone mari pentru
memorarea elementelor nule, care nu sunt purttoare de informaie. Ocuparea
unor zone de memorie cu elemente nule nu se justific deoarece acestea nu
contribuie la formarea rezultatului operaiilor cu matrice, adunare, nmulire
etc., conducnd totodat i la mrirea duratei de realizare a acestor operaii
prin ocuparea procesorului cu adunri i nmuliri scalare cu zero. Acest
inconvenient se manifest cu att mai pregnant cu ct dimensiunea matricei
este mai mare.
Prin urmare, pentru probleme de dimensiuni mari, s-a cutat gsirea
unor modaliti de reprezentare compact a matricelor rare, n care s se
renune la memorarea elementelor nule. n acest caz este necesar ca tehnicile
de memorare s ncorporeze pe lng elementele nenule i mijloacele de
identificare a poziiilor acestor elemente n matrice.
Sunt prezentate n continuare cteva posibiliti de memorare compact
a matricelor rare MR. Se face, de asemenea, o analiz a oportunitii folosirii
fiecrei tehnici n parte, n funcie de densitatea matricei.
Memorarea prin identificare binar se bazeaz pe natura binar a
sistemului de calcul, constnd n memorarea numai a elementelor nenule ale
matricei ntr-o zon primar ZP avnd tipul de baz corespunztor tipului
elementelor matricei i dimensiunea egal cu numrul elementelor nenule.
Structura matricei este indicat printr-o secven binar memorat ntr-
o zon secundar ZS.
Matricea A prezentat anterior se memoreaz astfel:
Zona primar:

Locaie 1 2 3 4
Valoare 1 -2 4 -1

Figura 6.1 Structura ZP pentru matricea A

Zona secundar:

Locaie 1 5 6 10
Valoare 1 0 0 0 0 0 0 1 0 1
Locaie 11 15 16 20
Valoare 0 0 0 0 0 0 1 0 0 0

Figura 6.2 Structura ZS pentru matricea A

Matricea A a fost memorat n ordinea liniilor, o alt posibilitate de
memorare fiind n ordinea coloanelor. Pentru a reduce spaiul ocupat de zona
secundar se poate implementa soluia dat de memorarea la nivel de bit a
valorilor acesteia.
Dac matricea B cu dimensiunea (m, n) are densitatea G i dac tipul de
baz al matricei, respectiv tipul fiecruia dintre elemente nenule ale matricei,
este reprezentat printr-un cuvnt de b octei, atunci zona primar va necesita
m*n*G cuvinte de b octei iar zona secundar (m*n)/(8*b) cuvinte. Numrul
total de cuvinte necesare memorrii matricei B prin intermediul celor dou
zone este

DMR
1
= m*n*G + (m*n)/(8*b) (6.3)

ntruct pentru memorarea matricei n forma clasic sunt necesare DM = m*n
cuvinte, raportul dintre cerinele de memorie ale structurii de mai sus i a celei
standard este:


8
1
1
1
b
G
DM
DMR
c

+ = = (6.4)

n relaia anterioar s-a considerat c memorarea zonei secundare se
face la nivel de bit.
Considernd c elementele matricei A sunt reale i se reprezint pe 4
octei, rezult:

23 , 0
32
1
2 , 0
1
= + =
A
c (6.5)

ceea ce indic c memorarea matricei A conform acestei structuri ocup de
aproximativ patru ori mai puin memorie dect cea standard.
Egalnd se determin limita superioar a densitii unei matrice
pentru care aceast structur necesit mai puin memorie dect cea
standard:
1
1
= c


8
1
1
lim
b
G

= (6.6)

Pentru matricea A:

% 96 96 , 0
32
1
1
lim
= = = G (6.7)

Aceast structur de memorare difer de abordri prin faptul c n zona
secundar este alocat memorie i pentru elementele nule ale matricei.
Structura este mai puin eficient pentru matricele de mari dimensiuni foarte
rare. Principala dificultate const n complexitatea programelor de
implementare a operaiilor matriciale.
O alt modalitate de memorare prin identificare binar se obine prin
modificarea informaiilor din zona secundar. Aceast zon va conine pe
jumti de cuvnt indicii de coloan a elementelor nenule din matrice, precum
i anumite informaii de control pentru identificarea rapid a poziiei
elementelor nenule n matrice. Structura ZS pe cuvinte este urmtoarea:

Tabelul nr. 6.1 Structura ZS pe cuvinte

Numrul
cuvntului
Jumtatea stng Jumtatea dreapt

1 Numrul de linii Numrul de coloane
2 Numrul de elemente nenule
3 Numrul de elemente nenule
n linia 1
Numrul de elemente nenule
n linia 2
4 Numrul de elemente nenule
n linia 3
Numrul de elemente nenule
n linia 4

k Numrul de elemente nenule
n linia m-1
Numrul de elemente nenule
n linia m
k + 1 Indicele de coloan al
primului element memorat
Indicele de coloan al celui
de-al doilea element
memorat
k + 2 Indicele de coloan al celui
de-al treilea element
etc.
memorat

j Indicele de coloan al
ultimului element memorat

Pentru matricea A, zona secundar ZS are structura din figura 6.3.

Locaie 1 2 3 4 5 6
Valoare 4 5 4 1 2 0 1 1 3 5 2

Figura 6.3 Structura ZS pentru matricea A

n reprezentarea din figura 6.3 s-a considerat c elementele nenule sunt
reprezentate pe 4 octei astfel c o jumtate de cuvnt n zona secundar se
reprezint pe 2 octei. Prin structura de memorare prezentat mai sus se
memoreaz matrice a cror dimensiune maxim este de 9999 de linii sau
coloane cu numrul maxim de elemente nenule memorate egal cu 10
8
1. Se
face observaia c n cazul matricelor ptrate n primul cuvnt din ZS se va
memora dimensiunea matricei.
Numrul total de cuvinte necesare zonei secundare este egal cu

2 / ) * * 5 ( G n m m+ + (6.8)

valoarea fiind rotunjit la cel mai mare ntreg. Numrul total de cuvinte
necesar memorrii unei matrice prin intermediul celor dou zone ZP i ZS este
egal cu

DMR
2
= 2 / ) * * * 3 5 ( G n m m+ + (6.9)

Raportul dintre cerinele de memorie ale acestei structuri de identificare
binar i a celei standard este:


* * 2
5
2
3
2
n m
m G
c
+
+

= (6.10)

Pentru o matrice ptrat (m=n), egalnd c
2
= 1 i trecnd la limit
pentru rezult valoarea maxim a densitii unei matrice rare pentru
care structura prezentat este eficient:
m

6 66 666 0
2
5
1
3
2
2
% , ,
lim
= =
|
.
|

\
| +


m
m
G
m
(6.11)

n relaia anterioar se ajunge la acelai rezultat n cazul unei matrice
neptratic pentru care se trece la limit pentru n i . m
Pentru o matrice rar de dimensiune (100, 100), cu o medie de 66
elemente nenule pe linie, structura de mai sus necesit un total de 6600 + (5
+ 100 + 6600)/2 = 9952 cuvinte, cu 0,6% mai puin dect 10.000 cuvinte
necesare pentru memorarea standard. ntruct densitatea elementelor nenule
ale unei matrice rare este de obicei ntre 1% i 3%. Structura se dovedete a fi
deosebit de eficient.
Memorarea compact aleatoare const n utilizarea unei zone primare
ZP, coninnd numai elementele nenule ale matricei i a dou zone secundare
coninnd indicii de linie i de coloan corespunztoare elementelor nenule.
Deoarece fiecare element nenul al matricei este identificat individual,
este posibil ca matricea s fie memorat n ordine aleatoare. Matricea A se
memoreaz astfel:

Locaia 1 2 3 4
Valoare 1 -2 4 -1
Indice linie 1 2 2 4
Indice coloan 1 3 5 2

Figura 6.4 Model de memorare compact aleatoare a matricei A

Avantajele memorrii compacte aleatoare constau n faptul c noile
elemente nenule ale matricei sunt adugate la sfritul zonelor de memorare
fr a afecta celelalte elemente, precum i o manevrabilitate rapid a datelor.
n cazul matricelor simetrice aceast structur de memorare este simplificat
prin memorarea numai a elementelor nenule de deasupra diagonalei principale,
precum i a elementelor nenule situate pe aceast diagonal.
Numrul total de cuvinte necesare memorrii unei matrice de
dimensiune (m, n) este n acest caz

DMR
3
= 3*m*n (6.12)

Raportul dintre cerinele de memorie ale acestei structuri i a celei
standard este:

3
3
G c = (6.13)

Egalnd relaia anterioar cu unitatea se determin valoarea limit a
densitii matricei rare pentru care aceast structur este eficient,
. % 3 , 33
lim
= G
n structura din figura 6.4, pentru identificarea elementelor nenule ale
matricei rare au fost folosite dou zone secundare corespunztoare indicelui de
linie i de coloan. Se prezint n continuare o alt posibilitate de memorare n
care se va utiliza o singur zon secundar de dimensiune egal cu numrul de
elemente nenule ale matricei, coninnd simultan informaii asupra indicilor de
linie i de coloan.
Astfel, fiecrui element din zona primar i se ataeaz n zona secundar
un numr ntreg din care se determin indicii de linie i de coloan. Dac
elementul este memorat n locaia k a zonei primare atunci n zona
secundar se va memora un indice agregat ig a crui valoare este dat de
relaia
0 =
ij
a

ig = i+(j-1)*n (6.14)

unde n este numrul de coloane a matricei. Acest numr este suficient pentru
identificarea elementului n matrice.
Utiliznd acest artificiu, matricea A se memoreaz astfel:

Locaia 1 2 3 4
Valoare 1 -2 4 -1
Indice agregat, ig 1 12 22 9

Figura 6.5 Model derivat de memorare compact a matricei A

Pentru a regsi indicele de linie i de coloan al oricrui element
memorat n locaia k se utilizeaz urmtoarea tehnic de calcul:
- coloana j este obinut prin relaia:

j > ig(k)/n (6.15)

- linia i este determinat prin relaia:

i = ig(k) ( j 1 ) n (6.16)

Avantajul acestei structuri de memorare const n faptul c necesit mai
puin memorie dect cea precedent, fiind n schimb mai puin rapid n ce
privete manevrarea datelor.
Numrul total de cuvinte necesar memorrii matricei este

DMR
4
= 2*m*n*G (6.17)

Raportul dintre cerinele de memorie ale acestei structuri i a celei
standard este:

G c 2
4
= (6.18)

Valoarea limit a densitii matricei pentru care aceast structur este
eficient este G = 50%.
Memorarea compact sistematic presupune c elementele nenule ale
unei matrice rare sunt memorate ntr-o anumit ordine, respectiv pe linii sau
pe coloane. n acest caz nu este necesar s se memoreze n zonele secundare
indicii de linie, respectiv de coloan. Pentru o memorare n ordinea liniilor, ne
mai sunt necesari indicii de linie, ns se cere specificarea nceputului fiecrei
linii.
i n acest caz exist mai multe structuri de memorare. Cea prezentat
n continuare este caracterizat prin faptul c utilizeaz o singur zon
secundar ZS, care conine indicii de coloan ale elementelor nenule din
matricea considerat, precum i elemente false care indic nceputul fiecrei
linii i sfritul memorrii ntregii matrice. De exemplu, un element zero n ZS
marcheaz prezena unui element fals i acesta specific n ZP numrul liniei
elementelor de la dreapta locaiei. Sfritul matricei este marcat prin prezena
n ZP a unui element fals cu valoarea zero.
Pentru matricea A, memorarea n aceast form este urmtoarea:

Locaia 1 2 3 4 5 6 7 8
ZP 1 1 2 -2 4 4 -1 0
ZS 0 1 0 3 5 0 2 0

Figura 6.6 Model de memorare compact sistematic a matricei A

Pentru aceast structur de memorare numrul maxim de cuvinte
necesar pentru a reine o matrice rar de dimensiune (m, n) este

DMR
5
= 2*(m*n*r+m+1) (6.19)

Raportul de memorare este:


*
) 1 ( * 2
* 2
5
n m
m
G c
+
+ = (6.20)

Se constat c structura este eficient pentru memorarea matricelor
rare cu o densitate a elementelor nenule de maximum 50%.
Memorarea cu ajutorul listelor reprezint o extensie a memorrii
compacte aleatoare. n timpul operaiilor de inversare a matricelor rare, noi
elemente nenule sunt continuu generate, iar altele sunt anulate i deci
structurile de memorare trebuie s fie capabile s execute aceste modificri
ntr-un mod eficient. De aceea structurile de memorare bazate pe aceast
tehnic sunt folosite pentru memorarea i manipularea matricelor rare de mari
dimensiuni.
Structura propus utilizeaz o zon principal ZP pentru memorarea
elementelor nenule i trei zone secundare:

ZSL memorarea indicilor de linie ale elementelor nenule;
ZSC indicii de coloan;
ZSU memorarea adresei urmtorului element al matricei.

Matricea A se memoreaz dup cum urmeaz:

Locaia 1 2 3 4
ZP 1 -2 4 -1
ZSL 1 2 2 4
ZSC 1 3 5 2
ZSU &2 &3 &4 NULL

Figura 6.7 Model de memorare cu ajutorul listelor a matricei A

unde prin &2 se nelege adresa celei de-a doua locaii.
Raportul dintre cerinele de memorare ale acestei structuri i a celei
standard este:

* 4
6
G c = (6.21)

Prin urmare aceast structur de memorare este eficient pentru
memorarea matricelor cu o densitate a elementelor nenule de maximum 25%.


6.3 Determinarea gradului de umplere al unei matrice rare

Pentru a deduce dac o matrice este sau nu rar, se definete gradul de
umplere al unei matrice, notat cu p. n cazul n care p < 0,3*m*n, se
consider c matricea este rar.
Problema matricelor rare comport dou abordri:
- abordarea static, n care alocarea memoriei se efectueaz n faza de
compilare; aceasta presupune ca programatorul s cunoasc cu o precizie
bun numrul maxim al elementelor nenule;
- abordarea dinamic, n care alocarea se efectueaz n timpul execuiei, caz
n care nu este necesar informaia asupra numrului de elemente nenule;
aceast abordare este dezvoltat n partea destinat listelor.
Memorarea elementelor matricei rare, presupune memorarea indicelui
liniei, a indicelui coloanei i, respectiv, valoarea nenul a elementului.
Se consider matricea:

(
(
(
(

=
0 0 2 8 0
0 9 0 0 0
0 0 0 0 7
0 0 6 0 0
A (6.22)

Gradul de umplere al matricei A cu numrul de linii m = 4, numrul de
coloane, n= 5 i numrul elementelor nenule k = 5 este:

25 . 0
4 5
5
=

= G (6.23)

Se definesc 3 vectori:
lin [ ] memoreaz poziia liniei ce conine elemente nenule;
col [ ] memoreaz poziia coloanei ce conine elemente nenule;
val [ ] memoreaz valoarea nenul a elementelor.

Vectorii se iniializeaz cu valorile:

Tabelul nr. 6.2 Valorile iniiale ale vectorilor LIN, COL i VAL

LIN COL VAL
1 3 6
2 1 7
3 4 9
4 2 8
4 3 2

Pentru efectuarea calculelor cu matrice rare definite n acest fel, un rol
important l au vectorii LIN, COL, iar pentru matricele rare rezultat se definesc
vectori cu un numr de componente care s asigure i stocarea noilor
elemente ce apar.
Astfel, pentru adunarea matricelor rare definite prin:

Tabelul nr. 6.3 Valorile matricei rare A

LIN_A COL_A VAL_A
1 1 -4
2 2 7
4 4 8

i
Tabelul nr. 6.4 Valorile matricei rare B

LIN_B COL_B VAL_B
1 1 4
2 2 -7
3 2 8
4 1 5
4 3 6

rezultatul final se stocheaz n vectorii:

Tabelul nr. 6.5 Valorile matricei rare rezultat C

LIN_C COL_C VAL_C
1 1 0
2 2 0
3 2 8
4 1 5
4 3 6
4 4 8
? ? ?
? ? ?

Vectorii LIN_C, COL_C i VAL_C au un numr de componente definite,
egal cu:

DIM (LIN_A) + DIM (LIN_A) (6.24)

unde DIM() este funcia de extragere a dimensiunii unui masiv unidimensional:
Astfel, dac:

int a[n-m]; (6.25)

atunci:

DIM (a) = n - m+1 (6.26)

Fiind abordat problematica matricelor rare, n mod natural se produce
eliminarea elementelor nenule, obinndu-se n final:

Tabelul nr. 6.6 Coninutul final al matricei rare C

LIN_C COL_C VAL_C
3 2 8
4 1 5
4 3 6
4 4 8
? ? ?
? ? ?
? ? ?
? ? ?

Prin secvene de program adecvate, se face diferena ntre definirea unui
masiv bidimensional i componentele iniializate ale acestora, cu care se
opereaz pentru rezolvarea unei probleme concrete. Din punct de vedere al
nivelului de umplere, tabelul 6.6 descrie o matrice rar cu un grad de umplere
egal cu

G =
32
12
*100 = 37.5 % (6.27)

Situaia evideniaz ineficien n utilizarea spaiului de memorie alocat.
De exemplu, vectorii LIN_A i LIN_B au 3, respectiv 5 componente n
utilizare, dar la definire au rezervate zone de memorie ce corespund pentru
cte 10 elemente. Rezult c vectorul LIN_C trebuie definit cu 20 componente
nct s preia i cazul n care elementele celor dou matrice rare au poziii
disjuncte.
Din punct de vedere al criteriului minimizrii spaiului ocupat, aceast
abordare nu este eficient deoarece presupune n cele mai multe situaii
alocarea de spaiu care nu este utilizat. Pentru a atinge acest obiectiv,
implementarea unei clase asociate matricei rare va defini vectori alocai
dinamic, iar operaiile aritmetice vor genera vectori rezultat cu grad de
umplere egal cu 100%.
n cazul operaiilor de nmulire sau inversare, este posibil ca matricele
rezultat s nu mai ndeplineasc cerina de matrice rar.
n acest scop, se efectueaz calculele cu matrice rezultat complet
definite i numai dup efectuarea calculelor se analizeaz gradul de umplere i
dac acesta este redus, se trece la reprezentarea matricei complete ca matrice
rar.
Funciile full( ) i rar( ), au rolul de a efectua trecerea la matricea
complet, respectiv la matricea rar.
Funcia full( ) conine secvena:

for( i = 0; i < n; i++)
a [LIN_a[i]] [COL_a[i]] = val_a[i];

ce descrie iniializarea elementelor matricei pe baza valorilor din vectori, iar
funcia rar( ) conine secvena:

k =1;
for( i = 0; i < m; i++)
for( j = 0; j < n; j++)
if (a[i][j] != 0)
{
LIN_a[k] = i;
COL_a[k] = j;
val_a[k] = a[i][j];
k = k + i;
}

n cazul n care gradul de umplere nu este suficient de mic astfel nct
matricea s fie considerat rar, pentru memorare se utilizeaz o structur
arborescent care conine pe nivelul al doilea poziiile elementelor nenule, iar
pe nivelul al treilea valorile.
Astfel matricei:

(
(
(
(

=
1 8 9 8 6
5 0 9 0 0
0 8 4 2 0
0 0 5 3 7
A (6.28)

i corespunde reprezentarea din figura 6.8.



7
A
a[0]
1 2 3
a[1]
2 3 4
a[2]
3 5
a[3]
-1
3 5 2 4 8 9 5 6 1


Figura 6.8 Model grafic al matricei A

Se elaboreaz convenii asupra modului de stabilire a lungimii
vectorului de poziii, fie prin indicarea la nceput a numrului de componente
iniializate, fie prin definirea unui simbol terminal.
De asemenea. n cazul considerat s-a adoptat convenia ca liniile
complete s fie marcate cu simbolul -1, fr a mai specifica poziiile
elementelor nenule, care sunt de fapt termenii unei progresii aritmetice.
Liniarizarea masivelor bidimensionale conduce la ideea suprapunerii
acestora peste vectori. Deci, punnd n coresponden elementele unei matrice
cu elementele unui vector, se pune problema transformrii algoritmilor, n aa
fel nct opernd cu elementele vectorilor s se obin rezultate corecte pentru
calcule matriceale.
Astfel, considernd matricea:

(
(
(

=
15 14 13 12 11
10 9 8 7 6
5 4 3 2 1
A (6.29)

prin punerea n coresponden cu elementele vectorului b, s se obin
interschimbul ntre dou coloane oarecare k i j ale matricei.

a
00
a
01
a
02
a
03
a
04
a
10
a
11
a
20
a
21
a
22
a
23
a
24

1 2 3 4 5 6 7 11 12 13 14 15
b
0
b
1
b
2
b
3
b
4
b
5
b
6
b
10
b
11
b
12
b
13
b
14


Figura 6.9 Punerea n coresponden a matricei A cu vectorul b

Dac matricea are M linii i N coloane i elemente de tip int, atunci
adresa elementului a[i][j] este dat de relaia

adr(a[i][j]) = adr(a[0][0] ) + ( (i-0 ) * N+j ) * 1g(int) (6.30)

iar din modul n care se efectueaz punerea n coresponden a matricei A cu
vectorul b, rezult:

adr(b[0]) = adr(a[0][0]) (6.31)

Pentru o matrice liniarizat, adresa elementului a[i][j] n cadrul vectorului este
dat de relaia

adr(a[i][j]) = adr(b[0] )+( (i-0) * N+j ) * lg(int) = adr(b[(i-0) * N+j]) (6.32)

Dac se consider problema interschimbrii valorilor coloanelor j i k pentru
o matrice liniarizat atunci secvena de nlocuire a coloanelor

for( i = 0; i < M; i++)
{
c = a[i][j];
a[i][j] = a[i][k];
a[i][k] = c;
}

este nlocuit prin secvena:

for( i = 0; i < M; i++)
{
c = b[(i-0) * N+j];
b [(i-0) * N+j] = b[(i-0) * N+k];
b[(i-0) * N+k] = c;
}

Transformarea algoritmilor de lucru cu masive bidimensionale n
algoritmi de lucru cu masive unidimensionale este benefic deoarece nu se mai
impune cerina de transmitere ca parametru a dimensiunii efective a numrului
de linii, dac liniarizarea se face pe coloane, respectiv a numrului de coloane,
dac liniarizarea se face pe linii.
n cazul matricelor rare, aceeai problem revine la interschimbarea
valorilor de pe coloana a treia dintre elementele corespondente ale coloanelor
k i j cu posibilitatea inserrii unor perechi i, respectiv, tergerii altora.
Pentru generalizare, un masiv n-dimensional rar, este reprezentat prin n
+ 1 vectori, fiecare permind identificarea coordonatelor elementului diferit de
zero, iar ultimul stocnd valoarea acestuia.
n cazul n care se construiete o matrice boolean ce se asociaz
matricei rare, o dat cu comprimarea acesteia se dispun elementele nenule
ntr-un vector. Punerea n coresponden a elementelor vectorului are loc n
acelai moment cu decomprimarea matricei booleene i analiza acesteia.
De exemplu, matricei :

(
(
(
(

=
0 0 0 9 6 5
0 7 1 0 0 0
0 0 0 0 3 3
0 4 0 0 0 8
A (6.33)

se asociaz matricea boolean:

(
(
(
(

=
0 0 0 1 1 1
0 1 1 0 0 0
0 0 0 0 1 1
0 1 0 0 0 1
B (6.34)

care prin compactare, ocup primii 3 octei ai unei descrieri, urmai de
componentele vectorului:

C = ( 8, 4, 3, 3, 1, 7, 5, 6, 9) (6.35)

Compactarea este procedeul care asociaz un bit fiecrei cifre din forma
liniarizat a matricei B.


6.4 Software orientat spre lucrul cu matrice rare

Metodele de calcul cu matrice rar pentru a fi eficiente trebuie s
beneficieze de proporia mare de elemente nule din aceste matrice, ceea ce
creeaz necesitatea considerrii unor tehnici speciale de memorare,
programare i analiz numeric.
O cerin esenial n programarea matricelor rare const n memorarea
i executarea operaiilor numerice numai cu elementele nenule ale matricei, de
a salva memorie i timp de calcul. n acest caz memorarea standard, devenind
ineficient, este abandonat i nlocuit cu metode de memorare adecvate,
cteva dintre acestea fiind prezentate n paragraful anterior.
Un program de calcul cu matrice rare este cu att mai eficient cu ct
timpul de calcul i cerinele de memorie necesare sunt mai reduse fa de
acelea ale unui program tradiional. De aceea, tehnica de programare trebuie
s realizeze o proporie convenabil ntre timpul de calcul i memoria utilizat,
cerine care de cele mai multe ori sunt contradictorii. n general, este
recunoscut necesitatea unei anumite de structuri de memorare a datelor i o
anumit tehnic de manipulare a acestora n cadrul unui algoritm n care sunt
implicate matricele rare.
Principiul fundamental de programare cu matrice rare const n
memorarea i manipularea numai a elementelor nenule, de sortare i ordonare
n structuri speciale n vederea meninerii structurii de matrice rar i a
stabilitii numerice, de evitare a buclelor complete.
n scopul ilustrrii principalelor operaii efectuate asupra matricelor rare
s-a fcut implementarea acestora n C++, utiliznd mediul de programare
Visual C++. Pentru reprezentarea matricelor s-a ales memorarea compact
aleatoare, datorit flexibilitii n manevrarea datelor. Este prezentat n
continuare o parte a clasei MatriceRara, coninnd constructorii, destructorul,
cteva dintre funciile i operatorii implementai i seciunea privat.

class MatriceRara
{
/*******************************/
/* Atribute */
/*******************************/
private:
long dim; //numarul de elemente nenule
int m,n; //dimensiunea matricei
int * coloane; //vectorul pentru index coloane
int * linii; //vectorul pentru index linii
double * valori; //vectorul pentru valori

/*******************************/
/* Constructor & Destructor */
/*******************************/
public:
MatriceRara(void);
MatriceRara(const MatriceRara & MR);
MatriceRara(int M, int N, int D, double *val, int *lin, int *col);
MatriceRara(double **matrice, int M, int N);
virtual ~ MatriceRara( );

/*******************************/
/* Metode auxiliare */
/*******************************/
public:
bool EsteRara();
static MatriceRara Unitate(int);
double Urma();
double ** GetMatrice();

/*******************************/
/* Metode de acces */
/*******************************/
public:
inline int getDim();
inline int getLinii();
inline int getColoane();
inline double getValoareElement(int i);
inline int getColoanaElement(int i);
inline int getLinieElement(int i);

double getValoareElement(int i,int j);
bool setValoareElement(int i,int j, int valoare);
double operator ()(int i, int j);

friend ostream& operator <<(ostream&, MatriceRara &);
friend istream& operator >>(istream&, MatriceRara &);

/*******************************/
/* Metode de prelucrare */
/*******************************/

void Sortare();
MatriceRara operator =(MatriceRara &);
MatriceRara operator +(MatriceRara &);
MatriceRara operator -(MatriceRara &);
MatriceRara operator *(MatriceRara &);
MatriceRara operator *(double);
MatriceRara operator !();
MatriceRara Inversa();
};

n cadrul seciunii private sunt definite urmtoarele atribute:

m,n dimensiunea matricei iniiale;
dim numrul de elemente nenule;
coloane pointer la masive de ntregi reprezentnd coloana elementelor
nenule;
linii pointer la masive de ntregi reprezentnd linia elementelor nenule;
valori pointer la un masiv avnd tipul de baz al elementelor matricei.

Aplicaia informatic realizat vizeaz principalele operaii necesare
manipulrii matricelor rare:
- construirea acestora prin introducerea datelor de la tastatur; acest
obiectiv este atins prin suprancrcarea operatorului >> prin rutina

istream& operator >>(istream& intrare, MatriceRara &MR)
{
if(MR.dim)
{
delete[] MR.coloane;
delete[] MR.linii;
delete[] MR.valori;
}
cout<<"\n Numarul de linii ale matricei:";intrare>>MR.m;
cout<<"\n Numarul de coloane ale matricei:";intrare>>MR.n;
cout<<"\n Numarul de elemente nenule:";intrare>>MR.dim;
MR.coloane = new int[MR.dim];
MR.linii = new int[MR.dim];
MR.valori = new double[MR.dim];
for(int i=0;i<MR.dim;i++)
{
cout<<"\n Valoare a "<<i+1<<"-a este:";
cout<<"\n\t Linia:";intrare>>MR.linii[i];
cout<<"\n\t Coloana:";intrare>>MR.coloane[i];
cout<<"\n\t Valoare:";intrare>>MR.valori[i];
}
return intrare;
}

- vizualizarea matricelor rare prin intermediul operatorului >>;

ostream& operator <<(ostream& iesire, MatriceRara & MR)
{
iesire<<"\n Matricea rara de dimensiune ("<<
MR.m<<","<<MR.n<<") este:";
for(int k=0;k<MR.dim;k++)
iesire<<"\n element["<<
MR.linii[k]<<"]["<<MR.coloane[k]<<"] - "<<MR.valori[k];

iesire<<"\n Vizualizare normala :\n";
for(int i=0;i<MR.m;i++)
{
for(int j = 0;j<MR.n;j++)
iesire<<"\t"<<MR.getValoareElement(i,j);
iesire<<"\n";
}
return iesire;
}

- prin intermediul constructorilor clasei este posibil crearea unei
matrice rare iniial fr valori, sau a unei matrice ce preia valorile
dintr-o colecie de trei vectori sau dintr-o matrice normal ce este
validat

/*****************************/
/* Constructori */
/*****************************/
MatriceRara::MatriceRara(void):m(0),n(0),dim(0)
{
coloane=NULL;
linii=NULL;
valori=NULL;
}

MatriceRara::MatriceRara(int M, int N, int D, double *val, int *lin, int
*col)
{
m=M;
n=N;
dim = D;
if(dim)
{
coloane = new int[dim];
linii = new int[dim];
valori = new double[dim];
for(int i=0;i<dim;i++)
{
coloane[i] = col[i];
linii[i] = lin[i];
valori[i] = val[i];
}
}
else
{
coloane = linii = NULL;
valori = NULL;
}

}
MatriceRara::MatriceRara(double **matrice, int M, int N)
{
/* validare matrice rara */
int nenule = 0;
for(int i=0;i<M;i++)
for(int j=0;j<N;j++)
if(matrice[i][j]) nenule++;
if(((nenule*100)/(M*N))>100)
{
/* matricea nu este rara */
coloane = linii = NULL;
valori = NULL;
m = n = dim = 0;
}
else
{
/* matricea este rara */
coloane = new int[nenule];
linii = new int[nenule];
valori = new double[nenule];
m = M;
n = N;
dim = nenule;

int k=0;
for(i=0;i<M;i++)
for(int j=0;j<N;j++)
if(matrice[i][j])
{
coloane[k]= j;
linii[k] = i;
valori[k] = matrice[i][j];
k++;
}
}
}

- clasa permite copierea valorilor ntre diferite obiecte de tip
MatriceRara prin intermediul constructorului de copiere i a
operatorului =;

/*****************************/
/* Copy constructor */
/*****************************/

MatriceRara::MatriceRara(const MatriceRara &MR)
{
dim = MR.dim;
m = MR.m;
n = MR.n;

if(dim)
{
coloane = new int[dim];
linii = new int[dim];
valori = new double[dim];
for(int i=0;i<dim;i++)
{
coloane[i] = MR.coloane[i];
linii[i] = MR.linii[i];
valori[i] = MR.valori[i];
}
}
else
{
coloane = linii = NULL;
valori = NULL;
}
}

MatriceRara MatriceRara::operator =(MatriceRara & MR)
{
if(dim)
{
delete[] coloane;
delete[] linii;
delete[] valori;
}
dim = MR.dim;
m = MR.m;
n = MR.n;
if(dim)
{
coloane = new int[dim];
linii = new int[dim];
valori = new double[dim];
for(int i=0;i<dim;i++)
{
coloane[i] = MR.coloane[i];
linii[i] = MR.linii[i];
valori[i] = MR.valori[i];
}
}
else
{
coloane = linii = NULL;
valori = NULL;
}
return *this;
}

- pentru a asigura gestiunea eficient a memoriei aplicaiei se
implementeaz destructorul clasei care asigur eliberarea memoriei
rezervate de cele trei masiv de date;

/*****************************/
/* Desstructor */
/*****************************/
MatriceRara::~MatriceRara()
{
delete[] coloane;
delete[] linii;
delete[] valori;
}

- principalele operaii matriceale: adunarea, scderea, transpunerea,
nmulirea i inversarea.

Pe parcursul dezvoltrii clasei MatriceRara s-a dovedit necesar
implementarea unei funcii bool MatriceRara::EsteRara(), care s verifice dac
o matrice este rar.

bool MatriceRara::EsteRara()
{
if(((dim*100)/(n*m)>30)) return false;
else return true;
}

n urma prelucrrii matricelor i prin generarea unor obiecte noi ca
rezultate ale prelucrrilor aritmetice exist situaii n care matricea i pierde
caracteristica de a fi rar. Pentru a implementa soluii software eficiente, este
indicat ca modul de stocare a matricei s fie ales n funcie de nivelul de
memorie ocupat. Prin validarea matricei rare cu metoda EsteRara(), datele pot
fi stocate sub form de matrice normal prin intermediul metodei double **
GetMatrice()

double** MatriceRara::GetMatrice()
{
double **matrice=NULL;
matrice = new double*[m];
for(int k=0;k<m;k++)
matrice[k] = new double[n];
for(int i=0;i<m;i++)
for(int j=0;j<n;j++)
{
matrice[i][j]=0;
}
for(i=0;i<this->dim;i++)
matrice[linii[i]][coloane[i]]=valori[i];
return matrice;
}

Produsul implementeaz metoda void Sortare() ce permite rearanjarea
valorilor din matricea rar astfel nct acestea s corespund unui mode de
aranjare bazat pe parcurgerea pe linii a matricei. Aceast condiie reprezint o
ipotez de start n derularea operaiilor aritmetice de adunare, scdere i
nmulire deoarece contribuie la obinerea unei metode de prelucrare mai
eficiente din punctul de vedere al efortului procesor.

void MatriceRara::Sortare()
{
/* metoda rearanjeaza elementele dupa linii */
bool flag = true;
while(flag)
{
flag = false;
for(int i=0;i<dim-1;i++)
if(linii[i]>linii[i+1])
{
int temp = linii[i];
linii[i] = linii[i+1];
linii[i+1] = temp;
temp = coloane[i];
coloane[i] = coloane[i+1];
coloane[i+1] = temp;
double valoaretemp = valori[i];
valori[i] = valori[i+1];
valori[i+1] = valoaretemp;
flag = true;
}
else
if(linii[i]==linii[i+1])
if(coloane[i]>coloane[i+1])
{
int temp = coloane[i];
coloane[i] = coloane[i+1];
coloane[i+1] = temp;
double valoaretemp = valori[i];
valori[i] = valori[i+1];
valori[i+1] = valoaretemp;
flag = true;
}

}
}

Pentru a permite accesul programatorilor la atributele matricei rare, sunt
implementate o serie de metode care returneaz valorile acestor caracteristici.

/*******************************/
/* Metode de acces */
/*******************************/
int MatriceRara::getDim(){ return this->dim;}
int MatriceRara::getLinii(){ return this->m;}
int MatriceRara::getColoane(){ return this->n;}
double MatriceRara::getValoareElement(int i){ return valori[i];}
int MatriceRara::getColoanaElement(int i){ return coloane[i];}
int MatriceRara::getLinieElement(int i){ return linii[i];}

Metodele de prelucrare a unei matrice sunt bazate pe algoritmi n care
accesul la elementele matricei se realizeaz direct prin intermediul sintaxei
matricei[i][j]. Din punct de vedere al structurii interne, modelul ales n clasa
MatriceRara pentru implementarea unei matrice rare difer de abordarea
clasic a masivului bidimensional. Pentru a permite programatorilor, ntr-un
mod transparent, accesul direct la elementele matricei se definesc metodele:

double MatriceRara::getValoareElement(int i, int j)
{
for(int k=0;k<dim;k++)
if((linii[k]==i)&&(coloane[k]==j)) return valori[k];
return 0;
}

bool MatriceRara::setValoareElement(int i, int j, int valoare)
{
/* metoda valideaza noua valoare */
if(valoare) return false;

for(int k=0;k<dim;k++)
if((coloane[k]==i)&&(linii[k]==j))
{
valori[k]=valoare;
return true;
}
return false;
}

double MatriceRara::operator ()(int i, int j)
{
return this->getValoareElement(i,j);
}

n subcapitolele urmtoare se face o prezentare detaliat a operatorilor
care implementeaz principalele operaii matriceale: adunarea, scderea,
transpunerea, nmulirea i inversarea.


6.5 Adunarea, scderea i transpunerea

Prin prisma caracterului dinamic al modului de alocare a memoriei i a
caracteristicilor unice ale matricelor rare, adunarea acestor structuri de date
presupune parcurgerea unei serii pai:
- determinarea numrului de elemente nenule ale matricei sum; din
punctul de vedere al operanzilor sunt definite dou situaii de
realizare a sumei, cu elemente comune i cu elemente distincte; n
cazul sumei a dou elemente comune, se verific dac suma acestora
este zero, caz n care rezultatul nu este reinut n matricea rar
generat;
- alocarea memoriei corespunztoare acestui numr pentru cele trei
masive unidimensionale;
- parcurgerea celor dou matrice pe linii sau pe coloane i
determinarea sumei.
Prin elemente comune au fost desemnate valorile caracterizate prin
indici de linie i de coloan care sunt indentice n ambele matrice.
Pentru implementare s-a folosit suprascrierea operatorilor, tehnic ce
ofer o mai mare putere de sugestie operaiilor matriceale implementate. Este
prezentat n continuare operatorul care implementeaz operaia de adunare,
structurat conform pailor prezentai mai sus.

MatriceRara MatriceRara::operator +(MatriceRara & MR)
{
/* se determina dimensiunea matricei rezultat */

// se simuleaza suma si se contorizeaza numarul
// de sume zero si numarul de sume nonzero

MatriceRara rezMR;

if((this->m!=MR.m)||(this->n!=MR.n))
return rezMR;

int nrsz = 0, nrsnz = 0;
int i = 0, j = 0;
while((i<this->dim)&&(j<MR.dim))
{
if(this->linii[i]<MR.linii[j])
i++;
else
if(this->linii[i]>MR.linii[j])
j++;
else
if(this->coloane[i]<MR.coloane[j])
i++;
else
if(this->coloane[i]>MR.coloane[j])
j++;
else
if(this->valori[i]+MR.valori[j])
{
nrsnz++;
i++;
j++;
}
else
{
nrsz++;
i++;
j++;
}
}

int rezdim = this->dim+MR.dim-nrsnz-2*nrsz;
rezMR.dim = rezdim;
rezMR.m = this->m;
rezMR.n = this->n;

rezMR.coloane = new int[rezdim];
rezMR.linii = new int[rezdim];
rezMR.valori = new double[rezdim];

// se determina suma elementelor

int k=i=j=0;

while((i<this->dim)&&(j<MR.dim))
{
if(this->linii[i]<MR.linii[j])
{
rezMR.linii[k] = this->linii[i];
rezMR.coloane[k] = this->coloane[i];
rezMR.valori[k] = this->valori[i];
i++;
k++;
}

else
if(this->linii[i]>MR.linii[j])
{
rezMR.linii[k] = MR.linii[j];
rezMR.coloane[k] = MR.coloane[j];
rezMR.valori[k] = MR.valori[j];
k++;
j++;
}
else
if(this->coloane[i]<MR.coloane[j])
{
rezMR.linii[k] = this->linii[i];
rezMR.coloane[k] = this->coloane[i];
rezMR.valori[k] = this->valori[i];
i++;
k++;
}
else
if(this->coloane[i]>MR.coloane[j])
{
rezMR.linii[k] = MR.linii[j];
rezMR.coloane[k] = MR.coloane[j];
rezMR.valori[k] = MR.valori[j];
k++;
j++;
}
else
if(this->valori[i]+MR.valori[j])
{
rezMR.linii[k] = MR.linii[j];
rezMR.coloane[k] = MR.coloane[j];
rezMR.valori[k] = this-
>valori[i]+MR.valori[j];
k++;
j++;
i++;
}
else
{
i++;
j++;
}
}
if(i<this->dim)
for(;i<dim;i++,k++)
{
rezMR.linii[k] = this->linii[i];
rezMR.coloane[k] = this->coloane[i];
rezMR.valori[k] = this->valori[i];
}
if(j<MR.dim)
for(;j<MR.dim;j++,k++)
{
rezMR.linii[k] = MR.linii[j];
rezMR.coloane[k] = MR.coloane[j];
rezMR.valori[k] = MR.valori[j];
}

return rezMR;
}

Pentru a minimiza numrul de parcurgeri ale celor dou matrice rare, n
acest caz sunt necesare doar dou parcurgeri, n metoda prezentat se
pornete de la ipoteza c matricea rar este generat prin parcurgerea pe linii
a matricei iniiale. Acest lucru asigur o ordine ntre elementele matricei rare i
permite identificare mai eficient a elementelor comune. De asemenea, este
implementat o parcurgere simultan a celor dou matrice. Elementele curente
din cele dou matrice sunt analizate n ordine prin prisma valorii liniei i a
coloanei. n cazul n care elementele se gsesc pe linii diferite, elementul care
are valoarea liniei mai mic este adugat la rezultat i se trece la urmtorul
element din matricea respectiv. Dac elementele curente din cele dou
matrice prezint aceeai valoare pentru linie, atunci se compar valoarea
coloanelor. Pentru elementele comune, se analizeaz rezultatul sumei i se
memoreaz doar valorile nenule.
Implementarea operatorului de scdere este absolut similar celui de
adunare, singura diferen fiind aceea c n cazul elementelor comune se
calculeaz diferena lor, n locul adunrii. O alt abordare, este dat de
utilizarea sumei, negnd anterior valorile matricei ce se scade. Prin utilizarea
operatorului MatriceRara MatriceRara::operator *(double valoare) ce permite
nmulirea matricei cu o valoare dat, scderea se realizeaz prin
suprancrcarea operatorului -.

MatriceRara MatriceRara::operator *(double valoare)
{
MatriceRara rezMR;
if(valoare)
{
rezMR = *this;
for(int i=0;i<rezMR.dim;i++)
rezMR.valori[i]*=valoare;
}
return rezMR;
}
MatriceRara MatriceRara::operator -(MatriceRara &MR)
{
return ((*this)+(MR*-1));
}

Transpunerea matricelor rare, prin intermediul operatorului !, este
similar celei efectuate pe structur tablou, constnd n inversarea indicilor de
linie i coloan ntre ei.

MatriceRara MatriceRara::operator !()
{
MatriceRara rezMR= *this;
/* metoda transpune matricea */
for(int i=0;i<dim;i++)
{
int temp = rezMR.linii[i];
rezMR.linii[i] = rezMR.coloane[i];
rezMR.coloane[i] = temp;
}
return rezMR;
}

O alt metod de a realiza transpunerea este dat de inversarea
pointerilor pentru masivele de ntregi reprezentnd liniile, respectiv coloanele
elementelor nenule

MatriceRara MatriceRara::operator !()
{
MatriceRara rezMR= *this;
int * temp = rezMR.coloane;
rezMR.coloane = rezMR.linii;
rezMR.linii = temp;
return rezMR;
}


6.6 nmulirea i inversarea matricelor rare

Pentru nmulirea matricei rare A, (m, l) dimensional, cu matricea rar
B, (l, n) dimensional, se utilizeaz procedura standard, avnd n vedere c
metoda getValoareElement i operatorul (i,j) permit accesul direct la
elementele matricei rare.
Pentru a genera matricea rezultat, ca i n cazul operaiilor de adunare i
scdere, este nevoie s se determine, anterior efecturii produsului, numrul
de elemente ale rezultatului. Acest lucru se realizeaz prin simularea
produsului i contorizarea numrului de valori nenule.

MatriceRara MatriceRara::operator *(MatriceRara &MR)
{
MatriceRara rezMR;

if(this->n!=MR.m)
return rezMR;

/* se determina numarul de elemente ale rezultatului */
int rezdim=0;

for(int i=0;i<this->m;i++)
for(int j=0;j<MR.n;j++)
{
double val = 0;
for(int k=0;k<this->n;k++)
{
val+=this->getValoareElement(i,k)*MR.getValoareElement(k,j);
}
if(val) rezdim++;
}

rezMR.dim = rezdim;
rezMR.m = this->m;
rezMR.n = MR.n;

rezMR.coloane = new int[rezdim];
rezMR.linii = new int[rezdim];
rezMR.valori = new double[rezdim];

int l = 0;

for(i=0;i<this->m;i++)
for(int j=0;j<MR.n;j++)
{
double val = 0;
for(int k=0;k<this->n;k++)
{
val+=this->getValoareElement(i,k)*MR.getValoareElement(k,j);
}
if(val)
{
rezMR.linii[l] = i;
rezMR.coloane[l] = j;
rezMR.valori[l] = val;
l++;
}
}

return rezMR;
}

Prin analiza acestui operator se constat c matricea rezultat pstreaz
structura de matrice rar.
Pentru implementarea operatorului de inversare s-a folosit algoritmul lui
Krlov. Acesta const n parcurgerea unui numr de pai egal cu dimensiunile
matricei:

1: A
1
= A ) tr(A
1
1
p
1 1
=
1 1 1
A * p I B =
2: A
2
= A * B
1
) tr(A
2
1
p
2 2
= B
2
= I p
2
* A
2

. . .
n-1: A
n-1
= A * B
n-2

1 n 1 n 1 n 1 n 1 n
A * p I B ) tr(A
1 n
1
p

=

=

n: A
n
= A* B
n-1

n n n n
A * p I B tr(A)
n
1
p = =


Prin tr(A) se nelege urma matricei A, suma elementelor diagonale, iar I
reprezint matricea unitate de aceeai dimensiune cu matricea A. Aceste
elemente sunt implementate n clasa MatriceRar prin intermediul metodelor
Unitate(int) i Urma().

MatriceRara MatriceRara::Unitate(int n)
{
MatriceRara rezMR;
if(n>0)
{
rezMR.n=rezMR.m=rezMR.dim = n;
rezMR.coloane = new int[n];
rezMR.linii = new int[n];
rezMR.valori = new double[n];

for(int i=0;i<n;i++)
{
rezMR.coloane[i] = i;
rezMR.linii[i] = i;
rezMR.valori[i] = 1;
}

}
return rezMR;
}

double MatriceRara::Urma()
{
double rez = 0;
if(this->m==this->n)
{
for(int i=0;i<this->m;i++)
rez+=this->getValoareElement(i,i);
}
return rez;
}

Krlov a demonstrat c dup parcurgerea celor n pai, B
n
este o matrice
identic nul. De aici rezult inversa matricei A:

A
-1
= p
n
* B
n-1
(6.36)

Se prezint n continuare operatorul de inversare a matricelor rare care
implementeaz algoritmul prezent.

MatriceRara MatriceRara::Inversa()
{
MatriceRara tempMR, rezMR;

MatriceRara unitateMR = MatriceRara::Unitate(this->m);

MatriceRara initialaMR = *this;

if(initialaMR.m==initialaMR.n)
{
double p = initialaMR.Urma() ;
rezMR = initialaMR - (unitateMR*p);

for(int k=2;k<initialaMR.m;k++)
{
tempMR = initialaMR*rezMR;
p = (1.0/(double)k)*tempMR.Urma();
rezMR = tempMR - (unitateMR * p);
}

tempMR = initialaMR*rezMR;
p = (1.0/(double)k)*tempMR.Urma();
rezMR = rezMR*(1.0/p);

}
return rezMR;
}

Avantajele acestui algoritm constau n simplitatea implementrii i
precizia rezultatelor, datorat folosirii unui numr redus de operaii de
mprire.


6.7 Tipuri particulare de matrice rare

Exist tipuri de matrice rare ce prezint o serie de caracteristici prin
prisma crora se pot defini noi metode de a stoca valorile matricei.
O astfel de matrice rar este matricea band, n care valorile nenule
sunt poziionate n mijlocul liniei. n cazul matricelor rare band ce sunt
ptratice, elemente utilizabile se grupeaz n jurul diagonalei principale sau
secundare. De exemplu, matricea de dimensiune (5,8) din figura 6.10 este o
matrice rar n care elementele nenule sunt grupate n jurul diagonalei.

9 10 0 0 0 0 0 0
0 7 0 9 0 0 0 0
0 0 12 3 0 0 0 0
0 0 0 3 3 0 0 0
0 0 0 0 0 5 0 10

Figura 6.10 Matrice rar band

Pe baza ipotezei c elementele nenule sunt grupate pe linii n zone de
dimensiune redus, se definete o nou metod de memorare a matricei
band. Spre deosebire de abordarea compact bazat pe cei trei vectori, n
aceast situaie minimizarea memoriei ocupate se realizeaz prin reducerea
informaiilor necesare localizrii elementelor. Pentru fiecare linie se reine
indexul primei i ultimei valori din grupul de valori nenule. Figura 6.11 descrie
structura asociat matricei band

0
1
1
3
2
3
3
4
5
7
9 10 7 0 9 12 3 3 3 5 0 10
linia 1 linia 2 linia 5 linia 3 linia 4
index start grup n matrice
index terminare grup

Figura 6.11 Model de stocare a matricei band

Se observ c pentru fiecare grup de valori nenule se reine prin
intermediul a doi vectori coloana primei valori nenule i coloana ultimei valori
nenule. Din acest motiv, vectorul de valori stocheaz i valorile nule cuprinse
n grup, fapt care conduce la pierderea eficienei metodei pe msur ce
matricea band crete n lime.
Pentru exemplul considerat, aceast metod de stocare este mai
eficient dect modelul compact. Dac se consider valorile ca fiind ntregi,
nivelul de memorie necesar pentru datele matricei este egal cu

DMR
banda
= DM
index_start
+DM
index_term
+DM
valori
= (5 + 5 + 12)*4 = 88 octei (6.37)

unde:
DM
index_start
dimensiunea zonei de memorie asociat indexului de start;
DM
index_term
dimensiunea zonei de memorie asociat indexului de terminare;
DM
valori
dimensiunea zonei de memorie asociat valorilor;

Aceeai matrice stocat n forma compact, necesit DMR
compact
= 3 * 12
* 4 = 144 octei.
Din punctul de vedere al programatorului, aceast abordare conduce la
definirea clasei MatriceBanda

class MatriceBanda
{
private:
int m,n; //dimensiunea matricei
int dim; //numarul de elemente nenule
int *index_start; //vector pentru index start
int *index_term; //vector pentru index terminare
double *valori; //vector pentru valori

public:
MatriceBanda();
MatriceBanda(double **matrice, int m, int n);
MatriceBanda(const MatriceBanda&);
~MatriceBanda();

double getValoare(int i, int j);}

Se observ c pe lng informaiile descrise n figura 6.11 este necesar
s se memoreze dimensiunea matricei band i numrul de elemente nenule.
Pentru a parcurge vectorii index_start i index_term nu este nevoie de
informaii suplimentare, deoarece masivele au un numr de elemente egal cu
numrul de linii ale matricei.
Pentru a asigura programatorilor un nivel de transparen la accesarea
direct a valorilor din matricea band i pentru a trece peste bariera dat de
structura intern a obiectului MatriceBanda se definete metoda double
getValoare(int i, int j) ce permite afiarea valorii elementului de pe linia i i
coloana j.

double MatriceBanda::getValoare(int i, int j)
{
if((i<0 || i>=m) || (j<0||j>=n))
{
cerr<<"Index gresit !";
return 0;
}
if((j<this->index_start[i])||(j>this->index_term[i]))
return 0;
else
{
int index_linie=0;
for(int k =0;k<i;k++)
index_linie+=(index_term[i]-index_start[i]+1);
return this->valori[index_linie+(j-index_start[i])];
}
}

Un alt caz de matrice rar particular este matricea diagonal. Acest
masiv bidimensional este ptratic i are elemente nenule doar pe diagonala
principal. Dac se consider matricea din figura 6.12

9 0 0 0
0 7 0 0
0 0 10 0
0 0 0 3

Figura 6.12 Matrice rar triunghiular.

se definete o metod de reprezentare particular ce se bazeaz pe
memorarea dimensiunii matricei i a valorilor de pe diagonala principal, clasa
MatriceDiagonala.

class MatriceDiagonala
{
private:
int n;
int *valori;

public:
MatriceDiagonala();
MatriceDiagonala(MatriceDiagonala&);
~MatriceDiagonala();

double getValoare(int, int);
};

Pentru a accesa elementele matricei se implementeaz metoda double
getValoare(int, int).

double MatriceDiagonala::getValoare(int i, int j)
{
if((i<0 || i>=n) || (j<0||j>=n))
{
cerr<<"Index gresit !";
return 0;
}
if(i!=j)
return 0;
else
{
return this->valori[i];
}
}

Metoda returneaz valoare elementelor pentru care i este egal cu j,
celelalte elemente ale matricei avnd valoarea zero.
Matricea diagonal este o matrice rar, deoarece o matrice ptratic de
ordin n 4, conine pe diagonala principal mai puin de 30% din valori.

Prin prisma matricei diagonale se observ c matricea unitate, figura
6.13, reprezint un caz special al acestui tip de matrice deoarece toate
elementele de pe diagonal au valoarea 1. Pentru a memora o matrice unitate
este nevoie s se indice doar ordinul matricei, aceasta putnd fi generat cu
uurin.

Matricea triunghiulara reprezint o matrice ptratic n care toate
valorile aflate sub diagonala principal au valoarea 0. Pentru matricea
triunghiulara numrul de elemente nenule este
( )
2
* 1 n n
, unde n reprezint
dimensiunea matricei ptratice, iar raportul acestora n mulimea de elemente
ale matricei,
( )
( ) 1
1
+

n
n
ia valori n intervalul [0,33 ; 1) pentru n 2. Cu toate c
ponderea elementelor nenule nu este suficient de mic pentru a fi considerat
o matrice rar, acest tip de matrice are n funcie de rangul su un numr
destul de mare de elemente nenule pentru a fi acordat o atenie special
modului de stocare. De asemenea, proprietile algebrice ale matricei
triunghiulare contribuie la alegerea acestui tip de matrice n rezolvarea
sistemelor de ecuaii compatibile cu acest tip de matrice:
- suma i diferena dintre dou matrice triunghiulare reprezint tot o
matrice triunghiular;
- rezultatul nmulirii a dou matrice triunghiulare de dimensiune egal
reprezint tot o matrice triunghiular;
- valoarea determinantului unei matrice triunghiular este dat de
produsul elementelor de pe diagonala principal.
De exemplu, matricea triunghiular din figura 6.13

2 9 3 3
0 7 1 5
0 0 10 2
0 0 0 3

Figura 6.13 Matrice triunghiular

este stocat, prin memorarea ntr-un masiv unidimensional a valorilor nenule
i prin indicarea indexului de nceput a valorilor de pe fiecare linie, figura 6.14.


0 4 7 9
2 9 3 3 7 1 5 10 2 3
linia 1 linia 2 linia 3 linia 4
index start linie n mulime a
de valori


Figura 6.14 Model de stocare a matricei triunghiulare

Clasa MatriceTriunghiulara implementeaz aceast soluie i definete
metode de acces direct la elementele matricei.

class MatriceTriunghiulara
{
private:
int * linii; //indexul fiecarei linii in lista de valori
int n; //dimensiunea matricei patratice
double * valori; //valorile nenule din matrice

public:
MatriceTriunghiulara();
MatriceTriunghiulara(int);
virtual ~MatriceTriunghiulara();
MatriceTriunghiulara(const MatriceTriunghiulara&);

bool setValoare(int i, int j, double valoare);
double getValoare(int i, int j);

double getDeterminant();
int getDimensiune(){return n;};

MatriceTriunghiulara operator+(MatriceTriunghiulara& );
MatriceTriunghiulara operator=(MatriceTriunghiulara& );

friend ostream& operator <<(ostream&, MatriceTriunghiulara&);
};

Constructorul implicit iniializeaz o matrice triunghiular vid, iar
constructorul cu parametrii primete dimensiunea matricei ptratice. Pentru
aceast abordare, valorile nenule sunt introduse de la tastatur de ctre
utilizator parcurgnd matricea pe linii.

MatriceTriunghiulara::MatriceTriunghiulara()
{
linii = NULL;
n = 0;
valori = NULL;
}

MatriceTriunghiulara::MatriceTriunghiulara(int dim)
{
if(dim)
{
this->n=dim;
linii = new int[n];
valori = new double[n*(n+1)/2];
int indexLinie=0;
for(int i=0;i<n;i++)
{
linii[i]=indexLinie;
for(int j=i;j<n;j++)
{
cout<<"\n Element ["<<i<<"]["<<j<<"]:";
cin>>valori[indexLinie+j-i];
}
indexLinie+=n-i;
}
}
else
{
n = 0;
linii = NULL;
valori = NULL;
}
}

Constructorul de copiere al clasei i metoda ce suprancarc operatorul
= permit crearea de noi obiecte prin copierea valorilor unor matrice existent.
Diferena dintre cele dou metode este dat de situaia n care se apeleaz
fiecare metod. Apelul operatorului = presupune existena ambelor obiecte i
programatorul trebuie s dezaloce zona de memorie a obiectului curent nainte
de a face iniializarea.

MatriceTriunghiulara::MatriceTriunghiulara (const MatriceTriunghiulara&
MT)
{
if(MT.n)
{
this->n=MT.n;
linii = new int[n];
valori = new double[n*(n+1)/2];
for(int i=0;i<n;i++)
linii[i] = MT.linii[i];
for(int j=0;j<n*(n+1)/2;j++)
valori[j]=MT.valori[j];
}
else
{
n=0;
linii = NULL;
valori=NULL;
}
}

MatriceTriunghiulara MatriceTriunghiulara::operator =
(MatriceTriunghiulara &MT)
{
if(n)
{
delete[] linii;
delete[] valori;
}
if(MT.n)
{
this->n=MT.n;
linii = new int[n];
valori = new double[n*(n+1)/2];
for(int i=0;i<n;i++)
linii[i] = MT.linii[i];
for(int j=0;j<n*(n+1)/2;j++)
valori[j]=MT.valori[j];
}
else
{
n=0;
linii = NULL;
valori=NULL;
}
return *this;
}

Destructorul clasei gestioneaz dezalocarea zonei de memorie rezervat
de un obiect de tip MatriceTriunghiulara prin alocarea dinamic a spaiului
aferent celor dou masive linii i valori.

MatriceTriunghiulara::~MatriceTriunghiulara()
{
delete[] linii;
delete[] valori; }

Pentru a asigura accesul la elementele matricei, ntr-un mod transparent
i apropiat cu abordarea direct dat de sintaxa matrice[i][j], clasa
implementeaz metodele getValoare i setValoare pentru a returna valoarea
elementului de pe linia i i coloana j, respectiv, pentru a iniializa elementul.

double MatriceTriunghiulara::getValoare(int i, int j)
{
if((i<0 || i>=n) || (j<0||j>=n))
{
cerr<<"Index gresit !";
return 0;
}
if(j<i)
return 0;
else
return this->valori[linii[i]+j-i];
}

bool MatriceTriunghiulara::setValoare(int i, int j,double valoare)
{
if((i<0 || i>=n) || (j<0||j>=n))
return false;
if(j>=i)
{
valori[linii[i]+j-i]=valoare;
return true;
}
else
return false;
}

n cazul metodei getValoare se returneaz valoarea zero pentru orice
element pentru care valoarea j este mai mare dect i deoarece aceste
elemente se gsesc sub diagonala principal.
Metoda setValoare valideaz coordonatele elementului de iniializat
deoarece nu este permis setarea unui element al matricei ce se gsete sub
diagonala principal, caz n care matricea i pierde caracteristica de a fi
triunghiular.
Pornind de la ipoteza c suma a dou matrice triunghiulare genereaz o
matrice de acelai tip, metoda care implementeaz aceast operaie aritmetic
adun elementele de pe poziii comune fr a lua n considerare rezultatul
acestora i fr a lua n considerare valorile de sub diagonal.

MatriceTriunghiulara MatriceTriunghiulara::operator + (
MatriceTriunghiulara& MT)
{
MatriceTriunghiulara rezMT;
if(this->n==MT.n)
{
rezMT.linii = new int[n];
rezMT.valori = new double[n];
rezMT.n=this->n;
for(int i=0;i<n;i++)
{
rezMT.linii[i] = this->linii[i];
for(int j=0;j<n-i;j++)
{
rezMT.valori[rezMT.linii[i]+j]=valori[linii[i]+j]+MT.valori[MT.lini
i[i]+j];
}
}
}
return rezMT;
}

Pentru a calcula determinantul matricei triunghiulare, ipoteza de lucru
este dat de faptul c elementele de pe diagonala principal reprezint prima
valoare de pe fiecare linie a matricei.

double MatriceTriunghiulara::getDeterminant(){
double determinant = 1;
for(int i=0;i<n;i++)
determinant*=valori[linii[i]];
return determinant;
}

Matricea de permutare este un masiv bidimensional n care fiecare linie
sau coloan conine o singur valoare unu, n rest elementele fiind nule.
Matricea are aceast denumire deoarece este utilizat n operaii algebrice
pentru a permuta elementele unui vector conform unui model stabilit anterior.
Dac se consider matricea MP din figura 6.15 i vectorul X = 1,2,3,4,5

0 0 0 1 0
0 0 1 0 0
1 0 0 0 0
0 1 0 0 0
0 0 0 0 1

Figura 6.15 Matrice de permutare de ordin egal cu cinci

prin nmulirea X * MP se obine vectorul XP = 3,4,2,1,5, fapt ce evideniaz c
elementele vectorului au fost rearanjate conform poziionrii valorilor egale cu
unu n matrice de permutare.
Pentru a stoca o astfel de matrice, n care n elemente sunt egale cu unu,
restul fiind zero, se definete clasa MatricePermutare.

class MatricePermutare
{
private:
int n; //ordinul matricei
int* index_coloane; //indexul coloanei
public:
MatricePermutare();
~MatricePermutare();
MatricePermutare(const MatricePermutare&);

};

Valorile memorate pentru a reprezenta corect matricea de permutare
sunt reprezentate de:
- rangul matricei ptratice;
- indexul coloanei pe care se gsete valoarea unu de pe fiecare linie;
deoarece exist o singur valoare nenul pe fiecare linie i coloan,
poziia valorii n cadrul vectorului index_coloane indic linia
corespondent.
Figura 6.16 descrie vectorul index_coloane asociat matricei de permutare din
figura 6.15.


n = 5
3 2 0 1 5
ordinul matricei ptratice
pe linia i = 2, valoarea 1 se gsete pe
coloana j = 0


Figura 6.16 Model de stocare a matricei de permutare.

ntr-o matrice de permutare de ordin n, numrul de valori nenule este
egal cu n, iar n cazul n care aceast valoare depete nivelul trei, matricea
este validat ca fiind o matrice rar datorit ponderii mici a valorilor nenule.


6.8 Estimarea parametrilor unei regresii statistice folosind
clasa MR

Se consider datele din tabelul 6.7 ce caracterizeaz cinci ntreprinderi
din punctul de vedere al productivitii y, al numrului de utilaje de mare
performan deinute x
1
i al veniturilor suplimentare acordate salariailor x
2
.
Se dorete determinarea unei funcii care s caracterizeze dependena dintre
productivitate i celelalte dou variabile considerate independente.

Tabelul nr. 6.7 Evoluia indicatorilor y, x
1
i x
2
ntr-o ntreprindere

y productivitatea muncii (creteri procentuale) 1 2 5 6 7
x
1
utilaje de mare randament (buci) 2 4 4 4 5
x
2
venituri suplimentare (mil. lei) 1 1 3 5 5

Pentru a specifica forma funciei, se analizeaz pe cale grafic
dependena variabilei efect(y) n raport cu fiecare dintre variabilele cauzale.

y
x2
-
-
-
-
-
y
x1
-
-
-

-
-



Figura 6.17 Dependena y= f(x
1
), y= f(x
2
)

ntruct norul de puncte din fiecare reprezentare grafic sugereaz o
linie dreapt, specificm modelul astfel:

y
i
= a
0
+ a
1
x1
i
+ a
2
x2
i
+ u
i
(6.38)

unde u
i
reprezint o variabil rezidual ce caracterizeaz influena altor
factori asupra variabilei efect y, factori care din diverse motive nu pot fi luai n
considerare.
Dac simbolizm y valorile ajustate, rezultate n urma aplicrii
modelului liniar, specificm modelul astfel:

2i 2 1i 1 0 i
x a x a a y + + = (6.39)

Relaia anterioar se scrie pentru fiecare set de valori prezentate n
tabelul 6.7, rezultnd:

|
|
|
|
|
.
|

\
|
+
|
|
|
|
|
.
|

\
|

|
|
|
|
|
.
|

\
|
=
|
|
|
|
|
.
|

\
|
n n n n n
u
u
u
a
a
a
x x
x x
x x
y
y
y
A A A A A A
2
1
1
0
2 2
1 1
2
1
2 1 1
2 1 1
2 1 1
(6.40)

Aadar:

Y = XA + U (6.41)

iar

A X Y = (6.42)

Determinarea dependenei dintre variabila efect i variabilele cauz
nsemn determinarea valorilor numerice ale parametrilor
1 0
a , a
i
2
a
. n acest
scop se utilizeaz metoda celor mai mici ptrate. Aceast metod presupune
minimizarea expresiei:

t
2
t
u
(6.43)

adic, matriceal, U*U. Dar:

( ) ( ) A X Y A X Y U U
'
= '
(6.44)

unde prin U' s-a notat transpusa matricei U.
n [Peci94] se demonstreaz c prin minimizarea relaiei de mai sus se
ajunge la expresia:

( ) Y X X X A
1
' ' =

(6.45)

O determinare ct mai precis a matricei parametrilor unei regresii
presupune existena unui numr foarte mare de date, adic un numr mare de
linii n matricea X. n multe cazuri practice valorile acestor date sunt nule, fapt
ce justific implementarea relaiei anterioare pe o structur de matrice rare.
Avnd deja definii operatorii de transpunere, nmulire i inversare,
implementarea relaiei de mai sus presupune scrierea unei singure linii de cod:

( ) ( ) ( ) ( ) Y * X ! * () . X * X ! A Inversa = (6.46)

Aadar, pentru aflarea matricei A sunt necesare dou operaii de
transpunere, trei nmuliri i o inversare. Matricele X i Y asupra crora se
opereaz au n multe dintre cazurile practice o densitate foarte mic, astfel c
este pe deplin justificat folosirea unor structuri de memorare specifice
matricelor rare.
Asistm n prezent la un fenomen care tinde s ating tot mai multe
domenii de activitate. Necesitatea de a cunoate ct mai precis anumii
factori sau parametri ce caracterizeaz domeniul respectiv, care pn nu de
mult erau fie considerai aleatori, fie nu se punea problema determinrii lor,
considerat a fi imposibil. Cunoaterea acestor factori ofer o descriere mai
detaliat a sistemului n care se lucreaz, permind n acest fel o mai bun
activitate de control i comand a acestuia.
n cele mai multe dintre cazuri baza de calcul a acestor factori o
constituie statistica matematic i teoria probabilitilor, ceea ce conduce la
necesitatea rezolvrii unor probleme liniare de foarte mari dimensiuni.
Caracterul de raritate al structurilor implicate n rezolvarea problemelor,
datorat caracteristicilor reale ale sistemelor, la care se adaug necesitatea unei
rezolvri rapide, n concordan cu dinamica crescnd a sistemelor actuale,
justific pe deplin introducerea n aplicaiile informatice asociate a unor
structuri de date adaptate acestor particulariti.
Softul orientat spre lucrul cu matrice rare exploateaz caracterul de
raritate al structurilor manipulate, oferind un dublu avantaj: memorie i timp.
n ultimii ani memoria nu mai constituie o problem, ns timpul necesar
calculelor, odat cu apariia sistemelor n timp real, se dovedete a fi tot mai
mult o resurs critic.
Referitor la lucrul cu matrice n general, n cadrul unui sistem n care
timpul reprezint o resurs critic, exist posibilitatea de a realiza un soft care
s fac o evaluare anterioar calculelor asupra densitii matricei, i, n funcie
de aceasta, s decid asupra structurilor de date ce vor fi folosite pentru
memorare i efectuarea calculelor, astfel nct timpul afectat calculelor s fie
minim.

You might also like