public List <int> najkrotsza(int vo, Siec _siec, int vt) { // Jest to wersja algorytmu poprawiania etykiet, szukajacych najkrotszej(wzgledem specjalnej wagi) sciezki double[] L = new double[_siec.liczba_wezlow]; int[] P = new int[_siec.liczba_wezlow]; //tablica poprzednikow wierzcholka na najkrotszej sciezce for (int j = 0; j < _siec.liczba_wezlow; j++) { if (_siec.zbior_wezlow[j].id == vo) { L[j] = 0; } else { L[j] = 100000.0; } } Queue <Wezel> fifo = new Queue <Wezel>(); fifo.Enqueue(_siec.zbior_wezlow[vo - 1]); while (fifo.Count != 0) { Wezel v = fifo.Dequeue(); int i = 0; for (; i < _siec.liczba_laczy; i++) { if ((_siec.zbior_laczy[i].wezel_pocz.id == v.id) && (_siec.zbior_laczy[i].przepustowosc_resztkowa != 0)) { if (L[_siec.zbior_laczy[i].wezel_konc.id - 1] > L[v.id - 1] + (1 + (_siec.zbior_laczy[i].przeplyw / (_siec.zbior_laczy[i].przepustowosc_resztkowa)) * Math.Pow((_siec.zbior_laczy[i].koszt), 2))) { L[_siec.zbior_laczy[i].wezel_konc.id - 1] = L[v.id - 1] + (1 + (_siec.zbior_laczy[i].przeplyw / (_siec.zbior_laczy[i].przepustowosc_resztkowa)) * Math.Pow((_siec.zbior_laczy[i].koszt), 2)); P[_siec.zbior_laczy[i].wezel_konc.id - 1] = v.id; fifo.Enqueue(_siec.zbior_laczy[i].wezel_konc); } } } } // Powyzej uzylismy specjalnej wagi (1 + (_siec.zbior_laczy[i].przeplyw / (_siec.zbior_laczy[i].przepustowosc_resztkowa)) * Math.Pow((_siec.zbior_laczy[i].koszt),2) // napoczatku przeplywy rownaja sie zero i kazde lacze ma wage 1 wiec algorytm wyszuka najkrotsza pod wzgledem ilosci laczy sciezke // potem bedzie znajdywal inne sciezki gdyz drugi czlon tej wagi bedzie sie zwiekszal, co chroni przed zapychaniem lacz // oraz minimalizuje koszt. // korzystajac z tablicy poprzednikow tworzymy sciezke int z = vt; List <int> sciezka = new List <int>(); while (z != 0) { sciezka.Insert(0, z); z = P[z - 1]; } int a = 0; Sciezka _sciezka = new Sciezka(); _sciezka.id_lacz = new List <int>(); for (; a < sciezka.Count - 1; a++) { int j = 0; for (; j < _siec.liczba_laczy; j++) { if ((_siec.zbior_laczy[j].wezel_pocz.id == sciezka[a]) && (_siec.zbior_laczy[j].wezel_konc.id == sciezka[a + 1])) { _sciezka.id_lacz.Add(_siec.zbior_laczy[j].id); } } } // zwraca najkrotsza sciezke return(_sciezka.id_lacz); }
public void projektujaca(string _wejscie, string _wyjscie) { // Wczytujemy dane z pliku wejsciowego do Sieci(obiekt grafik) string wejscie = _wejscie; FileStream plik; string odczyt; plik = new FileStream(wejscie, FileMode.Open); StreamReader p = new StreamReader(plik); p.ReadLine(); odczyt = p.ReadLine(); string[] tabodczyt = odczyt.Split(' '); int _liczbawezlow = int.Parse(tabodczyt[2]); p.ReadLine(); odczyt = p.ReadLine(); tabodczyt = odczyt.Split(' '); int _liczbalaczy = int.Parse(tabodczyt[2]); p.ReadLine(); Siec grafik = new Siec(_liczbalaczy, _liczbawezlow); int i = 0; for (; i < _liczbawezlow; i++) { grafik.zbior_wezlow[i] = new Wezel(i + 1); } odczyt = p.ReadLine(); tabodczyt = odczyt.Split(' '); string decimalCharacter = System.Globalization.CultureInfo.InstalledUICulture.NumberFormat.NumberDecimalSeparator; int j = 0; while (tabodczyt[0] != null && tabodczyt[0] != "") { grafik.zbior_laczy[j] = new Lacze(int.Parse(tabodczyt[0]), grafik.zbior_wezlow[int.Parse(tabodczyt[1]) - 1], grafik.zbior_wezlow[int.Parse(tabodczyt[2]) - 1], double.Parse(tabodczyt[3].Replace(".", decimalCharacter)), double.Parse(tabodczyt[4].Replace(".", decimalCharacter))); ++j; odczyt = p.ReadLine(); if (odczyt != null) { tabodczyt = odczyt.Split(' '); } else { break; } } p.ReadLine(); odczyt = p.ReadLine(); tabodczyt = odczyt.Split(' '); int ile_zapotrzebowan = int.Parse(tabodczyt[2]); p.ReadLine(); //wczytujemy zapotrzebowania zapotrzebowanie[] tabzapotrzebowan = new zapotrzebowanie[ile_zapotrzebowan]; grafik.liczba_zapotrzebowan = ile_zapotrzebowan; j = 0; odczyt = p.ReadLine(); tabodczyt = odczyt.Split(' '); while (tabodczyt[0] != null && tabodczyt[0] != "") { tabzapotrzebowan[j] = new zapotrzebowanie(int.Parse(tabodczyt[0]), grafik.zbior_wezlow[int.Parse(tabodczyt[1]) - 1], grafik.zbior_wezlow[int.Parse(tabodczyt[2]) - 1], double.Parse(tabodczyt[3].Replace(".", decimalCharacter))); odczyt = p.ReadLine(); if (odczyt != null) { tabodczyt = odczyt.Split(' '); } else { break; } j++; } plik.Close(); p.Close(); // Koniec wczytywania // tworzymy Liste sciezek w grafie oraz Sciezki wraz z przeplywami ktore reazlizuja zapotrzebowanie // (pierwszej sciezce(id) odpowiada pierwszy element na liście przepływów grafik.wszystkie_sciezki = new List <Sciezka>(); int v = 0; for (; v < grafik.liczba_zapotrzebowan; v++) { tabzapotrzebowan[v].id_sciezek = new List <int>(); tabzapotrzebowan[v].przeplywy = new List <double>(); } v = 0; // Tutaj zaczynamy szukać ścieżek powiększających // Dla każdego zapotrzebowania szukamy 200 razy sciezek powiekszajacyh, przerywamy gdy nie znajdujemy jej już lub gdy // zrealizowalismy zapotrzebowanie for (; v < grafik.liczba_zapotrzebowan; v++) { int x = 0; for (; x < 200; x++) { // wyznaczam przepustowości resisualne na laczach Sieci i = 0; for (; i < grafik.liczba_laczy; i++) { grafik.zbior_laczy[i].przepustowosc_resztkowa = grafik.zbior_laczy[i].przepustowosc - grafik.zbior_laczy[i].przeplyw; } poprawiania_etykiet znajdz_sciezke = new poprawiania_etykiet(); Sciezka sciezka_powiekszajaca = new Sciezka(); sciezka_powiekszajaca.id_lacz = new List <int>(); // Korzystajac z algorytmu poprawiania etykiet szukam najkrotszych sciezek(pod wzgledem specjalnej wagi) sciezka_powiekszajaca.id_lacz = znajdz_sciezke.najkrotsza(tabzapotrzebowan[v].zrodlo.id, grafik, tabzapotrzebowan[v].ujscie.id); if (sciezka_powiekszajaca.id_lacz.Count == 0) { break; } //wyznaczamy grubosc sciezki powiekszajacej i = 0; double min = 10000; for (; i < sciezka_powiekszajaca.id_lacz.Count; i++) { if (grafik.zbior_laczy[sciezka_powiekszajaca.id_lacz[i] - 1].przepustowosc_resztkowa < min) { min = grafik.zbior_laczy[sciezka_powiekszajaca.id_lacz[i] - 1].przepustowosc_resztkowa; } } // realizujemy tylko 1% grubosci sciezki by uchronic sie przed zapychaniem lacz min = 0.01 * min; if (tabzapotrzebowan[v].rozmiar - tabzapotrzebowan[v].zrealizowano < min) { min = tabzapotrzebowan[v].rozmiar - tabzapotrzebowan[v].zrealizowano; } // znalezlismy sciezke powiekszajaca. Teraz trzeba uaktualnic przeplywy. Cofamy sie po sciezce i dodajemy przeplyw i = 0; for (; i < sciezka_powiekszajaca.id_lacz.Count; i++) { grafik.zbior_laczy[sciezka_powiekszajaca.id_lacz[i] - 1].przeplyw += min; } // Teraz trzeba sciezke powiekszajaca dodac do listy sciezek powiekszajacych dla zapotrzebowania // Najpierw sprawdzamy czy w Sieci(grafik) nie ma juz takiej sciezki int l = 0; int f; int z = 0; for (; l < grafik.wszystkie_sciezki.Count; l++) { if (grafik.wszystkie_sciezki[l].id_lacz.Count == sciezka_powiekszajaca.id_lacz.Count) { int y = 0; bool bequal = true;; for (; y < grafik.wszystkie_sciezki[l].id_lacz.Count; y++) { if (grafik.wszystkie_sciezki[l].id_lacz[y] != sciezka_powiekszajaca.id_lacz[y]) { bequal = false; break; } } if (bequal) { z = 2; f = grafik.wszystkie_sciezki[l].id; int o = 0; for (; o < tabzapotrzebowan[v].id_sciezek.Count; o++) { if (tabzapotrzebowan[v].id_sciezek[o] == f) { tabzapotrzebowan[v].przeplywy[o] += min; } } } } } if (z == 0) { grafik.wszystkie_sciezki.Add(sciezka_powiekszajaca); grafik.wszystkie_sciezki[grafik.wszystkie_sciezki.Count - 1].id = grafik.wszystkie_sciezki.Count; tabzapotrzebowan[v].id_sciezek.Add(sciezka_powiekszajaca.id); tabzapotrzebowan[v].przeplywy.Add(min); } // Powyzszy kod jest niestety bardzo zawily. Ustawia flage z na 2 jesli znalazl juz sciezke w zbiorze sciezek w Sieci(grafik) // Wtedy juz nie jest ponowne jego dodawanie do grafiku. Dodaje przeplyw do tej sciezki. W przeciwnym razie z == 0 i dodajemy sciezke do grafiku // oraz zapotrzebowania //uaktualnienie zrealizowanego przeplywu tabzapotrzebowan[v].zrealizowano = tabzapotrzebowan[v].przeplywy.Sum(); if (tabzapotrzebowan[v].zrealizowano == tabzapotrzebowan[v].rozmiar) { break; } } } // obliczamy koszt realizacji przeplywow double koszt = 0; int r = 0; for (; r < grafik.liczba_laczy; r++) { koszt += (grafik.zbior_laczy[r].koszt) * (grafik.zbior_laczy[r].przeplyw); } // Zapis do pliku FileStream fs = File.Create(_wyjscie); StreamWriter qw = new StreamWriter(fs); qw.WriteLine("# koszt rozwiazania"); qw.Write("KOSZT = "); qw.WriteLine(koszt); qw.WriteLine(); qw.WriteLine("# liczba uzytych sciezek"); qw.Write("SCIEZKI = "); qw.WriteLine(grafik.wszystkie_sciezki.Count); qw.WriteLine("# kazda sciezka to id. sciezki i zbior id. laczy"); i = 0; for (; i < grafik.wszystkie_sciezki.Count; i++) { qw.Write(grafik.wszystkie_sciezki[i].id); qw.Write(" "); j = 0; for (; j < grafik.wszystkie_sciezki[i].id_lacz.Count; j++) { qw.Write(grafik.wszystkie_sciezki[i].id_lacz[j]); qw.Write(" "); } qw.WriteLine(); } qw.WriteLine(); qw.WriteLine("# liczba zapotrzebowan"); qw.Write("ZAPOTRZEBOWANIA = "); qw.WriteLine(ile_zapotrzebowan); qw.WriteLine("# kazde zapotrzebowanie to id. zapotrzebowania oraz zbior par: id. sciezki, pojemnosc zarezerwowana na sciezce"); i = 0; for (; i < ile_zapotrzebowan; i++) { qw.Write(tabzapotrzebowan[i].id); qw.Write(" "); j = 0; for (; j < tabzapotrzebowan[i].id_sciezek.Count; j++) { qw.Write(tabzapotrzebowan[i].id_sciezek[j]); qw.Write(" "); qw.Write(tabzapotrzebowan[i].przeplywy[j]); qw.Write(" "); } qw.WriteLine(); } qw.Close(); fs.Close(); }