Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LinearAlgebra: Add bareiss det for BigInt Matrices (#40128) :: Take 2 #40868

Merged
merged 3 commits into from
May 21, 2021

Conversation

Pramodh-G
Copy link
Contributor

@Pramodh-G Pramodh-G commented May 19, 2021

As said in the previous PR with the same name, I messed up my julia fork trying to rebase and push clean code.
This fixes #40128
Do suggest ways to improve this PR.
cc: @simeonschaub

@oscardssmith oscardssmith added bignums BigInt and BigFloat linear algebra Linear algebra maths Mathematical functions labels May 19, 2021
# Resolve Issue #40128
function det(A::AbstractMatrix{BigInt})
m, n = size(A)
if m == n || throw(DimensionMismatch("matrix is not square: dimensions are $(size(A))"))
Copy link
Member

@stevengj stevengj May 19, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like this test should be in det_bareiss!, and then just have:

det(A::AbstractMatrix{BigInt}) = det_bareiss(A)

Note also that you can simply call checksquare(A) in det_bareiss!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there any reasoning behind this design choice? I'm trying to learn as I go along, so It would be helpful if you could shed some light on this.

I'll add a commit correcting this, thanks!

Copy link
Member

@stevengj stevengj May 19, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It shouldn't matter whether someone calls det_bareiss! directly, or through det_bareiss, or through det — in all cases, it should check whether the matrix is square, because otherwise that function doesn't make sense.

@@ -355,6 +355,10 @@ end
@test [[1,2, [3,4]], 5.0, [6im, [7.0, 8.0]]] ≈ [[1,2, [3,4]], 5.0, [6im, [7.0, 8.0]]]
end

@testset "Issue 40128" begin
@test LinearAlgebra.det_bareiss(BigInt[1 2; 3 4]) == -2
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fix the indenting here. (4 spaces)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also check that the result is a BigInt

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that det([1 2; 3 4]) == -2 returns true as well, so this is not a great test.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Specifically, you should probably test something like BigInt[1 big(2)^65+1; 3 4]) which will ensure that no Float based method would produce the right answer.

Copy link
Member

@stevengj stevengj May 19, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could try det(BigInt[9 1 8 0; 0 0 8 7; 7 6 8 3; 2 9 7 7])::BigInt == -1, since for Int this is off by about 1e-12 (and even for BigInt it currently gives a non-integer result).

Copy link
Member

@stevengj stevengj May 19, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Specifically, you should probably test something like BigInt[1 big(2)^65+1; 3 4]) which will ensure that no Float based method would produce the right answer.

Actually the current LU algorithm gives the exact answer here:

julia> det(BigInt[1 big(2)^65+1; 3 4]) - (4 - 3*(big(2)^65+1))
0.0

(Remember that it uses BigFloat.)

