Narzędzia użytkownika

Narzędzia witryny


reprezentacje_macierzy

To jest stara wersja strony!


Biblioteka Boost.uBLAS

Wstęp

uBLAS (Basic Linear Algebra Subprograms) – biblioteka klas szablonowych, dostarczająca struktur do reprezentacji wektorów i macierzy różnego typu (np. macierz trójkątna,

symetryczna, rzadka) oraz operacji na nich. Różne reprezentacje macierzy służą przestrzeganiu zasad danego typu macierzy oraz zoptymalizowanemu przechowywaniu (np. macierzy

rzadkich - w formie upakowanej).

Biblioteka uBLAS reaguje w różny sposob na próby modyfikacji niezgodnej z cecha danego typu macierzy:

  1. błąd kompilacji - np.:
    • nie można modyfikować macierzy jednostkowej, zerowej, skalarnej - gdyż w momencie tworzenia są one inicjowane na stałe.
  2. błąd wykonania - np.:
    • nie można modyfikować elementu nad głowną przekatną dolnej macierzy trójkątnej, ale pozostałe elementy można
    • nie można przypisać wartości elementowi macierzy wstęgowej, nie należącemu do głównej przekątnej lub jednej z jego wstęg, określonych przy definicji danego obiektu klasy.
  3. brak sygnalizacji niezgodności - np.:
    • możliwość definicji macierzy o innej liczbie wierszy, niż kolumn, dla macierzy, które z definicji powinny być kwadratowe (np. macierz jednostkowa, trójkątna)
    • mozna przypisac elementom na głównej przekątnej macierzy hermitowskiej wartosci zespolone o niezerowej części urojonej - mimo, ze definicja macierzy Hermitowskiej nakazuje

wartości rzeczywiste na głównej przekątnej.

Typy

Biblioteka uBLAS udostępnia następujące typy macierzy:

  1. Matrix - podstawowy kontener dla macierzy gęstych
    • Identity Matrix - macierz jednostkowa. Jest macierzą kwadratową (wymiary M=N).
    • Zero Matrix - macierz zerowa
    • Scalar Matrix - macierz skalarna
  2. Triangular Matrix - macierz trójkątna
  3. Symmetric Matrix - macierz symetryczna
  4. Hermitian Matrix - macierz Hermitowska
  5. Banded Matrix - macierz wstęgowa
  6. Sparse Matrix - macierz rzadka
    • Mapped Matrix - macierz odwzorowania
    • Compressed Matrix - macierz skompresowana
    • Coordinate Matrix - macierz koordynacji

Matrix

Szablon klasy: matrix<T, F, A>
  • T - typ macierzy
  • F - organizacja zapisu
    • row_major (domyslne) - wierszami
    • column_major - kolumnami
  • A - typ tablicy zapisu:
    • unbounded_array<T> (domyslne) - brak ograniczenia na rozmiar macierzy podawany przy definicji
    • bounded_array<T, N, ALLOC> - alokacja macierzy na stercie, macierz moze miec ⇐ N elementow; ALLOC - domyślnie std::allocator
    • std::vector<T>

Inne typy macierzy gęstych - typy stałe, nie można modyfikowac ich elementow. Tak jak klasa matrix<>, inne klasy również obsługują rozszerzoną deklarację z kilkoma parametrami szablonu klasy.

Identity Matrix

Dla wymiarów macierzy NxN, 0 <= i < N, 0 <= j < N
  • jesli i <> j to id(i,j) = 0
  • jesli i=j to id(i,i) = 1.

Zero Matrix

Wszystkie elementy mają wartosc 0. Próba modyfikacji dowolnej wartości macierzy w kodzie kończy sie błędem kompilacji.

Scalar Matrix

Każdy element macierzy to stała wartość, podana w konstruktorze (domyslnie 0). Próba modyfikacji dowolnej wartości macierzy w kodzie kończy się błędem kompilacji.

Triangular Matrix

Jest to rodzaj macierzy kwadratowej, jednak w klasie należy definiować rozmiar obydwu wymiarow.

