function [maticeSpojuDleZpozdeni,VsechnySpojeDleZpozdeni,zpozdeniPL,serializacniZpozdeni] = OptDleZpozdeni(delka, pocatek, konec, BW, BWcel, BWpl, jednotkaBW, pocetuzlu, limit, cenaza1m, cenaza1b, cenaza1pa, cenaza1pb, presah)

%mfile pro navrh a optimalizaci navrhu site dle pozadavku na miniimalni
%chybovost. 
%delka - delka spoje, zadavejte v metrech
%BW - kapacita spoje, zadavejte v Bps, Mbps, Gbps
%jednotkaBW - pouzita jedntoka kakacity, zadavejte Bps, Mbps, Gbps
%cenaza1m, cenaza1b - zadejte jednotkovou cenu delky a kapacity
%BWpl - kapacita spoje pristupove linky, zadavejte v Bps, Mbps, Gbps
%cenaza1pa - zadejte jednotkovou cenu za prepojeny paket
%cenaza1pb - zadejte jednotkovou cenu za pametovy blok
%limit - maximalni pripustna hodnota zpozdeni
%presah - urceni hodnoty pro optimalizaci pri prekroceni zpozdeni.Zadavejste ve tvaru 1.xy, kde xy predstavuje procenta(napr. 1.05 pro 5 procent)
%celkovacena - celkova cena linek a uzlu drive spocitana pricnymi mfily.
%pocatek - vektor pocatecnich uzlu spoju
%konec - vektor koncovych uzlu spoju
%presah - hodnata zmeny kapacity ve spoji pri nedodrzeni hodnoty zpozdeni(zadavat ve tvaru 1.15 pro 15 procent). Vzyahuje se ke sloupci matice a danemu uzlu v ceste
%[maticeSpojuDleZpozdeni,VsechnySpojeDleZpozdeni,zpozdeniPL,serializacniZpozdeni] = OptDleZpozdeni(delka, pocatek, konec, BW, BWcel, BWpl, jednotkaBW, pocetuzlu, limit, cenaza1m, cenaza1b, cenaza1pa, cenaza1pb, presah)

disp('******************PARAMETRY OPTIMALIZACE DLE ZPOZDENI SPOJU*************************')

if nargin ~= 14
    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);

fixnizpozdeni = 1.4*(10^-3); % fixni zpozdeni v uzlech pro paket velikosti 1500B
zpozdenilinky = (delka./10^5)*(500*10^-6); %zpozdeni linek pri sireni signalu rychlosti 500mikro s/100km
packet = 1500*8;

switch jednotkaBW
    case 'Bps'
    serializacniZpozdeni = (BW.\packet).*2; %serializacni zpozdeni na zdrojovem a cilovem uzlu transportni site
    zpozdeniPL = BWpl.\packet; %serializacni zpozdeni vzhleem k pristupova lince
    
    case 'Mbps'
    serializacniZpozdeni = ((BW.*10^6).\packet).*2;
    zpozdeniPL = (BWpl.*10^6).\packet;
    
    case 'Gbps'
    serializacniZpozdeni = ((BW.*10^9).\packet).*2;
    zpozdeniPL = (BWpl.*10^9).\packet;
    
    otherwise
        disp('zadej spravnou jednotku BW> Bps, Mbps, Gbps')
      
end

zpTransportSite = serializacniZpozdeni + zpozdenilinky; %celkove zpozdeni linek transportni site

