% ******************* MATEMATICKÝ SEMINÁŘ č. 2 ************************
% 2.1  ZÁKLADY TVORBY MATIC
% 2.2. PŘÍMÉ VYTVÁŘENÍ MATIC VÝČTEM PRVKŮ
% 2.3. ZÍSKÁNÍ INFORMACÍ O DOSUD ALOKOVANÝCH MATICÍCH
% 2.4. GENEROVÁNÍ MATIC S JEDNODUCHOU STRUKTUROU
% 2.5. ÚDRŽBA MATIC
% 2.6. PRÁCE S ŘÍDKÝMI MATICEMI
%
% Copyright (C) 1996-2003 by V. Veselý (Masaryk University Brno, Czech Republic)
%
% Dávka je kompletně upravena pro menu-systém.

echo on
more on
format compact
clc
%======================================================================
% 2.1 ZÁKLADY TVORBY MATIC
%----------------------------------------------------------------------
%% Jméno matice = posloupnost písmen a číslic (včetně znaku podtrh) začínající
%% písmenem.
%% Matice se deklarují automaticky při přiřazení
%% Typy matic:
%% - číselná - reálná
%%           - komplexní
%% - logická
%% - textová
%%
%% Rozsáhlé matice s převahou nulových prvků (tzv. řídké matice)
%% lze zpracovávat pomocí standardního toolboxu sparfun.
%% U těchto matic se ukládají pouze nenulové prvky spolu s informací
%% o jejich pozici v matici.
   help sparfun
keyboard

%% Některá jména jsou rezervována pro předdefinované matice:
%% i,j  ... imaginární jednotka 
%% pi   ... Ludolfovo číslo pi 
%% eps  ... strojová přesnost reálných čísel v pohyblivé řádové čárce
%%          definovaná jako rozdíl mezi 1 a nejbližším větším číslem
%% Inf   ... +nekonečno
%% NaN   ... neurčitá hodnota (Not-a-Number)
%%
%% další viz help matlab\elmat
%%
%% POZOR! Pokud např. i přiřadíme nějaké číslo, bude mít při vyhodnocování
%% toto přiřazení přednost před tím, že i je původně imaginární jednotka. 
  format long
  i,j   % imaginární jednotka (POZOR NA PŘEPSÁNÍ!)
  pi    % Ludolfovo číslo pi 
  eps   % strojová přesnost reálných čísel v pohyblivé řádové čárce
        % definovaná jako rozdíl mezi 1 a nejbližším větším číslem
  realmax % maximální číslo v pohyblivé řádové čárce
  realmin % minimální číslo v pohyblivé řadové čárce
  ans   % proměnná answer pro ukládání implicitních výsledků
%  Tyto matice jsou tzv. vestavěné funkce. 
pause;
% Sledujte následující ukázku:               
  format short
eps                                                                             
eps=9                                                                           
% vytvoří se proměnná eps a vestavěná funkce eps se stane nepřístupnou          
clear eps       % proměnnou eps zruším                                          
eps             % funkce eps je znovu přístupná                                 
pause;         
%----------------------------------------------------------------------
   Inf  % +nekonečno
   1/0
  -1/0
   NaN  % neurčitá hodnota (Not-a-Number)
   0/0
keyboard;

pause;
%----------------------------------------------------------------------
  v=computer % jméno počítače, na němž běží MATLAB
pause;
%----------------------------------------------------------------------
% nargin  % počet vstupních parametrů skutečně předaných při volání funkce       
% nargout % počet výstupních parametrů skutečně požadovaných při volání funkce   
          % Uplatní se jen v těle funkce (funkčního m-souboru)                   
pause;
help nargin                                                                      
help nargout                                                                      
% Další funkce pro práci s argumenty funkcí viz help matlab\lang                 
keyboard;

%======================================================================
% 2.2. PŘÍMÉ VYTVÁŘENÍ MATIC VÝČTEM PRVKŮ MEZI [  ]:
%----------------------------------------------------------------------
%% Prvky vytvářené matice napíšeme mezi [ ]
%%    - prvky v řádku oddělujeme mezerou nebo čárkou (,)
%%    - řádky oddělujeme středníkem (;)
%% 
%% Příklad: A=[1,2,3;4,5,6] dá matici A = 1 2 3 
%%                                        4 5 6
%%          B=['Matematicky';'seminar    '] dá matici B = Matematicky
%%                                                        seminar  
% prázdná matice:
   E=[]     
