/// <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 ArrayMatrix[] Floyd(ArrayMatrix 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."); var n = adjacence_matrix.RowCount; var D = adjacence_matrix.Clone(); // distance matrix var P = new ArrayMatrix(n); double buf; for (var k = 1; k <= n; k++) for (var i = 1; i <= n; i++) for (var j = 1; j <= n; j++) { buf = D[i, k].Real + D[k, j].Real; if (buf < D[i, j].Real) { D[i, j].Real = buf; P[i, j].Real = k; } } return new ArrayMatrix[] {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 ArrayMatrix Solve(ArrayMatrix A, ArrayMatrix b) { var A2 = A.Clone(); var b2 = b.Clone(); if (!A2.IsSquare()) throw new InvalidOperationException("Cannot uniquely solve non-square equation system."); var n = A2.RowCount; var 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; }