source: git/Singular/LIB/decodegb.lib @ 7f3ad4

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