From 777f5ff50203f9fa5f75d03a1dab36f98d539c6d Mon Sep 17 00:00:00 2001 From: Leonid Pryadko Date: Wed, 17 Jan 2024 21:59:30 -0800 Subject: [PATCH 1/3] Read/write example in temporary directory --- doc/body.autodoc | 8 +-- examples/examples.g | 68 +++++++++--------- lib/qdistrnd.g | 163 ++++++++++++++++++++++---------------------- tst/qdistrnd01.tst | 12 ++-- tst/qdistrnd03.tst | 2 +- 5 files changed, 125 insertions(+), 128 deletions(-) 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) From 159da1ca1ad8963a975d89377f4eab538fbab85b Mon Sep 17 00:00:00 2001 From: Leonid Pryadko Date: Fri, 19 Jan 2024 16:06:44 -0800 Subject: [PATCH 2/3] replaced tabs with spaces --- CONTRIBUTING.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index fd398fb..0ff73d5 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -8,7 +8,7 @@ bug reports, and code reviews. * Before you report an issue, or wish to add functionality, please try and check to see if there are existing issues or pull requests. We do not want you wasting your time duplicating somebody else's work. - + * For substantial changes it is also advisable to contact us before you start work to discuss your ideas. @@ -20,10 +20,10 @@ bug reports, and code reviews. * To help increase the chance of your pull request being accepted: - Run the tests. - + - Update the documentation, tests, examples, guides, and whatever else is affected by your contribution. - + - Use appropriate code formatting for your code. * Try to follow *the Campsite Rule:* leave the codebase in better From e1f59a5919be31a48683ed3a92a2f8a7cc4aca24 Mon Sep 17 00:00:00 2001 From: Leonid Pryadko Date: Fri, 19 Jan 2024 16:16:49 -0800 Subject: [PATCH 3/3] minor change --- PackageInfo.g | 4 ++-- lib/qdistrnd.g | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/PackageInfo.g b/PackageInfo.g index 14fa206..58e549a 100644 --- a/PackageInfo.g +++ b/PackageInfo.g @@ -16,8 +16,8 @@ SetPackageInfo( rec( PackageName := "QDistRnd", Subtitle := "Calculate the distance of a q-ary quantum stabilizer code", - Version := "0.9.1", - Date := "12/01/2024", + Version := "0.9.2", + Date := "19/01/2024", License := "GPL-2.0-or-later", PackageWWWHome := "https://QEC-pages.github.io/QDistRnd", SourceRepository := diff --git a/lib/qdistrnd.g b/lib/qdistrnd.g index b5ff6f2..82c5d96 100644 --- a/lib/qdistrnd.g +++ b/lib/qdistrnd.g @@ -844,7 +844,7 @@ BindGlobal("DistRandCSS", if debug[2]=1 then # check the orthogonality if QDR_WeightMat(GX*TransposedMat(GZ))>0 then - Error("\nDistRandCSS: input matrices should have orthogonal rows!\n"); + Error("DistRandCSS: input matrices should have orthogonal rows!\n"); fi; fi;