/// <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> /// For this matrix A, this method solves Ax = b via LU factorization with /// column pivoting. /// </summary> /// <param name="b">Vector of appropriate length.</param> /// <remarks>Approximately n^3/3 + 2n^2 dot operations ~> O(n^3)</remarks> public static MatrixQ Solve(MatrixQ A, MatrixQ b) { MatrixQ A2 = A.Clone(); MatrixQ b2 = b.Clone(); if (!A2.IsSquare()) throw new InvalidOperationException("Cannot uniquely solve non-square equation system."); int n = A2.RowCount; MatrixQ P = A2.LUSafe(); // We know: PA = LU => [ Ax = b <=> P'LUx = b <=> L(Ux) = (Pb)] since P is orthogonal // set y := Ux, solve Ly = Pb by forward insertion // and Ux = y by backward insertion b2 = P * b2; // this solves Ly = Pb (A2.ExtractLowerTrapeze() - Diag(A2.DiagVector()) + Identity(n)).ForwardInsertion(b2); // this solves Ux = y (A2.ExtractUpperTrapeze()).BackwardInsertion(b2); return b2; }