/// <summary> /// Computes all shortest distance between any vertices in a given graph. /// </summary> /// <param name="adjacence_matrix">Square adjacence matrix. The main diagonal /// is expected to consist of zeros, any non-existing edges should be marked /// positive infinity.</param> /// <returns>Two matrices D and P, where D[u,v] holds the distance of the shortest /// path between u and v, and P[u,v] holds the shortcut vertex on the way from /// u to v.</returns> public static MatrixQ[] Floyd(MatrixQ adjacence_matrix) { if (!adjacence_matrix.IsSquare()) throw new ArgumentException("Expected square matrix."); else if (!adjacence_matrix.IsReal()) throw new ArgumentException("Adjacence matrices are expected to be real."); int n = adjacence_matrix.RowCount; MatrixQ D = adjacence_matrix.Clone(); // distance matrix MatrixQ P = new MatrixQ(n); double buf; for (int k = 1; k <= n; k++) for (int i = 1; i <= n; i++) for (int j = 1; j <= n; j++) { buf = D[i, k].Re + D[k, j].Re; if (buf < D[i, j].Re) { D[i, j].Re = buf; P[i, j].Re = k; } } return new MatrixQ[] { D, P }; }
/// <summary> /// Returns the shortest path between two given vertices i and j as /// int array. /// </summary> /// <param name="P">Path matrix as returned from Floyd().</param> /// <param name="i">One-based index of start vertex.</param> /// <param name="j">One-based index of end vertex.</param> /// <returns></returns> public static ArrayList FloydPath(MatrixQ P, int i, int j) { if (!P.IsSquare()) throw new ArgumentException("Path matrix must be square."); else if (!P.IsReal()) throw new ArgumentException("Adjacence matrices are expected to be real."); ArrayList path = new ArrayList(); path.Add(i); //int borderliner = 0; //int n = P.Size()[0] + 1; // shortest path cannot have more than n vertices! while (P[i, j] != 0) { i = Convert.ToInt32(P[i, j]); path.Add(i); //borderliner++; //if (borderliner == n) // throw new FormatException("P was not a Floyd path matrix."); } path.Add(j); return path; }
/// <summary> /// Performs depth-first search for a graph given by its adjacence matrix. /// </summary> /// <param name="adjacence_matrix">A[i,j] = 0 or +infty, if there is no edge from i to j; any non-zero value otherwise.</param> /// <param name="root">The vertex to begin the search.</param> /// <returns>Adjacence matrix of the computed spanning tree.</returns> public static MatrixQ DFS(MatrixQ adjacence_matrix, int root) { if (!adjacence_matrix.IsSquare()) throw new ArgumentException("Adjacence matrices are expected to be square."); else if (!adjacence_matrix.IsReal()) throw new ArgumentException("Adjacence matrices are expected to be real."); int n = adjacence_matrix.RowCount; if (root < 1 || root > n) throw new ArgumentException("Root must be a vertex of the graph, e.i. in {1, ..., n}."); MatrixQ spanTree = new MatrixQ(n); bool[] marked = new bool[n + 1]; Stack todo = new Stack(); todo.Push(root); marked[root] = true; // adajacence lists for each vertex ArrayList[] A = new ArrayList[n + 1]; for (int i = 1; i <= n; i++) { A[i] = new ArrayList(); for (int j = 1; j <= n; j++) if (adjacence_matrix[i, j].Re != 0 && adjacence_matrix[i, j].Im != double.PositiveInfinity) A[i].Add(j); } int v, w; while (todo.Count > 0) { v = (int)todo.Peek(); if (A[v].Count > 0) { w = (int)A[v][0]; if (!marked[w]) { marked[w] = true; // mark w spanTree[v, w].Re = 1; // mark vw todo.Push(w); // one more to search } A[v].RemoveAt(0); } else todo.Pop(); } return spanTree; }