%----------------------------------------------------------------------
% reálné skaláry:
  r1=3, r2=3., r3=.3, r4=3.14, r5=0.314e1, r6=0.314E1,
pause;
%----------------------------------------------------------------------
% komplexní skalár:
  c=3.14+2*i,
keyboard;

%----------------------------------------------------------------------
% matice reálná:
  R1=[1 r1 r2+r3;2,3 4], R2=[1,r1,r2+r3;2 3 4],
%----------------------------------------------------------------------
pause;
  A = [1 2;3 4], B=[5 6 7;8 9 10], C=[11 12 13 14 15;16 17 18 19 20]
pause;
%----------------------------------------------------------------------
% matice komplexní:
 c1=[1+j,2-i,3], c2=[c,1 2 3 4]
keyboard;

%----------------------------------------------------------------------
% Prvky matic mohou být maticové bloky i vypočtené maticovým výrazem:
  D1 = [A,B;C], D2=[A,B+R1;C]
pause;
%----------------------------------------------------------------------
% Rovněž lze vkládat i pseudohodnoty Inf, -Inf nebo NaN:
  D3 = [1, -Inf, 3, Inf+3, NaN-1]
keyboard

%----------------------------------------------------------------------
% matice textová:
  T1=['1.radek';'2.radek'], T2=[49 '.radek';'2.radek']
pause;
  ['pipnuti:',7]
%----------------------------------------------------------------------
pause;
   d='Dobry den, pratele' 
pause;
%----------------------------------------------------------------------
% Převod na číselnou matici:
  abs(d)
  RT1=abs(T1)
% nebo nověji (doporučuje se):
  double(T1)
pause;
% a zpět:
  TRT1=setstr(RT1)
% nebo nověji (doporučuje se):
  char(RT1) 
keyboard

%======================================================================
% 2.3. ZÍSKÁNÍ INFORMACÍ O DOSUD ALOKOVANÝCH MATICÍCH
%----------------------------------------------------------------------
%% Informace o vytvořených maticích je možno získat pomocí příkazů
%% who  ... seznam matic
%% whos ... seznam matic s informacemi o maticích
% nadefinujeme vzorové matice
A = [1 2;3 4], B=[5 6 7;8 9 10], C=[11 12 13 14 15;16 17 18 19 20]
c1=[1+j,2-i,3]
T1=['1.radek';'2.radek']
pause; 
  who;    % jen seznam
pause;
  whos;   % podrobný výpis
keyboard;

%% Rozměry matice:
%%  [m,n] = size(B)    Rozměry matice: m řádků a n sloupců
%%      m = size(B,1)  jen počet řádků
%%      n = size(B,2)  jen počet sloupců
%%      l = length(B)  = max(m,n), tj. u vektoru jeho délka
B=[5 6 7;8 9 10]
% Rozměry matice:
  [m,n] = size(B)    % Rozměry matice: m řádků a n sloupců
      m = size(B,1)  % jen počet řádků
      n = size(B,2)  % jen počet sloupců
      l = length(B)  % =max(m,n), tj. u vektoru jeho délka
keyboard


%% Výpis matice na displej ve formě textové tabulky:
%%  disp(A) 
%%  disp('primy vypis textu')
A = [1 2;3 4]
c1=[1+j,2-i,3]
T1=['1.radek';'2.radek']
% Výpis matice na displej ve formě textové tabulky:
  disp(A) 
  disp(c1) 
  disp(T1) 
  disp('primy vypis textu')
keyboard

%======================================================================
% 2.4. GENEROVÁNÍ MATIC S JEDNODUCHOU STRUKTUROU
%----------------------------------------------------------------------
%% Vektor, jehož (i+1) prvek vznikne přičtením konstanty k i-tému prvku, 
%% konstanta je pro všechna i stejná:  
%% r=m:n   = [m,m+1,m+2 ,...,n] 
%% r=m:k:n = [m,m+k,m+2k,...,n]
  10:15
  10:-1:5
  3.4:2:10
  a=6:5  
keyboard;

%% r=linspace(a,b,N) ... N-bodové ekvidistantní dělení intervalu [a,b]
%% r=linspace(a,b) = linspace(a,b,100)
  a=1; b=5; N=9; 
  linspace(a,b,N)
  a:(b-a)/(N-1):b
  linspace(b,a,N)
keyboard; 