Dla wymiarów macierzy NxN, 0 <= i < N,0 <= j < N
  • jesli dla i<j: id(i,j)=0 - dolna macierz trójkątna (lower)
    • jesli dodatkowo id(i,i) = 1 - dolna jednostkowa macierz trójkątna (unit_lower)
  • jesli dla i>j: id(i,j)=0 - gorna macierz trojkątna (upper)
    • jesli dodatkowo id(i,i) = 1 - gorna jednostkowa macierz trójkątna (unit_upper)
Szablon klasy: triangular_matrix<T, F1, F2, A>
  • F1 - typ macierzy: lower (domyślny), unit_lower, upper, unit_upper
  • F2 - organizacja zapisu, jak F w matrix<T, F, A>

Triangular Adaptor - adapter dla macierzy innych typów

Zmiana wartości w macierzy adaptowanej jest odzwierciedlona w obiekcie klasy adaptera. Tu także próba zmiany wartości na głównej przekątnej dla typu macierzy unit_lower lub unit_upper kończy się wyjątkiem.

Szablon klasy: triangular_adaptor<M, F>
  • M - typ adaptowanej macierzy

Symmetric Matrix

Jest to rodzaj macierzy kwadratowej, jednak w klasie należy definiować rozmiar obydwu wymiarów.

Dla wymiarów macierzy NxN, 0 <= i < N,0 <= j < N
  • id(i,j)=id(j,i)
    • jeśli dodatkowo dla i<j: id(i,j)=0 - dolna macierz symetryczna (lower)
    • jeśli dodatkowo dla i>j: id(i,j)=0 - górna macierz symetryczna (upper)
Szablon klasy: symetric_matrix<T, F1, F2, A>
  • F1 - typ macierzy: lower (domyslny), upper
  • F2 - organizacja zapisu, jak F w matrix<T, F, A>

Symmetric Adaptor - adapter dla macierzy innych typów

Zmiana wartości w macierzy adaptowanej jest odzwierciedlona w obiektcie klasy adaptera.

Szablon klasy: symmetric_adaptor<M, F>
  • M - typ adaptowanej macierzy

Hermitian Matrix

Jest to rodzaj macierzy kwadratowej, jednak w klasie należy definiować rozmiar obydwu wymiarow.

Szablon klasy: hermitian_matrix<T, F1, F2, A>
Dla wymiarów macierzy NxN, 0 <= i < N,0 <= j < N
  • id(i,j) = id'(j,i), gdzie id' = liczba sprzężona z id

Implementacja macierzy Hermitowskiej w uBLAS dopuszcza umieszszczenie na głównej przekątnej macierzy wartości zespolonych o niezerowej cześci urojonej mimo, ze nie jest to macierz Hermitowska.

Banded Matrix

Wszystkie elementy macierzy wstęgowej są zerowe poza główna przekątną i określonymi przekątnymi (wstęgami).

Dla wymiarów macierzy MxN, 0 <= i < M,0 <= j < N, l-liczba niezerowych dolnych przekątnych (tych pod przekątna główną), u-liczba górnych przekątnych
  • jesli i>j+l lub i<j-u to id(i,j)=0
Szablon klasy: banded_matrix<T, F, A>

Sparse Matrix

Poniższe klasy macierzy rzadkich różnią się tylko sposobem przechowywania macierzy.

Mapped Matrix

Kontenerem jest mapa (indeks elementu, wartość).

Dla wymiarów macierzy MxN, 0 <= i < M,0 <= j < N
  • odwzorowuje _niezerowe_ elementy id(i,j) na elementy kontenera typu podanego jako trzeci parametr (A) szablonu klasy.
Szablon klasy: mapped_matrix<T, F, A>
  • F - organizacja zapisu:
    • row_major (domyslne) - wierszami, id(i,j) → (i*n+j)-ty element kontenera
    • column_major - kolumnami, id(i,j) → (j*n+i)-ty element kontenera
  • A - typ kontenera zapisu:
    • map_array<std::size_t, T>
    • map_std<std::size_t, T>, czyli std::map<std::size_t, T>

Compressed Matrix, Coordinate Matrix

Osobne kontenery dla indeksów elementu i wartości.

