Documente Academic
Documente Profesional
Documente Cultură
MatriceRARE PDF
MatriceRARE PDF
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%.
0
1 0
0 0 2
A
0 0
0
0 1 0
0
0
0
0
4
0
(6.1)
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
1
1
11
0
5
0
15
0
6
0
16
0
10
1
20
0
c1
DMR1
1
G
8b
DM
(6.4)
c1 A 0,2
1
0,23 (6.5)
32
Glim 1
1
8b
(6.6)
Pentru matricea A:
Glim 1
1
0,96 96%
32
(6.7)
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
memorat
Indicele de coloan al
ultimului element memorat
1
4
2
4
3
1
4
2 0
5
1
6
3
(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)
c2
3G
5 m
2
2*m*n
(6.10)
Glimm
2 5 m
1
0,666 66,6%
3
2m 2
(6.11)
1
1
1
1
2
-2
2
3
3
4
2
5
4
-1
4
2
(6.12)
c3 3 G
(6.13)
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)
-
(6.16)
c 4 2G
(6.18)
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
(6.19)
c5 2 * G
2 * (m 1)
m*n
(6.20)
ZP
ZSL
ZSC
ZSU
1
1
1
1
&2
2
-2
2
3
&3
3
4
2
5
&4
4
-1
4
2
NULL
c6 4 * G
(6.21)
0
7
A
0
0
0
0
8
6
0
0
2
0
0
9
0
0
0
0
(6.22)
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
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
COL_C
1
2
2
1
3
4
?
?
VAL_C
0
0
8
5
6
8
?
?
(6.24)
(6.25)
atunci:
DIM (a) = n - m+1
(6.26)
COL_C
2
1
3
4
?
?
?
?
VAL_C
8
5
6
8
?
?
?
?
12
*100 = 37.5 %
32
(6.27)
7
0
A
0
3
2
0
8
5
4
9
9
0
8
0
8
0
0
5
(6.28)
a[0]
1
a[1]
2
a[2]
a[3]
-1
2 3 4 5
1
A 6
7 8 9 10
11 12 13 14 15
(6.29)
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
(6.30)
adr(b[0]) = adr(a[0][0])
(6.31)
(6.32)
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)
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)
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.
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
};
/*****************************/
/* 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++;
}
}
}
/*****************************/
/* 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;
}
/*****************************/
/* Desstructor
*/
/*****************************/
MatriceRara::~MatriceRara()
{
delete[] coloane;
delete[] linii;
delete[] valori;
}
*/
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;
}
}
}
}
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);
}
*/
//
//
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];
//
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;
}
*/
{
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;
}
1
p1 tr(A1 )
1
1
p 2 tr(A 2 )
2
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
(6.36)
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;
}
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
0 1 2 3 5
1 3 3 4 7
9 10 7 0 9 12 3 3 3 5 0 10
linia 1
linia 5
//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);}
MatriceDiagonala();
MatriceDiagonala(MatriceDiagonala&);
~MatriceDiagonala();
n 1 * n ,
2
unde n reprezint
n 1
n 1
0 4 7 9
2 9 3 3 7 1 5 10 2 3
linia 1
linia 2
linia 3
linia 4
MatriceTriunghiulara operator+(MatriceTriunghiulara& );
MatriceTriunghiulara operator=(MatriceTriunghiulara& );
friend ostream& operator <<(ostream&, MatriceTriunghiulara&);
};
(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;
}
{
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;
}
0
0
0
1
0
0
1
0
0
0
1
0
0
0
0
0
0
0
0
1
//ordinul matricei
//indexul coloanei
MatricePermutare(const MatricePermutare&);
};
3 2 0 1 5
pe linia i = 2, valoarea 1 se gsete pe
coloana j = 0
x1
x2
(6.38)
y i a 0 a 1x 1i a 2 x 2i
(6.39)
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
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)
U U Y XA Y XA
(6.44)
A X X X Y
1
(6.45)
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.