source: git/Singular/LIB/decodegb.lib @ 20f2239

fieker-DuValspielwiese
Last change on this file since 20f2239 was 20f2239, checked in by Hans Schoenemann <hannes@…>, 4 years ago
spelling p7
  • Property mode set to 100644
File size: 51.0 KB
Line 
1//////////////////////////////////////////////////////////////////////////////
2version="version decodegb.lib 4.1.2.0 Feb_2019 "; // $Id$
3category="Coding theory";
4info="
5LIBRARY: decodegb.lib         Decoding and min distance of linear codes with GB
6AUTHOR:  Stanislav Bulygin,   bulygin@mathematik.uni-kl.de
7
8OVERVIEW:
9 In this library we generate several systems used for decoding cyclic codes and
10 finding their minimum distance. Namely, we work with the Cooper's philosophy
11 and generalized Newton identities. The origindeal method of quadratic equations
12 is worked out here as well. We also (for comparison) enable to work with the
13 system of Fitzgerald-Lax. We provide some auxiliary functions for further
14 manipulations and decoding. For an overview of the methods mentioned above @ref{Decoding codes with Groebner bases}.
15 For the vanishing ideal computation the algorithm of Farr and Gao is
16 implemented.
17
18PROCEDURES:
19 sysCRHT(..);        generates the CRHT-ideal as in Cooper's philosophy
20 sysCRHTMindist(..); CRHT-ideal to find the minimum distance in the binary case
21 sysNewton(..);      generates the ideal with the generalized Newton identities
22 sysBin(..);         generates Bin system using Waring function
23 encode(x,g);        encodes given message x with the given generator matrix g
24 syndrome(h,c);      computes a syndrome w.r.t. the given check matrix
25 sysQE(..);          generates the system of quadratic equations for decoding
26 errorInsert(..);    inserts errors in a word
27 errorRand(y,num,e); inserts random errors in a word
28 randomCheck(m,n,e); generates a random check matrix
29 genMDSMat(n,a);     generates an MDS (actually an RS) matrix
30 mindist(check);     computes the minimum distance of a code
31 decode(rec);        decoding of a word using the system of quadratic equations
32 decodeRandom(..); a procedure for manipulation with random codes
33 decodeCode(..);   a procedure for manipulation with the given code
34 vanishId(points);   computes the vanishing ideal for the given set of points
35 sysFL(..);          generates the Fitzgerald-Lax system
36 decodeRandomFL(..); manipulation with random codes via Fitzgerald-Lax
37
38
39KEYWORDS:  Cyclic code; Linear code; Decoding;
40           Minimum distance; Groebner bases, decodeGB
41";
42
43LIB "linalg.lib";
44LIB "brnoeth.lib";
45
46///////////////////////////////////////////////////////////////////////////////
47// creates a list result, where result[i]=i, 1<=i<=n
48static proc lis (int n)
49{
50 list result;
51 if (n<=0) {print("ERRORlis");}
52 for (int i=1; i<=n; i++)
53 {
54  result=result+list(i);
55 }
56 return(result);
57}
58
59///////////////////////////////////////////////////////////////////////////////
60// creates a list of all combinations without repititions of m objects out of n
61static proc combinations (int m, int n)
62{
63 list result;
64 if (m>n) {print("ERRORcombinations");}
65 if (m==n) {result[size(result)+1]=lis(m);return(result);}
66 if (m==0) {result[size(result)+1]=list();return(result);}
67 list temp=combinations(m-1,n-1);
68 for (int i=1; i<=size(temp); i++)
69 {
70  temp[i]=temp[i]+list(n);
71 }
72 result=combinations(m,n-1)+temp;
73 return(result);
74}
75
76
77///////////////////////////////////////////////////////////////////////////////
78// the polynomial for Sala's restrictions
79static proc p_poly(int n, int a, int b)
80{
81  poly f;
82  for (int i=0; i<=n-1; i++)
83  {
84    f=f+Z(a)^i*Z(b)^(n-1-i);
85  }
86  return(f);
87}
88
89///////////////////////////////////////////////////////////////////////////////
90
91proc sysCRHT (int n, list defset, int e, int q, int m, list #)
92"USAGE:   sysCRHT(n,defset,e,q,m,[k]); n,e,q,m,k are int, defset list of int's
93@format
94         - n length of the cyclic code,
95         - defset is a list representing the defining set,
96         - e the error-correcting capacity,
97         - q field size
98         - m degree extension of the splitting field,
99         - if k>0 additional equations representing the fact that every two
100         error positions are either different or at least one of them is zero
101@end format
102RETURN: the ring to work with the CRHT-ideal (with Sala's additions),
103        containing an ideal with name 'crht'
104THEORY:  Based on 'defset' of the given cyclic code, the procedure constructs
105         the corresponding Cooper-Reed-Heleseth-Truong ideal 'crht'. With its
106         help one can solve the decoding problem. For basics of the method @ref{Cooper philosophy}.
107SEE ALSO: sysNewton, sysBin
108EXAMPLE: example sysCRHT; shows an example
109"
110{
111  int r=size(defset);
112  ring @crht=(q,a),(Y(e..1),Z(1..e),X(r..1)),lp;
113  ideal crht;
114  int i,j;
115  poly sum;
116  int k;
117  if ( size(#) > 0)
118  {
119    k = #[1];
120  }
121
122  //---------------------- add check equations --------------------------
123  for (i=1; i<=r; i++)
124  {
125    sum=0;
126    for (j=1; j<=e; j++)
127    {
128      sum=sum+Y(j)*Z(j)^defset[i];
129    }
130    crht[i]=sum-X(i);
131  }
132
133  //--------------------- field equations on syndromes ------------------
134  for (i=1; i<=r; i++)
135  {
136    crht=crht,X(i)^(q^m)-X(i);
137  }
138
139  //------ restrictions on error-locations: n-th roots of unity ----------
140  for (i=1; i<=e; i++)
141  {
142    crht=crht,Z(i)^(n+1)-Z(i);
143  }
144
145  for (i=1; i<=e; i++)
146  {
147    crht=crht,Y(i)^(q-1)-1;
148  }
149
150  //--------- add Sala's additional conditions if necessary --------------
151  if ( k > 0 )
152
153  {
154    for (i=1; i<=e; i++)
155    {
156      for (j=i+1; j<=e; j++)
157      {
158        crht=crht,Z(i)*Z(j)*p_poly(n,i,j);
159      }
160    }
161  }
162  export crht;
163  return(@crht);
164}
165example
166{ "EXAMPLE:"; echo=2;
167  // binary cyclic [15,7,5] code with defining set (1,3)
168  intvec v = option(get);
169
170  list defset=1,3;           // defining set
171  int n=15;                  // length
172  int e=2;                   // error-correcting capacity
173  int q=2;                   // basefield size
174  int m=4;                   // degree extension of the splitting field
175  int sala=1;                // indicator to add additional equations
176
177  def A=sysCRHT(n,defset,e,q,m);
178  setring A;
179  A;                         // shows the ring we are working in
180  print(crht);               // the CRHT-ideal
181  option(redSB);
182  ideal red_crht=std(crht);  // reduced Groebner basis
183  print(red_crht);
184
185  //============================
186  A=sysCRHT(n,defset,e,q,m,sala);
187  setring A;
188  print(crht);                // CRHT-ideal with additional equations from Sala
189  option(redSB);
190  ideal red_crht=std(crht);   // reduced Groebner basis
191  print(red_crht);
192  red_crht[5];                // general error-locator polynomial for this code
193  option(set,v);
194}
195
196///////////////////////////////////////////////////////////////////////////////
197
198
199proc sysCRHTMindist (int n, list defset, int w)
200"USAGE:  sysCRHTMindist(n,defset,w);  n,w are int, defset is list of int's
201@format
202        - n length of the cyclic code,
203        - defset is a list representing the defining set,
204        - w is a candidate for the minimum distance
205@end format
206RETURN:  the ring to work with the Sala's ideal for the minimum distance
207         containing the ideal with name 'crht_md'
208THEORY:  Based on 'defset' of the given cyclic code, the procedure constructs
209         the corresponding Cooper-Reed-Heleseth-Truong ideal 'crht_md'. With
210         its help one can find minimum distance of the code in the binary
211         case. For basics of the method @ref{Cooper philosophy}.
212EXAMPLE: example sysCRHTMindist; shows an example
213"
214{
215  int r=size(defset);
216  ring @crht_md=2,Z(1..w),lp;
217  ideal crht_md;
218  int i,j;
219  poly sum;
220
221  //------------ add check equations --------------
222  for (i=1; i<=r; i++)
223  {
224    sum=0;
225    for (j=1; j<=w; j++)
226    {
227      sum=sum+Z(j)^defset[i];
228    }
229    crht_md[i]=sum;
230  }
231
232
233  //----------- locations are n-th roots of unity ------------
234  for (i=1; i<=w; i++)
235  {
236    crht_md=crht_md,Z(i)^n-1;
237  }
238
239  //------------ adding conditions on locations being different ------------
240  for (i=1; i<=w; i++)
241  {
242    for (j=i+1; j<=w; j++)
243    {
244      crht_md=crht_md,Z(i)*Z(j)*p_poly(n,i,j);
245    }
246  }
247
248  export crht_md;
249  return(@crht_md);
250}
251example
252{
253  "EXAMPLE:"; echo=2;
254  intvec v = option(get);
255  // binary cyclic [15,7,5] code with defining set (1,3)
256
257  list defset=1,3;             // defining set
258  int n=15;                    // length
259  int d=5;                     // candidate for the minimum distance
260
261  def A=sysCRHTMindist(n,defset,d);
262  setring A;
263  A;                           // shows the ring we are working in
264  print(crht_md);              // the Sala's ideal for mindist
265  option(redSB);
266  ideal red_crht_md=std(crht_md);
267  print(red_crht_md);          // reduced Groebner basis
268
269  option(set,v);
270}
271
272///////////////////////////////////////////////////////////////////////////////
273// slightly modified mod function
274static proc mod_ (int n, int m)
275{
276  n=n mod m;
277  if (n<=0){ return(n+m);}
278  return(n);
279}
280
281///////////////////////////////////////////////////////////////////////////////
282
283proc sysNewton (int n, list defset, int t, int q, int m, list #)
284"USAGE:   sysNewton (n,defset,t,q,m,[tr]); n,t,q,m,tr int, defset is list int's
285@format
286         - n is length,
287         - defset is the defining set,
288         - t is the number of errors,
289         - q is basefield size,
290         - m is degree extension of the splitting field,
291         - if tr>0 it indicates that Newton identities in triangular
292           form should be constructed
293@end format
294RETURN:  the ring to work with the generalized Newton identities (in
295         triangular form if applicable) containing the ideal with name 'newton'
296THEORY:  Based on 'defset' of the given cyclic code, the procedure constructs
297         the corresponding ideal 'newton' with the generalized Newton
298         identities. With its help one can solve the decoding problem. For
299         basics of the method @ref{Generalized Newton identities}.
300SEE ALSO: sysCRHT, sysBin
301EXAMPLE:  example sysNewton; shows an example
302"
303{
304 string s="(";
305 int i,j;
306 int flag;
307 int tr;
308
309 if (size(#)>0)
310 {
311  tr=#[1];
312 }
313
314 for (i=n; i>=1; i--)
315 {
316  for (j=1; j<=size(defset); j++)
317  {
318    flag=1;
319    if (i==defset[j])
320    {
321      flag=0;
322      break;
323    }
324  }
325  if (flag)
326  {
327    s=s+"S("+string(i)+"),";
328  }
329 }
330 for (int zz = 1; zz <= t; zz++)
331 {
332  s = s + "sigma("+string(zz)+"),";
333 }
334 for (i=size(defset); i>=2; i--)
335 {
336  s=s+"S("+string(defset[i])+"),";
337 }
338 s=s+"S("+string(defset[1])+"))";
339 ring @newton = create_ring("("+string(q)+",a)", s, "lp");
340 ideal newton;
341 poly sum;
342
343
344 //------------ generate generalized Newton identities ----------
345 if (tr)
346 {
347  for (i=1; i<=t; i++)
348  {
349    sum=0;
350    for (j=1; j<=i-1; j++)
351    {
352      sum=sum+sigma(j)*S(i-j);
353    }
354    newton=newton,S(i)+sum+number(i)*sigma(i);
355  }
356 } else
357 {
358  for (i=1; i<=t; i++)
359  {
360    sum=0;
361    for (j=1; j<=t; j++)
362    {
363      sum=sum+sigma(j)*S(mod_(i-j,n));
364    }
365    newton=newton,S(i)+sum;
366  }
367 }
368 for (i=1; i<=n-t; i++)
369 {
370  sum=0;
371  for (j=1; j<=t; j++)
372  {
373    sum=sum+sigma(j)*S(t+i-j);
374  }
375  newton=newton,S(t+i)+sum;
376 }
377
378 //----------- add field equations on sigma's --------------
379 for (i=1; i<=t; i++)
380 {
381  newton=newton,sigma(i)^(q^m)-sigma(i);
382 }
383
384 //----------- add conjugacy relations ------------------
385 for (i=1; i<=n; i++)
386 {
387  newton=newton,S(i)^q-S(mod_(q*i,n));
388 }
389 newton=simplify(newton,2);
390 export newton;
391 return(@newton);
392}
393example
394{
395     "EXAMPLE:";  echo = 2;
396     // Newton identities for a binary 3-error-correcting cyclic code of
397     //length 31 with defining set (1,5,7)
398
399     int n=31;          // length
400     list defset=1,5,7; //defining set
401     int t=3;           // number of errors
402     int q=2;           // basefield size
403     int m=5;           // degree extension of the splitting field
404     int tr=1;          // indicator of triangular form of Newton identities
405
406
407     def A=sysNewton(n,defset,t,q,m);
408     setring A;
409     A;                 // shows the ring we are working in
410     print(newton);     // generalized Newton identities
411
412     //===============================
413     A=sysNewton(n,defset,t,q,m,tr);
414     setring A;
415     print(newton);     // generalized Newton identities in triangular form
416}
417
418///////////////////////////////////////////////////////////////////////////////
419// forms a list of special combinations needed for computation of Waring's
420//function
421static proc combinations_sum (int m, int n)
422{
423 list result;
424 list comb=combinations(m-1,n+m-1);
425 int i,j,flag,count;
426 list interm=comb;
427 for (i=1; i<=size(comb); i++)
428 {
429  interm[i][1]=comb[i][1]-1;
430  for (j=2; j<=m-1; j++)
431  {
432   interm[i][j]=comb[i][j]-comb[i][j-1]-1;
433  }
434  interm[i][m]=n+m-comb[i][m-1]-1;
435  flag=1;
436  count=2;
437  while ((flag)&&(count<=m))
438  {
439   if (interm[i][count] mod count != 0) {flag=0;}
440   count++;
441  }
442  if (flag)
443  {
444   for (j=2; j<=m; j++)
445   {
446    interm[i][j]=interm[i][j] div j;
447   }
448   result[size(result)+1]=interm[i];
449  }
450 }
451 return(result);
452}
453
454///////////////////////////////////////////////////////////////////////////////
455//if n=q^e*m, m and n are coprime, then return e
456static proc exp_count (int n, int q)
457{
458 int flag=1;
459 int result=0;
460 while(flag)
461 {
462  if (n mod q != 0) {flag=0;}
463   else {n=n div q; result++;}
464 }
465 return(result);
466}
467
468///////////////////////////////////////////////////////////////////////////////
469
470
471proc sysBin (int v, list Q, int n, list #)
472"USAGE:    sysBin (v,Q,n,[odd]);  v,n,odd are int, Q is list of int's
473@format
474          - v a number if errors,
475          - Q is a defining set of the code,
476          - n the length,
477          - odd is an additional parameter: if
478           set to 1, then the defining set is enlarged by odd elements,
479           which are 2^(some power)*(some element in the def.set) mod n
480@end format
481RETURN:    the ring with the resulting system called 'bin'
482THEORY:  Based on Q of the given cyclic code, the procedure constructs
483         the corresponding ideal 'bin' with the use of the Waring function.
484         With its help one can solve the decoding problem.
485         For basics of the method @ref{Generalized Newton identities}.
486SEE ALSO: sysNewton, sysCRHT
487EXAMPLE:   example sysBin; shows an example
488"
489{
490 int odd;
491 if (size(#)>0)
492 {
493  odd=#[1];
494 }
495
496 //ring r=2,(sigma(1..v),S(1..n)),(lp(v),dp(n));
497 ring r=2,(S(1..n),sigma(1..v)),lp;
498 list cyclot;
499 ideal result;
500 int i,j,k,s;
501 list comb;
502 poly sum_, mon;
503 int count1, count2, upper, coef_, flag, gener;
504 list Q_update;
505 if (odd==1)
506 {
507  for (i=1; i<=n; i++)
508  {
509   cyclot[i]=0;
510  }
511  for (i=1; i<=size(Q); i++)
512  {
513   flag=1;
514   gener=Q[i];
515   while(flag)
516   {
517    cyclot[gener]=1;
518    gener=2*gener mod n;
519    if (gener == Q[i]) {flag=0;}
520   }
521  }
522  for (i=1; i<=n; i++)
523  {
524   if ((cyclot[i] == 1)&&(i mod 2 == 1)) {Q_update[size(Q_update)+1]=i;}
525  }
526 }
527 else
528 {
529  Q_update=Q;
530 }
531
532 //---- form polynomials for the Bin system via Waring's function ---------
533 for (i=1; i<=size(Q_update); i++)
534 {
535  comb=combinations_sum(v,Q_update[i]);
536  sum_=0;
537  for (k=1; k<=size(comb); k++)
538  {
539   upper=0;
540   for (j=1; j<=v; j++)
541   {
542    upper=upper+comb[k][j];
543   }
544   count1=0;
545   for (j=2; j<=upper-1; j++)
546   {
547    count1=count1+exp_count(j,2);
548   }
549   count1=count1+exp_count(Q_update[i],2);
550   count2=0;
551   for (j=1; j<=v; j++)
552   {
553    for (s=2; s<=comb[k][j]; s++)
554    {
555     count2=count2+exp_count(s,2);
556    }
557   }
558   if (count1<count2) {print("ERRORsysBin");}
559   if (count1>count2) {coef_=0;}
560   if (count1 == count2) {coef_=1;}
561   mon=1;
562   for (j=1; j<=v; j++)
563   {
564    mon=mon*sigma(j)^(comb[k][j]);
565   }
566   sum_=sum_+coef_*mon;
567  }
568  result=result,S(Q_update[i])-sum_;
569 }
570 ideal bin=simplify(result,2);
571 export bin;
572 return(r);
573}
574example
575{
576     "EXAMPLE:";  echo = 2;
577     // [31,16,7] quadratic residue code
578     list l=1,5,7,9,19,25;
579     // we do not need even synromes here
580     def A=sysBin(3,l,31);
581     setring A;
582     print(bin);
583}
584
585///////////////////////////////////////////////////////////////////////////////
586
587proc encode (matrix x, matrix g)
588"USAGE:  encode (x, g);  x a row vector (message), and g a generator matrix
589RETURN:  corresponding codeword
590EXAMPLE: example encode; shows an example
591"
592{
593 if (nrows(x)>1) {print("ERRORencode1!");}
594 if (ncols(x)!=nrows(g)) {print("ERRORencode2!");}
595 return(x*g);
596}
597example
598{
599     "EXAMPLE:";  echo = 2;
600     ring r=2,x,dp;
601     matrix x[1][4]=1,0,1,0;
602     matrix g[4][7]=1,0,0,0,0,1,1,
603                    0,1,0,0,1,0,1,
604                    0,0,1,0,1,1,1,
605                    0,0,0,1,1,1,0;
606     //encode x with the generator matrix g
607     print(encode(x,g));
608}
609
610///////////////////////////////////////////////////////////////////////////////
611
612proc syndrome (matrix h, matrix c)
613"USAGE:  syndrome (h, c);  h a check matrix, c a row vector (codeword)
614RETURN:  corresponding syndrome
615EXAMPLE: example syndrome; shows an example
616"
617{
618 if (nrows(c)>1) {print("ERRORsyndrome1!");}
619 if (ncols(c)!=ncols(h)) {print("ERRORsyndrome2!");}
620 return(h*transpose(c));
621}
622example
623{
624     "EXAMPLE:";  echo = 2;
625     ring r=2,x,dp;
626     matrix x[1][4]=1,0,1,0;
627     matrix g[4][7]=1,0,0,0,0,1,1,
628                    0,1,0,0,1,0,1,
629                    0,0,1,0,1,1,1,
630                    0,0,0,1,1,1,0;
631     //encode x with the generator matrix g
632     matrix c=encode(x,g);
633     // disturb
634     c[1,3]=0;
635     //compute syndrome
636     //corresponding check matrix
637     matrix check[3][7]=1,0,0,1,1,0,1,0,1,0,1,0,1,1,0,0,1,0,1,1,1;
638     print(syndrome(check,c));
639     c[1,3]=1;
640     //now c is a codeword
641     print(syndrome(check,c));
642}
643
644///////////////////////////////////////////////////////////////////////////////
645// (coordinatewise) star product of two vectors
646static proc star(matrix m, int i, int j)
647{
648 matrix result[ncols(m)][1];
649 for (int k=1; k<=ncols(m); k++)
650 {
651  result[k,1]=m[i,k]*m[j,k];
652 }
653 return(result);
654}
655
656///////////////////////////////////////////////////////////////////////////////
657
658proc sysQE(matrix check, matrix y, int t, list #)
659"USAGE:   sysQE(check,y,t,[fieldeq,formal]);check,y matrix;t,fieldeq,formal int
660@format
661        - check is a parity check matrix of the code
662        - y is a received word,
663        - t the number of errors to be corrected,
664        - if fieldeq=1, then field equations are added,
665        - if formal=0, field equations on (known) syndrome variables
666          are not added, in order to add them (note that the exponent should
667          be equal to the number of elements in the INITIAL alphabet) one
668          needs to set formal>0 for the exponent
669@end format
670RETURN:   the ring to work with together with the resulting system called 'qe'
671THEORY:  Based on 'check' of the given linear code, the procedure constructs
672         the corresponding ideal that gives an opportunity to compute
673         unknown syndrome of the received word y. After computing the unknown
674         syndromes one is able to solve the decoding problem.
675         For basics of the method @ref{Decoding method based on quadratic equations}.
676SEE ALSO: sysFL
677EXAMPLE:  example sysQE; shows an example
678"
679{
680 int fieldeq;
681 int formal;
682 if (size(#)>0)
683 {
684  fieldeq=#[1];
685 }
686 if (size(#)>1)
687 {
688  formal=#[2];
689 }
690
691 def br=basering;
692 list rl=ringlist(br);
693
694 int red=nrows(check);
695 int n=ncols(check);
696 int q=rl[1][1];
697
698 if (formal==0)
699 {
700  ring work=(q,a),(V(1..t),U(1..n)),dp;
701 } else
702 {
703  ring work=(q,a),(V(1..t),U(1..n),s(1..red)),(dp(t),lp(n),dp(red));
704 }
705
706 matrix check=imap(br,check);
707 matrix y=imap(br,y);
708
709 matrix h_full=genMDSMat(n,a);
710 matrix h=submat(h_full,1..red,1..n);
711 if (nrows(y)!=1) {print("ERROR1Pell");}
712 if (ncols(y)!=n) {print("ERROR2Pell");}
713
714 ideal result;
715
716 list c;
717 list a;
718 list tmp,tmp2;
719 int i,j,l,k;
720 number sum,prod,sig;
721        poly sum1,sum2,sum3;
722 for (i=1; i<=n; i++)
723 {
724  c[i]=tmp;
725 }
726
727 matrix transf=inverse(transpose(h_full));
728
729 //------ expression matrix of check vectors w.r.t. the MDS basis -----------
730 for (i=1; i<=red ; i++)
731 {
732  a[i]=transpose(submat(check,i..i,1..n));
733  a[i]=transf*a[i];
734 }
735
736 //----------- compute the structure constants ------------------------
737 matrix te[n][1];
738 for (i=1; i<=n; i++)
739 {
740  for (j=1; j<=t+1; j++)
741  {
742   if ((j<i)&&(i<=t+1)) {c[i][j]=c[j][i];}
743   else
744   {
745    if (i+j<=n+1)
746    {
747     c[i][j]=te;
748     c[i][j][i+j-1,1]=1;
749    }
750    else
751    {
752     c[i][j]=star(h_full,i,j);
753     c[i][j]=transf*c[i][j];
754    }
755   }
756  }
757 }
758
759
760 if (formal==0)
761 {
762  matrix s[red][1]=syndrome(check,y);
763  for (j=1; j<=red; j++)
764  {
765   sum1=0;
766   for (l=1; l<=n; l++)
767   {
768    sum1=sum1+a[j][l,1]*U(l);
769   }
770   result=result,sum1-s[j,1];
771  }
772 } else
773 {
774  for (j=1; j<=red; j++)
775  {
776   sum1=0;
777   for (l=1; l<=n; l++)
778   {
779    sum1=sum1+a[j][l,1]*U(l);
780   }
781   result=result,sum1-s(j);
782  }
783  for (j=1; j<=red; j++)
784  {
785     result=result,s(j)^(formal)-s(j);
786  }
787 }
788 if (fieldeq)
789 {
790  for (i=1; i<=n; i++)
791  {
792   result=result,U(i)^q-U(i);
793  }
794  for (j=1; j<=t; j++)
795  {
796     result=result,V(j)^q-V(j);
797  }
798 }
799
800 //----- form the quadratic equations according to the theory -----------
801 for (i=1; i<=n; i++)
802 {
803  sum1=0;
804  for (j=1; j<=t; j++)
805  {
806   sum2=0;
807   for (l=1; l<=n; l++)
808   {
809    sum2=sum2+c[i][j][l,1]*U(l);
810   }
811   sum1=sum1+sum2*V(j);
812  }
813  sum3=0;
814  for (l=1; l<=n; l++)
815  {
816   sum3=sum3+c[i][t+1][l,1]*U(l);
817  }
818  result=result,sum1-sum3;
819 }
820
821 result=simplify(result,2);
822
823 ideal qe=result;
824 export qe;
825 return(work);
826}
827example
828{
829     "EXAMPLE:";  echo = 2;
830     intvec v = option(get);
831
832     //correct 2 errors in [7,3] 8-ary code RS code
833     int t=2; int q=8; int n=7; int redun=4;
834     ring r=(q,a),x,dp;
835     matrix h_full=genMDSMat(n,a);
836     matrix h=submat(h_full,1..redun,1..n);
837     matrix g=dual_code(h);
838     matrix x[1][3]=0,0,1,0;
839     matrix y[1][7]=encode(x,g);
840
841     //disturb with 2 errors
842     matrix rec[1][7]=errorInsert(y,list(2,4),list(1,a));
843
844     //generate the system
845     def A=sysQE(h,rec,t);
846     setring A;
847     print(qe);
848
849     //let us decode
850     option(redSB);
851     ideal sys_qe=std(qe);
852     print(sys_qe);
853
854     option(set,v);
855}
856
857///////////////////////////////////////////////////////////////////////////////
858
859proc errorInsert(matrix y, list pos, list val)
860"USAGE:  errorInsert(y,pos,val); y is matrix, pos,val are list of int's
861@format
862        - y is a (code) word,
863        - pos = positions where errors occurred,
864        - val = their corresponding values
865@end format
866RETURN:  corresponding received word
867EXAMPLE: example errorInsert; shows an example
868"
869{
870 matrix result[1][ncols(y)]=y;
871 if (size(pos)!=size(val)) {print("ERRORerror");}
872 for (int i=1; i<=size(pos); i++)
873 {
874  result[1,pos[i]]=y[1,pos[i]]+val[i];
875 }
876 return(result);
877}
878example
879{
880     "EXAMPLE:";  echo = 2;
881     //correct 2 errors in [7,3] 8-ary code RS code
882     int t=2; int q=8; int n=7; int redun=4;
883     ring r=(q,a),x,dp;
884     matrix h_full=genMDSMat(n,a);
885     matrix h=submat(h_full,1..redun,1..n);
886     matrix g=dual_code(h);
887     matrix x[1][3]=0,0,1,0;
888     matrix y[1][7]=encode(x,g);
889     print(y);
890
891     //disturb with 2 errors
892     matrix rec[1][7]=errorInsert(y,list(2,4),list(1,a));
893     print(rec);
894     print(rec-y);
895}
896
897///////////////////////////////////////////////////////////////////////////////
898
899proc errorRand(matrix y, int num, int e)
900"USAGE:    errorRand(y, num, e); y is matrix, num,e are int
901@format
902          - y is a (code) word,
903          - num is the number of errors,
904          - e is an extension degree (if one wants values to be from GF(p^e))
905@end format
906RETURN:    corresponding received word
907EXAMPLE:   example errorRand; shows an example
908"
909{
910 matrix result[1][ncols(y)]=y;
911 int i,j, flag, temp;
912 list pos, val;
913 matrix tempnum;
914
915 for (i=1; i<=num; i++)
916 {
917  while(1)
918  {
919   temp=random(1,ncols(y));
920   flag=1;
921   for (j=1; j<=size(pos); j++)
922   {
923    if (temp==pos[j]) {flag=0;}
924   }
925   if (flag) {pos[i]=temp;break;}
926  }
927 }
928
929 for (i=1; i<=num; i++)
930 {
931  flag=1;
932  while(flag)
933  {
934   tempnum=randomvector(1,e);
935   if (tempnum!=0) {flag=0;}
936  }
937  val[i]=tempnum;
938 }
939
940 for (i=1; i<=size(pos); i++)
941 {
942  result[1,pos[i]]=y[1,pos[i]]+val[i];
943 }
944 return(result);
945}
946example
947{
948  "EXAMPLE:";  echo = 2;
949     //correct 2 errors in [7,3] 8-ary code RS code
950     int t=2; int q=8; int n=7; int redun=4;
951     ring r=(q,a),x,dp;
952     matrix h_full=genMDSMat(n,a);
953     matrix h=submat(h_full,1..redun,1..n);
954     matrix g=dual_code(h);
955     matrix x[1][3]=0,0,1,0;
956     matrix y[1][7]=encode(x,g);
957
958     //disturb with 2 random errors
959     matrix rec[1][7]=errorRand(y,2,3);
960     print(rec);
961     print(rec-y);
962}
963
964///////////////////////////////////////////////////////////////////////////////
965
966proc randomCheck(int m, int n, int e)
967"USAGE:    randomCheck(m, n, e); m,n,e are int
968@format
969          - m x n are dimensions of the matrix,
970          - e is an extension degree (if one wants values to be from GF(p^e))
971@end format
972RETURN:    random check matrix
973EXAMPLE:   example randomCheck; shows an example
974"
975{
976 matrix result[m][n];
977 matrix rand[m][n-m];
978 int i,j;
979 matrix temp;
980 for (i=1; i<=m; i++)
981 {
982  temp=randomvector(n-m,e);
983  for (j=1; j<=n-m; j++)
984  {
985   rand[i,j]=temp[j,1];
986  }
987 }
988 result=concat(rand,unitmat(m));
989 return(result);
990}
991example
992{
993  "EXAMPLE:";  echo = 2;
994     int redun=5; int n=15;
995     ring r=2,x,dp;
996
997     //generate random check matrix for a [15,5] binary code
998     matrix h=randomCheck(redun,n,1);
999     print(h);
1000
1001     //corresponding generator matrix
1002     matrix g=dual_code(h);
1003     print(g);
1004}
1005
1006///////////////////////////////////////////////////////////////////////////////
1007
1008proc genMDSMat(int n, number a)
1009"USAGE:   genMDSMat(n, a); n is int, a is number
1010@format
1011        - n x n are dimensions of the MDS matrix,
1012        - a is a primitive element of the field.
1013@end format
1014NOTE:   An MDS matrix is constructed in the following way. We take 'a' to be a
1015        generator of the multiplicative group of the field. Then we construct
1016        the Vandermonde matrix with this 'a'.
1017ASSUME:   extension field should already be defined
1018RETURN:   a matrix with the MDS property.
1019SEE ALSO: Decoding method based on quadratic equations
1020EXAMPLE:  example genMDSMat; shows an example
1021"
1022{
1023 int i,j;
1024 matrix result[n][n];
1025 for (i=0; i<=n-1; i++)
1026 {
1027  for (j=0; j<=n-1; j++)
1028  {
1029   result[j+1,i+1]=(a^i)^j;
1030  }
1031 }
1032 return(result);
1033}
1034example
1035{
1036     "EXAMPLE:";  echo = 2;
1037     int q=16; int n=15;
1038     ring r=(q,a),x,dp;
1039
1040     //generate an MDS (Vandermonde) matrix
1041     matrix h_full=genMDSMat(n,a);
1042     print(h_full);
1043}
1044
1045///////////////////////////////////////////////////////////////////////////////
1046
1047
1048proc mindist (matrix check)
1049"USAGE:  mindist (check, q); check matrix, q int
1050@format
1051        - check is a check matrix,
1052        - q is the field size
1053@end format
1054RETURN:  minimum distance of the code
1055EXAMPLE: example mindist; shows an example
1056"
1057{
1058 intvec vopt = option(get);
1059
1060 int n=ncols(check); int redun=nrows(check); int t=redun+1;
1061
1062 def br=basering;
1063 list rl=ringlist(br);
1064 int q=rl[1][1];
1065
1066 ring work=(q,a),(V(1..t),U(1..n)),dp;
1067 matrix check=imap(br,check);
1068
1069 ideal temp;
1070 int count=1;
1071 int flag=1;
1072 int flag2;
1073 int i;
1074 matrix z[1][n];
1075 option(redSB);
1076 def A=sysQE(check,z,count);
1077
1078 //proceed with solving the system w.r.t zero vector until some solutions
1079 //are found
1080 while (flag)
1081 {
1082    A=sysQE(check,z,count);
1083    setring A;
1084    ideal temp=qe;
1085    temp=std(temp);
1086    flag2=1;
1087    setring work;
1088    temp=imap(A,temp);
1089    for (i=1; i<=n; i++)
1090    {
1091      if
1092        (temp[i]!=U(n-i+1))
1093        {
1094          flag2=0;
1095        }
1096    }
1097    if (!flag2)
1098    {
1099      flag=0;
1100    }
1101    else
1102    {
1103      count++;
1104    }
1105 }
1106 int result=count;
1107
1108 option(set,vopt);
1109 return(result);
1110}
1111example
1112{
1113     "EXAMPLE:";  echo = 2;
1114     //determine a minimum distance for a [7,3] binary code
1115     int q=8; int n=7; int redun=4; int t=redun+1;
1116     ring r=(q,a),x,dp;
1117
1118     //generate random check matrix
1119     matrix h=randomCheck(redun,n,1);
1120     print(h);
1121     int l=mindist(h);
1122     l;
1123}
1124
1125///////////////////////////////////////////////////////////////////////////////
1126
1127proc decode(matrix check, matrix rec)
1128"USAGE:    decode(check, rec, t); check, rec matrix, t int
1129@format
1130          - check is the check matrix of the code,
1131          - rec is a received word,
1132          - t is an upper bound for the number of errors one wants to correct
1133@end format
1134NOTE:     The method described in @ref{Decoding method based on quadratic equations}
1135          is used for decoding.
1136ASSUME:   Errors in rec should be correctable, otherwise the output is
1137          unpredictable
1138RETURN:   a codeword that is closest to rec
1139EXAMPLE:  example decode; shows an example
1140"
1141{
1142 intvec vopt = option(get);
1143
1144 def br=basering;
1145 int n=ncols(check);
1146
1147 int count=1;
1148 def A=sysQE(check,rec,count);
1149 while(1)
1150 {
1151  A=sysQE(check,rec,count);
1152  setring A;
1153  matrix h_full=genMDSMat(n,a);
1154  matrix rec=imap(br,rec);
1155  option(redSB);
1156  ideal qe_red=std(qe);
1157  if (qe_red[1]!=1)
1158  {
1159    break;
1160  }
1161  else
1162  {
1163    count++;
1164  }
1165  setring br;
1166 }
1167
1168 setring A;
1169
1170 //obtain a codeword
1171 //this works only if our code is indeed can correct these errors
1172 matrix syn[n][1];
1173 for (int i=1; i<=n; i++)
1174 {
1175  syn[i,1]=-qe_red[n-i+1]+lead(qe_red[n-i+1]);
1176 }
1177
1178 matrix real_syn=inverse(h_full)*syn;
1179 setring br;
1180 matrix real_syn=imap(A,real_syn);
1181
1182 option(set,vopt);
1183 return(rec-transpose(real_syn));
1184}
1185example
1186{
1187     "EXAMPLE:";  echo = 2;
1188     //correct 1 error in [15,7] binary code
1189     int t=1; int q=16; int n=15; int redun=10;
1190     ring r=(q,a),x,dp;
1191
1192     //generate random check matrix
1193     matrix h=randomCheck(redun,n,1);
1194     matrix g=dual_code(h);
1195     matrix x[1][n-redun]=0,0,1,0,1,0,1;
1196     matrix y[1][n]=encode(x,g);
1197     print(y);
1198
1199     // find out the minimum distance of the code
1200     list l=mindist(h);
1201
1202     //disturb with errors
1203     "Correct ",(l[1]-1) div 2," errors";
1204     matrix rec[1][n]=errorRand(y,(l[1]-1) div 2,1);
1205     print(rec);
1206
1207     //let us decode
1208     matrix dec_word=decode(h,rec);
1209     print(dec_word);
1210}
1211
1212///////////////////////////////////////////////////////////////////////////////
1213
1214
1215proc decodeRandom(int n, int redun, int ncodes, int ntrials, list #)
1216"USAGE:    decodeRandom(redun,q,ncodes,ntrials,[e]); all parameters int
1217@format
1218          - redun is a redundabcy of a (random) code,
1219          - q is the field size,
1220          - ncodes is the number of random codes to be processed,
1221          - ntrials is the number of received vectors per code to be corrected
1222          - If e is given it sets the correction capacity explicitly. It
1223          should be used in case one expects some lower bound,
1224          otherwise the procedure tries to compute the real minimum distance
1225          to find out the error-correction capacity
1226@end format
1227RETURN:    nothing;
1228EXAMPLE:   example decodeRandom; shows an example
1229"
1230{
1231 intvec vopt = option(get);
1232
1233 int i,j;
1234 matrix h;
1235 int dist, t;
1236 ideal sys;
1237 int tmp;
1238 int e;
1239 if (size(#)>0)
1240 {
1241  e=#[1];
1242 }
1243
1244 option(redSB);
1245 def br=basering;
1246 matrix h_full=genMDSMat(n,a);
1247 matrix z[1][ncols(h_full)];
1248
1249 //------------------ determine error-correction capacity -------------------
1250 for (i=1; i<=ncodes; i++)
1251 {
1252  setring br;
1253  h=randomCheck(redun,n,1);
1254  "check matrix:";
1255  print(h);
1256  if (e>0)
1257  {
1258     t=e;
1259  } else {
1260     tmp=mindist(h);
1261     dist=tmp;
1262     printf("d= %p",dist);
1263     t=(dist-1) div 2;
1264  }
1265
1266  //------------- generate the template system ----------------------
1267  def A=sysQE(h,z,t);
1268  setring A;
1269  matrix word,y,rec;
1270  ideal sys2,sys3;
1271  matrix h=imap(br,h);
1272  matrix g=dual_code(h);
1273  ideal sys=qe;
1274  print("The system is generated");
1275
1276  //------ modify the template according to every received word --------------
1277  for (j=1; j<=ntrials; j++)
1278  {
1279   word=randomvector(n-redun,1);
1280   y=encode(transpose(word),g);
1281   print("Codeword:");
1282   print(y);
1283   rec=errorRand(y,t,1);
1284   print("Received word:");
1285   print(rec);
1286   sys2=add_synd(rec,h,redun,sys);
1287   option(redSB);
1288   sys3=std(sys2);
1289   print("The Groebenr basis of the QE system:");
1290   print(sys3);
1291  }
1292  kill A;
1293  option(set,vopt);
1294 }
1295}
1296example
1297{
1298     "EXAMPLE:";  echo = 2;
1299     int q=32; int n=25; int redun=n-11; int t=redun+1;
1300     ring r=(q,a),x,dp;
1301
1302     // correct 2 errors in 2 random binary codes, 3 trials each
1303     decodeRandom(n,redun,2,3,2);
1304}
1305
1306///////////////////////////////////////////////////////////////////////////////
1307
1308
1309proc decodeCode(matrix check, int ntrials, list #)
1310"USAGE:     decodeCode(check, ntrials, [e]); check matrix, ntrials,e int
1311@format
1312           - check is a parity check matrix for the code,
1313           - ntrials is the number of received vectors per code to be
1314           corrected.
1315           - If e is given it sets the correction capacity explicitly. It
1316           should be used in case one expects some lower bound,
1317           otherwise the procedure tries to compute the real minimum distance
1318           to find out the error-correction capacity
1319@end format
1320RETURN:     nothing;
1321EXAMPLE:    example decodeCode; shows an example
1322"
1323{
1324 intvec vopt = option(get);
1325
1326 int n=ncols(check);
1327 int redun=nrows(check);
1328 int i,j;
1329 matrix h;
1330 int dist, t;
1331 ideal sys;
1332 int tmp;
1333 int e;
1334 if (size(#)>0)
1335 {
1336  e=#[1];
1337 }
1338
1339 option(redSB);
1340 def br=basering;
1341 matrix h_full=genMDSMat(n,a);
1342 matrix z[1][ncols(h_full)];
1343 setring br;
1344 h=check;
1345 "check matrix:";
1346 print(h);
1347
1348 //------------------ determine error-correction capacity -------------------
1349 if (e>0)
1350 {
1351    t=e;
1352 } else {
1353   tmp=mindist(h);
1354   dist=tmp;
1355   printf("d= %p",dist);
1356   t=(dist-1) div 2;
1357 }
1358
1359 //------------- generate the template system ----------------------
1360 def A=sysQE(h,z,t);
1361 setring A;
1362 matrix word,y,rec;
1363 ideal sys2,sys3;
1364 matrix h=imap(br,h);
1365 matrix g=dual_code(h);
1366 ideal sys=qe;
1367 print("The system is generated");
1368
1369 //--- modify the template according to every received word ---------------
1370 for (j=1; j<=ntrials; j++)
1371 {
1372   word=randomvector(n-redun,1);
1373   y=encode(transpose(word),g);
1374   print("Codeword:");
1375   print(y);
1376   rec=errorRand(y,t,1);
1377   print("Received word:");
1378   print(rec);
1379   sys2=add_synd(rec,h,redun,sys);
1380   option(redSB);
1381   sys3=std(sys2);
1382   print("Groebner basis of the QE system:");
1383   print(sys3);
1384 }
1385
1386 option(set,vopt);
1387}
1388example
1389{
1390     "EXAMPLE:";  echo = 2;
1391     int q=32; int n=25; int redun=n-11; int t=redun+1;
1392     ring r=(q,a),x,dp;
1393     matrix check=randomCheck(redun,n,1);
1394
1395     // correct 2 errors in using the code above, 3 trials
1396     decodeCode(check,3,2);
1397}
1398
1399
1400///////////////////////////////////////////////////////////////////////////////
1401// adding syndrome values to the template system
1402static proc add_synd (matrix rec, matrix check, int redun, ideal sys)
1403{
1404     ideal result=sys;
1405     matrix s[redun][1]=syndrome(check,rec);
1406     for (int i=1; i<=redun; i++)
1407
1408     {
1409          result[i]=result[i]-s[i,1];
1410     }
1411     return(result);
1412}
1413
1414///////////////////////////////////////////////////////////////////////////////
1415// evaluate a polynomial at a given point
1416static proc ev (poly f, matrix p)
1417{
1418     if (ncols(p)>1) {ERROR("not a column vector");};
1419     int m=size(p);
1420     poly temp=f;
1421     for (int i=1; i<=m; i++)
1422     {
1423          temp=subst(temp,var(i),p[i,1]);
1424     }
1425     return(number(temp));
1426}
1427
1428///////////////////////////////////////////////////////////////////////////////
1429// return index of an element in the ideal where it does not vanish at the
1430//given point
1431static proc find_index (ideal G, matrix p)
1432{
1433     if (ncols(p)>1) {ERROR("not a column vector");};
1434     int i=1;
1435     int n=size(G);
1436     while(i<=n)
1437     {
1438          if (ev(G[i],p)!=0) {return(i);}
1439          i++;
1440     }
1441     return(-1);
1442}
1443
1444///////////////////////////////////////////////////////////////////////////////
1445// convert ideal to list
1446static proc ideal2list (ideal id)
1447{
1448     list l;
1449     for (int i=1; i<=size(id); i++)
1450     {
1451          l[i]=id[i];
1452     }
1453     return(l);
1454}
1455
1456///////////////////////////////////////////////////////////////////////////////
1457// convert list to ideal
1458static proc list2ideal (list l)
1459{
1460     ideal id;
1461     for (int i=1; i<=size(l); i++)
1462     {
1463          id[i]=l[i];
1464     }
1465     return(id);
1466}
1467
1468///////////////////////////////////////////////////////////////////////////////
1469// check whether given polynomial is divisible by some leading monomial of the
1470//ideal
1471static proc divisible (poly m, ideal G)
1472{
1473     for (int i=1; i<=size(G); i++)
1474     {
1475          if (m/leadmonom(G[i])!=0) {return(1);}
1476     }
1477     return(0);
1478}
1479
1480///////////////////////////////////////////////////////////////////////////////
1481
1482proc vanishId (list points)
1483"USAGE:  vanishId (points); point is a list of matrices
1484        'points' is a list of points for which the vanishing ideal is to be
1485        constructed
1486RETURN:  Vanishing ideal corresponding to the given set of points
1487EXAMPLE: example vanishId; shows an example
1488"
1489{
1490     int m=size(points[1]);
1491     int n=size(points);
1492
1493     ideal G=1;
1494     int i,k,j;
1495     list temp;
1496     poly h,cur;
1497
1498     //------------- proceed according to Farr-Gao algorithm ----------------
1499     for (k=1; k<=n; k++)
1500     {
1501          i=find_index(G,points[k]);
1502          cur=G[i];
1503          for(j=i+1; j<=size(G); j++)
1504          {
1505               G[j]=G[j]-ev(G[j],points[k])/ev(G[i],points[k])*G[i];
1506          }
1507          G=simplify(G,2);
1508          temp=ideal2list(G);
1509          temp=delete(temp,i);
1510          G=list2ideal(temp);
1511          for (j=1; j<=m; j++)
1512          {
1513               if (!divisible(var(j)*leadmonom(cur),G))
1514               {
1515                    attrib(G,"isSB",1);
1516                    h=NF((var(j)-points[k][j,1])*cur,G);
1517                    temp=ideal2list(G);
1518                    temp=insert(temp,h);
1519                    G=list2ideal(temp);
1520                    G=sort(G)[1];
1521               }
1522          }
1523     }
1524     attrib(G,"isSB",1);
1525     return(G);
1526}
1527example
1528{
1529     "EXAMPLE:";  echo = 2;
1530      ring r=3,(x(1..3)),dp;
1531
1532     //generate all 3-vectors over GF(3)
1533     list points=pointsGen(3,1);
1534
1535     list points2=convPoints(points);
1536
1537     //grasps the first 11 points
1538     list p=graspList(points2,1,11);
1539     print(p);
1540
1541     //construct the vanishing ideal
1542     ideal id=vanishId(p);
1543     print(id);
1544}
1545
1546///////////////////////////////////////////////////////////////////////////////
1547// construct the list of all vectors of length m with elements in p^e, where p
1548// is theharacteristic
1549proc pointsGen (int m, int e)
1550{
1551     if (e>1)
1552     {
1553     list result;
1554     int count=1;
1555     int i,j;
1556     list l=ringlist(basering);
1557     int charac=l[1][1];
1558     number a=par(1);
1559     list tmp;
1560     for (i=1; i<=charac^(e*m); i++)
1561     {
1562          result[i]=tmp;
1563     }
1564     if (m==1)
1565     {
1566          result[count][m]=0;
1567          count++;
1568          for (j=1; j<=charac^(e)-1; j++)
1569          {
1570               result[count][m]=a^j;
1571               count++;
1572          }
1573          return(result);
1574     }
1575     list prev=pointsGen(m-1,e);
1576     for (i=1; i<=size(prev); i++)
1577     {
1578          result[count]=prev[i];
1579          result[count][m]=0;
1580          count++;
1581          for (j=1; j<=charac^(e)-1; j++)
1582          {
1583               result[count]=prev[i];
1584               result[count][m]=a^j;
1585               count++;
1586          }
1587     }
1588     return(result);
1589     }
1590
1591     if (e==1)
1592     {
1593     list result;
1594     int count=1;
1595     int i,j;
1596     list l=ringlist(basering);
1597     int charac=l[1][1];
1598     list tmp;
1599     for (i=1; i<=charac^m; i++)
1600     {
1601          result[i]=tmp;
1602     }
1603     if (m==1)
1604     {
1605          for (j=0; j<=charac-1; j++)
1606          {
1607               result[count][m]=number(j);
1608               count++;
1609          }
1610          return(result);
1611     }
1612     list prev=pointsGen(m-1,e);
1613     for (i=1; i<=size(prev); i++)
1614     {
1615          for (j=0; j<=charac-1; j++)
1616          {
1617               result[count]=prev[i];
1618               result[count][m]=number(j);
1619               count++;
1620          }
1621     }
1622     return(result);
1623     }
1624
1625}
1626
1627///////////////////////////////////////////////////////////////////////////////
1628// convert list to a column vector
1629static proc list2vec (list l)
1630{
1631     matrix m[size(l)][1];
1632     for (int i=1; i<=size(l); i++)
1633     {
1634          m[i,1]=l[i];
1635     }
1636     return(m);
1637}
1638
1639///////////////////////////////////////////////////////////////////////////////
1640// convert all the point in the list with list2vec
1641proc convPoints (list points)
1642{
1643     for (int i=1; i<=size(points); i++)
1644     {
1645          points[i]=list2vec(points[i]);
1646     }
1647     return(points);
1648}
1649
1650///////////////////////////////////////////////////////////////////////////////
1651// extracts elements from l in the range m..n
1652proc graspList (list l, int m, int n)
1653{
1654     list result;
1655     int count=1;
1656     for (int i=m; i<=n; i++)
1657     {
1658          result[count]=l[i];
1659          count++;
1660     }
1661     return(result);
1662}
1663
1664///////////////////////////////////////////////////////////////////////////////
1665// "characteristic" polynomial
1666static proc xi_gen (matrix p, int e, int s)
1667{
1668     poly prod=1;
1669     list rl=ringlist(basering);
1670     int charac=rl[1][1];
1671     int l;
1672     for (l=1; l<=s; l++)
1673     {
1674          prod=prod*(1-(var(l)-p[l,1])^(charac^e-1));
1675     }
1676     return(prod);
1677}
1678
1679///////////////////////////////////////////////////////////////////////////////
1680// generating polynomials in Fitzgerald-Lax construction
1681static proc gener_funcs (matrix check, list points, int e, ideal id, int s)
1682{
1683     int n=ncols(check);
1684     if (n!=size(points)) {ERROR("Incompatible sizes of check and points");}
1685     ideal xi;
1686     int i,j;
1687     for (i=1; i<=n; i++)
1688     {
1689          xi[i]=xi_gen(points[i],e,s);
1690     }
1691     ideal result;
1692     int m=nrows(check);
1693     poly sum;
1694     for (i=1; i<=m; i++)
1695     {
1696          sum=0;
1697          for (j=1; j<=n; j++)
1698          {
1699               sum=sum+check[i,j]*xi[j];
1700          }
1701          result[i]=NF(sum,id);
1702     }
1703     return(result);
1704}
1705
1706///////////////////////////////////////////////////////////////////////////////
1707
1708proc sysFL (matrix check, matrix y, int t, int e, int s)
1709"USAGE:    sysFL (check,y,t,e,s); check,y matrix, t,e,s int
1710@format
1711          - check is a parity check matrix of the code,
1712          - y is a received word,
1713          - t the number of errors to correct,
1714          - e is the extension degree,
1715          - s is the dimension of the point for the vanishing ideal
1716@end format
1717RETURN:  the system of Fitzgerald-Lax for the given decoding problem
1718THEORY:  Based on 'check' of the given linear code, the procedure constructs
1719         the corresponding ideal constructed with a generalization of
1720         Cooper's philosophy. For basics of the method @ref{Fitzgerald-Lax method}.
1721SEE ALSO: sysQE
1722EXAMPLE:   example sysFL; shows an example
1723"
1724{
1725     list rl=ringlist(basering);
1726     int charac=rl[1][1];
1727     int n=ncols(check);
1728     int m=nrows(check);
1729     list points=pointsGen(s,e);
1730     list points2=convPoints(points);
1731     list p=graspList(points2,1,n);
1732     ideal id=vanishId(p,e);
1733     ideal funcs=gener_funcs(check,p,e,id,s);
1734
1735     ideal result;
1736     poly temp;
1737     int i,j,k;
1738
1739     //--------------- add vanishing relations ---------------------
1740     for (i=1; i<=t; i++)
1741     {
1742          for (j=1; j<=size(id); j++)
1743          {
1744               temp=id[j];
1745               for (k=1; k<=s; k++)
1746               {
1747                    temp=subst(temp,var(k),x_var(i,k,s));
1748               }
1749               result=result,temp;
1750          }
1751     }
1752
1753     //--------------- add field equations --------------------
1754     for (i=1; i<=t; i++)
1755     {
1756          for (k=1; k<=s; k++)
1757          {
1758               result=result,x_var(i,k,s)^(charac^e)-x_var(i,k,s);
1759          }
1760     }
1761     for (i=1; i<=t; i++)
1762     {
1763          result=result,e(i)^(charac^e-1)-1;
1764     }
1765
1766     result=simplify(result,8);
1767
1768     //--------------- add check relations --------------------
1769     poly sum;
1770     matrix syn[m][1]=syndrome(check,y);
1771     for (i=1; i<=size(funcs); i++)
1772     {
1773          sum=0;
1774          for (j=1; j<=t; j++)
1775          {
1776               temp=funcs[i];
1777               for (k=1; k<=s; k++)
1778               {
1779                    temp=subst(temp,var(k),x_var(j,k,s));
1780               }
1781               sum=sum+temp*e(j);
1782          }
1783          result=result,sum-syn[i,1];
1784     }
1785
1786     result=simplify(result,2);
1787
1788     points=points2;
1789     export points;
1790     return(result);
1791}
1792example
1793{
1794     "EXAMPLE:";  echo = 2;
1795     intvec vopt = option(get);
1796
1797     list l=FLpreprocess(3,1,11,2,"");
1798     def r=l[1];
1799     setring r;
1800     int s_work=l[2];
1801
1802     //the check matrix of [11,6,5] ternary code
1803     matrix h[5][11]=1,0,0,0,0,1,1,1,-1,-1,0,
1804          0,1,0,0,0,1,1,-1,1,0,-1,
1805          0,0,1,0,0,1,-1,1,0,1,-1,
1806          0,0,0,1,0,1,-1,0,1,-1,1,
1807          0,0,0,0,1,1,0,-1,-1,1,1;
1808     matrix g=dual_code(h);
1809     matrix x[1][6];
1810     matrix y[1][11]=encode(x,g);
1811     //disturb with 2 errors
1812     matrix rec[1][11]=errorInsert(y,list(2,4),list(1,-1));
1813
1814     //the Fitzgerald-Lax system
1815     ideal sys=sysFL(h,rec,2,1,s_work);
1816     print(sys);
1817     option(redSB);
1818     ideal red_sys=std(sys);
1819     red_sys;
1820     // read the solutions from this redGB
1821     // the points are (0,0,1) and (0,1,0) with error values 1 and -1 resp.
1822     // use list points to find error positions;
1823     points;
1824
1825     option(set,vopt);
1826}
1827
1828///////////////////////////////////////////////////////////////////////////////
1829// preprocessing steps for the Fitzgerald-Lax scheme
1830proc FLpreprocess (int p, int e, int n, int t, string minp)
1831{
1832     ring r1=p,x,dp;
1833     int s=1;
1834     while(p^(s*e)<n)
1835     {
1836          s++;
1837     }
1838     list var_ord;
1839     int i,j;
1840     int count=1;
1841     for (i=s; i>=1; i--)
1842     {
1843          var_ord[count]=string("x("+string(i)+")");
1844          count++;
1845     }
1846     for (i=t; i>=1; i--)
1847     {
1848          var_ord[count]=string("e("+string(i)+")");
1849          count++;
1850          for (j=s; j>=1; j--)
1851          {
1852               var_ord[count]=string("x1("+string(s*(i-1)+j)+")");
1853               count++;
1854          }
1855     }
1856
1857     list rl;
1858     list tmp;
1859
1860     if (e>1)
1861     {
1862          rl[1]=tmp;
1863          rl[1][1]=p;
1864          rl[1][2]=tmp;
1865          rl[1][2][1]=string("a");
1866          rl[1][3]=tmp;
1867          rl[1][3][1]=tmp;
1868          rl[1][3][1][1]=string("lp");
1869          rl[1][3][1][2]=1;
1870          rl[1][4]=ideal(0);
1871     } else {
1872          rl[1]=p;
1873     }
1874
1875     rl[2]=var_ord;
1876
1877     rl[3]=tmp;
1878     rl[3][1]=tmp;
1879     rl[3][1][1]=string("lp");
1880     intvec v=1;
1881     for (i=1; i<=size(var_ord)-1; i++)
1882     {
1883          v=v,1;
1884     }
1885     rl[3][1][2]=v;
1886     rl[3][2]=tmp;
1887     rl[3][2][1]=string("C");
1888     rl[3][2][2]=intvec(0);
1889
1890     rl[4]=ideal(0);
1891
1892     def r2=ring(rl);
1893     setring r2;
1894     list l=ringlist(r2);
1895     if (e>1)
1896     {
1897          execute(string("poly f="+minp));
1898          ideal id=f;
1899          l[1][4]=id;
1900     }
1901
1902     def r=ring(l);
1903     setring r;
1904
1905     return(list(r,s));
1906}
1907
1908///////////////////////////////////////////////////////////////////////////////
1909// imitating two indices
1910static proc x_var (int i, int j, int s)
1911{
1912     return(x1(s*(i-1)+j));
1913}
1914
1915///////////////////////////////////////////////////////////////////////////////
1916// random vector of length n with entries from p^e, p the characteristic
1917static proc randomvector(int n, int e)
1918{
1919    int i;
1920    matrix result[n][1];
1921    for (i=1; i<=n; i++)
1922    {
1923        result[i,1]=asElement(random_prime_vector(e));
1924    }
1925    return(result);
1926}
1927
1928///////////////////////////////////////////////////////////////////////////////
1929// "convert" representation of an element from the field extension from vector
1930//to an elelemnt
1931static proc asElement(list l)
1932{
1933  number s;
1934  int i;
1935  number w=1;
1936  if (size(l)>1) {w=par(1);}
1937  for (i=0; i<=size(l)-1; i++)
1938  {
1939    s=s+w^i*l[i+1];
1940  }
1941  return(s);
1942}
1943
1944///////////////////////////////////////////////////////////////////////////////
1945// random vector of length n with entries from p, p the characteristic
1946static proc random_prime_vector (int n)
1947{
1948  list rl=ringlist(basering);
1949  int i, charac;
1950  for (i=2; i<=rl[1][1]; i++)
1951  {
1952    if (rl[1][1] mod i ==0)
1953    {
1954      break;
1955    }
1956  }
1957  charac=i;
1958
1959  list l;
1960
1961  for (i=1; i<=n; i++)
1962  {
1963    l=l+list(random(0,charac-1));
1964  }
1965  return(l);
1966}
1967
1968///////////////////////////////////////////////////////////////////////////////
1969
1970proc decodeRandomFL(int n, int redun, int p, int e, int t, int ncodes, int ntrials, string minpol)
1971"USAGE:    decodeRandomFL(redun,p,e,n,t,ncodes,ntrials,minpol);
1972@format
1973          - n is length of codes generated,
1974          - redun = redundancy of codes generated,
1975          - p is the characteristic,
1976          - e is the extension degree,
1977          - t is the number of errors to correct,
1978          - ncodes is the number of random codes to be processed,
1979          - ntrials is the number of received vectors per code to be corrected,
1980          - minpol: due to some peculiarities of SINGULAR one needs to provide
1981          minimal polynomial for the extension explicitly
1982@end format
1983RETURN:    nothing
1984EXAMPLE:   example decodeRandomFL; shows an example
1985"
1986{
1987 intvec vopt = option(get);
1988
1989 list l=FLpreprocess(p,e,n,t,minpol);
1990
1991 def r=l[1];
1992 int s_work=l[2];
1993 export(s_work);
1994 setring r;
1995
1996 int i,j;
1997 matrix h, g, word, y, rec;
1998 ideal sys, sys2, sys3;
1999
2000
2001 option(redSB);
2002 matrix z[1][n];
2003
2004 for (i=1; i<=ncodes; i++)
2005 {
2006     h=randomCheck(redun,n,e);
2007     g=dual_code(h);
2008
2009     //---------------- generate the template system -----------------------
2010     sys=sysFL(h,z,t,e,s_work);
2011
2012     //------ modifying the template according to the received word ---------
2013     for (j=1; j<=ntrials; j++)
2014     {
2015          word=randomvector(n-redun,1);
2016          y=encode(transpose(word),g);
2017          print("Codeword:");
2018          print(y);
2019          rec=errorRand(y,t,e);
2020          print("Received word");
2021          print(rec);
2022          sys2=LF_add_synd(rec,h,sys);
2023          sys3=std(sys2);
2024          print("Groebner basis of the FL system:");
2025          print(sys3);
2026     }
2027 }
2028
2029 option(set,vopt);
2030}
2031example
2032{
2033     "EXAMPLE:";  echo = 2;
2034
2035     // correcting one error for one random binary code of length 25,
2036     // redundancy 14; 10 words are processed
2037     decodeRandomFL(25,14,2,1,1,1,10,"");
2038}
2039
2040///////////////////////////////////////////////////////////////////////////////
2041// add syndrome values to the template system in FL
2042static proc LF_add_synd (matrix rec, matrix check, ideal sys)
2043{
2044     int redun=nrows(check);
2045     ideal result=sys;
2046     matrix s[redun][1]=syndrome(check,rec);
2047     for (int i=size(sys)-redun+1; i<=size(sys); i++)
2048     {
2049          result[i]=result[i]-s[i-size(sys)+redun,1];
2050     }
2051     return(result);
2052}
2053
2054
2055/*
2056//////////////     SOME RELATIVELY EASY EXAMPLES    //////////////
2057///////////////////  THAT RUN AROUND ONE MINUTE  ////////////////
2058
2059"EXAMPLE:";  echo = 2;
2060int q=128; int n=120; int redun=n-30;
2061ring r=(q,a),x,dp;
2062decodeRandom(n,redun,1,1,6);
2063
2064int q=128; int n=120; int redun=n-20;
2065ring r=(q,a),x,dp;
2066decodeRandom(n,redun,1,1,9);
2067
2068int q=128; int n=120; int redun=n-10;
2069ring r=(q,a),x,dp;
2070decodeRandom(n,redun,1,1,19);
2071
2072int q=256; int n=150; int redun=n-10;
2073ring r=(q,a),x,dp;
2074decodeRandom(n,redun,1,1,22);
2075
2076//////////////     SOME HARD EXAMPLES    //////////////////////
2077//////      THAT MAYBE WILL BE DOABLE LATER     ///////////////
2078
20791.) These random instances are not doable in <=1000 sec.
2080
2081"EXAMPLE:";  echo = 2;
2082int q=128; int n=120; int redun=n-40;
2083ring r=(q,a),x,dp;
2084decodeRandom(n,redun,1,1,6);
2085
2086redun=n-30;
2087decodeRandom(n,redun,1,1,8);
2088
2089redun=n-20;
2090decodeRandom(n,redun,1,1,12);
2091
2092redun=n-10;
2093decodeRandom(n,redun,1,1,24);
2094
2095int q=256; int n=150; int redun=n-10;
2096ring r=(q,a),x,dp;
2097decodeRandom(n,redun,1,1,26);
2098
2099
21002.) Generic decoding is hard!
2101
2102int q=32; int n=31; int redun=n-16; int t=3;
2103ring r=(q,a),(V(1..n),U(n..1),s(redun..1)),(dp(n),lp(n),dp(redun));
2104matrix check[redun][n]= 1,1,0,1,1,0,0,0,1,0,1,0,0,1,0,0,1,0,0,0,0,
21050,0,0,0,0,0,0,0,0,0,0,1,1,0,1,1,0,0,0,1,
21060,1,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,
21070,0,1,1,0,1,1,0,0,0,1,0,1,0,0,1,0,0,1,0,0,
21080,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,1,1,0,0,
21090,1,0,1,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,
21100,0,0,0,1,1,0,1,1,0,0,0,1,0,1,0,0,1,0,0,1,
21110,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,1,1,
21120,0,0,1,0,1,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,
21130,0,0,0,0,0,1,1,0,1,1,0,0,0,1,0,1,0,0,1,0,
21140,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,
21151,1,0,0,0,1,0,1,0,0,1,0,0,1,0,0,0,0,0,0,0,
21160,0,0,0,0,0,0,0,1,1,0,1,1,0,0,0,1,0,1,0,0,
21171,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
21181,0,1,1,0,0,0,1,0,1,0,0,1,0,0,1,0,0,0,0,0,
21190,0,0,0,0,0,0,0,0,0,1,1,0,1,1,0,0,0,1,0,1,
21200,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
21210,1,1,0,1,1,0,0,0,1,0,1,0,0,1,0,0,1,0,0,0,
21220,0,0,0,0,0,0,0,0,0,0,0,1,1,0,1,1,0,0,0,1,
21230,1,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,
21240,0,0,1,1,0,1,1,0,0,0,1,0,1,0,0,1,0,0,1,0,
21250,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,1,1,0,0,
21260,1,0,1,0,0,1,0,0,1;
2127matrix rec[1][n];
2128
2129def A=sysQE(check,rec,t,1,2);
2130setring A;
2131print(qe);
2132ideal red_qe=stdfglm(qe);
2133
2134*/
Note: See TracBrowser for help on using the repository browser.