%% r=logspace(a,b,N) ... N-bodové logaritmicko ekvidistantní dělení 
%%                       intervalu [10^a,10^b]   pro b~=pi  
%%                       intervalu [10^a,pi]     pro b==pi  
%% r=logspace(a,b) = logspace(a,b,50)
  a=1; b=5; N=5; 
  logspace(a,b,N)
  10.^(a:(b-a)/(N-1):b)
  logspace(b,a,N)
pause;
  logspace(a,pi,N)
  logspace(a,log10(pi),N)
  logspace(a-1,pi,N)
  logspace(a-1,log10(pi),N)
keyboard;


%% Předdefinované matice
%% G=zeros ... nulová matice 
%% G=ones  ... matice ze samých jedniček
%% G=eye   ... jednotková matice
%% G=rand  ... matice pseudonáhodných čísel rovnoměrně rozložených 
%%             v intervalu (0,1)
%% G=randn ... matice pseudonáhodných čísel s normálním rozložením N(0,1), tj.
%%             nulovou střední hodnotou a jednotkovou směrodatnou odchylkou
%% Rozměr generované matice je určen parametry funkce, např. pro zeros:
%% G=zeros(n)      ... čtvercová matice n x n
%% G=zeros(m,n)    ... obdélníková matice m x n
%% G=zeros([m,n])  ... obdélníková matice m x n, speciálně
%% G=zeros(size(A))... matice stejného rozměru jako A
  G=zeros(4)
  G=ones(2,5)
  G=eye([2,5])
pause
  G=rand(size(G))
  G=randn(size(G))
% Generování náhodné matice s rozložením N(5,10)
  5+10*randn(2,5) 
pause
% U rand a randn lze zadávat ještě speciální parametry ovlivňující způsob
% generování - viz help rand a help randn.
% V kombinací rand s příkazem round pro zaokrouhlování je možno pohodlně 
% generovat náhodnou celočíselnou matici s čísly v zadaném intervalu,
% např. matici 10 x 10 s čísly v intervalu [-3,12]: 
  round(15*rand(10))-3
keyboard; 
  

%% Diagonální matice
%% D=diag(d,p) ... diagonální matice s vektorem d na vedlejší diagonále
%%               na p-té pozici relativně k hlavní diagonále
%%               p=0 ... hlavní diagonála
%%               p>0 ... p-tá pozice nad hlavní diagonálou
%%               p<0 ..  p-ta pozice pod hlavní diagonálou
%% D=diag(d)=diag(d,0) ... diagonální matice s vektorem d v hlavní diagonále
%% Podobně z existující matice D lze extrahovat její diagonálu do sloupcového
%% vektoru s:
%% s=diag(D,p)           
%% s=diag(D)=diag(D,0)
  D=diag(1:3)
  diag(D)
pause
  D=diag(1:3,1)
  diag(D,1)
pause;
  D=diag(1:3,-1)
  diag(D,-1)  
pause;
% Jednotková matice 5 x 5 generovaná pomocí diag:
  diag(ones(1,5))
keyboard;
%======================================================================
% 2.5. ÚDRŽBA MATIC
%----------------------------------------------------------------------
%% Ukládání matic v binární formě a zpětné načtení:
%% příkazy save [soubor] [co] [volby]
%%         load [soubor] [volby]
%%         clear [co] ... smazání matic z paměti
%%
%% Pomocí příkazu load lze do MATLABu vkládat data z externích zdrojů.   
%% Pomocí příkazu save s parametrem -ascii lze data z MATLABu exportovat.
%%
%% Existují i další možnosti zadávání parametrů pro save, clear a load.
%% Rovněž existují další příkazy pro dokonalejší řádkový nebo formátovaný
%% vstup a výstup - viz help.
  A = [1 2;3 4], B=[5 6 7;8 9 10], C=[11 12 13 14 15;16 17 18 19 20]
  save allsaved     % uloží všechny matice do souboru allsaved.mat
  save              % uloží do implicitního souboru matlab.mat
  clear             % odstraní z paměti všechny matice
  who
pause
%----------------------------------------------------------------------
  load allsaved     % načte zpět všechny matice ze souboru allsaved.mat
  who
pause
%----------------------------------------------------------------------
  clear
  load              % načte zpět z implicitního souboru matlab.mat
  who
keyboard

%----------------------------------------------------------------------
  save absaved A B  % uloží jen matice A a B do souboru absaved.mat
  clear A B         % odstraní z paměti jen matice A a B
  who
pause
%----------------------------------------------------------------------
  load absaved      % načte zpět všechny matice ze souboru absaved.mat
  who
