Skip to content

Add a canonical form for lattices#6102

Open
Kazak-11 wants to merge 16 commits into
oscar-system:masterfrom
Kazak-11:add_lattice_canonical_form
Open

Add a canonical form for lattices#6102
Kazak-11 wants to merge 16 commits into
oscar-system:masterfrom
Kazak-11:add_lattice_canonical_form

Conversation

@Kazak-11

@Kazak-11 Kazak-11 commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Added function to get canonical form of lattice following ideas of Sikirić, Haensch, Voight and van Woerden [SHVW20]

@Kazak-11

Kazak-11 commented Jul 7, 2026

Copy link
Copy Markdown
Contributor Author

@simonbrandhorst here is an initial version of this algorithm

Comment thread src/NumberTheory/ZLattices.jl Outdated
Comment thread src/NumberTheory/ZLattices.jl Outdated
Comment thread test/NumberTheory/ZLattices.jl Outdated
Comment thread test/NumberTheory/ZLattices.jl
matrix2 = [2,1,1,-1,-1,1,-1,1,-1,-1,2,0,-1,-1,1,-1,1,-1,0,4,-2,1,2,-2,-1,-1,0,4,1,-2,2,1,2,1,4,1,-1,0,0,1,4,-2,1,-2,-1,4,-1,2,1,4,0,-1,4,1,4]
G1 = create_gram(matrix1)
G2 = create_gram(matrix2)
U = hnf_with_transform(matrix(ZZ,n,n,rand(0:1,n^2)))[2];

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

the ; here and in the following lines is not necessary

return transpose(U_inv)*A*U_inv
end

function _get_edge_labeled_graph(cv_set, gram)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

here as well

Comment thread src/NumberTheory/ZLattices.jl Outdated
Comment thread src/NumberTheory/ZLattices.jl Outdated
max_w = w
end
add_edge!(res_graph, i, j)
merge!(weightDict, Dict((i, j) => w))

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

it looks like you are merging with a new dict instead of adding entries to the already existing dict (which would be a bit more performant.
This would look like

Suggested change
merge!(weightDict, Dict((i, j) => w))
weightDict[(i, j)] = w

The difference would just be in the handling of duplicate keys. Do you want to update a value in case the key is already there, or do you want to keep the original value? In the former case, you can apply the above suggestion.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This same pattern occurrs also a few more times.

Comment thread src/NumberTheory/ZLattices.jl
Comment thread src/NumberTheory/ZLattices.jl Outdated
@simonbrandhorst simonbrandhorst added the release notes: use body For PRs: the release notes string is included in the body text of the PR label Jul 7, 2026
Comment thread src/NumberTheory/ZLattices.jl Outdated
Comment on lines +229 to +235
for i = 1:p
for j = i+1:p

w = (cv_set[i]*gram*transpose(cv_set[j]))[1]
if w>max_w
max_w = w
end

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This should be considered a hot loop. Suppose that p=10000. Then the inner part is called p(p-1)/2= 49995000 times.
Some suggestions:

  • move cv_set[i]*gram to the outer loop on i. There is no dependence on j
  • use inplace operations such as transpose! and mul! with preallocated vectors
  • you can detect overflow before hand using the Cauchy-Schwarz inequality. If n= max(v*g*transpose(v)) and n^2 fits in Int, then we are fine. If this is the case (and it will be the case in almost all use cases), convert to Vector{Int} if and the matrix to Matrix{Int}. Then you can use LinearAlgebra.mul! which should be the fastest matrix vector multiplication with overflow that we have in julia. Be careful though, it does not support alialising on the first argument.
  • Is there a way to label the edge directly, instead of collecting all labels beforehand?
    Otherwise we are creating 49995000 dict entries. But I do not know enough of the internals of how labels work to judge if this makes sense.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Is there a way to label the edge directly, instead of collecting all labels beforehand?
Otherwise we are creating 49995000 dict entries. But I do not know enough of the internals of how labels work to judge if this makes sense.

There is option to use label!() with a newly made Dict with 1 edge. But the problem is, it looks that if you add more edges, the graph object don't merge them inside. Instead, it stores all the dictionaries as is and as Dict uses a lot of memory by default => it results in enourmous memory usage for big graphs. That's why I collect here all edges in one big dictionary.

Comment on lines +241 to +248
a = 1+max_w
b = a + 1
for i = 1:p
add_edge!(res_graph, i, p+2)
merge!(weightDict, Dict((i, p+2) => a))
end
add_edge!(res_graph, p+1, p+2)
merge!(weightDict, Dict((p+1, p+2) => b))

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Can you explain what happens here?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yes, here I follows the paper and it looks, that we need 2 more vertices to preserve automorphisms of graphs correctly. So, basically another step to not lose isomorphism/not get "new" isom. of resulting forms

Comment on lines +229 to +230
for i = 1:p
for j = i+1:p

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

What about the squared length of the vector, i.e. cv_set[i]*gram*transpose(cv_set[i])? This should be relevant as well.

Kazak-11 and others added 9 commits July 8, 2026 10:53
Co-authored-by: Lars Göttgens <lars.goettgens@gmail.com>
Co-authored-by: Lars Göttgens <lars.goettgens@gmail.com>
Co-authored-by: Lars Göttgens <lars.goettgens@gmail.com>
Co-authored-by: Lars Göttgens <lars.goettgens@gmail.com>
Co-authored-by: Lars Göttgens <lars.goettgens@gmail.com>
Co-authored-by: Lars Göttgens <lars.goettgens@gmail.com>
Co-authored-by: Lars Göttgens <lars.goettgens@gmail.com>
Co-authored-by: Lars Göttgens <lars.goettgens@gmail.com>
Co-authored-by: Simon Brandhorst <brandhorst@math.uni-sb.de>
@lgoettgens lgoettgens added enhancement New feature or request and removed release notes: use body For PRs: the release notes string is included in the body text of the PR labels Jul 8, 2026
@lgoettgens lgoettgens changed the title Add lattice canonical form Add a canonical form for lattices Jul 8, 2026
@lgoettgens lgoettgens added the release notes: use title For PRs: the title of this PR is suitable for direct use in the release notes label Jul 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request release notes: use title For PRs: the title of this PR is suitable for direct use in the release notes topic: number theory

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants