-
Notifications
You must be signed in to change notification settings - Fork 132
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
Exterior powers of finitely presented modules #2879
Conversation
49d38d7
to
4062c3b
Compare
@jankoboehm it would be great if you could have a look at this and comment on it. We want to make sure that potential applications can actually use this interface; and if not, revise it. But for this of course we need to know what is needed / missing / ... |
This reverts commit 48b9752.
5f01142
to
6ace053
Compare
test/Modules/ExteriorPowers.jl
Outdated
@testset "multiplication map" begin | ||
R, (x, y, u, v, w) = QQ[:x, :y, :u, :v, :w] | ||
|
||
F = FreeMod(R, 5) | ||
F3, mm = Oscar.exterior_power(F, 3) | ||
v = (F[1], F[3], F[4]) | ||
u = (F[1], F[4], F[3]) | ||
@test mm(v) == -mm(u) | ||
w = mm(v) | ||
@test preimage(mm, w) == v | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@fieker : Is this like you had intended?
test/Modules/GradedModules.jl
Outdated
@testset "all_monomials for graded free modules" begin | ||
R, (x, y, u, v, w) = QQ[:x, :y, :u, :v, :w] | ||
S, (x, y, u, v, w) = grade(R) | ||
|
||
F = graded_free_module(S, [-1, 2]) | ||
|
||
for d in -4:4 | ||
amm = Oscar.all_monomials(F, d) | ||
@test d < -1 || !isempty(amm) | ||
@test all(x->degree(x) == grading_group(F)([d]), amm) | ||
end | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jankoboehm : Sorry, this was not intended to be here. It was a little play-around for me needed to take some steps towards implementing sheaf cohomology. But I guess this might be useful also for you and the graded modules in general. Would you like this to be put in a separate PR?
Since some people like performance comparisons:
|
It looks good to me, shall we call the function mult_map rather pure and the inverse inv_pure as in the tensor product? See also in the tensor product code:
Note that these functions are created, when creating the module, so they do not create a parent on the fly. Perhaps add a show function similar to the one for the tensor product of modules, see:
With regard to the show function of the elements, you can set the field F.S in a free module F, which should have the symbols for the generators. We need not only the case of free modules but also subquos. That we can do in a seperate effort. |
I think it would make sense to put |
Agreed and done. @lgoettgens : There seems to be some problem with an existing function |
I think you create a function with that name in the global Oscar module, right? In this case, to make the two same-named functions the same, you would need to remove the two exports in |
return first(koszul_duals([v], cached=cached)) | ||
end | ||
|
||
function induced_map_on_exterior_power(phi::FreeModuleHom{<:FreeMod, <:FreeMod, Nothing}, p::Int; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A similar function already exists for LieAlgebraModule.jl under the name hom_exterior_power
. It would be great to have a unified interface for both types of modules.
This is not a request for you to change your proposal, I just wanted to mention it.
@fieker suggested to name this method simply hom
and supply both exterior powers as arguments, as well as the home on the base modules
If anyone found the time to approve and merge this, that would be great! I'm afraid the green lights of the tests might be corrupted by future merge conflicts. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I started to look at this but have to run to other appointments, so just some quick comments, I hope I can look at the rest later.
# generators of M. But they can also be used for other purposes | ||
# like enumerating subsets of p elements out of a set with n elements. | ||
######################################################################## | ||
mutable struct OrderedMultiIndex{IntType<:IntegerUnion} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this struct mutable?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good question. It probably shouldn't be, unless we want to allow in-place iteration. Do we? Is there a potential speedup from making it immutable?
@assert bound(a) == bound(b) "multiindices must have the same bounds" | ||
|
||
# in case of a double index return zero | ||
any(x->(x in indices(b)), indices(a)) && return 0, a |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This makes this function _mult
not type stable. Maybe
any(x->(x in indices(b)), indices(a)) && return 0, a | |
any(x->(x in indices(b)), indices(a)) && return 0, indices(a) |
or (IMHO nicer)
any(x->(x in indices(b)), indices(a)) && return 0, a | |
any(x->(x in indices(b)), indices(a)) && return 0, T[] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the catch. But the second needs to reallocate memory, doesn't it?
|
||
######################################################################## | ||
# A data type to facilitate iteration over all ordered multiindices | ||
# of the form 0 < i₁ < i₂ < … < iₚ ≤ n for fixed 0 ≤ p ≤ n. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So... this is essentially the parent of OrderedMultiIndex{T}
, except that it does not specify T
...? Or "hardcodes" T
to be Int
(?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was not so sure about this, to be honest. It's not actually a parent in the Oscar sense, but in spirit: yes. And it's true: It doesn't know about the T
. But it's hardcoded only in the sense that iterating over this will always produce an OrderedMultiIndex
with T = Int64
.
At some point I thought of removing the T
altogether, but then I didn't see any real problem in keeping it either. It's just a bit weird that OrderdMultiIndexSet
doesn't know about it. But since it's not an actual parent: Do you see a real problem here?
As discussed with @wdecker: I deprecated some of the singular methods around koszul complexes etc. Speed tests revealed that singular's depth computation is significantly faster. The same might hold for Either way: All methods imported from singular are now still available as internal methods. In particular for the depth computation I still use it whenever the coefficient ring is a field. For the Koszul homology I'm not so sure what the best solution is: If we were using singular's version, then the user might be wondering why the output is not compatible with the output of |
@ederc, @hannes14: Can you see why importing the functions mentioned by @HechtiDerLachs are slower on the OSCAR side as compared to the Singular side? See |
R = parent(V[1]) | ||
@assert all(x->parent(x) == R, V) | ||
n = length(V) | ||
KM = [koszul_matrix(V, i) for i=n:-1:1] | ||
KM = [_koszul_matrix_from_singular(V, i) for i=n:-1:1] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@wdecker: I suppose it's because of this line here. The morphisms of the Koszul complex have huge matrices which are sparse. This forces Oscar to allocate the full matrix as a dense matrix. If we had the possibility to pull the morphisms from the Singular side as a list of module elements (images of the generators), we would probably be better off.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Even if not urgent since anyway seemingly fast, we should use a ModuleGens to transfer sparse data.
I'm taking back my doubts about the speed of Oscar vs. Singular in julia> n = 5
5
julia> R, _ = polynomial_ring(QQ, "x"=>1:n)
(Multivariate polynomial ring in 5 variables over QQ, QQMPolyRingElem[x[1], x[2], x[3], x[4], x[5]])
julia> FR = FreeMod(R, 1)
Free module of rank 1 over Multivariate polynomial ring in 5 variables over QQ
julia> IR = ideal(R, gens(R))
ideal(x[1], x[2], x[3], x[4], x[5])
julia> IR = IR*IR
ideal(x[1]^2, x[1]*x[2], x[1]*x[3], x[1]*x[4], x[1]*x[5], x[2]^2, x[2]*x[3], x[2]*x[4], x[2]*x[5], x[3]^2, x[3]*x[4], x[3]*x[5], x[4]^2, x[4]*x[5], x[5]^2)
julia> @time koszul_homology(gens(IR), FR, 5);
14.186331 seconds (32.92 M allocations: 1.295 GiB, 6.16% gc time)
julia> @time Oscar._koszul_homology_from_singular(gens(IR), FR, 5);
197.457997 seconds (332.20 M allocations: 10.411 GiB, 0.16% gc time) |
With the julia> n = 4
4
julia> R, _ = polynomial_ring(QQ, "x"=>1:n)
(Multivariate polynomial ring in 4 variables over QQ, QQMPolyRingElem[x[1], x[2], x[3], x[4]])
julia> FR = FreeMod(R, 1)
Free module of rank 1 over Multivariate polynomial ring in 4 variables over QQ
julia> IR = ideal(R, gens(R))
ideal(x[1], x[2], x[3], x[4])
julia> IR = IR*IR
ideal(x[1]^2, x[1]*x[2], x[1]*x[3], x[1]*x[4], x[2]^2, x[2]*x[3], x[2]*x[4], x[3]^2, x[3]*x[4], x[4]^2)
julia> @time depth(IR, FR) # Oscar version
0.409409 seconds (1.72 M allocations: 69.002 MiB)
4
julia> @time Oscar._depth_from_singular(IR, FR)
0.188377 seconds (419 allocations: 21.906 KiB)
4
julia> @time depth(IR, FR)
0.374969 seconds (1.72 M allocations: 68.984 MiB)
4
julia> @time Oscar._depth_from_singular(IR, FR)
0.184218 seconds (417 allocations: 21.875 KiB)
4 |
I can not find the reason why Singular's depth computation is so much faster. The only thing I could imagine is that the |
At the moment the homology computes kernel (which might be expensive), and image (which is free of cost) creates a subquo (which is free of cost), and then does membership to determine whether the generators are (hence the module is) zero, which triggers a Gröbner basis computation of the image. One could go via a presentation to determine whether the module is zero (which would rely on modulo). The other thing is, that we do a lot of bookkeeping in Oscar to have things free of an ordering of a basis, which might also cost a bit and is not needed to find that something is zero. I think as a first step, we should restructure the is_zero for subquos a bit relying rather on division of one ModuleGens by another, than checking is_zero for individual generators, to avoid copying things around. I will have a look. If that does nor work, we can try to use the presentation command. If (and only if) that is slower than in Singular, we can map it to modulo. |
I think that this PR tries to achieve many different things, in particular, it does a lot more than written in the PR title. What do you think about splitting it into one that just implements exterior powers for different types of modules, and a second one with everything about homology happening here that builds on the first one? |
No, I strongly object to this proposal. We have discussed splitting this at earlier points and decided against it. Splitting it now will produce several hours of more work for the person performing the split with relatively little benefit. Reviewing will probably become a little more structured, but the actual amount of work will not decrease. Moreover, the review has already taken place incrementally here and I don't see the point in doing these discussions again on different PRs. If anything, I can change the title again. |
I spoke with @fingolfin and he has no objections to merging this anymore. If needed, we can clean up things later. |
This is a suggestions for how we could do exterior powers of modules. See the test file for how this can be used.