Szablon klasy: compressed_matrix<T, F, IB, IA, TA>
  • IB - baza indeksu skompresowanego kontenera (domyślnie: 0)
  • IA - typ kontenera indeksow elementow macierzy
  • TA - typ kontenera wartosci elementow
    • unbounded_array<T> - domyslnie: unbounded_array<std::size_t>
    • bounded_array<T>
    • std::vector<T>

Kod źródłowy

Poniższy kod prezentuje zastosowanie przykładowych klas biblioteki uBLAS. Można go pobrać tu:

ublas_repr.cpp

// Zbigniew Fabijanski, H1ISIII
 
// ZPR - praca domowa - Zad.27 - Biblioteki boost - boost::uBLAS (reprezentacje macierzy).
 
 
 
#include <boost/numeric/ublas/matrix.hpp> // Macierz gesta.
 
#include <boost/numeric/ublas/triangular.hpp> // Macierz trojkatna.
 
#include <boost/numeric/ublas/symmetric.hpp> // Macierz symetryczna.
 
#include <boost/numeric/ublas/hermitian.hpp> // Macierz Hermitowska
 
#include <boost/numeric/ublas/banded.hpp> // Macierz wstegowa.
 
#include <boost/numeric/ublas/matrix_sparse.hpp> // Macierze rzadkie.
 
 
 
#include <boost/numeric/ublas/io.hpp> // Operatory << i >> dla klas macierzy.
 
 
 
 
 
