[SYSTEMDS-3778] Introduce determinant computation primitives #2196
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
[SYSTEMDS-3778] Introduce determinant computation primitives
This PR introduces the computation of the determinant of a matrix. It
provides different strategies of computing those determinants. Internally
it is possible to switch between calculating the determinant using the
builtin LU decomposition of the commons math library, Gaussian algorithm,
Bareiss algorithm and Laplace expansion. Furthermore, static simplification
rewrites
det(t(X)) -> det(X)
det(X%*%Y) -> det(X)*det(Y)
det(lambda*X) -> lambda^nrow(X)*det(X)
have been implemented.
All strategies have been benchmarked using 12x12-matrices. Very large matrices
can result in the laplace algorithm to take too long. The numbers consist
of the average execution time of three runs; with different matrix seeds
(7, 233, 4242). Furthermore, it we distinguish between sparse and dense matrices,
because each algorithm has its own way of optimizing for sparse matrices.
Further observations:
decomposition.
numbers are used, because the divisions in the algorithm have no remainder in
that case.
the matrix is transposed
(det(t(X)) in R vs det(X) in SystemDS)
. The LUdecomposition does not have this issue. This could be an indicator that
the LU decomposition is more robust against floating-point errors.
comparison to the equivalent implementation in R. It does not pass the
test with matrix size of around 30x30. LU decomposition and Bareiss
algorithm are suspected to have lower floating-point errors.
It is adviced to never use the laplace expansion, because of its inefficiency;
the runtime is factorial. Those observations lead to using using the
LU decomposition because of its higher accuracy, despite being a bit slower
than the alternatives.
The reasoning
det(lambda*X) -> lambda^nrow(X)*det(X)
as rule is, thatcomputing the power of a scalar can be done in logarithmic time, whereas
the multiplication of a scalar with a matrix is quadratic. Another reason
for this simplification are simplifications of examples such as
det(lambda*t(X)) -> lambda^nrow(X)*det(X)
, which would be harder to implementwithout this simplification.