Warning
This page is located in archive. Go to the latest version of this course pages. Go the latest version of this page.

HW 04 - Maticové počty

Termín odevzdání 22.5.2022 23:59 CEST
Možný bodový zisk až 9b (3+3+3)
Počet uploadů 10

Zadání

Napište modul, který bude definovat strukturu matic a bude s nimi provádět různé operace. Matice musí uchovány v instancích objektů třídy Matrix. Část struktury třídy “Matrix” a rozhraní funkcí určených k implementaci je předem dané. Součástí zadání jsou 3 soubory zdrojových kódů:

  • main.cpp - kód hlavního programu, který využívá (testuje) jednotlivé funkce, jež májí být implementovány. Tento soubor se neodevzdává, nemusíte ho tedy nijak upravovat. Využijte ho pouze k testování vašich zdrojových kódů.
  • matrix.hpp - hlavičkový soubor knihovny. Obsahuje povinnou část třídy Matrix a deklaraci funkcí, které je třeba implementovat. Tento soubor lze upravit, nicméně rozhraní funkcí musí být zachováno tak, jak je. Můžete ovšem přidávat deklarace vašich funkcí, případně si vylepšit třídu Matrix. Soubor rovněž definuje výjimky, které by vaše funkce měly vyvolávat, při špatném zadání.
  • matrix.cpp - zdrojový kód knihovny. Zatím obsahuje pouze prázdné funkce. Vaším úkolem je doplnit těla funkcí tak, aby celý program korektně fungoval.

Testování probíhá ve dvou úrovních, označovaných L1 a L2, pro každou z úrovní je třeba naprogramovat některé z funkcí uvedených v hlavičkovém souboru matrix.hpp. V komentářích hlavičkového souboru je uvedeno, do které úrovně funkce patří.

Úroveň L1 je ohodnocena 3 body, úroveň L2 ohodnocena taktéž 3 body. Obě úrovně je potřeba splnit.

Podoba třídy Matrix

Třída Matrix musí obsahovat proměnné s viditelností public:

nrows počet řádků matice, může nabývat hodnot nrows>=0
ncols počet sloupců matice , může nabývat hodnot ncols>=0

Data matice uchovejte v libovolné vhodné formě. Je výhodné využít knihovnu standadních šablon.

Třída Matrix definovat následující konstruktory:

Matrix(int rows, int cols); Vytvoří matici o počtu řádků rows a počtu sloupců cols naplněnou nulami.
Matrix(int rowscols=0); Vytvoří čtvercovou matici o velikosti rowscols naplněnou nulami. Výchozí hodnotou je matice o velikosti 0x0.
Matrix(const Matrix &m); Kopírující konstruktor.
Při pokusu o vytvoření matice se záporným rozměrem dojde k vyvolání výjimky matrix_negative_size.
U kopírujícího konstruktoru dejte pozor, aby zkopírovaná a původní matice nevyužívaly stejný paměťový prostor. Pokud by se tak stalo, při úpravě jedné z matic by se upravila i ta druhá.
Bude-li to potřeba, implementujte i destruktor třídy Matrix

Pro jednotlivé úrovně testování je třeba implementovat následující funkce a operátory třídy Matrix:

Úroveň L1
Funkce/Operátor Popis Výjimky
void Matrix::zeros() Nastaví všechny prvky dané matice na hodnotu 0. Žádné
void Matrix::uniform(value element) Nastaví všechny prvky dané matice na hodnotu element. Žádné
void Matrix::eye() Vytvoří matici identity - prvky na hlavní diagonále mají hodnotu 1, ostatní hodnotu 0. Pokud není matice čtvercová, doplní se zbytek nulami. Žádné
void Matrix::bias(value b) Pričte ke každému prvku matice hodnotu b. Žádné
bool operator == (const Matrix & m) Operátor porovnání dvou matic. Vrací true pouze při shodě rozměrů matic i všech prvků. Žádné
Matrix & operator=(const Matrix &m) Operator přiřazení celé matice. Žádné
value Matrix::operator () (int row, int col) const Náhodný přístup - čtení. Vrací prvek matice na řádku 'row' a ve sloupci 'col' (indexováno od nuly). std::out_of_range(“Row index is out of range”), při překročení šířky matice, std::out_of_range(“Column index is out of range”) při překročení výšky matice. Při překročení obou rozměrů dochází k vyvolání první z výjimek.
value & Matrix::operator () (int row, int col) Náhodný přístup - zápis. Vrací adresu prvku matice na řádku 'row' a ve sloupci 'col' (indexováno od nuly). std::out_of_range(“Row index is out of range”), při překročení šířky matice, std::out_of_range(“Column index is out of range”) při překročení výšky matice. Při překročení obou rozměrů dochází k vyvolání první z výjimek.
Úroveň L2
Funkce/Operátor Popis Výjimky
void Matrix::scale(value s) Vynásobí každý prvek matice hodnotou s. Žádné
void Matrix::transpose() Transponuje matici. Žádné

