/// <summary> /// Tworzy Liste wszystkich spojnych skladowych /// </summary> /// <param name="f">graf</param> /// <returns>lista spojnych</returns> public static List <List <int> > spojne(DirectedGraphMatrix f) { List <int> stark = new List <int>(); bool[] visited = new bool[f.NodesNr]; visited[0] = true; DirectedGraphList q = Converter.ConvertToSList(f); for (int i = 0; i < f.NodesNr; i++) { rek(q, i, stark, visited); } q = Converter.ConvertToSList(transpose(f)); stark.Reverse(); //tworzyc listy spojnosci OK List <List <int> > lista = new List <List <int> >(); lista.Add(new List <int>()); int ind = 0; bool[] visited2 = new bool[f.NodesNr]; for (int i = 0; i < f.NodesNr; i++) { rek2(q, i, stark, visited2, lista, ref ind); } lista.Remove(lista[ind]); return(lista); }
private static void topologicSorting(DirectedGraphMatrix originalGraph, List <int> retList, List <int> Done) { DirectedGraphMatrix graph = new DirectedGraphMatrix(1); graph.Set(originalGraph); while (retList.Count != originalGraph.NodesNr) { //find node with 0 dim for (int i = 0; i < graph.NodesNr; ++i) { if (Done.Contains(i)) { continue; } var neighbours = graph.GetNeighbours(i); if (neighbours.Count == 0) { //remove this node retList.Add(i); Done.Add(i); foreach (var node in graph.GetConnectedToNodes(i)) { graph.RemoveConnection(node, i); } } } } }
/// <summary> /// Szukanie cykli na grafie /// </summary> /// <param name="f">graf</param> /// <returns>Lista cykli(lista)</returns> public static List <List <int> > circuts(DirectedGraphMatrix f) { DirectedGraphList li = Converter.ConvertToSList(f); List <List <int> > cycle = new List <List <int> >(); List <int> white = new List <int>(); for (int i = 0; i < f.NodesNr; i++) { white.Add(i); } List <int> grey = new List <int>(); List <int> black = new List <int>(); List <int> temp = new List <int>(); for (int i = 0; i < li.NodesNr; i++) { rekc(li, white, grey, black, cycle, temp, i); } //formatowanie listy !!! for (int i = 0; i < cycle.Count; i++) { while (cycle[i][0] != cycle[i][cycle[i].Count - 1]) { cycle[i].Remove(cycle[i][0]); } } return(cycle); }
/// <summary> /// Tworzy graf skierowany na podstawie spójnego grafu nieskierowanego /// </summary> /// <param name="matrix">Spójny graf nieskierowany</param> /// <returns>Graf skierowany</returns> public static DirectedGraphMatrix CreateDirectional(GraphMatrix matrix) { Random r = new Random(); DirectedGraphMatrix directedMatrix = new DirectedGraphMatrix(matrix.NodesNr); for (int i = 0; i < matrix.NodesNr; i++) { for (int j = 0; j <= i; j++) { if (matrix.GetConnection(i, j)) { switch (r.Next(3)) { case 0: directedMatrix.MakeConnection(i, j); break; case 1: directedMatrix.MakeConnection(j, i); break; case 2: directedMatrix.MakeConnection(i, j); directedMatrix.MakeConnection(j, i); break; } } } } return(directedMatrix); }
public static List <int> TopologicSorting(DirectedGraphMatrix Graph) { List <int> topologicList = new List <int>(); List <int> done = new List <int>(); topologicSorting(Graph, topologicList, done); return(topologicList); }
/// <summary> /// Wyznacza wage polaczenia /// przydatne do Bellmana forda /// </summary> /// <param name="g">graf</param> /// <param name="list">sciezka z elementem poczatkowym /reszta/ koniec</param> /// <returns></returns> public static int pathWeight(DirectedGraphMatrix g, List <int> list) { int sum = 0; for (int i = 0; i < list.Count - 1; i++) { sum += g.getWeight(list[i], list[i + 1]); //Console.Write(list[i] + "->" + list[i + 1] + ":" + g.getWeight(list[i], list[i + 1]) + "; "); } //Console.WriteLine(); return(sum); }
public MaxFlow1(DirectedGraphMatrix g) { int nodes = g.NodesNr; FlowMatrix = new int[nodes, nodes]; weightMatrix = new int[nodes, nodes]; for (int i = 0; i < nodes; ++i) { for (int j = 0; j < nodes; ++j) { weightMatrix[i, j] = g.getWeight(i, j); } } }
public DirectedWindow() { InitializeComponent(); Graph = GraphGenerator.CreateDirectional(GraphGenerator.generatorGER(10, 11)); Renderer = new DirectionalGraphRenderer(Graph, GraphControl, VM); Graph.OnChange += onGraphChange; GraphControl.OnLineClick += createWeight; GraphControl.OnTwoNodeClickEvent += ConnectTwoNodes; Graph.OnChange(); DataContext = VM; }
/// <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); }
/// SKIEROWANE KONWERSJE public static DirectedGraphMatrix ConvertToSMatrix(DirectedGraphMatrixInc from) { DirectedGraphMatrix x = new DirectedGraphMatrix(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> /// Czy w grafie wystepuje ujemny cykl /// </summary> /// <param name="x"></param> /// <param name="w"></param> /// <returns></returns> public static bool ujemnyCykl(DirectedGraphMatrix x, int[,] w) { List <List <int> > l = circuts(x); for (int i = 0; i < l.Count; i++) { int sum = 0; for (int j = 0; j < l[i].Count - 1; j++) { sum += w[l[i][j], l[i][j + 1]]; } if (sum < 0) { return(true); } } return(false); }
private DirectedGraphMatrix createGraphFromRows(List <Row> rows) { DirectedGraphMatrix graph = new DirectedGraphMatrix(Node.Indexer); for (int i = 0; i < rows.Count; ++i) { var row = rows[i]; foreach (var node in row) { graph.AddToColumn(i); foreach (var connectedTo in node.JoinedTo) { graph.MakeConnection(node.Index, connectedTo.Index); } } } return(graph); }
/// <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)); }
private DirectedGraphMatrix createGraphFromRows(List <Row> rows) { DirectedGraphMatrix graph = new DirectedGraphMatrix(Node.Indexer); for (int i = 0; i < rows.Count; ++i) { var row = rows[i]; foreach (var node in row) { graph.AddToColumn(i); foreach (var connectedTo in node.JoinedTo) { var flow = flows.First(f => f.Item1.Index == node.Index && f.Item2.Index == connectedTo.Index); graph.MakeConnection(node.Index, connectedTo.Index); graph.setWeight(node.Index, connectedTo.Index, flow.Item3); } } } return(graph); }
public int findMaxFlow(DirectedGraphMatrix g) { int size = g.nodesNr; int max; int min; List <int> tempList = new List <int>(); int[,] tempWeightMatrix = new int[nodes, nodes]; for (int i = 0; i < nodes; ++i) { for (int j = 0; j < nodes; ++j) { tempWeightMatrix[i, j] = weightMatrix[i, j]; } } do { tempList = createFlowRoute(tempWeightMatrix, size); if (tempList.Count > 1) { min = findMinWeight(tempList); if (tempList.Count > 1) { turnRoute(tempList, min); } odejmijWageOdTrasy(tempList, min); max += min; } else { break; } } while (tempList.Count != 0); createFlowMatrix(weightMatrix, tempWeightMatrix, size); return(max); }
public DirectionalGraphRenderer(DirectedGraphMatrix Graph, GraphControl GraphControl, DirectedWindowViewModel vm) { this.GraphControl = GraphControl; this.Graph = Graph; this.DirectedWindowVM = vm; }
/// <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); }
/// <summary> /// Tworzenie macierzy odleglosci pomiedzy wszystkimi parami wierzcholkow w grafie spojnym skierowanym, wykorzystuje algorytm Dijkstry /// </summary> /// <param name="from"></param> Graf skierowany, w ktorym liczymy odleglosci miedzy wszystkimi parami wierzcholkow /// <returns></returns> distances - Macierz odleglosci miedzy wszystkimi parami wierzcholkow public static int[,] distancesDirectedMatrix(DirectedGraphMatrix graph) { int nodes = graph.NodesNr; int[,] distances = new int[nodes, nodes]; List <int> path = new List <int>(); int total_dist = 0; int dist = 0; const int INF = int.MaxValue - 10000; for (int i = 0; i < nodes; ++i) { for (int j = 0; j < nodes; ++j) { if (i == j) { distances[i, j] = 0; } else { distances[i, j] = INF; } } } for (int i = 0; i < nodes; ++i) { for (int j = 0; j < nodes; ++j) { if (i == j) { continue; } else { path = PathFinding.Dijkstra(graph, i, j); if (path.Count == 0) { continue; } else if (path.Count == 1) { distances[i, j] = graph.getWeight(i, path[0]); path.Clear(); } else { for (int k = 0; k < path.Count - 1; ++k) { dist += graph.getWeight(path[k], path[k + 1]); } total_dist = dist + graph.getWeight(i, path[0]); distances[i, j] = total_dist; total_dist = dist = 0; path.Clear(); } } } } return(distances); }
/// <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]); } }