-
Notifications
You must be signed in to change notification settings - Fork 181
Add a canonical form for lattices #6102
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
base: master
Are you sure you want to change the base?
Changes from all commits
48bc8a3
22f89ef
a4bb47f
e97212a
78b29db
7135fdb
76a763c
7a2c44f
3aa9b85
e4ceffc
c518654
d5c90a6
31a9500
0a3a0cc
75ec61b
8d61f27
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -211,3 +211,59 @@ function characteristic_vectors(L::ZZLat) | |
| @hassert :Lattice 1 isone(hnf(reduce(vcat, cvL))[1:rank(L),:]) | ||
| return cvL | ||
| end | ||
|
|
||
| function _get_canonical_form(A, char_vectors_set, canonical_ordering) | ||
| p = length(char_vectors_set) | ||
| filter!(e->e!=p+1 && e!=p+2, canonical_ordering) | ||
| can_char_vectors_set = transpose(matrix(ZZ, reduce(vcat, char_vectors_set[canonical_ordering]))) | ||
| H, U = hnf_with_transform(can_char_vectors_set) | ||
| U_inv = inv(U) | ||
| return transpose(U_inv)*A*U_inv | ||
| end | ||
|
|
||
| function _get_edge_labeled_graph(cv_set, gram) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. here as well |
||
| p = length(cv_set) | ||
| res_graph = graph(Undirected, p+2) | ||
| max_w = QQ(0) | ||
| weightDict= Dict{Tuple{Int64, Int64}, QQFieldElem,}() | ||
| for i = 1:p | ||
| for j = i+1:p | ||
|
Comment on lines
+229
to
+230
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What about the squared length of the vector, i.e. |
||
|
|
||
| w = (cv_set[i]*gram*transpose(cv_set[j]))[1] | ||
| if w>max_w | ||
| max_w = w | ||
| end | ||
|
Comment on lines
+229
to
+235
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There is option to use |
||
| add_edge!(res_graph, i, j) | ||
| weightDict[(i, j)] = w | ||
| end | ||
| add_edge!(res_graph, i, p+1) | ||
| end | ||
| 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)) | ||
|
Comment on lines
+241
to
+248
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you explain what happens here?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 |
||
| label!(res_graph, weightDict, nothing; name=:edge) | ||
| return res_graph | ||
| end | ||
|
|
||
| """ | ||
|
Kazak-11 marked this conversation as resolved.
|
||
| canonical_form(L::ZZLat) -> ZZMatrix | ||
| Return the canonical form of ``L``. The form is canonical in the sense, that two isomorphic latticies would have the same canonical form. | ||
|
|
||
| We follow ideas of Sikirić, Haensch, Voight and van Woerden [SHVW20](@cite). | ||
|
|
||
| !!! note | ||
| We do not give any guarantees that the canonical form stays the same | ||
| between different versions of Oscar. | ||
| """ | ||
| function canonical_form(L::ZZLat) | ||
| gram = gram_matrix(L) | ||
| char_vectors_set = characteristic_vectors(L) | ||
| graph = _get_edge_labeled_graph(char_vectors_set, gram) # transform from adjenctcy matrix A to edge-vertex weighted graph Ga, then to edge weighted graph T1(Ga) | ||
| can_order = _canonical_perm(graph; label=:edge) #_canonical_perm uses _edge_label_to_vertex_label themselfs | ||
| return _get_canonical_form(gram, char_vectors_set, can_order) | ||
| end | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -8,3 +8,40 @@ end | |
| @test 7 == length(unique!(Oscar.invariant_function_graph_hash.(L))) | ||
| @test 7 == length(unique!(Oscar.oscar_invariant_function.(L))) | ||
| end | ||
|
|
||
| @testset "Lattice Canonical Form" begin | ||
|
Kazak-11 marked this conversation as resolved.
|
||
| function create_gram(data) # helper function to create gram matricies of latticies | ||
| U = upper_triangular_matrix(data) | ||
| return U + transpose(U) - diagonal_matrix(diagonal(U)) | ||
| end | ||
|
|
||
| n = 10 | ||
| matrix1 = [2,1,-1,1,1,0,0,0,0,-1,2,-1,0,0,0,0,0,0,-1,2,0,0,0,0,0,0,0,2,1,0,0,0,0,-1,2,0,0,0,0,-1,4,-2,2,2,0,4,-2,-2,0,4,0,0,4,0,4] | ||
| 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]; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the ; here and in the following lines is not necessary |
||
| L1 = integer_lattice(gram = G1); | ||
| L2 = integer_lattice(gram = G2); | ||
| L3 = lattice_in_same_ambient_space(L1,U*basis_matrix(L1)); | ||
| can_form1 = canonical_form(L1) | ||
| can_form2 = canonical_form(L2) | ||
| can_form3 = canonical_form(L3) | ||
| @test can_form1 != can_form2 | ||
| @test can_form1 == can_form3 | ||
|
|
||
| n = 18 | ||
| matrix1 = [4,0,0,2,1,2,2,1,0,0,0,0,0,0,0,0,0,0,4,0,2,3,1,0,2,0,0,0,0,0,0,0,0,0,0,4,2,3,3,1,1,0,0,0,0,0,0,0,0,0,0,4,4,3,2,2,0,0,0,0,0,0,0,0,0,0,6,4,2,3,0,0,0,0,0,0,0,0,0,0,4,2,2,0,0,0,0,0,0,0,0,0,0,2,1,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,4,0,0,2,1,2,2,1,0,0,4,0,2,3,1,0,2,0,0,4,2,3,3,1,1,0,0,4,4,3,2,2,0,0,6,4,2,3,0,0,4,2,2,0,0,2,1,0,0,2,0,0,4,0,8] | ||
| matrix2 = [2,1,1,1,0,0,0,0,1,1,-1,1,-1,0,-1,1,1,1,2,1,0,0,0,0,0,0,0,-1,1,-1,0,-1,1,0,1,2,0,0,0,0,0,1,1,-1,0,0,0,0,0,1,0,2,0,0,0,0,1,1,0,0,0,0,-1,0,0,1,2,0,0,0,-1,-1,-1,-1,1,0,0,0,0,0,2,1,-1,-1,-1,-1,1,-1,1,-1,-1,-1,1,2,-1,-1,-1,-1,1,-1,0,-1,-1,0,1,2,1,1,0,-1,1,0,0,0,1,-1,4,3,0,-1,1,0,1,1,2,0,4,1,-1,1,0,0,0,1,-1,4,0,1,-1,1,0,-1,-2,4,-3,0,-1,1,0,1,4,0,1,-1,0,-2,2,-1,-1,-1,0,4,1,1,-1,4,1,1,4,0,4] | ||
| G1 = create_gram(matrix1) | ||
| G2 = create_gram(matrix2) | ||
| U = hnf_with_transform(matrix(ZZ,n,n,rand(0:1,n^2)))[2]; | ||
| L1 = integer_lattice(gram = G1); | ||
| L2 = integer_lattice(gram = G2); | ||
| L3 = lattice_in_same_ambient_space(L1,U*basis_matrix(L1)); | ||
| can_form1 = canonical_form(L1) | ||
| # can_form2 = canonical_form(L2) # too long time, circa 1 hour to calculate can form | ||
| can_form3 = canonical_form(L3) | ||
| # @test can_form1 != can_form2 | ||
| @test can_form1 == can_form3 | ||
| 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.
please add some types to the signature. This makes it easier to understand what the function is doing