Sunteți pe pagina 1din 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 (n, n) - dimensional este rar atunci cnd conine
un numr mic de elemente nenule , adic n 2 . 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%.

6.2 Memorarea matricelor rare


Se consider matricea:

0
1 0

0 0 2
A
0 0
0

0 1 0

0
0
0
0

4
0

(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:

p
100 (%)
nm

(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 G ( A) 20% , 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 ntro 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
Valoare
Locaie
Valoare

1
1
11
0

5
0
15
0

6
0
16
0

10
1
20
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
DMR1 = 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:

c1

DMR1
1
G
8b
DM

(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:

c1 A 0,2

1
0,23 (6.5)
32

ceea ce indic c memorarea matricei A conform acestei structuri ocup de


aproximativ patru ori mai puin memorie dect cea standard.
Egalnd c1 1 se determin limita superioar a densitii unei matrice
pentru care aceast structur necesit mai puin memorie dect cea
standard:

Glim 1

1
8b

(6.6)

Pentru matricea A:

Glim 1

1
0,96 96%
32

(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
1
2
3
4

k
k+1
k+2

Jumtatea stng

Jumtatea dreapt

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

Numrul de elemente nenule Numrul de elemente nenule


n linia m-1
n linia m
Indicele de coloan al
Indicele de coloan al celui
primului element memorat
de-al doilea element
memorat
Indicele de coloan al celui
etc.
de-al treilea element

memorat

Indicele de coloan al
ultimului element memorat

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


Locaie
Valoare

1
4

2
4

3
1

4
2 0

5
1

6
3

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 108 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

(5 m m * n * G ) / 2

(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
DMR2 = (5 m 3 * m * n * G ) / 2

(6.9)

Raportul dintre cerinele de memorie ale acestei structuri de identificare


binar i a celei standard este:

c2

3G
5 m

2
2*m*n

(6.10)

Pentru o matrice ptrat (m=n), egalnd c2 = 1 i trecnd la limit


pentru m rezult valoarea maxim a densitii unei matrice rare pentru
care structura prezentat este eficient:

Glimm

2 5 m
1
0,666 66,6%
3
2m 2

(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
Valoare
Indice linie
Indice coloan

1
1
1
1

2
-2
2
3

3
4
2
5

4
-1
4
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
DMR3 = 3*m*n

(6.12)

Raportul dintre cerinele de memorie ale acestei structuri i a celei


standard este:

c3 3 G

(6.13)

Egalnd relaia anterioar cu unitatea se determin valoarea limit a


densitii matricei rare pentru care aceast structur este eficient,
Glim 33,3% .
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 aij 0 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

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
DMR4 = 2*m*n*G (6.17)
Raportul dintre cerinele de memorie ale acestei structuri i a celei
standard este:

c 4 2G

(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

ZP
ZS

1
1
0

2
1
1

3
2
0

4
-2
3

5
4
5

6
4
0

7
-1
2

8
0
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
DMR5 = 2*(m*n*r+m+1)

(6.19)

Raportul de memorare este:

c5 2 * G

2 * (m 1)
m*n

(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

ZP
ZSL
ZSC
ZSU

1
1
1
1
&2

2
-2
2
3
&3

3
4
2
5
&4

4
-1
4
2
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:

c6 4 * G

(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
7
A
0

0
0
0
8

6
0
0
2

0
0
9
0

0
0
0

(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:

5
0.25
54

(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
1
2
3
4
4

COL
3
1
4
2
3

VAL
6
7
9
8
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
1
2
4

COL_A
1
2
4

VAL_A
-4
7
8

i
Tabelul nr. 6.4 Valorile matricei rare B
LIN_B
1
2
3
4
4

COL_B
1
2
2
1
3

VAL_B
4
-7
8
5
6

rezultatul final se stocheaz n vectorii:


Tabelul nr. 6.5 Valorile matricei rare rezultat C
LIN_C
1
2
3
4
4
4
?
?

COL_C
1
2
2
1
3
4
?
?

VAL_C
0
0
8
5
6
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
3
4
4
4
?
?
?
?

COL_C
2
1
3
4
?
?
?
?

VAL_C
8
5
6
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=

12
*100 = 37.5 %
32

(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:

7
0
A
0

3
2
0
8

5
4
9
9

0
8
0
8

0
0
5

i corespunde reprezentarea din figura 6.8.

(6.28)

a[0]
1

a[1]
2

a[2]

a[3]

-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:

2 3 4 5
1

A 6
7 8 9 10
11 12 13 14 15

(6.29)

prin punerea n coresponden cu elementele vectorului b, s se obin


interschimbul ntre dou coloane oarecare k i j ale matricei.
a00
1
b0

a01
2
b1

a02
3
b2

a03
4
b3

a04
5
b4

a10
6
b5

a11
7
b6

a20
11
b10

a21
12
b11

a22
13
b12

a23
14
b13

a24
15
b14

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 :

8
3
A
0

0
3
0
6

0
0
0
9

0
0
1
0

4
0
7
0

0
0
0

(6.33)

se asociaz matricea boolean:

1
1
B
0

1
care prin compactare, ocup
componentele vectorului:

0
1
0
1

0
0
0
1

0
0
1
0

1
0
1
0

0
0
0

(6.34)

primii 3 octei ai unei

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

descrieri, urmai de

(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
MatriceRara
MatriceRara
MatriceRara
};

operator *(MatriceRara &);


operator *(double);
operator !();
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: A1 = A
2: A2 = A * B1
...

1
p1 tr(A1 )
1
1
p 2 tr(A 2 )
2

n-1: An-1 = A * Bn-2 p n 1

n: An = A* Bn-1

pn

B1 I p1 * A1
B2 = I p2 * A2

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

1
tr(A)
n

Bn I p n * A n

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, Bn este o matrice


identic nul. De aici rezult inversa matricei A:
A-1 = pn * Bn-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
0
0
0
0

10
7
0
0
0

0
0
12
0
0

0
9
3
3
0

0
0
0
3
0

0
0
0
0
5

0
0
0
0
0

0
0
0
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 2 3 5

index start grup n matrice

1 3 3 4 7

index terminare grup

9 10 7 0 9 12 3 3 3 5 0 10
linia 1

linia 2 linia 3 linia 4

linia 5

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
DMRbanda = DMindex_start+DMindex_term+DMvalori = (5 + 5 + 12)*4 = 88 octei (6.37)
unde:
DMindex_start dimensiunea zonei de memorie asociat indexului de start;
DMindex_term dimensiunea zonei de memorie asociat indexului de terminare;
dimensiunea zonei de memorie asociat valorilor;
DMvalori
Aceeai matrice stocat n forma compact, necesit DMRcompact = 3 * 12
* 4 = 144 octei.
Din punctul de vedere al programatorului, aceast abordare conduce la
definirea clasei MatriceBanda
class MatriceBanda
{
private:
int m,n;
int dim;
int *index_start;
int *index_term;
double *valori;

//dimensiunea matricei
//numarul de elemente nenule
//vector pentru index start
//vector pentru index terminare
//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

n 1 * n ,
2

unde n reprezint

dimensiunea matricei ptratice, iar raportul acestora n mulimea de elemente


ale matricei,

n 1
n 1

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.
index start linie n mulime a
de valori

0 4 7 9

2 9 3 3 7 1 5 10 2 3
linia 1

linia 2

linia 3

linia 4

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
MT)

(const

MatriceTriunghiulara&

{
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
1
0
0

0
0
0
1
0

0
1
0
0
0

1
0
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;
int* index_coloane;
public:
MatricePermutare();
~MatricePermutare();

//ordinul matricei
//indexul coloanei

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

ordinul matricei ptratice

3 2 0 1 5
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 x1 i al veniturilor suplimentare acordate salariailor x2.
Se dorete determinarea unei funcii care s caracterizeze dependena dintre
productivitate i celelalte dou variabile considerate independente.
Tabelul nr. 6.7 Evoluia indicatorilor y, x1 i x2 ntr-o ntreprindere
y productivitatea muncii (creteri procentuale) 1 2 5 6 7
x1 utilaje de mare randament (buci)
2 4 4 4 5
x2 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.

x1

x2

Figura 6.17 Dependena y= f(x1), y= f(x2)


ntruct norul de puncte din fiecare reprezentare grafic sugereaz o
linie dreapt, specificm modelul astfel:
yi = a0 + a1x1i + a2x2i + ui

(6.38)

unde ui 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:

y i a 0 a 1x 1i a 2 x 2i

(6.39)

Relaia anterioar se scrie pentru fiecare set de valori prezentate n


tabelul 6.7, rezultnd:

y1 1

y2 1


yn 1

x11
x12

x1n

x 21 a 0 u1

x 2 2 a1 u2



x 2 n a n un

(6.40)

Aadar:
Y = XA + U

(6.41)

Y XA

(6.42)

iar

Determinarea dependenei dintre variabila efect i variabilele cauz


nsemn determinarea valorilor numerice ale parametrilor

a 0 , a1 i a 2 . n acest

scop se utilizeaz metoda celor mai mici ptrate. Aceast metod presupune
minimizarea expresiei:

2
t

(6.43)

adic, matriceal, U*U. Dar:

U U Y XA Y XA

(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:

A X X X Y
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:

A !X * X .Inversa() * !X * Y (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.

S-ar putea să vă placă și