% Ukládání matic ve znakové formě a zpětné načtení:
  save bsaved.txt B -ascii  % uloží jen matici B do souboru bsaved.txt
  clear B                   % odstraní z paměti jen matici B
  who
pause
  type bsaved.txt
pause
%----------------------------------------------------------------------
  load bsaved.txt -ascii % načte zpět matici ze souboru bsaved.txt
                         % do proměnné se jménem bsaved (nikoliv B)
% nebo
% load bsaved.txt        % přípona souboru není .mat, takže soubor
                         % se považuje za textový
  who
keyboard

%----------------------------------------------------------------------
% Soubory s uloženými maticemi smažeme
  delete allsaved.mat
  delete absaved.mat
  delete matlab.mat
  delete bsaved.txt
pause;
%----------------------------------------------------------------------
  help load
pause;
%----------------------------------------------------------------------
  help clear
keyboard

%% Při opakovaném rušení a vytváření matic během práce s MATLABem
%% dochází k fragmentaci paměti - volné "díry" v paměti , které nejsou 
%% dost velké pro alokaci dalších větších matic (chybové hlášení OUT OF 
%% MEMORY). Fragmentaci lze odstranit příkazem pack, který "díry" spojí 
%% do souvislého volného bloku, což dává šanci pro další alokace.
  help pack
keyboard

%======================================================================
% 2.6 PRÁCE S ŘÍDKÝMI MATICEMI
%----------------------------------------------------------------------
%% Řídké matice obsahují jen malý počet nenulových prvků.
%% K uchování reálné řídké matice typu m x n s nnz nenulovými prvky se 
%% použijí 3 pole:
%%
%% - pole délky 8*nnz bytů pro nenulové prvky matice
%% - pole délky 4*nnz bytů pro řádkové indexy nenulových prvků
%% - pole délky 4*n   bytů pro ukazatele na začátky jednotlivých sloupců
%%
%% V případě řídké matice komplexních čísel přibude ještě jedno pole 
%% délky 8*nnz bytů pro imaginární složky nenulových prvků.
%% Řídkou matici vytváříme pomocí příkazu
%%
%%   S=sparse(i,j,s,m,n)
%%
%% i     ... vektor řádkových indexů nenulových koeficientů (délky nnz)  
%% j     ... vektor sloupcových indexu nenulových koeficientů (délky nnz)  
%% s     ... vektor nenulových prvků (délky nnz) 
%% m     ... počet řádků matice S
%% n     ... počet sloupců matice S
%%
%% Platí S(i(k),j(k))=s(k), k=1,...,nnz.
%% Existuje několik zjednodušení :
%%
%%   S=sparse(i,j,s) ... pak n=max(i), m=max(j)
%%   S=sparse(m,n)   ... pak S je prázdná matice
%%
%% Argument s a jeden z argumentů i,j mohou být skaláry. V tom případě jsou
%% skaláry expandovány do vektoru tak, aby všechny 3 první argumenty měly
%% stejnou délku.
%%
%%   S=sparse(A) ... převádí plnou matici na řídkou.
%%   A=full(S)   ... převádí řídkou matici na plnou.
%%
%% Další příkazy :
%% speye(m,n) ... řídká jednotková matice typu m x n
%% nzmax(A)   ... počet paměťových míst alokovaných pro nenulové prvky matice A
%% nnz(A)     ... počet nenulových prvků matice A, nnz <= nzmax
%% Pro další příkazy použijte help sparfun
% Příklad 1
% Vytvoříme čtvercovou řídkou matici, která má na hlavní diagonále 2 a na
% dvou sousedních diagonálách -1. K přehlednému čtení řídké matice použijeme
% příkaz full
n=5;       % malá úloha
S=sparse(2:n,1:n-1,-1,n,n), full(S)
S=S+S', full(S)
S=S+sparse(1:n,1:n,2), A=full(S)
nzmax(S),nnz(S)
nzmax(A),nnz(A)
whos S A
pause;     % větší úloha
n=100;
S=sparse(2:n,1:n-1,-1,n,n); S=S+S'; S=S+sparse(1:n,1:n,2); A=full(S);
whos S A
clear A
pause;
% Příklad 2
% Vytvoříme čtvercovou řídkou blokově diagonální matici řádu N=n*n tvaru
%
%             | B C O O ...            |
%             | C B C O ...            |
%             | O C B C ...            |
%       S  =  |          :             |
%             |            ... C B C O |  
%             |            ... O C B C |
%             |            ... O O C B |
%
% kde B=-I je diagonální matice řádu n s -1 na diagonále a C je tridiagonální
% matice řádu n s 4 na hlavní diagonále a s -1 na první naddiagonále a poddiagonále.
n=3; N=n^2;        % malá úloha
S1=sparse(n+1:N,1:N-n,-1,N,N),       full(S1)
S1=S1+sparse(2:N,1:N-1,-1,N,N),      full(S1)
S1=S1+sparse(n+1:n:N,n:n:N-n,1,N,N), full(S1)
S1=S1+S1',                           full(S1)
S1=S1+sparse(1:N,1:N,4,N,N),       A=full(S1)
nzmax(S1),nnz(S1)
nzmax(A),nnz(A)
whos S1 A
pause; n=20; N=n^2;        % větší úloha
S=sparse(n+1:N,1:N-n,-1,N,N);  
S=S+sparse(2:N,1:N-1,-1,N,N);  
S=S+sparse(n+1:n:N,n:n:N-n,1,N,N); 
S=S+S';                        
S=S+sparse(1:N,1:N,4,N,N);
A=full(S);
nzmax(S),nnz(S)
nzmax(A),nnz(A)
whos S A
clear A
keyboard;

