function [maticeSpojuDleToku,VsechnySpojeDletoku, UT, alternativaToku] = OptDleToku (pocatek, konec, BW, BWcel, pocetuzlu, BWpl,cenaza1pa, cenaza1pb, jednotkaBW, delka, cenaza1m, cenaza1b, upravaToku)

% n-file slouzi pro vypocet maximalniho toku v siti. V potaz se berou cesty
%mezi nejvzdalenejsimi uzly. Zjistime tok, spoj, ktery je nadbytecny pro
%dosazeni max. toku a spoje, jenz budou naopak vytizene, v krajnim pripade,
%pres svou kapacitu.
%pocatek - vektor pocatecnich uzlu
%konec - vektor koncovych uzlu uzlu
%BW - vektor kapacit spoju
%BWcel - celkova kapacita spoju do uzlu, zadavejte v Bps, Mbps, Gbps
%pocetuzlu - pocet uzlu site
%BWpl - kapacita spoje pristupove linky, zadavejte v Bps, Mbps, Gbps
%jednotkaBW - pouzita jedntoka kakacity, zadavejte Bps, Mbps, Gbps
%cenaza1pa - zadejte jednotkovou cenu za prepojeny paket
%cenaza1pb - zadejte jednotkovou cenu za pametovy blok
%delka - delka spoje, zadavejte v metrech
%cenaza1m, cenaza1b - zadejte jednotkovou cenu delky a kapacity
%upravaToku - hodnota zmeny toku toku ve spoji pri poddimenzovani(yadavat ve tvaru 1.15 pro 15 procent)
%[maticeSpojuDleToku,VsechnySpojeDletoku, UT, alternativaToku] = OptDleToku (pocatek, konec, BW, BWcel, pocetuzlu, BWpl,cenaza1pa, cenaza1pb, jednotkaBW, delka, cenaza1m, cenaza1b, upravaToku)

%pocitano pro transportni sit a maximum toho, kolik v ni muze proudit. do
%pristupovych linek smeruji pakety z bufferu.

disp('******************PARAMETRY OPTIMALIZACE DLE TOKU VE SPOJICH*************************')

if nargin ~= 13
    error('Spatny pocet vstupu')
end

