diff --git a/doc/body.autodoc b/doc/body.autodoc
index 7f5538e..4039f9d 100644
--- a/doc/body.autodoc
+++ b/doc/body.autodoc
@@ -436,7 +436,7 @@ storage options for elements of an extension field can in be used.
$a_0+a_1x+a_2x^2+\ldots +a_{m-1}x^{m-1}$ as
digits of a $p$-ary integer $(a_{m-1}a_{m-2}\ldots a_2a_1)_p$.
(**this is currently not implemented**)
-
+
@Subsection Matrix storage format
There are two recommended storage formats.
@@ -593,7 +593,7 @@ i j element[i,j]
@EndCode
@InsertCode MMXFormatLineB
-* `type=complex`:
+* `type=complex`:
@BeginCode MMXFormatLineC
i j a[i,j] b[i,j]
@EndCode
@@ -649,7 +649,7 @@ is specified explicitly, this matrix would work with any
prime field.
@BeginCode SampleFileA
-%%MatrixMarket matrix coordinate integer general
+%%MatrixMarket matrix coordinate integer general
% Field: GF(7)
% 5-qubit code generator matrix / normal storage with intercalated cols
5 10 20
@@ -679,7 +679,7 @@ prime field.
This same matrix is stored in the file `matrices/n5k1A.mtx`. This is
how the matrix can be read and distance calculated:
@BeginExample
- filedir:=DirectoriesPackageLibrary("QDistRnd","matrices");;
+ filedir:=DirectoriesPackageLibrary("QDistRnd","matrices");;
lis:=ReadMTXE(Filename(filedir,"n5k1A.mtx" ));;
Print("field ",lis[1],"\n");
#! field GF(7)
diff --git a/examples/examples.g b/examples/examples.g
index 8171e11..34aa7e5 100644
--- a/examples/examples.g
+++ b/examples/examples.g
@@ -1,12 +1,14 @@
#! @Chapter Examples
#! @Section The 5-qubit code
-#! Generate the matrix of the 5-qubit code over GF(3) with the stabilizer group
+#! In this example, we generate the matrix of the 5-qubit code over GF(3) with
+#! the stabilizer group
#! generated by cyclic shifts of the operator $X_0Z_1 \bar Z_2 \bar
#! X_3$ which corresponds to the polynomial $h(x)=1+x^3-x^5-x^6$
#! (a factor $X_i^a$ corresponds to a monomial $a x^{2i}$, and a
#! factor $Z_i^b$ to a monomial $b x^{2i+1}$),
-#! calculate the distance, and save into the file.
+#! calculate the distance, save into a file using the function `WriteMTXE()`, and read the file back in
+#! using the function `ReadMTXE()`.
#! @BeginExample
q:=3;; F:=GF(q);;
x:=Indeterminate(F,"x");; poly:=One(F)*(1+x^3-x^5-x^6);;
@@ -19,14 +21,39 @@ Display(mat);
#! . 2 2 . . . 1 . . 1
d:=DistRandStab(mat,100,1,0 : field:=F,maxav:=20/n);
#! 3
-WriteMTXE("matrices/n5_q3_complex.mtx",3,mat,
+tmp_file_name:=Filename(DirectoryTemporary(),"n5_q3_complex.mtx");;
+WriteMTXE(tmp_file_name,3,mat,
"% The 5-qubit code [[5,1,3]]_3",
"% Generated from h(x)=1+x^3-x^5-x^6",
- "% Example from the QDistRnd GAP package" : field:=F);
-#! File matrices/n5_q3_complex.mtx was created
+ "% Example from the QDistRnd GAP package" : field:=F);;
+lis:=ReadMTXE(tmp_file_name);; # Filename(filedir,"n5_q3_complex.mtx")
+lis[1]; # the field
+#! GF(3)
+lis[2]; # converted to `pair=1`
+#! 1
+Display(lis[3]);
+#! 1 . . 1 . 2 2 . . .
+#! . . 1 . . 1 . 2 2 .
+#! 2 . . . 1 . . 1 . 2
+#! . 2 2 . . . 1 . . 1
#! @EndExample
-
-#! Here is the contents of the resulting file which also illustrates
+#! The function `WriteMTXE()` takes several arguments which specify the details of the output file format
+#! and the optional comments, see Section for the details.
+#! These ensure that all information about the code is written into the file, so that for
+#! reading with the function `ReadMTXE()` only the file name is needed.
+#! Output is a list: `[field,pair,matrix,(list of comments)]`, where the `pair` parameter describes
+#! the ordering of columns in the matrix, see .
+#! Notice that a `pair=2` or `pair=3` matrix is always converted to `pair=1`, i.e., with $2n$
+#! intercalated columns $(a_1,b_1,a_2,b_2,\ldots)$.
+#! The remaining portion is the list of comments. Notice that the 1st
+#! and the last comment lines have been added automatically.
+#! @BeginLog
+#! gap> lis[4];
+#! [ "% Field: GF(3)", "% The 5-qubit code [[5,1,3]]_3",
+#! "% Generated from h(x)=1+x^3-x^5-x^6",
+#! "% Example from the QDistRnd GAP package", "% Values Z(3) are given" ]
+#! @EndLog
+#! Here is the contents of the created file which illustrates
#! the `coordinate complex` data format. Here a pair $(a_{i,j},b_{i,j})$
#! in row $i$ and column $j$ is written as a row of 4 integers, "$i$ $j$ $a_{i,j}$
#! $b_{i,j}$", e.g., "1 2 0 1"
@@ -58,33 +85,6 @@ WriteMTXE("matrices/n5_q3_complex.mtx",3,mat,
#! 4 5 0 1
#! @EndLog
-#! And now let us read the matrix back from the file using the function `ReadMTXE`. In the simplest
-#! case, only the file name is needed.
-#! Output is a list: `[field,pair,matrix,(list of comments)]`, where the `pair` parameter describes
-#! the ordering of columns in the matrix, see .
-#! Notice that a `pair=2` or `pair=3` matrix is always converted to `pair=1`, i.e., with $2n$
-#! intercalated columns $(a_1,b_1,a_2,b_2,\ldots)$.
-#! @BeginExample
-lis:=ReadMTXE("matrices/n5_q3_complex.mtx");;
-lis[1]; # the field
-#! GF(3)
-lis[2]; # converted to `pair=1`
-#! 1
-Display(lis[3]);
-#! 1 . . 1 . 2 2 . . .
-#! . . 1 . . 1 . 2 2 .
-#! 2 . . . 1 . . 1 . 2
-#! . 2 2 . . . 1 . . 1
-#! @EndExample
-#! The remaining portion is the list of comments. Notice that the 1st
-#! and the last comment lines have been added automatically.
-#! @BeginLog
-#! gap> lis[4];
-#! [ "% Field: GF(3)", "% The 5-qubit code [[5,1,3]]_3",
-#! "% Generated from h(x)=1+x^3-x^5-x^6",
-#! "% Example from the QDistRnd GAP package", "% Values Z(3) are given" ]
-#! @EndLog
-
#! @Section Hyperbolic codes from a file
#! Here we read two CSS matrices from two different files which
diff --git a/lib/qdistrnd.g b/lib/qdistrnd.g
index 037c088..b5ff6f2 100644
--- a/lib/qdistrnd.g
+++ b/lib/qdistrnd.g
@@ -42,12 +42,12 @@ BindGlobal("QDR_SymplVecWeight",
len := Length(vec);
# if (not IsInt(len / 2)) then
- # Error(" symplectic vector must have even length, = ", len,"\n");
+ # Error(" symplectic vector must have even length, = ", len,"\n");
# fi;
wgt := 0;
for i in [1..(len/2)] do
- if (vec[2*i-1] <> Zero(F) or vec[2*i] <> Zero(F)) then
+ if (vec[2*i-1] <> Zero(F) or vec[2*i] <> Zero(F)) then
wgt := wgt + 1;;
fi;
od;
@@ -472,7 +472,7 @@ BindGlobal("ReadMTXE",
# fmt - array returned by QDR_ProcessFieldHeader
# pair - 0,1,2 (integer) or 3 (complex), see input variables
# indicates if we store matrix in the compressed form,
- # using complex representation a+i*b
+ # using complex representation a+i*b
# (normal form if pair=integer and compressed form if pair=complex),
# F - Galois field, over which we are working
# rowsG - number of rows in G
@@ -528,14 +528,14 @@ BindGlobal("ReadMTXE",
# search for the end of top comment section (including any empty lines):
iComment := iCommentStart;
while Length(data[iComment + 1]) = 0 or data[iComment + 1, 1] = '%' do
- iComment := iComment + 1;
+ iComment := iComment + 1;
if Length(data[iComment]) = 0 then
data[iComment]:="%"; # suppress empty comment lines
fi;
od;
for i in [iComment+1..Length(data)] do
- data[i] := SplitString(data[i], " ");; # separate into records
+ data[i] := SplitString(data[i], " ");; # separate into records
od;
# Parameters (dimensions and number of non-zero elemments) of G
@@ -546,14 +546,14 @@ BindGlobal("ReadMTXE",
G := NullMat(rowsG, colsG, F);; # empty matrix
# Then we fill G with the elements from data (no more empty / comment lines allowed)
- if (pair <>3 ) then
- for i in [(iComment + 2)..Length(data)] do
- G[Int(data[i,1]), Int(data[i,2])] :=
+ if (pair <>3 ) then
+ for i in [(iComment + 2)..Length(data)] do
+ G[Int(data[i,1]), Int(data[i,2])] :=
QDR_ProcEntry(data[i,3],fmt,StrPath,i);
- od;
- else # pair=3
+ od;
+ else # pair=3
for i in [(iComment + 2)..Length(data)] do
- G[Int(data[i,1]),2*Int(data[i,2])-1]:=
+ G[Int(data[i,1]),2*Int(data[i,2])-1]:=
QDR_ProcEntry(data[i,3],fmt,StrPath,i);
G[Int(data[i,1]),2*Int(data[i,2])]:=
QDR_ProcEntry(data[i,4],fmt,StrPath,i);
@@ -629,7 +629,7 @@ BindGlobal("WriteMTXE", # function (StrPath,pair,G,comment...)
# We check pair parameter
if (pair <0 ) or (pair>3) or (pair=2) then
- Error("\n", "Parameter pair=",pair," not supported, must be in {0,1,3}", "\n");
+ Error("\n", "Parameter pair=",pair," not supported, must be in {0,1,3}", "\n");
fi;
# full file name with extension
@@ -647,9 +647,9 @@ BindGlobal("WriteMTXE", # function (StrPath,pair,G,comment...)
for i in [1..Length(comment)] do
if comment[i,1]<>'%' then
- AppendTo(filename, "% ", comment[i], "\n");
+ AppendTo(filename, "% ", comment[i], "\n");
else
- AppendTo(filename, comment[i], "\n");
+ AppendTo(filename, comment[i], "\n");
fi;
od;
if IsPrime(Size(F)) then
@@ -666,13 +666,13 @@ BindGlobal("WriteMTXE", # function (StrPath,pair,G,comment...)
# count non-zero elements depending on the 'pair' parameter
nonzero := 0;
if (pair = 3) then
- for i in [1..rows] do
+ for i in [1..rows] do
nonzero := nonzero + QDR_SymplVecWeight(G[i], F);;
od;
else
- for i in [1..rows] do
- nonzero := nonzero + WeightVecFFE(G[i]);;
- od;
+ for i in [1..rows] do
+ nonzero := nonzero + WeightVecFFE(G[i]);;
+ od;
fi;
if (pair < 3) then
@@ -681,17 +681,17 @@ BindGlobal("WriteMTXE", # function (StrPath,pair,G,comment...)
# Finally, write nonzero elements and their positions according to pair parameter and field F.
if IsPrime(Size(F)) then # this includes binary field
- for i in [1..rows] do
- row := G[i];;
+ for i in [1..rows] do
+ row := G[i];;
- pos := PositionNonZero(row, 0);;
- while pos <= cols do
+ pos := PositionNonZero(row, 0);;
+ while pos <= cols do
AppendTo(filename, i, " ", pos, " ", Int(row[pos]), "\n");
pos := PositionNonZero(row, pos);;
- od;
- od;
- else # extension field
- for i in [1..rows] do
+ od;
+ od;
+ else # extension field
+ for i in [1..rows] do
row := G[i];;
pos := PositionNonZero(row, 0);;
@@ -701,29 +701,29 @@ BindGlobal("WriteMTXE", # function (StrPath,pair,G,comment...)
pos := PositionNonZero(row, pos);;
od;
od;
- fi;
+ fi;
else # pair=3
# write dimensions of the matrix and number of line containing nonzero elements
AppendTo(filename, rows, " ", cols/2," ", nonzero, "\n");
# Finally, write nonzero elements and their positions according to pair parameter and field F.
- if IsPrime(Size(F)) then
- for i in [1..rows] do
+ if IsPrime(Size(F)) then
+ for i in [1..rows] do
row := G[i];;
- pos := PositionNonZero(row, 0);;
- while pos <= cols do
- # For Ai = 0
- if IsInt(pos/2) then
- AppendTo(filename, i, " ", pos/2, " ", 0, " ", Int(row[pos]), "\n");
- pos := PositionNonZero(row, pos);;
- # For Ai != 0
+ pos := PositionNonZero(row, 0);;
+ while pos <= cols do
+ # For Ai = 0
+ if IsInt(pos/2) then
+ AppendTo(filename, i, " ", pos/2, " ", 0, " ", Int(row[pos]), "\n");
+ pos := PositionNonZero(row, pos);;
+ # For Ai != 0
else
- AppendTo(filename, i, " ", (pos+1)/2, " ", Int(row[pos]), " ", Int(row[pos + 1]), "\n");
- pos := PositionNonZero(row, pos + 1);;
- fi;
+ AppendTo(filename, i, " ", (pos+1)/2, " ", Int(row[pos]), " ", Int(row[pos + 1]), "\n");
+ pos := PositionNonZero(row, pos + 1);;
+ fi;
od;
od;
else # extension field
- for i in [1..rows] do
+ for i in [1..rows] do
row := G[i];;
pos := PositionNonZero(row, 0);;
@@ -743,13 +743,12 @@ BindGlobal("WriteMTXE", # function (StrPath,pair,G,comment...)
fi;
pos := PositionNonZero(row, pos + 1);;
- fi;
- od;
+ fi;
+ od;
od;
fi;
fi;
-
- Print("File ", filename, " was created\n");
+ # Print("File ", filename, " was created\n");
end
);
@@ -776,7 +775,7 @@ BindGlobal("QDR_MakeH",
# Checking that G has even number of columns
if (Gcd(dims[2] , 2) = 1) then
- Error("\n", "Generator Matrix G has odd number of columns!", "\n");
+ Error("\n", "Generator Matrix G has odd number of columns!", "\n");
fi;
# Introducing check matrix
@@ -867,11 +866,11 @@ BindGlobal("DistRandCSS",
if debug[2]=1 then # Check that H*c = 0
if (WeightVecFFE(GX * TempVec) > 0) then
Print("\nError: codeword found is not orthogonal to rows of HX!\n");
- if (colsWZ <= 100) then
- Print("The improper vector is:\n");
- Display(TempVec);
+ if (colsWZ <= 100) then
+ Print("The improper vector is:\n");
+ Display(TempVec);
fi;
- Error("\n");
+ Error("\n");
fi;
fi;
@@ -976,7 +975,7 @@ BindGlobal("DistRandStab",
function(G,num,mindist,opt...) # supported options: field, maxav
local F, debug, CodeWords, mult, TempPos, dims, H, i, l, j, W, V, dimsW,
rows, cols, DistBound, FirstVecFound, VecCount, per, W1, W2, TempVec, TempWeight,maxav,
- per1, per2;
+ per1, per2;
# CodeWords - if debug[4] = 1, record the first 100 different CWs with the lowest weight found so far
# mult - number of times codewords from CodeWords were found
# TempPos - temporary variable corresponding to the position of TempVec in CodeWords
@@ -1023,9 +1022,9 @@ BindGlobal("DistRandStab",
# optionally check for orthogonality
if (debug[2] = 1) then
- if QDR_WeightMat(G * TransposedMat(H))>0 then
- Error("\n", "Problem with ortogonality GH^T!", "\n");
- fi;
+ if QDR_WeightMat(G * TransposedMat(H))>0 then
+ Error("\n", "Problem with ortogonality GH^T!", "\n");
+ fi;
fi;
# Below we are getting vector spaces W and V ortogonal to the columns of H and G correspondingly.
@@ -1042,13 +1041,13 @@ BindGlobal("DistRandStab",
# The main part of algorithm.
for i in [1..num] do
#Print(i);
- ## We start by creating random permutation for columns in W.
- # per1 := ListPerm(Random(SymmetricGroup(cols/2)), cols/2);; # random permutation of length cols/2
- # per2 := []; # We extend the permutation, so it works now on pairs
- # for l in [1..cols/2] do
- # Append(per2, [2*per1[l]-1, 2*per1[l]]); # per2 contains the permutation we want as a list
- # od;
- # per := PermList(per2); # this is a permutation of length 2n moving pairs
+ ## We start by creating random permutation for columns in W.
+ # per1 := ListPerm(Random(SymmetricGroup(cols/2)), cols/2);; # random permutation of length cols/2
+ # per2 := []; # We extend the permutation, so it works now on pairs
+ # for l in [1..cols/2] do
+ # Append(per2, [2*per1[l]-1, 2*per1[l]]); # per2 contains the permutation we want as a list
+ # od;
+ # per := PermList(per2); # this is a permutation of length 2n moving pairs
per := Random(SymmetricGroup(cols));;
@@ -1057,22 +1056,22 @@ BindGlobal("DistRandStab",
W2 := PermutedCols(W2,Inverse(per));; # Inverse permutation
for j in [1..rows] do
- # We take one of the sample vectors for this iteration. It supposed to be low-weight.
+ # We take one of the sample vectors for this iteration. It supposed to be low-weight.
TempVec := W2[j];;
TempWeight := QDR_SymplVecWeight(TempVec, F);;
- # check if this vector is a logical operator).
- # First, rough check:
+ # check if this vector is a logical operator).
+ # First, rough check:
if (TempWeight > 0) and (TempWeight <= DistBound) then
if (WeightVecFFE(V * TempVec) > 0) then # linear independence from rows of G
if debug[2]=1 then # Check that H*c = 0
if (WeightVecFFE(H * TempVec) > 0) then
Print("\nSomething wrong: cw found is not orthogonal to rows of H!\n");
- if (Length(TempVec) <= 100) then
- Print("The improper vector is:\n");
- Display(TempVec);
- fi;
- Error("\n");
+ if (Length(TempVec) <= 100) then
+ Print("The improper vector is:\n");
+ Display(TempVec);
+ fi;
+ Error("\n");
fi;
fi;
@@ -1081,38 +1080,38 @@ BindGlobal("DistRandStab",
DistBound := TempWeight;; # min weight found
VecCount := 1;; # reset the overall count of vectors of such weight
- # Recording all discovered codewords of minimum weight and their multiplicities
+ # Recording all discovered codewords of minimum weight and their multiplicities
if debug[4] = 1 or ValueOption("maxav")<>fail then
- CodeWords := [TempVec];;
- mult := [1];;
+ CodeWords := [TempVec];;
+ mult := [1];;
fi;
if debug[1] = 1 then
FirstVecFound := TempVec;;
fi;
- # If we already received such a weight (up to now - it is minimal),
+ # If we already received such a weight (up to now - it is minimal),
# we want to update number of vectors, corresponding to it
elif (TempWeight = DistBound) then
VecCount := VecCount + 1;;
- # Recording of the first 100 different discovered codewords of
+ # Recording of the first 100 different discovered codewords of
# minimum weight with their multiplicities
if debug[4] = 1 or ValueOption("maxav")<>fail then
TempPos := Position(CodeWords, TempVec);
- if ((TempPos = fail) and (Length(mult) < 100)) then
- Add(CodeWords, TempVec);
- Add(mult, 1);
- elif (TempPos <> fail) then
- mult[TempPos] := mult[TempPos] + 1;;
- fi;
- fi;
+ if ((TempPos = fail) and (Length(mult) < 100)) then
+ Add(CodeWords, TempVec);
+ Add(mult, 1);
+ elif (TempPos <> fail) then
+ mult[TempPos] := mult[TempPos] + 1;;
+ fi;
+ fi;
fi;
- # Specific terminator, if we don't care for distances below a particular value.
+ # Specific terminator, if we don't care for distances below a particular value.
if (DistBound <= mindist) then # not interesting, exit immediately!
if debug[1]=1 then
- Print("\n", "The found distance ",DistBound,"<=",mindist,
+ Print("\n", "The found distance ",DistBound,"<=",mindist,
" too small, exiting!\n");
fi;
return -DistBound;
diff --git a/tst/qdistrnd01.tst b/tst/qdistrnd01.tst
index 2683b34..48930f7 100644
--- a/tst/qdistrnd01.tst
+++ b/tst/qdistrnd01.tst
@@ -10,7 +10,7 @@
#
gap> START_TEST("qdistrnd01.tst");
-# doc/_Chapter_Examples.xml:20-37
+# doc/_Chapter_Examples.xml:22-49
gap> q:=3;; F:=GF(q);;
gap> x:=Indeterminate(F,"x");; poly:=One(F)*(1+x^3-x^5-x^6);;
gap> n:=5;;
@@ -22,14 +22,12 @@ gap> Display(mat);
. 2 2 . . . 1 . . 1
gap> d:=DistRandStab(mat,100,1,0 : field:=F,maxav:=20/n);
3
-gap> WriteMTXE("matrices/n5_q3_complex.mtx",3,mat,
+gap> tmp_file_name:=Filename(DirectoryTemporary(),"n5_q3_complex.mtx");;
+gap> WriteMTXE(tmp_file_name,3,mat,
> "% The 5-qubit code [[5,1,3]]_3",
> "% Generated from h(x)=1+x^3-x^5-x^6",
-> "% Example from the QDistRnd GAP package" : field:=F);
-File matrices/n5_q3_complex.mtx was created
-
-# doc/_Chapter_Examples.xml:79-90
-gap> lis:=ReadMTXE("matrices/n5_q3_complex.mtx");;
+> "% Example from the QDistRnd GAP package" : field:=F);;
+gap> lis:=ReadMTXE(tmp_file_name);; # Filename(filedir,"n5_q3_complex.mtx")
gap> lis[1]; # the field
GF(3)
gap> lis[2]; # converted to `pair=1`
diff --git a/tst/qdistrnd03.tst b/tst/qdistrnd03.tst
index af4c215..c398720 100644
--- a/tst/qdistrnd03.tst
+++ b/tst/qdistrnd03.tst
@@ -11,7 +11,7 @@
gap> START_TEST("qdistrnd03.tst");
# doc/_Chapter_FileFormat.xml:344-351
-gap> filedir:=DirectoriesPackageLibrary("QDistRnd","matrices");;
+gap> filedir:=DirectoriesPackageLibrary("QDistRnd","matrices");;
gap> lis:=ReadMTXE(Filename(filedir,"n5k1A.mtx" ));;
gap> Print("field ",lis[1],"\n");
field GF(7)