%% Řídké matice s nenulovými prvky v diagonálách lze snadno vytvářet 
%% pomocí příkazu
%%
%%   S=spdiags(B,d,m,n)
%%
%% Chceme-li vytvořit matici S typu m x n s prvky na p diagonálách, pak:
%% B   je matice typu q x p, kde q=min(m,n). Sloupce B vytvoří diagonály S.
%% d   je celočíselný vektor délky p, jehož prvky určují diagonály. Přitom 
%%     d(k)=0 označuje hlavní diagonálu,
%%     d(k)=l > 0 l-tou naddiagonálu a
%%     d(k)=l < 0 l-tou poddiagonálu.
%%
%% Některé prvky z prvních a posledních řádků matice B zůstanou nevyužity:
%% pro m >= n umístíme vektor B(:,k) do l=d(k)-té diagonály tak,
%%            aby prvek B(1,k) ležel v prvním sloupci; tak se může stát,
%%            že budou nevyužity pro l > 0 některé počáteční a pro l < 0 
%%            některé koncové prvky vektoru B(:,k)
%% pro m <  n umístíme vektor B(:,k) do l=d(k)-té diagonály tak,
%%            aby prvek B(1,k) ležel v prvním řádku; tak se může stát,
%%            že budou nevyužity pro l > 0 některé koncové a pro l < 0 
%%            některé počáteční prvky vektoru B(:,k)
B=[-31:-1:-35;-21:-1:-25;-11:-1:-15;1:5;11:15;21:25;31:35]',d=-3:3
full(spdiags(B,d,5,5))     % m = n
full(spdiags(B,d,7,5))     % m > n
full(spdiags(B,d,5,7))     % m < n
pause;
% Příklad
% Vytvoříme čtvercovou řídkou blokově diagonální matici řádu N=n*n tvaru
%
%             | B C O O ...            |
%             | C B C O ...            |
%             | O C B C ...            |
%       S  =  |          :             |
%             |            ... C B C O |  
%             |            ... O C B C |
%             |            ... O O C B |
%
% kde B=-I je diagonální matice řádu n s -1 na diagonále a C je tridiagonální
% matice řádu n s 4 na hlavní diagonále a s -1 na první naddiagonále a poddiagonále.
% Tentokrát budeme příklad řešit pomocí spdiags. 
n=3; N=n^2;        % malá úloha
e=ones(N,1);      % sloupec jedniček
S2=spdiags([-e -e 4*e -e -e],[-n,-1,0,1,n],N,N); full(S2)
i=n+1:n:N;
S2=S2+sparse(i,i-1,1,N,N)+sparse(i-1,i,1,N,N); full(S2)
nzmax(S2),nnz(S2)
whos S2 
% Všimněte si, že matice S2 zabírá více paměti než matice S1. To je dáno
% postupem jejího vytváření. Vytvořme nyní ještě matici S3 a uvidíme, že
% spotřebovává stejný počet paměťových míst jako matice S1.
S3=spdiags([-e -e],[-n,-1],N,N);
S3=S3+sparse(i,i-1,1,N,N); S3=S3+S3';
S3=S3+spdiags(4*e,0,N,N); full(S3)
nzmax(S3),nnz(S3)
whos S3 

%================================= KONEC ==============================
%
%
%%
more off
echo off
