private void ConnectTwoNodes(int node1, int node2) { if (Graph.GetConnection(node1, node2) == false) { Graph.MakeConnection(node1, node2); Graph.OnChange(); } else { Graph.RemoveConnection(node1, node2); Graph.OnChange(); } }
public static DirectedGraphList ConvertToSList(DirectedGraphMatrix from) { DirectedGraphList x = new DirectedGraphList(from.NodesNr); for (int i = 0; i < from.NodesNr; i++) { for (int j = 0; j < from.NodesNr; j++) { if (from.GetConnection(i, j)) { x.MakeConnection(i, j); } x.setWeight(i, j, from.getWeight(i, j)); } } return(x); }
public static DirectedGraphMatrix CreateRandomDirectedWeights(DirectedGraphMatrix f, int minWeight = -5, int maxWeight = 20) { Random r = new Random(); DirectedGraphMatrix ret = new DirectedGraphMatrix(f.NodesNr); for (int k = 0; k < f.NodesNr; k++) { for (int p = 0; p < f.NodesNr; p++) { if (f.GetConnection(k, p)) { ret.MakeConnection(k, p, r.Next(minWeight, maxWeight + 1)); } } } return(ret); }
/// <summary> /// Implementacja algorytmu Floyda-Warshalla /// </summary> /// <param name="g"></param> Graf ktory jest spojny. Ten algorytm dziala takze dla grafow niespojnych w przeciwienstwie do johnsona /// <returns></returns> Macierz odleglosci miedzy wszystkimi wierzcholkami public static int[,] FloydWarshall(DirectedGraphMatrix graph) { int nodes = graph.NodesNr; int[,] distances = new int[nodes, nodes]; int w = 0; const int INF = int.MaxValue - 10000; for (int i = 0; i < nodes; ++i) { for (int j = 0; j < nodes; ++j) { distances[i, j] = INF; if (graph.GetConnection(i, j)) { distances[i, j] = graph.getWeight(i, j); } } distances[i, i] = 0; } for (int k = 0; k < nodes; ++k) { for (int i = 0; i < nodes; ++i) { for (int j = 0; j < nodes; ++j) { if (k == i || k == j || i == j) { continue; } if ((distances[i, k] == INF) || (distances[k, j] == INF)) { continue; } w = distances[i, k] + distances[k, j]; if (distances[i, j] > w) { distances[i, j] = w; } } } } return(distances); }
/// <summary> /// Transpozycja macierzy sasiedztwa /// potrzebna do algorytmu Kosaraju /// </summary> /// <param name="from"></param> /// <returns>Graf z transponowana macierza sasiedztwa</returns> public static DirectedGraphMatrix transpose(DirectedGraphMatrix from) { int[,] t = new int[from.NodesNr, from.NodesNr]; for (int i = 0; i < from.NodesNr; i++) { for (int j = 0; j < from.NodesNr; j++) { if (from.GetConnection(i, j)) { t[j, i] = 1; } else { t[j, i] = 0; } } } return(new DirectedGraphMatrix(from.NodesNr, t)); }
/// <summary> /// Tworzy graf maxymalnie spojny /// </summary> /// <param name="f">graf</param> /// <returns>max spojny graf</returns> public static DirectedGraphMatrix Directedmaxspojny(DirectedGraphMatrix f) { List <List <int> > sp = spojne(f); int k = 0; for (int i = 0; i < sp.Count; i++) { if (sp[i].Count >= sp[k].Count) { k = i; } } List <int> q = sp[k]; int[,] t = new int[q.Count, q.Count]; k = 0; int l; for (int i = 0; i < f.NodesNr; i++) { l = 0; if (!q.Contains(i)) { continue; } for (int j = 0; j < f.NodesNr; j++) { if (!q.Contains(j)) { continue; } if (f.GetConnection(i, j)) { t[k, l] = 1; } l++; } k++; } return(new DirectedGraphMatrix(q.Count, t)); }
/// <summary> /// Implementacja algorytmu Johnsona, korzysta z algorytmow Bellmana-Forda i Dijkstry /// </summary> /// <param name="g"></param> Musi to byc graf skierowany ktory ma juz randomowe wagi i musi byc on spojny(WAŻNE)!!!! /// Mozna np stworzyc graf skierowany, wydobyc z niego skladowa maksymalnie spojna i nadać jej randomowe wagi /// <returns></returns> Macierz odleglosci miedzy wszystkimi wierzcholkami public static int[,] Johnson(DirectedGraphMatrix graph) { try { int nodes = graph.NodesNr; int[,] distances = new int[nodes, nodes]; int[] d = new int[nodes]; const int INF = int.MaxValue - 10000; int[,] wagi = new int[nodes, nodes]; int q = nodes + 1; int[,] new_connect = new int[q, q]; for (int i = 0; i < nodes; ++i) { for (int j = 0; j < nodes; ++j) { new_connect[i, j] = graph.getConnect(i, j); wagi[i, j] = graph.getWeight(i, j); } } DirectedGraphMatrix dgraph = new DirectedGraphMatrix(q, new_connect); for (int i = 0; i < q - 1; ++i) { dgraph.MakeConnection(q - 1, i, 0); dgraph.setWeight(i, q - 1, INF); for (int j = 0; j < q - 1; ++j) { dgraph.setWeight(i, j, graph.getWeight(i, j)); } } List <List <int> > bellman = new List <List <int> >(); for (int i = 0; i < nodes; ++i) { bellman.Add(BellmanFord(dgraph, q - 1, i)); d[i] = pathWeight(dgraph, bellman[i]); if (ujemnyCykl(graph, wagi)) { throw new Exception("Algorytm Johnsona zostal zatrzymany."); } } for (int i = 0; i < q - 1; ++i) { for (int j = 0; j < q - 1; ++j) { if (dgraph.GetConnection(i, j)) { dgraph.setWeight(i, j, dgraph.getWeight(i, j) + d[i] - d[j]); } } } int[,] last_connect = new int[nodes, nodes]; for (int i = 0; i < nodes; ++i) { for (int j = 0; j < nodes; ++j) { last_connect[i, j] = dgraph.getConnect(i, j); } } DirectedGraphMatrix lgraph = new DirectedGraphMatrix(nodes, last_connect); for (int i = 0; i < nodes; ++i) { for (int j = 0; j < nodes; ++j) { lgraph.setWeight(i, j, dgraph.getWeight(i, j)); } } distances = distancesDirectedMatrix(lgraph); for (int i = 0; i < nodes; ++i) { for (int j = 0; j < nodes; ++j) { distances[i, j] = distances[i, j] - d[i] + d[j]; } } return(distances); } catch (Exception) { Console.WriteLine("Algorytm Johnsona zatrzymany z powodu ujemnego cyklu w grafie."); return(new int[5, 5]); } }
/// <summary> /// Bellman ford /// </summary> /// <param name="g"></param> /// <param name="start">skad</param> /// <param name="finish">dokad</param> /// <returns>lista wierzcholkow po ktorych otrzymamy najkrotsza sciezke start /rest/ finish</returns> public static List <int> BellmanFord(DirectedGraphMatrix g, int start, int finish) { const int INF = int.MaxValue - 1000; //uzywam jako nieskonczonosci var map = new Dictionary <int, Tuple <int, int> >(); //nr wierzch. < odleglosc, skad przyszedl > for (int i = 0; i < g.NodesNr; i++) { if (i == start) { map.Add(i, new Tuple <int, int>(0, -1)); } else { map.Add(i, new Tuple <int, int>(INF, -1)); } } var con = new List <Tuple <int, int, int> >();//lista polaczen skad / dokad / waga for (int i = 0; i < g.NodesNr; i++) { for (int j = 0; j < g.NodesNr; j++) { if (g.GetConnection(i, j)) { con.Add(new Tuple <int, int, int>(i, j, g.getWeight(i, j))); } } } for (int i = 0; i < g.NodesNr - 1; i++) { for (int j = 0; j < con.Count; j++) { if (map[con[j].Item2].Item1 == INF && map[con[j].Item1].Item1 == INF)//pozbywam sie operacji na nieskonczonosciach { continue; } if (map[con[j].Item2].Item1 > map[con[j].Item1].Item1 + con[j].Item3)//relaksacja { map[con[j].Item2] = new Tuple <int, int>(map[con[j].Item1].Item1 + con[j].Item3, con[j].Item1); } } } //sprawdzenie czy istnieje cykl ujemny //jesli wykona sie warunek istnieje ujemny for (int j = 0; j < con.Count; j++) { if (map[con[j].Item2].Item1 > map[con[j].Item1].Item1 + con[j].Item3) //relaksacja { return(null); //jesli relaksacja jest możliwa po V-1 przejściach istnieje cykl ujemny } } //sciezka wynikowa List <int> path = new List <int>(); recBellman(map, path, start, finish); //sciezke otrzymamy od konca if (path.Count == 1) //brak sciezki { return(null); } path.Reverse(); return(path); }