Applies Thomas algorithm to solve a linear system where the linear operand is a tri-diagonal matrix. See https://en.wikipedia.org/wiki/Tridiagonal_matrix_algorithm for a simple reference on the Thomas algorithm. It is expected that the three diagonals are represented as tensors of shape [..., 1, num_equations] where num_equations is the number of dimensions of the unknowns considered in the linear
| 133 | // the right-hand-side `rhs` should be [..., num_rhs, num_equations]. The |
| 134 | // solution will have the shape [..., num_rhs, num_equations]. |
| 135 | StatusOr<XlaOp> ThomasSolver(XlaOp lower_diagonal, XlaOp main_diagonal, |
| 136 | XlaOp upper_diagonal, XlaOp rhs) { |
| 137 | TF_ASSIGN_OR_RETURN(TridiagonalSystemShape system_shape, |
| 138 | CheckSystemAndReturnShape(lower_diagonal, main_diagonal, |
| 139 | upper_diagonal, rhs)); |
| 140 | |
| 141 | auto rank = system_shape.rank; |
| 142 | auto num_eqs = system_shape.num_equations; |
| 143 | |
| 144 | std::vector<XlaOp> main_diag_after_elimination(num_eqs); |
| 145 | std::vector<XlaOp> rhs_after_elimination(num_eqs); |
| 146 | std::vector<XlaOp> upper_diagonal_coeffs(num_eqs); |
| 147 | |
| 148 | main_diag_after_elimination[0] = Coefficient(main_diagonal, 0); |
| 149 | rhs_after_elimination[0] = Coefficient(rhs, 0); |
| 150 | for (int64 i = 0; i < num_eqs - 1; i++) { |
| 151 | upper_diagonal_coeffs[i] = Coefficient(upper_diagonal, i); |
| 152 | } |
| 153 | |
| 154 | // Forward transformation. |
| 155 | for (int64 i = 1; i < num_eqs; i++) { |
| 156 | auto lower_diagonal_i = Coefficient(lower_diagonal, i); |
| 157 | auto main_diagonal_i = Coefficient(main_diagonal, i); |
| 158 | auto rhs_i = Coefficient(rhs, i); |
| 159 | |
| 160 | auto w_i = lower_diagonal_i / main_diag_after_elimination[i - 1]; |
| 161 | |
| 162 | main_diag_after_elimination[i] = |
| 163 | main_diagonal_i - w_i * upper_diagonal_coeffs[i - 1]; |
| 164 | rhs_after_elimination[i] = rhs_i - w_i * rhs_after_elimination[i - 1]; |
| 165 | } |
| 166 | |
| 167 | std::vector<XlaOp> x_coeffs(num_eqs); |
| 168 | |
| 169 | // Backward reduction. |
| 170 | x_coeffs[num_eqs - 1] = rhs_after_elimination[num_eqs - 1] / |
| 171 | main_diag_after_elimination[num_eqs - 1]; |
| 172 | for (int i = num_eqs - 2; i >= 0; i--) { |
| 173 | x_coeffs[i] = (rhs_after_elimination[i] - |
| 174 | upper_diagonal_coeffs[i] * x_coeffs[i + 1]) / |
| 175 | main_diag_after_elimination[i]; |
| 176 | } |
| 177 | |
| 178 | return ConcatInDim(lower_diagonal.builder(), x_coeffs, rank - 1); |
| 179 | } |
| 180 | |
| 181 | // Applies Thomas algorithm to solve a linear system where the linear operand |
| 182 | // is a tri-diagonal matrix. |
nothing calls this directly
no test coverage detected