Skip to content

Commit 62bb646

Browse files
committed
fixed rref bug
1 parent 0ce7818 commit 62bb646

File tree

3 files changed

+93
-80
lines changed

3 files changed

+93
-80
lines changed

src/Quantum/stabilizer_code.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -486,9 +486,9 @@ function StabilizerCode(stabs::CTMatrixTypes; char_vec::Union{Vector{zzModRingEl
486486
end
487487
else
488488
if !iszero(stand_k)
489-
_, mat = _rref_symp_col_swap(vcat(stabs, logs_mat))
489+
mat = _rref_symp_col_swap(vcat(stabs, logs_mat))
490490
anti = hcat(logs_mat[:, n + 1:end], -logs_mat[:, 1:n]) * transpose(_remove_empty(mat, :rows))
491-
u_bound, _ = minimum(row_wts_symplectic(mat[findall(!iszero(anti[i:i, :]) for i in axes(anti, 1)), :]))
491+
u_bound = minimum(row_wts_symplectic(mat[findall(!iszero(anti[i:i, :]) for i in axes(anti, 1)), :]))
492492
return StabilizerCode(F, n, dim_code, missing, 1, u_bound, stabs, logs, logs_mat,
493493
char_vec, signs, missing, missing, missing, over_comp, missing, stabs_stand,
494494
stand_r, stand_k, P_stand, missing)

src/Quantum/weight_dist.jl

Lines changed: 88 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -641,7 +641,7 @@ function random_information_set_minimum_distance_bound!(S::T, which::Symbol = :f
641641
dressed::Bool = true, max_iters::Int = 10000, verbose::Bool = false) where T <: AbstractSubsystemCode
642642

643643
which (:full, :X, :Z) || throw(DomainError(which, "Must choose `:full`, `:X` or `:Z`."))
644-
# order(field(S)) == 2 || throw(DomainError(S, "Currently only implemented for binary codes."))
644+
order(field(S)) == 2 || throw(DomainError(S, "Currently only implemented for binary codes."))
645645
is_positive(max_iters) || throw(DomainError(max_iters, "The number of iterations must be a positive integer."))
646646

647647
return random_information_set_minimum_distance_bound!(GaugeTrait(T), CSSTrait(T),
@@ -658,28 +658,37 @@ function random_information_set_minimum_distance_bound!(::HasGauges, ::IsCSS, ::
658658

659659
n = S.n
660660
if which == :full
661-
upperx, foundx = random_information_set_minimum_distance_bound!(HasGauges(), IsCSS(), HasLogicals(), S, :X, dressed, max_iters, verbose)
662-
upperz, foundz = random_information_set_minimum_distance_bound!(HasGauges(), IsCSS(), HasLogicals(), S, :Z, dressed, max_iters, verbose)
663-
if upperx <= upperz
664-
if dressed
665-
S.u_bound_dressed = min(upperx, S.u_bound_dressed)
666-
else
667-
S.u_bound_bare = min(upperx, S.u_bound_bare)
668-
end
669-
return upperx, foundx
661+
!ismissing(S.d_dressed) && (println("Dressed distance already known"); return S.d_dressed;)
662+
verbose && println("Bounding the full dressed distance")
663+
stabs = _Flint_matrix_to_Julia_T_matrix(stabilizers(S), UInt8)
664+
if dressed
665+
gauges = _Flint_matrix_to_Julia_T_matrix(gauges_matrix(S), UInt8)
666+
stabs = vcat(stabs, gauges)
667+
end
668+
_rref_no_col_swap_binary!(stabs)
669+
stabs = _remove_empty(stabs, :rows)
670+
logs = _Flint_matrix_to_Julia_T_matrix(logicals_matrix(S), UInt8)
671+
operators_to_reduce = vcat(stabs, logs)
672+
check_against = permutedims(logs[:, [n + 1:2n; 1:n]])
673+
curr_l_bound = if dressed
674+
S.l_bound_dressed
670675
else
671-
if dressed
672-
S.u_bound_dressed = min(upperz, S.u_bound_dressed)
673-
else
674-
S.u_bound_bare = min(upperz, S.u_bound_bare)
675-
end
676-
return upperz, foundz
676+
S.l_bound_bare
677677
end
678+
verbose && println("Starting lower bound: $curr_l_bound")
679+
680+
# this is done in the constructor but the logical is not stored at the time
681+
# so must redo here
682+
mat = _rref_no_col_swap_binary(operators_to_reduce)
683+
anti = mat * check_against
684+
curr_u_bound, index = findmin(row_wts_symplectic(mat[findall(!iszero(anti[i, :]) for i in axes(anti, 1)), :]))
685+
found = operators_to_reduce[index, :]
686+
verbose && println("Starting upper bound: $curr_u_bound")
678687
else
679688
stabs = _Flint_matrix_to_Julia_T_matrix(stabilizers(S)[:, (which == :X ? (1:n) : (n + 1:2n))], UInt8)
680689
if dressed
681690
gauges = _Flint_matrix_to_Julia_T_matrix(gauge_operators_matrix(S)[:, (which == :X ? (1:n) : (n + 1:2n))], UInt8)
682-
stabs = [stabs; gauges]
691+
stabs = vcat(stabs, gauges)
683692
end
684693
_rref_no_col_swap_binary!(stabs)
685694
stabs = _remove_empty(stabs, :rows)
@@ -702,49 +711,56 @@ function random_information_set_minimum_distance_bound!(::HasGauges, ::IsCSS, ::
702711
uppers, founds = _RIS_bound_loop!(operators_to_reduce, check_against, curr_l_bound,
703712
curr_u_bound, found, max_iters, n, verbose)
704713
loc = argmin(uppers)
714+
verbose && println("Ending $max_iters iterations with an upper bound of $(uppers[loc])")
705715
if dressed
706716
if which == :full
707717
S.u_bound_dressed = uppers[loc]
718+
flint_mat_found = matrix(field(S), permutedims(founds[loc]))
708719
elseif which == :X
709720
S.u_bound_dx_dressed = uppers[loc]
721+
flint_mat_found = matrix(field(S), [permutedims(founds[loc]) zeros(Int, 1, n)])
710722
else
711723
S.u_bound_dz_dressed = uppers[loc]
724+
flint_mat_found = matrix(field(S), [zeros(Int, 1, n) permutedims(founds[loc])])
712725
end
713726
else
714727
if which == :full
715728
S.u_bound_bare = uppers[loc]
729+
flint_mat_found = matrix(field(S), permutedims(founds[loc]))
716730
elseif which == :X
717731
S.u_bound_dx_bare = uppers[loc]
732+
flint_mat_found = matrix(field(S), [permutedims(founds[loc]) zeros(Int, 1, n)])
718733
else
719734
S.u_bound_dz_bare = uppers[loc]
735+
flint_mat_found = matrix(field(S), [zeros(Int, 1, n) permutedims(founds[loc])])
720736
end
721737
end
722-
verbose && println("Ending $max_iters iterations with an upper bound of $(uppers[loc])")
723-
flint_mat_found = if which == :full
724-
matrix(field(S), permutedims(founds[loc]))
725-
elseif which == :X
726-
matrix(field(S), [permutedims(founds[loc]) zeros(Int, 1, n)])
727-
else
728-
matrix(field(S), [zeros(Int, 1, n) permutedims(founds[loc])])
729-
end
738+
730739
return uppers[loc], flint_mat_found
731740
end
732741

742+
# TODO
743+
# 2. check changes to other cases
744+
733745
function random_information_set_minimum_distance_bound!(::HasNoGauges, ::IsCSS, ::HasLogicals,
734746
S::AbstractSubsystemCode, which::Symbol, dressed::Bool, max_iters::Int, verbose::Bool)
735747
# CSS stabilizer code
736748

737749
n = S.n
738750
if which == :full
739-
upperx, foundx = random_information_set_minimum_distance_bound!(HasNoGauges(), IsCSS(), HasLogicals(), S, :X, dressed, max_iters, verbose)
740-
upperz, foundz = random_information_set_minimum_distance_bound!(HasNoGauges(), IsCSS(), HasLogicals(), S, :Z, dressed, max_iters, verbose)
741-
if upperx <= upperz
742-
S.u_bound = upperx
743-
return upperx, foundx
744-
else
745-
S.u_bound = upperz
746-
return upperz, foundz
747-
end
751+
!ismissing(S.d) && (println("Distance already known"); return S.d;)
752+
stabs = _Flint_matrix_to_Julia_T_matrix(stabilizers(S), UInt8)
753+
_rref_no_col_swap_binary!(stabs)
754+
stabs = _remove_empty(stabs, :rows)
755+
logs = _Flint_matrix_to_Julia_T_matrix(logicals_matrix(S), UInt8)
756+
operators_to_reduce = vcat(stabs, logs)
757+
println(size(operators_to_reduce))
758+
check_against = permutedims(logs)
759+
curr_l_bound = S.l_bound
760+
verbose && println("Starting lower bound: $curr_l_bound")
761+
curr_u_bound, index = findmin(count(!iszero, logs[i, :]) for i in 1:size(logs, 1))
762+
found = logs[index, :]
763+
verbose && println("Starting upper bound: $curr_u_bound")
748764
else
749765
if verbose && which == :X
750766
verbose && println("Bounding the X-distance")
@@ -759,7 +775,7 @@ function random_information_set_minimum_distance_bound!(::HasNoGauges, ::IsCSS,
759775
operators_to_reduce = vcat(stabs, logs)
760776
check_against = _Flint_matrix_to_Julia_T_matrix(logicals_matrix(S)[:, (which == :X ? (n + 1:2n) : (1:n))], UInt8)
761777
check_against = permutedims(_remove_empty(check_against, :rows))
762-
curr_l_bound = S.l_bound_dx
778+
which == :X ? (curr_l_bound = S.l_bound_dx;) : (curr_l_bound = S.l_bound_dz;)
763779
verbose && println("Starting lower bound: $curr_l_bound")
764780
curr_u_bound, index = findmin(count(!iszero, logs[i, :]) for i in 1:size(logs, 1))
765781
found = logs[index, :]
@@ -774,21 +790,20 @@ function random_information_set_minimum_distance_bound!(::HasNoGauges, ::IsCSS,
774790
curr_u_bound, found, max_iters, n, verbose)
775791
end
776792
loc = argmin(uppers)
793+
verbose && println("Ending $max_iters iterations with an upper bound of $(uppers[loc])")
777794
if which == :full
778795
S.u_bound = uppers[loc]
796+
flint_mat_found = matrix(field(S), permutedims(founds[loc]))
779797
elseif which == :X
780798
S.u_bound_dx = uppers[loc]
799+
S.u_bound = min(S.u_bound_dx, S.u_bound_dz)
800+
flint_mat_found = matrix(field(S), [permutedims(founds[loc]) zeros(Int, 1, n)])
781801
else
782802
S.u_bound_dz = uppers[loc]
803+
S.u_bound = min(S.u_bound_dx, S.u_bound_dz)
804+
flint_mat_found = matrix(field(S), [zeros(Int, 1, n) permutedims(founds[loc])])
783805
end
784-
verbose && println("Ending $max_iters iterations with an upper bound of $(uppers[loc])")
785-
flint_mat_found = if which == :full
786-
matrix(field(S), permutedims(founds[loc]))
787-
elseif which == :X
788-
matrix(field(S), [permutedims(founds[loc]) zeros(Int, 1, n)])
789-
else
790-
matrix(field(S), [zeros(Int, 1, n) permutedims(founds[loc])])
791-
end
806+
792807
return uppers[loc], flint_mat_found
793808
end
794809

@@ -799,44 +814,34 @@ function random_information_set_minimum_distance_bound!(::HasGauges, ::IsNotCSS,
799814
which == :full || throw(ArguementError(which, "Parameter is not valid for non-CSS codes."))
800815

801816
n = S.n
817+
!ismissing(S.d_dressed) && (println("Dressed distance already known"); return S.d_dressed;)
818+
stabs = _Flint_matrix_to_Julia_T_matrix(stabilizers(S), Int)
819+
_rref_no_col_swap_binary!(stabs)
820+
stabs = _remove_empty(stabs, :rows)
802821
if dressed
803822
verbose && println("Bounding the full dressed distance")
804-
stabs = _Flint_matrix_to_Julia_T_matrix(stabilizers(S), Int)
805-
_rref_no_col_swap_binary!(stabs)
806-
stabs = _remove_empty(stabs, :rows)
807-
gauges = _Flint_matrix_to_Julia_T_matrix(gauges_matrix(S), Int)
808-
logs = _Flint_matrix_to_Julia_T_matrix(logicals_matrix(S), Int)
809-
operators_to_reduce = vcat(stabs, gauges, logs)
810-
check_against = permutedims(logs[:, [n + 1:2n; 1:n]])
811-
curr_l_bound = S.l_bound_dressed
812-
verbose && println("Starting lower bound: $curr_l_bound")
813-
814-
# this is done in the constructor but the logical is not stored at the time
815-
# so must redo here
816-
mat = _rref_no_col_swap_binary(operators_to_reduce)
817-
anti = mat * check_against
818-
curr_u_bound, index = findmin(row_wts_symplectic(mat[findall(!iszero(anti[i, :]) for i in axes(anti, 1)), :]))
819-
found = operators_to_reduce[index, :]
820-
verbose && println("Starting upper bound: $curr_u_bound")
823+
gauges = _Flint_matrix_to_Julia_T_matrix(gauge_operators_matrix(S), UInt8)
824+
stabs = vcat(stabs, gauges)
821825
else
822826
verbose && println("Bounding the full bare distance")
823-
stabs = _Flint_matrix_to_Julia_T_matrix(stabilizers(S), Int)
824-
_rref_no_col_swap_binary!(stabs)
825-
stabs = _remove_empty(stabs, :rows)
826-
logs = _Flint_matrix_to_Julia_T_matrix(logicals_matrix(S), Int)
827-
operators_to_reduce = vcat(stabs, logs)
828-
check_against = permutedims(logs[:, [n + 1:2n; 1:n]])
829-
curr_l_bound = S.l_bound_bare
830-
verbose && println("Starting lower bound: $curr_l_bound")
831-
832-
# this is done in the constructor but the logical is not stored at the time
833-
# so must redo here
834-
mat = _rref_no_col_swap_binary(operators_to_reduce)
835-
anti = mat * check_against
836-
curr_u_bound, index = findmin(row_wts_symplectic(mat[findall(!iszero(anti[i, :]) for i in axes(anti, 1)), :]))
837-
found = operators_to_reduce[index, :]
838-
verbose && println("Starting upper bound: $curr_u_bound")
839827
end
828+
logs = _Flint_matrix_to_Julia_T_matrix(logicals_matrix(S), Int)
829+
operators_to_reduce = vcat(stabs, logs)
830+
check_against = permutedims(logs[:, [n + 1:2n; 1:n]])
831+
curr_l_bound = if dressed
832+
S.l_bound_dressed
833+
else
834+
S.l_bound_bare
835+
end
836+
verbose && println("Starting lower bound: $curr_l_bound")
837+
838+
# this is done in the constructor but the logical is not stored at the time
839+
# so must redo here
840+
mat = _rref_no_col_swap_binary(operators_to_reduce)
841+
anti = mat * check_against
842+
curr_u_bound, index = findmin(row_wts_symplectic(mat[findall(!iszero(anti[i, :]) for i in axes(anti, 1)), :]))
843+
found = operators_to_reduce[index, :]
844+
verbose && println("Starting upper bound: $curr_u_bound")
840845

841846
uppers, founds = _RIS_bound_loop_symp!(operators_to_reduce, check_against, curr_l_bound,
842847
curr_u_bound, found, max_iters, n, verbose)
@@ -847,7 +852,7 @@ function random_information_set_minimum_distance_bound!(::HasGauges, ::IsNotCSS,
847852
S.u_bound_bare = uppers[loc]
848853
end
849854
verbose && println("Ending $max_iters iterations with an upper bound of $(uppers[loc])")
850-
return uppers[loc], founds[loc]
855+
return uppers[loc], matrix(field(S), permutedims(founds[loc]))
851856
end
852857

853858
function random_information_set_minimum_distance_bound!(::HasNoGauges, ::IsNotCSS, ::HasLogicals,
@@ -857,6 +862,7 @@ function random_information_set_minimum_distance_bound!(::HasNoGauges, ::IsNotCS
857862
which == :full || throw(ArguementError(which, "Parameter is not valid for non-CSS codes."))
858863

859864
n = S.n
865+
!ismissing(S.d) && (println("Distance already known"); return S.d;)
860866
verbose && println("Bounding the full distance")
861867
stabs = _Flint_matrix_to_Julia_T_matrix(stabilizers(S), Int)
862868
_rref_no_col_swap_binary!(stabs)
@@ -891,6 +897,7 @@ end
891897
# end
892898

893899
function _RIS_bound_loop_symp!(operators_to_reduce, check_against, curr_l_bound::Int, curr_u_bound::Int, found, max_iters::Int, n::Int, verbose::Bool)
900+
894901
num_thrds = Threads.nthreads()
895902
verbose && println("Detected $num_thrds threads.")
896903

@@ -906,9 +913,12 @@ function _RIS_bound_loop_symp!(operators_to_reduce, check_against, curr_l_bound:
906913
perm_ops = similar(orig_ops)
907914
ops = similar(orig_ops)
908915
perm = collect(1:n)
916+
# perm2 = [perm; perm]
909917
for _ in 1:(thread_load + (t <= remaining ? 1 : 0))
910918
if flag[]
911919
shuffle!(perm)
920+
# perm2[1:n] .= perm
921+
# perm2[n + 1:end] .= (perm .+ n)
912922
_col_permutation_symp!(perm_ops, orig_ops, perm)
913923
# modifying this in place is not thread safe (apparently)
914924
# perm_ops = _rref_no_col_swap_binary(perm_ops)
@@ -943,6 +953,7 @@ function _RIS_bound_loop_symp!(operators_to_reduce, check_against, curr_l_bound:
943953
end
944954

945955
function _RIS_bound_loop!(operators_to_reduce, check_against, curr_l_bound::Int, curr_u_bound::Int, found, max_iters::Int, n::Int, verbose::Bool)
956+
946957
num_thrds = Threads.nthreads()
947958
verbose && println("Detected $num_thrds threads.")
948959

src/utils.jl

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -694,6 +694,7 @@ function _rref_col_swap!(A::CTMatrixTypes, row_range::AbstractUnitRange{Int}, co
694694
end
695695

696696
function _rref_symp_col_swap!(A::CTMatrixTypes, row_range::AbstractUnitRange{Int}, col_range::AbstractUnitRange{Int})
697+
697698
# don't do anything to A if the range is empty, return rank 0 and missing permutation matrix
698699
isempty(row_range) && return 0, missing
699700
isempty(col_range) && return 0, missing
@@ -821,7 +822,8 @@ function _rref_symp_col_swap!(A::CTMatrixTypes, row_range::AbstractUnitRange{Int
821822
return rnk, P
822823
end
823824
_rref_symp_col_swap!(A::CTMatrixTypes) = _rref_symp_col_swap!(A, axes(A, 1), axes(A, 2))
824-
_rref_symp_col_swap(A::CTMatrixTypes) = (B = deepcopy(A); return _rref_symp_col_swap!(B);)
825+
_rref_symp_col_swap(A::CTMatrixTypes) = (B = deepcopy(A); _rref_symp_col_swap!(B, axes(B, 1),
826+
axes(B, 2)); return B;)
825827

826828
function _col_permutation!(X::Matrix{T}, A::Matrix{T}, p::AbstractVector{Int}) where T
827829
length(p) == size(A, 2) || throw(ArgumentError("`p` should have length `size(A, 2)`."))

0 commit comments

Comments
 (0)