Funkce a operátory mimo třídu Matrix

Pro jednotlivé úrovně testování je třeba implementovat následující funkce a operátory mimo třídu Matrix:

Úroveň L1
Funkce/Operátor Popis Výjimky
std::ostream & operator « (std::ostream & os, const Matrix & m) Výpis matice m do výstupního proudu. Vypisují se jednotlivé prvky matice po řádcích. Pro každou hodnotu je rezervováno 5 míst, za každým číslem je mezera (i na konci řádku). Na konci matice je newline. Pokud matice neobsahuje žádný prvek (nějaký z rozměrů je nulový), vypíše se pouze std::endl Žádné
void loadMatrixFile(Matrix &m, std::string fname) Načtení matice m ze souboru se jménem fname. Formát souboru matice je definován níže.
Matrix operator + (const Matrix & lhs, const Matrix & rhs) Součet dvou matic se stejnými rozměry. matrix_bad_sizes při neshodě rozměrů matic.
Matrix operator + (const value & lhs, const Matrix & rhs) Přičtení skaláru ke každému prvku matice. Žádné
Matrix operator + (const Matrix & lhs, const value & rhs)
Matrix operator - (const Matrix & lhs, const Matrix & rhs) Rozdíl dvou matic se stejnými rozměry. matrix_bad_sizes při neshodě rozměrů matic.
Matrix operator - (const value & lhs, const Matrix & rhs) Odečtení matice od skaláru (rozdíl pro každý prvek). Žádné
Matrix operator - (const Matrix & lhs, const value & rhs) Odečtení skaláru od matice (rozdíl pro každý prvek). Žádné
Úroveň L2
Funkce/Operátor Popis Výjimky
Matrix operator * (const Matrix & lhs, const Matrix & rhs) Součin dvou matic. matrix_bad_sizes při nevhodných rozměrech.
Matrix operator * (const value & lhs, const Matrix & rhs) Součin matice a skaláru. matrix_bad_sizes při nevhodných rozměrech.
Matrix operator * (const Matrix & lhs, const value & rhs)
Matrix hadamard (const Matrix & lhs, const Matrix & rhs) Hadamardův součin - prvek po prvku (ekvivalent .* z Matlabu) matrix_bad_sizes při neshodě rozměrů matic.
Matrix power (const Matrix & m, unsigned int pow) Kladná mocnina čtvercové matice: power(A, 3) je ekvivalent A*A*A. matrix_bad_sizes při špatném rozměru matice
Funkce musí pracovat i když bude nějaký z rozměrů matice nulový. Např. součit matic 0x5 a 5×0 je matice rozměru 0x0
Nultou mocninou libovolné čtercové matice je matice identity. Privní mocninou je totožná matice.
Není nutné implementovat každou funkci nebo operátor od začátku. Často stačí chytře zavolat funkci, kterou již máte hotovou.
Ze souboru matrix.hpp nemažte deklarace funkcí, které nechcete nebo nemusíte implementovat (např. funkce úrovně L3)! Pokud smažete tyto deklarace, nebude možné zkompilovat main.cpp. Funkce, které neimplementujte, musí vracet návratovou hodnotu odpovídajícího datového typu (i když jinak nic nedělají).

Výjimky definované v matrix.hpp

Výjimky, které mají být vyvolány jsou v matrix.hpp definovány následovně:

// Vyjimka pri spatnych rozmerech matice pro danou operaci:
struct matrix_bad_sizes: public std::exception 
    {const char * what () const throw (){return "matrix_bad_sizes";}};
// Vyjimka pri zadani negativniho rozmeru
struct matrix_negative_size: public std::exception 
    {const char * what () const throw (){return "matrix_negative_size";}};
// Vyjimka pri chybe nacteni rozmeru matice
struct matrix_in_bad_header: public std::exception 
    {const char * what () const throw (){return "matrix_in_bad_header";}}; 
// Vyjimka pri chybe nacteni prvku matice
struct matrix_in_bad_body: public std::exception 
    {const char * what () const throw (){return "matrix_in_bad_body";}};
// Vyjimka pri otevirani souboru matice
struct cannot_open_file: public std::exception 
    {const char * what () const throw (){return "cannot_open_file";}};

Neupravujte definice výjimek! Pokud byste je změnili, nemusely by být při vyhodnocení korektně rozpoznány.

Vstupy programu

Program bude zavolán příkazem ./main -l1 nebo ./main -l2. Samotný program 'main' poté provádí řadu testů funkcí modulu 'matrix', který naprogramujete. V průběhu se program pokusí načíst několik matic ze souborů. Formát souboru matice je následující:

* Na prvním řádku jsou dvě čísla - počet řádků a počet sloupců. * Na dalších řádcích jsou po řádcích hodnoty prvků matice oddělené mezerami.

Příklad obsahu souboru matice:

4 6
  -54   -36   -37   -49    59   -33 
  -80    57   -93   -36    94    24 
  -48   -45   -55   -48   -98   -68 
   28    24   -31   -83   -89    75 

Při načítání soubodu musí být vyvolána výjimka když:

* když je chyba v řádku hlavičky - chybí číslo, nebo se tam objeví písmeno. * když chybí data - nějaký řádek je příliš krátký, nebo úplně chybí. * když se mezi data zatoulá písmeno

Nemusíte kontrolovat, zdanení řádek příliš dlouhý, nebo jestli nepřebývají řádky. Data navíc se ignorují. Testovací matice jsou k dispozici v balíčku zadání. Při náhodném testu se některé z matic mohou změnit.

Výstup programu

Výstupem programu je výpis testovacího protokolu. Příklady testovacích protokolů pro jednotlivé úrovně jsou dostupné v balíčku zadání. Některé testy vypisují celou matici, některé Pass nebo Fail, některé název výjimky, která byla vyvolána.

K výpisu celé matice je využitý vždy operátor «, který máte naprogramovat. Příklad výstupu celé matice:

   26   -57    99   -73 
   61    -8   -23    96 
   16    57    97    17 
   23    91   -95   -25 

Na konci každého z řádků výpisu matice je mezera.
V poskytnutém main.cpp můžete dohledat, jak je každý z testů proveden. U testů s výstupem Pass/Fail, byste vždy měli dojít k hodnotě Pass.
Testy úrovně L2 předpokládájí, že již byla splněna úroveň L1.

Náhodný test v BRUTE

Při náhodném testu jsou spuštěny stejné testy, pouze je náhodně změněn obsah některých souborů matic. Mohou se změnit i rozměry matic.

Bonus

Bonusovým zadáním je implementace funkcí úrovně označené L3.

BONUS: Úroveň L3
Funkce/Operátor Popis Výjimky
Matrix::Matrix(const std::vector<value> &v) Konstruktor, který vytvoří čtvercovou matici. Prvky na hlavní diagonále jsou prvky vectoru v, ostatní prvky matice jsou nulové. Pracuje jako funkce diag() v Matlabu. Žádné
std::vector<value> operator () (void) const Vrací vektor prvků na hlavní diagonále matice, ostatní prvky ignoruje. Pracuje jako funkce diag() v Matlabu. Žádné
void Matrix::changedim(int rows, int cols) Změní rozměry matice. Dojde buď ke korektnímu oříznutí, nebo doplnění nulami. matrix_negative_size při zadání záporné velikosti.
Matrix horzcat (const Matrix & lhs, const Matrix & rhs) Horizontální sloučení matic (ekvivalent [lhs, rhs] v Matlabu). matrix_bad_sizes při nevhodných rozměrech.
Matrix vertcat (const Matrix & top, const Matrix & bot) Vertikálnísloučení matic (ekvivalent [top; bot] v Matlabu). matrix_bad_sizes při nevhodných rozměrech.
Matrix blkdiag (const Matrix & lhs, const Matrix & rhs) Diagonální skládání matic. Vstupy musí byt čtvercové matice nebo skaláry (chovají se jako matice 1×1), zbytek je doplněn nulami. matrix_bad_sizes při nevhodných rozměrech.
Matrix blkdiag (const value & lhs, const Matrix & rhs)
Matrix blkdiag (const Matrix & lhs, const value & rhs)
Matrix blkdiag (const value & lhs, const value & rhs)
Matrix kronecker (const Matrix & lhs, const Matrix & rhs) Kroneckerův součin matic. Žádné
Definici Kroneckerova součinu můžete nalézt např. zde: https://mathworld.wolfram.com/KroneckerProduct.html
Způsob vyhodnocení je stejný, jako v případě povinných úrovní L1 a L2. Program main je však spuštěn příkazem ./main -l3

Odevzdání

Odevzdává se balík s jakýmkoliv počtem souborů cpp nebo hpp s tím, že hlavní soubor main.cpp není třeba připojovat, bude nahrazen standardním souboraem, který je přiložen v šabloně HW04.zip .

Povinné i bonusové zadání
Název v BRUTE HW04
Argumenty při spuštění -l1, -l2, -l3
Kompilace pomocí g++ -pedantic -Wall -Werror -std=c++17
Procvičované oblasti polymorfismus v C++, přetěžování operátorů, STL, hlavičkový soubor, algoritmizace
courses/b2b99ppc/hw/hw04.txt · Last modified: 2022/02/17 16:04 by nentvond