navrh = sparse(pocatek,konec,zpTransportSite,pocetuzlu,pocetuzlu); %vytvoreni matice spoju
VsechnySpojeDleZpozdeni = navrh + zeros(pocetuzlu,pocetuzlu);
doltrojmatice = tril(navrh + navrh'); %prevod na dolni trojuhelnikovou matici, nutnost pro dalsi vypocet
[MKdz,pred] = graphminspantree(doltrojmatice); %vypocet minimalni kostry vzhledem k ohodnoceni
grafOptDZ = biograph(MKdz,[], 'Label', 'Minimalni kostra dle zpozdeni','Description', 'MinimKostradleZpozdeni','EdgeType', 'straight','ShowArrows','off'); %optimalizovany navrh
view(grafOptDZ)

disp ('Spoje minimalni kostry grafu jsou:')
SpojeNavrhu = MKdz' %pouzite spoje v min. kostre
SpojeMK = SpojeNavrhu + zeros(pocetuzlu,pocetuzlu);

%musim urcit zpozdeni vsech cest v siti, zatim bez fixnigo zpozdeni
maticeZpozdeni = graphallshortestpaths(MKdz,'directed',false); %matice sousednosti na zaklade doby celkoveho zpozdeni kazde cesty v transport. siti návrhu dle min kostry.
zpozdeniPL = zpozdeniPL';


for i = 1:pocetuzlu
    
    %musim pricist zpozdeni vychozi PL a vsech cilovych PL
    maticeZpozdeni(i,:) = (maticeZpozdeni(i,:) + zpozdeniPL(1,i)) + zpozdeniPL(1,:); %cyklus pro pricteni zpozdeni pristupovych linek a vytvoreni matice celkoveho zpozdeni
    maticeZpozdeni(i,i) = 0;
    
end

%musim urcit, pres kolik uzlu to jde a podle toho pricist fixni zpozdeni

UG = tril(SpojeNavrhu + SpojeNavrhu');

for i = 1:(pocetuzlu) %opakovani pro zdrojove uzly
    
    for j = 1: pocetuzlu %opakovani pro cilove uzly
        [dist,path,pred] = graphshortestpath(UG,i,'directed',false); %hledani vsech nejkratsich tras ze zdrojoveho uzlu
        nejrychlejsiTrasa = path{j}; % nejrzchlejsi cesta k cili trasa k danemu cili
        pocetMezUzlu = length(nejrychlejsiTrasa);%pocet mezilehlych uzlu
        maticeZpozdeni(i,j) = maticeZpozdeni(i,j) + (pocetMezUzlu * fixnizpozdeni);%podle poctu mezilehlych uzlu prictu fixni zpozdeni
        
    end
end

%odstanim cesty k uzlum samotnym 1 do 1 atd
for i = 1:pocetuzlu
    maticeZpozdeni(i,i) = 0;
end

disp('Zpozdeni jednotlivych linek mezi koncovymi ucastniky v [s] v navrhu minimalni kostry mezi koncovymi uzly:')
maticeZpozdeni = triu(maticeZpozdeni);
zpozdeni = sparse(maticeZpozdeni)

% V pripade ze dojde k prekroceni limitu zpozdeni, tak urcit co to je za spoj, o kolik a
% jak to resit
zpozdeneLinky = zeros(pocetuzlu, pocetuzlu);
Delay = zpozdeni > limit; %hledej hodnoty presahujici limit
najdiDelay = find(Delay); %hledej pozice v matici zpozdeni linek
zpozdeneLinky(najdiDelay) = zpozdeni(najdiDelay) - limit; %prirazeni hodnoty do matice zpozdenych linek a jeji zmena na hodnotu o kterou je prekrocen limit
disp('Linky, ktere prekracuji maximalni limit zpozdeni a jakym rozdilem')
zpozdeneLinky = sparse(zpozdeneLinky)       


zpozdeni = zpozdeni(:);
NNzp = zpozdeni > 0;%hledam nenulove prvky a temi budu delit
hledejNNzp = find(NNzp);
[x,y] = size(hledejNNzp);
average = sum(zpozdeni)/x; %prumerna doba zpozdeni linky
maximum = max(zpozdeni);

disp(sprintf('Prumerna doba zpozdeni = %9.9f s \n',average(1,1)));
disp(sprintf('Maximalni doba zpozdeni = %9.9f s \n',maximum(1,1)));

disp ('Nevyuzite spoje pri navrhu minimalni kostrou jsou:')
nevyuzitespoje = navrh - SpojeNavrhu %nevyuzite spoje v min kostre
nevyuzitespoje2 = nevyuzitespoje;

%Redundanci doplnim tak, ze k uzlum se stupnem 1 hledeam spolecne cesty,
%pokud takove neexistuji, hledam minima do uzlu a testuji na stupen

%Otestovat matici dodanych spoju podle Opt dle zpozdeni

redundance = SpojeMK; %matice hodnot min kostry
volneSpoje = nevyuzitespoje + zeros(pocetuzlu,pocetuzlu); %nevyuzite spoje
kontrola = zeros(pocetuzlu,pocetuzlu); %pro testovani stupne uzlu
VsechnySpojeDleZpozPR = VsechnySpojeDleZpozdeni - redundance; %rozdilova matice vsech spoju a tech pouzitych v navrhu min kostry

redundanceStupen = redundance;
redundanceStupen(redundanceStupen > 0) = ones(size(find(redundanceStupen > 0))); %nahrad prvky vetsi nez 0 jednickou

for i = 1:pocetuzlu
kontrola(i,i) = sum(redundanceStupen(i,:)) + sum(redundanceStupen(:,i)); %nenulove hodnoty prevede v danem sloupci a radku na 1, vytvori jejich soucet a dle toho se urci stupen grafu
end

%doplnuji spolecne spoje pro uzly se stupnem 1
stupen1 = find(any(kontrola == 1)); %hledam vsechny sloupce, kde se vyskytuje stupen 1
[x,y] = size(stupen1);
nalezeneSpolSpoje = zeros(pocetuzlu,pocetuzlu);

if y > 1
for i = 1 : y-1    
    nalezeneSpolSpoje(stupen1(1,i),stupen1(1,i+1)) = sum(volneSpoje(stupen1(1,i),stupen1(1,i+1))); %matice spolecnych spoju, ktere mohou byt pridany 
end
end

redundance = redundance + nalezeneSpolSpoje; %matice spoju po pridani spolednych

%finalni kontrola pro pripad, ze se nanasly spolecne
redundanceStupen = redundance;
redundanceStupen(redundanceStupen > 0) = ones(size(find(redundanceStupen > 0))); %nahrad prvky vetsi nez 0 jednickou
for i = 1:pocetuzlu
kontrola(i,i) = sum(redundanceStupen(i,:)) + sum(redundanceStupen(:,i)); %nenulove hodnoty prevede v danem sloupci a radku na 1, vytvori jejich soucet a dle toho se urci stupen grafu
end

for i = 1:pocetuzlu    
    
    if kontrola(i,i) < 2 %pokud ma nektery uzel stupen mesi nez 2   
        
            VsechnySpojeDleZpozPR(VsechnySpojeDleZpozPR == 0) = Inf*ones(size(find(VsechnySpojeDleZpozPR == 0)));
            index1 = min(VsechnySpojeDleZpozPR(i,:));%hledej maximum v patricnem radku matice smazanych hodnot
            index2 = min(VsechnySpojeDleZpozPR(:,i)); %hledej maximum v patricnem sloupci matice smazanych hodnot
            
            %musim zkouset ,jestli pridani minimalniho spoje nezapricini
            %pridani zbytecne mnoha dalsich spoju
            
            if index1 > index2 && index2 < Inf
            index3 = index2;                       
            elseif index1 < index2 && index1 < Inf
            index3 = index1;
            end
            
            L = VsechnySpojeDleZpozPR == index3; 
            najdi = find(L); %pozice minima v matici smazanych hodnot
            redundance(L) = index3*ones(size(najdi)); %prirazeni hodnoty do matice spoju
                        
            VsechnySpojeDleZpozPR(VsechnySpojeDleZpozPR == Inf) = 0*ones(size(find(VsechnySpojeDleZpozPR == Inf)));
                    
     end
      
end

%kontrola na zpetne spoje z horni poloviny uzlu. Takze veymu matici
%prvku a vzberu sloupce od poloviny nahoru a prvni polovinu radku
zbyleSpoje = VsechnySpojeDleZpozdeni - redundance;
zbyleSpojeVysec = zbyleSpoje(1:(pocetuzlu/2),(pocetuzlu/2):pocetuzlu);
redundanceStupen = redundance(1:(pocetuzlu/2),(pocetuzlu/2):pocetuzlu);
redundanceStupen(redundanceStupen > 0) = ones(size(find(redundanceStupen > 0))); %nahrad prvky vetsi nez 0 jednickou

%mozna jeste zapremzslet, jestli by nebzlo vhodne vyclenit z prohledavanych
%sloupcu ten posledni

for i = 1:pocetuzlu/2
    if sum(redundanceStupen(:,i)) > 0
        continue
    else
        zbyleSpojeVysec(zbyleSpojeVysec == 0) = Inf*ones(size(find(zbyleSpojeVysec == 0)));
        index1 = min(zbyleSpojeVysec(i,:)); %hledej minimum v patricnem radku matice smazanych hodnot
        index2 = min(zbyleSpojeVysec(:,i)); %hledej minimum v patricnem sloupci matice smazanych hodnot
            
        %musim zkouset ,jestli pridani minimalniho spoje nezapricini
        %pridani zbytecne mnoha dalsich spoju
            
        if index1 > index2 && index2 < Inf
        index3 = index2;                       
        elseif index1 < index2 && index1 < Inf
        index3 = index1;
        elseif index1 == index2 && index1 || index2 ~= Inf
        index3 = index1;    
        end
            
        L = zbyleSpoje == index3; 
        najdi = find(L); %pozice minima v matici smazanych hodnot
        redundance(L) = index3*ones(size(najdi)); %prirazeni hodnoty do matice spoju
                       
        zbyleSpojeVysec(zbyleSpojeVysec == Inf) = 0*ones(size(find(zbyleSpojeVysec == Inf)));
    end
end

%nova matice spoju spridanymi hodnotami
disp('Spoje pouzite v konecnem navrhu:')
redundance = sparse(redundance)

maticeSpojuDleZpozdeni = redundance + zeros(pocetuzlu,pocetuzlu);
UG = tril(redundance + redundance');

disp ('Nevyuzite spoje pri navrhu s redundanci jsou:')
nevyuzitespojeNevrhSredun = navrh - redundance %nevyuzite spoje dale pouzite pri vypoctu hodnot cen

disp ('Spoje dodane pro redundanci:')
dodanespoje = redundance - SpojeNavrhu; %redundantni spoje
dodanespoje(dodanespoje < 0) = 0*ones(size(find(dodanespoje < 0)))

doltrojmatice2 = tril(redundance + redundance'); %prevod na dolni trojuhelnikovou matici, nutnost pro dalsi vypocet
maticeZpozdeniSredun = graphallshortestpaths(doltrojmatice2,'directed',false); %matice sousednosti na zaklade doby celkoveho zpozdeni kazde cesty v transport. siti návrhu dle min kostry s redundanci

for i = 1:pocetuzlu
    
    maticeZpozdeniSredun(i,:) = (maticeZpozdeniSredun(i,:) + zpozdeniPL(1,i)) + zpozdeniPL(1,:); %cyklus pro pricteni zpozdeni pristupovych linek a vytvoreni matice celkoveho zpozdeni
    maticeZpozdeniSredun(i,i) = 0;
    
end

%musim urcit, pres kolik uzlu to jde a podle toho pricist fixni zpozdeni

for i = 1:(pocetuzlu) %opakovani pro zdrojove uzly
    
    for j = 1: pocetuzlu %opakovani pro cilove uzly
        [dist,path,pred] = graphshortestpath(UG,i,'directed',false); %hledani vsech nejkratsich tras ze zdrojoveho uzlu
        nejrychlejsiTrasa = path{j}; % nejrzchlejsi cesta k cili trasa k danemu cili
        pocetMezUzlu = length(nejrychlejsiTrasa);%pocet mezilehlych uzlu
        maticeZpozdeniSredun(i,j) = maticeZpozdeniSredun(i,j) + (pocetMezUzlu * fixnizpozdeni);%podle poctu mezilehlych uzlu prictu fixni zpozdeni
        
    end
end

%odstanim cesty k uzlum samotnym 1 do 1 atd
for i = 1:pocetuzlu
    maticeZpozdeniSredun(i,i) = 0;
end

disp('Zpozdeni jednotlivych linek mezi koncovymi ucastniky v [s] mezi koncovymi uzly v navrhu s redundanci:')
maticeZpozdeniSredun = triu(maticeZpozdeniSredun);
zpozdeniSredun = sparse(maticeZpozdeniSredun)

% V pripade ze nastane hodnota presahujici limit zpozdeni, tak urcit co to je za spoj, o kolik a
% jak to resit
zpozdeneLinkySRedun = zeros(pocetuzlu, pocetuzlu);
Delay = zpozdeniSredun > limit; %hledej hodnoty presahujici limit
najdiDelay = find(Delay); %hledej pozice v matici zpozdeni linek
zpozdeneLinkySRedun(najdiDelay) = zpozdeniSredun(najdiDelay) - limit; %prirazeni hodnoty do matice zpozdenych linek a jeji zmena na hodnotu o kterou je prekrocen limit
disp('Linky, ktere prekracuji maximalni limit zpozdeni a jakym rozdilem.')
zpozdeneLinkySRedun = sparse(zpozdeneLinkySRedun)

%pokud se nektery prvke matice zpozdenych nerovna nula, probejne uprave
%zpozdeni
NNzps = zpozdeneLinkySRedun > 0;
hledejNNzps = find(NNzps);
kontrolaPraz = isempty(hledejNNzps);

if kontrolaPraz == 0
for i = 1:pocetuzlu %na zaklade poctu uzlu definuji pocet opakovani
    
    if zpozdeneLinkySRedun(i,:) == 0 %kontrola zde radek obsahuje poze nuly
        continue %pokud ano, pokracuj v dalsi iteraci
        
    else
    
    [x,y] = find(zpozdeneLinkySRedun(i,:) > 0);%hledej pozice nenulovyzch prvku matice
    xs = i;
    ys = y;
    delkaYs = length(ys);
    
    [dist,path,pred] = graphshortestpath(UG,xs,'directed',false); %najdi vsechny nejkratsi trasy z vychoziho bodu xs
    
    for q = 1 : delkaYs
    trasa = path{ys(1,q)} %trase k ys, tedy zjistena s prekrocenym limitem
    dilciZpozdeni = dist(path{ys(1,q)}) %zpozdeni jednotlivych usek na trase
    
    [a,b] = size(dilciZpozdeni); %rozmery matice
    for j = 1:b-1
        
       dilciZpozdeni(1,j) =  dilciZpozdeni(1,j+1) - dilciZpozdeni(1,j); %hledej rozdily mezi zpozdenimi na trase
               
    end
    
    limitZmeny = min(dilciZpozdeni); %najdi minimalni hodnotu rozdilu
    maxim = max(dilciZpozdeni); %najdi maximalni hodnotu rozdilu
    dilciZpozdeni(dilciZpozdeni == maxim) = 0 * ones(size(find(dilciZpozdeni == maxim))); %maximalni hodnotu zmen na 0
    Q = dilciZpozdeni >= (limitZmeny *presah); %hledane prvky budou ty, ktere presahuji limit o zvolena procenta
    najdi = find(Q); %vyhledej hodnoty  ktere presahuji minimum a zvolena procenta
    TP = isempty(najdi); %test, zda=li je prazdna matice najdi
    if TP == 1
        disp('Zvysit rovnomerne kapacitu cele trasy. O procenta presahu rozpocteno na useky')
        
    elseif TP == 0
        disp('Zvysit kapacitu spuju vzhledem ke sloupcum matice:')
        najdi
    end
    end
    
    end
end
elseif kontrolaPraz == 1
    disp('Nedoslo k prekroceni hodnoty zpozdeni')
end

zpozdeniSredun = zpozdeniSredun(:);
NNzpsr = zpozdeniSredun > 0;%hledam nenulove prvky a temi budu delit
hledejNNzpsr = find(NNzpsr);
[x,y] = size(hledejNNzpsr);
averageSredun = sum(zpozdeniSredun)/x; %prumerna doba zpozdeni linky
maximumSredun = max(zpozdeniSredun);

rozdilMax = maximum - maximumSredun;
rozdilAver = average - averageSredun;

disp(sprintf('Prumerna doba zpozdeni = %9.9f s \n',averageSredun(1,1)));
disp(sprintf('Maximalni doba zpozdeni = %9.9f s \n',maximumSredun(1,1)));
disp(sprintf('Prumerna doba zpozdeni v navrhu s redundanci klesla o = %9.9f s \n',rozdilAver(1,1)));
disp(sprintf('Maximalni doba zpozdeni v navrhu s redundanci klesla o = %9.9f s \n',rozdilMax(1,1)));

%%%toky v navrhu s redundanci

sitDleToku = sparse(pocatek,konec,BW,pocetuzlu,pocetuzlu); %vytvoreni matice spoju dle zpozdeni

redundancePT = redundance; %pro potraby testu zpozdeni
NNsdz = redundancePT > 0;%musim najit spoje v matici spoju min kostry a dle nich vybrat ty z matice dle zpozdeni
hledejNNsdz = find(NNsdz);
redundancePT(hledejNNsdz) = sitDleToku(hledejNNsdz);

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

for i = 1:zdroje
[MaxTok,TokVeSpoji,Rez] = graphmaxflow(redundancePT,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 navrhu s redundanci po vypoctu max. toku: %s',jednotkaBW))
toky = sparse(tok) %zobrazeni matice souctu max. toku

grafOptSRedun = biograph(redundance,[], 'Label', 'Navrh dle zpozdeni s redundanci','Description', 'MinimKostraSRedun','EdgeType', 'segmented','ShowArrows','off','LayoutScale', 3.0); %navrh s redundanci
view(grafOptSRedun)
%%%Naklady

%Urceni celkove vstupni kapacity z transportni site do jednotlivych uzlu v
%navrhu bez redundance
BWCelOptNavrhu = sparse(pocatek,konec,BW,pocetuzlu,pocetuzlu);
ind = find(SpojeNavrhu <= 0);
BWCelOptNavrhu(ind) = 0*(ind);
BWCelOptNavrhu = BWCelOptNavrhu + zeros(pocetuzlu,pocetuzlu);

for i = 1:pocetuzlu
    
    BWcel(i,1) = sum(BWCelOptNavrhu(i,:)) + sum(BWCelOptNavrhu(:,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);

delkaOptNavrhu = sparse(pocatek,konec,delka,pocetuzlu,pocetuzlu); %ridka matice ohodnocena delkou
ind = find(nevyuzitespoje2 > 0); %najdi prvky vetsi nez nula v matici nadbytecnych spoju
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(nevyuzitespoje2 > 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));
end 

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

celkovacena = sum(celkovacena);
rozdilNakladuBezRed = celkovacenaBezRed - celkovacena;
disp(sprintf('Rozdil v nakladech navrhu dle min. kostry proti vychozimu stavu je: %9.9f\n',rozdilNakladuBezRed))

%Urceni celkove vstupni kapacity z transportni site do jednotlivych uzlu v
%navrhu s redundanci
BWCelOptNavrhuSred = sparse(pocatek,konec,BW,pocetuzlu,pocetuzlu);
indsred = find(redundance <= 0);
BWCelOptNavrhuSred(indsred) = 0*(indsred);
BWCelOptNavrhuSred = BWCelOptNavrhuSred + zeros(pocetuzlu,pocetuzlu);

for i = 1:pocetuzlu
    
    BWcelSred(i,1) = sum(BWCelOptNavrhuSred(i,:)) + sum(BWCelOptNavrhuSred(:,i)); %nove hodnoty toku do uzlu
    
end

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

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

for i=1:x %na zaklade indexu ind4 vytor novou matici delek pro vypocet cen
delkaPoOptSred(i,1)=delkaOptNavrhuSred(ind4(i,1));
end 

BWOptNavrhuSred = sparse(pocatek,konec,BW,pocetuzlu,pocetuzlu);
indsred = find(nevyuzitespojeNevrhSredun > 0);
BWOptNavrhuSred(indsred) = 0*(indsred);
BWOptNavrhuSred = BWOptNavrhuSred + zeros(pocetuzlu,pocetuzlu);
BWOptNavrhuSred = BWOptNavrhuSred';
BWOptNavrhuSred = BWOptNavrhuSred(:);
ind5 = find(BWOptNavrhuSred > 0);
[x,y] = size(ind5);

for i=1:x
BWPoOptSred(i,1)=BWOptNavrhuSred(ind5(i,1));
end 

[cenalinky] = CenaLinky (delkaPoOptSred, BWPoOptSred, jednotkaBW, cenaza1m, cenaza1b); %vypocet ceny linky
cenalinky = sum(cenalinky);
SumaCenySredDleZpoz = cenalinky + cenacelkemuzlu;
disp(sprintf('Celkove naklady navrhu s redundanci jsou: %9.9f\n',SumaCenySredDleZpoz))

RozdilSredABezRed = SumaCenySredDleZpoz - celkovacenaBezRed;
disp(sprintf('Rozdil v nakladech navrhu s redundanci proti navrhu minimalni kostrou je: %9.9f\n',RozdilSredABezRed))

celkovacena = sum(celkovacena);
rozdilNakladuSRed = SumaCenySredDleZpoz - celkovacena;
disp(sprintf('Rozdil v nakladech navrhu s redundanci proti vychozimu stavu je: %9.9f\n',rozdilNakladuSRed))
end