int main () {
 
	// import przestrzeni nazw
 
	using namespace boost::numeric::ublas;
 
	using cout;
 
	using endl;
 
 
 
	// --------------------------------------- Matrix ---------------------------------------
 
	{
 
		// Definicja macierzy gestej o 2 wierszach i 3 kolumnach.
 
		matrix<double> m (2, 3); // Typ rownowazny: matrix<double, row_major, unbounded_array<double> >
 
		try {
 
			cout << "Proba deklaracji macierzy 3x3 zapisane w kontenerze o rozmiarze 8: " << endl;
 
 
 
			// Nieprawidlowa definicja klasy z wieksza liczba elementow (3*3=9), niz okreslono w typie kontenera przechowujacego zawartosci macierzy (8).
 
			// matrix<double, row_major, bounded_array<double, 8> > mb (3, 3);
 
			// Taki rodzaj deklaracji jest rowniez dostepny dla wszystkich innych klas macierzy.
 
			matrix<double, row_major, bounded_array<double, 8> > mb (3, 3); // Ta definicja wygeneruje wyjatek blednego rozmiaru przydzielonej na zawartosc macierzy sterty.
 
		}
 
		catch (std::exception &e){
 
			cout << "Exception: " << e.what() << endl;
 
		}
 
 
 
		// Przypisanie do macierzy wartosci kolejny liczb naturalnych - wierszami.
 
		for (unsigned i = 0; i < m.size1 (); ++ i) // dla kazdego wiersza macierzy
 
			for (unsigned j = 0; j < m.size2 (); ++ j) // dla kazdej kolumny macierzy
 
				m (i, j) = 3 * i + j;
 
 
 
		// Wyswietlenie zawartosci macierzy - przeciazony operator<< dla klas macierzy.
 
		cout << "Macierz gesta:" << endl << m << endl;
 
	}
 
 
 
	// Macierz jednostkowa
 
	{
 
		// W definicji nastepuje automatyczne inicjowanie _stalych_ wartosci macierzy.
 
		identity_matrix<double> m (3); // Podajemy jedyny wymiar macierzy, poniewaz macierz jednostkowa jest z definicji kwadratowa (M=N).
 
		cout << "Macierz jednostkowa:"  << endl << m << endl;
 
 
 
		// Odkomentowanie ponizszej linijki skutkuje bledem kompilacji, bez wzgledu na to, czy naruszymy reguly wartosci elementow macierzy jednostkowej, czy nie.
 
		// m(0,0) = 1;
 
	}
 
 
 
	// Macierz zerowa
 
	{
 
		// Tu rowniez inicjalizacja wszystkich elementow - na wartosci zerowe.
 
		zero_matrix<double> m (3,4); // Mozliwy takze konstruktor z 1 argumentem - macierz kwadratowa.
 
		cout << "Macierz zerowa:"  << endl << m << endl;
 
	}
 
 
 
	// Macierz skalarna
 
	{
 
		scalar_matrix<double> m(3,3,4); // Macierz o wymiarach 3x3, wypelniona wartosciami 4.
 
		cout << "Macierz skalarna:"  << endl << m << endl;
 
	}
 
 
 
 
 
	// --------------------------------------- Triangular Matrix ---------------------------------------
 
	{
 
		// Wypelnienie kolejnymi liczbami tylko dolnej czesci macierzy i glownej przekatnej, gdyz jest to macierz dolna,
 
		// a wiec elementy nad glowna przekatna maja wartosci 0 przypisane na stale w definicji.
 
		triangular_matrix<double, lower> tml (3, 4);
 
		for (unsigned i = 0; i < tml.size1 (); ++ i) // dla kazdego wiersza macierzy
 
			for (unsigned j = 0; j <= i; ++ j) // dla kazdej kolumny macierzy, ale dla elementow pod glowna przekatna
 
				tml (i, j) = 3 * i + j;
 
		cout << "Dolna macierz trojkatna:" << endl << tml << endl;
 
 
 
		// Definicja gornej jednostkowej macierzy trojkatnej.
 
		triangular_matrix<double, unit_upper> tmup (3, 3);
 
		// Wypelnienie liczbami tylko elementow nad glowna przekatna macierzy.
 
		for (unsigned i = 0; i < tmup.size1 (); ++ i) // dla kazdego wiersza macierzy
 
			// Wartosci na glownej przekatnej zostaly juz zainicjowane przy definicji macierzy,
 
			// dlatego petla wewnetrzna od j=i+1, a nie j=i.
 
			for (unsigned j = i+1; j < tmup.size2 (); ++ j) // dla kazdej kolumny macierzy, ale dla elementow nad glowna przekatna
 
				tmup (i, j) = 3 * i + j;
 
 
 
		cout << "Gorna jednostkowa macierz trojkatna:" << endl << tmup << endl;
 
 
 
		// Proba zmiany wartosci na glownej przekatnej macierzy jednostkowej.
 
		try {
 
			cout << "Proba zmiany wartosci na glownej przekatnej gornej jednostkowej macierzy trojkatnej:" << endl;
 
			tmup(0,0)=-1; // Ta linijka rzuci wyjatek, poniewaz w gornej _jednostkowej_ macierzy trojkatnej
 
							// mozemy zmieniac tylko wartosci pod glowna przekatna.
 
		}
 
		catch (std::exception &e){
 
			cout << "Exception: " << e.what() << endl;
 
		}
 
 
 
	}
 
	// Triangular Adaptor
 
	{
 
		// Definicja macierzy gestej - adaptowanej.
 
		matrix<double> m(3,3);
 
		for (unsigned i = 0; i < m.size1 (); ++ i) // dla kazdego wiersza macierzy
 
			for (unsigned j = 0; j < m.size2 (); ++ j) // dla kazdej kolumny macierzy
 
				m (i, j) = 3 * i + j + 1; // Przypisanie macierzy adaptowanej kolejnych liczb naturalnych.
 
 
 
		// Definicja dolnego adaptera macierzy gestej.
 
		triangular_adaptor<matrix<double>, lower> tal (m);
 
		cout << "Dolny adapter trojkatny macierzy : " << m << " to: " << endl;
 
		cout << tal << endl; // Elementy nad glowna przekatna maja wartosc 0.
 
	}
 
 
 
	// --------------------------------------- Symmetric Matrix ---------------------------------------
 
	{
 
		// Dolna macierz symetryczna. Wartosci nad glowna przekatna wskazuja na odpowiednie wartosci symetrycznych pod przekatna.
 
		symmetric_matrix<double, lower> sml (3, 3);
 
		// Wystarczy przypisac wartosci czesci macierzy po jednej stronie glownej przekatnej,
 
		//	gdyz elementy po drugiej stronie wskazuja na swoich symetrycznych odpowiednikow.
 
		for (unsigned i = 0; i < sml.size1 (); ++ i) // dla kazdego wiersza macierzy
 
			for (unsigned j = 0; j < /*i*/sml.size2 (); ++ j) // dla kazdej kolumny macierzy, ten sam efekt, co dla petli z warunkiem j <= i
 
				sml(i, j) = 3 * i + j + 1;
 
		// Modyfikacja wartosci id(i,j) powoduje modyfikacje takze id(j,i).
 
		sml(1, 0)=-1; // Ten sam efekt, co instrukcja sml(0,1)=-1;
 
		cout << "Dolna macierz symetryczna: " << endl << sml << endl;
 
	}
 
	// Symmetric Adaptor
 
	{
 
		// Macierz adaptowana.
 
		matrix<double> m(3,3);
 
		for (unsigned i = 0; i < m.size1 (); ++ i) // dla kazdego wiersza macierzy
 
			for (unsigned j = 0; j < m.size2 (); ++ j) // dla kazdej kolumny macierzy
 
				m (i, j) = 3 * i + j + 1;
 
 
 
		// Poniewaz adaptowanie przebiega w porzadku wierszowym, a nie kolumnowym,
 
		//	wartosci po gornej stronie glownej przekatnej wskazuja symetryczne wartosci spod glownej przekatnej, a nie odwrotnie.
 
		symmetric_adaptor<matrix<double> > sa (m); // Brak 2.argumentu klasy szablonu => wartosc domyslna (lower)
 
 
 
		// Dopiero tutaj widac roznice pomiedzy dolna a gorna macierza symetryczna.
 
		// Instrukcja zmiany wartosci adaptera zmienia oba symetryczne elementy obiektu adaptera macierzy.
 
		// Ale poniewaz jest to gorny adapter macierzy, w macierzy adaptowanej zmienia sie tylko element nad glowna przekatna macierzy.
 
		sa(1,0)=-1; // A dla macierzy adaptowanej m - ten sam efekt, co instrukcja sa(0,1)=-1;
 
		cout << "Dolny adapter symetryczny stworzonej z macierzy gestej: " << m << " to: " << endl;
 
		cout << sa << endl;
 
	}
 
	// --------------------------------------- Hermitian Matrix ---------------------------------------
 
	{
 
		// Deklaracja dolnej macierzy Hermitowskiej.
 
		hermitian_matrix<std::complex<double>, lower> hml (3, 3);
 
		for (unsigned i = 0; i < hml.size1 (); ++ i) { // dla kazdego wiersza macierzy
 
			for (unsigned j = 0; j < i; ++ j) // dla kazdej kolumny macierzy
 
				hml (i, j) = std::complex<double> (3 * i + j, 3 * i + j); // Wypelniamy macierzy liczbami zespolonymi (complex)
 
			hml (i, i) = std::complex<double> (4 * i, 0); // wartosci na glownej przekatnej
 
		}
 
		cout << "Dolna macierz Hermitowska:" << endl << hml << endl;
 
	}
 
	// Hermitian Adaptor - analogicznie do innych adapterow.
 
 
 
	// --------------------------------------- Banded Matrix ---------------------------------------
 
	{
 
		signed l=1, u=1; // l,u - ilosc niezerowych przekatnych pod,nad przekatna glowna
 
		banded_matrix<double> bm (3, 3, l, u); // l=1, u=1
 
		// Dla wszystkich wierszy.
 
		for (signed i = 0; i < signed (bm.size1 ()); ++ i) // dla kazdego wiersza macierzy
 
			// Dla kolumn, ktorych indeks nalezy do przedzialu [-l,u) wzgledem
 
			for (signed j = std::max (i - l, 0); j < std::min (i + u, signed (bm.size2 ())); ++ j)
 
				bm (i, j) = 3 * i + j + 1;
 
		cout << "Macierz wstegowa:" << endl << bm << endl;
 
		//	bm(2,0)=0; // ta instrukcja generuje wyjatek
 
	}
 
	// Banded Adaptor - analogicznie do innych adapterow.
 
}

Linki zewnętrzne

reprezentacje_macierzy.1240945440.txt.gz · ostatnio zmienione: 2009/04/28 21:04 przez zfabijan