return sign * M[end,end]
end
"""
LinearAlgebra.det_bareiss(M)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't put the LinearAlgebra. in the docstring, I think.

Copy link
Contributor Author

@Pramodh-G Pramodh-G May 19, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll change it, butLinearAlgebra.jl contains docstrings like

LinearAlgebra.peakflops()

This is the one example I could find though, should I change this too?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would leave the peakflops case out of this PR.

@Pramodh-G
Copy link
Contributor Author

@stevengj thanks for the test case. Turns out the findfirst was causing indices to be returned relative to column i, which was throwing a 0/0 error on your test case. I fixed it along with other suggestions

Thanks!

@stevengj
Copy link
Member

Needs a NEWS.md entry, otherwise looking good

@oscardssmith oscardssmith added the merge me PR is reviewed. Merge when all tests are passing label May 21, 2021
@simeonschaub simeonschaub merged commit d6701bb into JuliaLang:master May 21, 2021
@Pramodh-G Pramodh-G deleted the pramodh/bareiss branch May 28, 2021 09:56
@simeonschaub simeonschaub removed the merge me PR is reviewed. Merge when all tests are passing label May 29, 2021
shirodkara pushed a commit to shirodkara/julia that referenced this pull request Jun 9, 2021
johanmon pushed a commit to johanmon/julia that referenced this pull request Jul 5, 2021
Keno added a commit that referenced this pull request Oct 18, 2021
We have several implementations of the Bareiss fraction-free row-reduction
algorithm in the Julia ecosystem. The one in Base was added in #40868
to compute exact determinants. We also have implementations in MTK [1]
and Modia [2].

The MTK and Modia versions additionally have support for custom pivot
selection, open-code a sparse matrix data structure adapted to their
domains and support rank-deficient matrices.

I would like to separate out the algorithmic and data-structures concerns
so that they may tested independently. Of course this function isn't
particularly large, but implementing it correctly and performantly
is still not trivial, so it seems better to have one implementation
rather than three.

[1] https://github.com/SciML/ModelingToolkit.jl/blob/master/src/systems/alias_elimination.jl#L236
[2] https://github.com/ModiaSim/ModiaBase.jl/blob/6c341eed72d9867553cb9565330d8ae85221b343/src/LinearIntegerEquations.jl#L204
Keno added a commit that referenced this pull request Oct 18, 2021
We have several implementations of the Bareiss fraction-free row-reduction
algorithm in the Julia ecosystem. The one in Base was added in #40868
to compute exact determinants. We also have implementations in MTK [1]
and Modia [2].

The MTK and Modia versions additionally have support for custom pivot
selection, open-code a sparse matrix data structure adapted to their
domains and support rank-deficient matrices.

I would like to separate out the algorithmic and data-structures concerns
so that they may tested independently. Of course this function isn't
particularly large, but implementing it correctly and performantly
is still not trivial, so it seems better to have one implementation
rather than three.

[1] https://github.com/SciML/ModelingToolkit.jl/blob/master/src/systems/alias_elimination.jl#L236
[2] https://github.com/ModiaSim/ModiaBase.jl/blob/6c341eed72d9867553cb9565330d8ae85221b343/src/LinearIntegerEquations.jl#L204
oscardssmith pushed a commit that referenced this pull request Feb 1, 2022
We have several implementations of the Bareiss fraction-free row-reduction
algorithm in the Julia ecosystem. The one in Base was added in #40868
to compute exact determinants. We also have implementations in MTK [1]
and Modia [2].

The MTK and Modia versions additionally have support for custom pivot
selection, open-code a sparse matrix data structure adapted to their
domains and support rank-deficient matrices.

I would like to separate out the algorithmic and data-structures concerns
so that they may tested independently. Of course this function isn't
particularly large, but implementing it correctly and performantly
is still not trivial, so it seems better to have one implementation
rather than three.

[1] https://github.com/SciML/ModelingToolkit.jl/blob/master/src/systems/alias_elimination.jl#L236
[2] https://github.com/ModiaSim/ModiaBase.jl/blob/6c341eed72d9867553cb9565330d8ae85221b343/src/LinearIntegerEquations.jl#L204
oscardssmith pushed a commit that referenced this pull request Mar 9, 2024
New users are commonly surprised that determinants of integer matrices
give an approximate floating-point answer (#40128), and are unaware that
an exact algorithm is implemented for `BigInt` matrices (#40868). This
PR comments on both of these facts in the `det` documentation.

(At some point, we may want to mark `LinearAlgebra.det_bareiss` as
`public`, and document it, but that can be done in a future PR.)
mkitti pushed a commit to mkitti/julia that referenced this pull request Apr 13, 2024
New users are commonly surprised that determinants of integer matrices
give an approximate floating-point answer (JuliaLang#40128), and are unaware that
an exact algorithm is implemented for `BigInt` matrices (JuliaLang#40868). This
PR comments on both of these facts in the `det` documentation.

(At some point, we may want to mark `LinearAlgebra.det_bareiss` as
`public`, and document it, but that can be done in a future PR.)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bignums BigInt and BigFloat linear algebra Linear algebra maths Mathematical functions
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Integer-matrix determinants are not computed exactly
4 participants