delkaPocatek = length(pocatek);
delkaKonec = length(konec);
delkaDelka = length(delka);
delkaBW = length(BW');
delkaBWpl = length(BWpl');

if delkaPocatek ~= delkaKonec || delkaPocatek ~= delkaDelka || delkaPocatek ~= delkaBW
    error('Pocet prvku vektoru pocatek, konec, delka a BW musi byt stejny')
elseif delkaBWpl ~= pocetuzlu
    error('Pocet prvku vektoru BWpl musi byt stejny jako pocet uzlu')
end

[celkovacena,cenalinek,cenauzlu] = CelCenaSpoje (BW, BWcel, jednotkaBW, pocetuzlu, cenaza1m, cenaza1b, BWpl, cenaza1pa, cenaza1pb, delka);

BWt = BW'; %prevedeni na sloupcovy vektor

disp(sprintf('Vychozi toky ve spojich: %s',jednotkaBW))
spoj = sparse(pocatek,konec,BWt,pocetuzlu,pocetuzlu) %matice spoju
VsechnySpojeDletoku = spoj + zeros(pocetuzlu,pocetuzlu);

zdroje = pocetuzlu - 1;
tok = zeros(pocetuzlu,pocetuzlu); %budouci matice toku

for i = 1:zdroje
[MaxTok,TokVeSpoji,Rez] = graphmaxflow(spoj,i,pocetuzlu); %hleda max. toky
      tok = tok + TokVeSpoji; % a vytvari novou matici spoju na zaklade souctu nalezenych max. toku
     
end

disp(sprintf('Toky ve spojich po vypoctu max. toku: %s',jednotkaBW))
toky = sparse(tok) %zobrazeni matice souctu max. toku

delenec = max(tok(:)); %nalezeni maxima v matici toku

vychozimatice = zeros(pocetuzlu,pocetuzlu) + spoj; %prevedeni z ridke matice
vychozimatice(vychozimatice==0) = Inf * ones(size(find(vychozimatice==0))); %nahradi prvky rovnajici se 0 v matici vychozimatice hodnotami Inf
delitel = min(vychozimatice(:)); %nalezeni minima v matici vychozi matice

nasobek = delenec / delitel; %koeficient, kterym se nasobi matice toku
nasobtok = tok.* nasobek; %nasobeni matice max toku 

vychozimatice2 = zeros(pocetuzlu,pocetuzlu) + spoj;
nadbtok = nasobtok - vychozimatice2; %urceni nadbytecneho toku (zaporne hodnoty)
nadbtok(nadbtok >= 0) = 0 * ones(size(find(nadbtok >= 0))); %odstraneni vsech toku krom nadbytecneho
ind = find(nadbtok <= 0); %vyhlede vsechny prvky mensi nez 0
nadbtok(ind) = -nadbtok(ind); % a zmen jejich znamenko

%doslo k tomu, ze se kapacita daneho toku nezmenila a tim padem skrze nej
%nesla zadan cesta
disp(sprintf('Nadbytecny spoj a tok: %s',jednotkaBW))
nadbytecnost = sparse(nadbtok) %nadbytecne spoje

vykresleni = spoj - nadbytecnost; %matice spoju pro vykresleni
maticeSpojuDleToku = vykresleni + zeros(pocetuzlu,pocetuzlu); %promenna pro celkovy navrh
grafOptDleToku = biograph(vykresleni,[], 'Label', 'Optimalizace dle toku','Description', 'OptDleToku','EdgeType', 'straight','ShowArrows','off','LayoutScale', 3.0);
view(grafOptDleToku)

vykresleni = vykresleni + zeros(pocetuzlu,pocetuzlu);% matice pro vypocet kapacity v navrhu
%celkova kapacita navrhu
for i = 1:pocetuzlu
    
    BWcel(i,1) = sum(vykresleni(i,:)) + sum(vykresleni(:,i)); %nove hodnoty toku do uzlu
    
end

[cenapaketu, cenapambloku, cenacelkemuzlu] = CenaZaUzel (BWpl, BWcel, cenaza1pa, cenaza1pb, jednotkaBW); %vypocet cen uzlu v danem navrhu
cenacelkemuzlu = sum(cenacelkemuzlu); %cena za uzly v navrhu

delkaOptNavrhu = sparse(pocatek,konec,delka,pocetuzlu,pocetuzlu); %ridka matice ohodnocena delkou
ind = find(nadbytecnost > 0); %najdi prvky vetsi nez nula v matici nadbytecnych toku
delkaOptNavrhu(ind) = 0*(ind); %pomoci malezenych indexu vynuluj prislusne delky
delkaOptNavrhu = delkaOptNavrhu + zeros(pocetuzlu,pocetuzlu);
delkaOptNavrhu = delkaOptNavrhu';
delkaOptNavrhu = delkaOptNavrhu(:);
ind2 = find(delkaOptNavrhu > 0); %najdi prvky vetsi nez 0 v matici novych delek
[x,y] = size(ind2);

for i=1:x %na zaklade indexu ind2 vytor novou matici delek pro vypocet cen
delkaPoOpt(i,1)=delkaOptNavrhu(ind2(i,1));
end 


BWOptNavrhu = sparse(pocatek,konec,BW,pocetuzlu,pocetuzlu);
ind = find(nadbytecnost > 0);
BWOptNavrhu(ind) = 0*(ind);
BWOptNavrhu = BWOptNavrhu + zeros(pocetuzlu,pocetuzlu);
BWOptNavrhu = BWOptNavrhu';
BWOptNavrhu = BWOptNavrhu(:);
ind3 = find(BWOptNavrhu > 0);
[x,y] = size(ind3);

for i=1:x
BWPoOpt(i,1)=BWOptNavrhu(ind3(i,1));%potrebuji sloupcovy vektor bez nul 
end 

[cenalinky] = CenaLinky (delkaPoOpt, BWPoOpt, jednotkaBW, cenaza1m, cenaza1b); %vypocet ceny linky
cenalinky = sum(cenalinky);
SumaCenySredDleToku = cenalinky + cenacelkemuzlu;
disp(sprintf('Celkove naklady navrhu jsou: %9.9f\n',SumaCenySredDleToku))

celkovacena = sum(celkovacena);
rozdilNakladu = SumaCenySredDleToku - celkovacena;
disp(sprintf('Rozdil v nakladech opt. navrhu proti vychozimu stavu je: %9.9f\n',rozdilNakladu))

%cast, kde se zabyvam spoji s poddimenzovanou kapacitou

vytizenespoje = tok - vychozimatice2; %spoje vytizene pres kapacitu
vytizenespoje(vytizenespoje <= 0) = 0 * ones(size(find(vytizenespoje <= 0)));

disp('V pripade nekterych spoju je kapacita nedotatecna a je potraba jejich uprava')
disp('*****************************************************************************')
disp(sprintf('Spoje teoreticky poddimenzovane o: %s',jednotkaBW))
vytizenost = sparse(vytizenespoje)

%Zvysit kapacitu poddimenzovanych spoku o zadanou hodnotu. Znovu vypocitat
%toky, zkontrolovat nadbytecnost, vypocitat znovu ceny

%pokud se nektery prvek matice poddimenzovanych nerovna nula, probehne
%uprava zpozdeni
NNvyt = vytizenost > 0;
hledejNNvyt = find(NNvyt);
kontrolaPraz = isempty(hledejNNvyt);

if kontrolaPraz == 0

    vytizenost = vytizenost + zeros(pocetuzlu,pocetuzlu); %pokud ano, preved matici na obycejnou
    vytizenostPO = (vytizenost*upravaToku) - vytizenost; %uprav toky dle koeficientu
    UT = 1;
    
    disp(sprintf('Zvyseni toku v poddimenzovanych spojich dle koeficientu o nasobek %3.3f\n:',upravaToku))
    vytizenost = sparse(vytizenostPO)
    
    maticeSpojuUpravaKoef = maticeSpojuDleToku + vytizenostPO; % vytvor novou matici spoju dle toku
    alternativaToku = maticeSpojuUpravaKoef + zeros(pocetuzlu,pocetuzlu);
    maticeSpojuUpravaKoef = sparse(maticeSpojuUpravaKoef);
    
    for i = 1:zdroje
    [MaxTok,TokVeSpoji,Rez] = graphmaxflow(maticeSpojuUpravaKoef,i,pocetuzlu); %hleda max. toky
    tok = tok + TokVeSpoji; % a vytvari novou matici spoju na zaklade souctu nalezenych max. toku
    end

    disp('Toky ve spojich po vypoctu max. toku dle upravenych hodnot: ')
    toky = sparse(tok) %zobrazeni matice souctu max. toku
    
elseif kontrolaPraz == 1
    
    disp('Toky jsou v poradku')
    
end

%vypocet pro hodnoty po zmene dle koeficientu

if UT == 1
for i = 1:pocetuzlu
    
    BWcelPOdK(i,1) = sum(maticeSpojuUpravaKoef(i,:)) + sum(maticeSpojuUpravaKoef(:,i)); %nove hodnoty toku do uzlu
    
end
end

disp('*********************Hodnoty po zmene dle koeficientu upravaToku:*********************')

if UT == 1
[cenapaketu, cenapambloku, cenacelkemuzlu] = CenaZaUzel (BWpl, BWcelPOdK, cenaza1pa, cenaza1pb, jednotkaBW); %vypocet cen uzlu v danem navrhu
cenacelkemuzlu = sum(cenacelkemuzlu);

%udelat sloupcovy vektor bez nul z novych hodnot toku maticeSpojuUpravaKoef
maticeSpojuDleTokuTR = maticeSpojuUpravaKoef';
maticeSpojuDleTokuTR = maticeSpojuDleTokuTR(:);
NNodk = find(maticeSpojuDleTokuTR > 0);
[x,y] = size(NNodk);

for i=1:x
BWPoOptdk(i,1)=maticeSpojuDleTokuTR(NNodk(i,1));%potrebuji sloupcovy vektor bez nul 
end 

[cenalinky] = CenaLinky (delkaPoOpt, BWPoOptdk, jednotkaBW, cenaza1m, cenaza1b); %vypocet ceny linky
cenalinky = sum(cenalinky);
SumaCenySredDleToku = cenalinky + cenacelkemuzlu;
disp(sprintf('Celkove naklady navrhu jsou: %9.9f\n',SumaCenySredDleToku))

celkovacena = sum(celkovacena);
rozdilNakladu = SumaCenySredDleToku - celkovacena;
disp(sprintf('Rozdil v nakladech navrhu s opt. proti vychozimu stavu je: %9.9f\n',rozdilNakladu))

end
end


