[BACK]Return to la_solution_guide.rr CVS log [TXT][DIR] Up to [local] / OpenXM / src / asir-contrib / packages / src

File: [local] / OpenXM / src / asir-contrib / packages / src / la_solution_guide.rr (download)

Revision 1.14, Tue Dec 9 01:47:06 2014 UTC (9 years, 5 months ago) by takayama
Branch: MAIN
CVS Tags: HEAD
Changes since 1.13: +4 -2 lines

Forget to include a change in the previous commit.

/* $OpenXM: OpenXM/src/asir-contrib/packages/src/la_solution_guide.rr,v 1.14 2014/12/09 01:47:06 takayama Exp $ */
/* The file name should be la_solution_guide.rr (la = linear algebra) */

/* ctrl("show_crossref",1)$ */
/*
  if (!Loaded_noro_print) load(FileName); else ;
*/
/*
extern Loaded_noro_print$ 
*/
/* The next two lines cannot be in a module */
/*
ox_loadfile(Loaded_noro_print,"noro_print.rr")$ 
ox_loadfile(Loaded_ok_matrix,"ok_matrix.rr")$ 
*/
import("names.rr")$

def taka_tex_form_old(Ob)  {
   Tb = string_to_tb("");
   taka_tex_form(Ob,Tb);
   return tb_to_string(Tb);
}

module lasg;

localf matrix_to_dp $
localf v $ 
localf dp_to_matrix,
       lasg_1, lasg_2, lasg_3, lt, gen_1, should_zero,
       gen_1b, gen_rank_prob, print_matrix_list,
       gen_eq_prob, gen_eq_nosol_prob,
       make_dense, copy_matrix, reduced_form,
       reduced_form_old, build_solution,
       zero_row, kernel, gen_lineq_quiz,
       test, gen_ans, gen_reduced_matrix,
       gen_regmat, print_det_prob,
  random_unimod,is_diagonal,eigen_prob,print_eigen_prob;

#define min(a,b) (a>b? b: a)
#define MaxN 3
#define Step 2
#define MaxC 1
print("Type in lasg.test();  Problems will be saved in hoge.tex")$

static Seed0 $
static Dense $
static Lasg_test_data_1 $

Seed0 = 1 $
Dense = 1 $

def matrix_to_dp(M) {
  local S;
  local Ans;
  local I,J;
  local F;
  S = size(M);
  Ans = [];
  for (I=0; I<S[0]; I++) {
    F = 0;
    for (J=0; J<S[1]; J++) {
      F = F+M[I][J]*v(J,S[1]);
    }
    Ans = append(Ans,[F]);
  }  
  return(Ans);
}

def v(I,N) {
  V = newvect(N);
  V[I] = 1;
  return(dp_vtoe(V));
}

def dp_to_matrix(FF,N) {
  local M, A, I, F, HH, H, K;
  M = length(FF);
  A = newmat(M,N);
  for (I=0; I<M; I++) {
    F = FF[I];
    while (F != 0) {
      HH = dp_hm(F);
      H = dp_etov(HH);
      F = F-HH;
      for (K=0; K<N; K++) {
        if (H[K] != 0) {
          A[I][K] = dp_hc(HH);
        }
      }
    }
  }  
  return A;
}

def lasg_1(F,I,J) {
  G = newvect(length(F),F);
  T = G[I];
  G[I] = G[J];
  G[J] = T;
  return vtol(G);
}

def lasg_2(F,I,C) {
  G = newvect(length(F),F);
  G[I] = G[I]*C;
  return vtol(G);
}

def lasg_3(F,I,J,C) {
  G = newvect(length(F),F);
  G[I] = G[I] + G[J]*C;
  return vtol(G);
}

def lt(A,B) {
  N=size(A)[0];
  for (I=0; I<N; I++) {
   if (A[I] < B[I]) return(1);
   if (A[I] > B[I]) return(0);
  }
  return(2);
}

def gen_1(M,N,Rank,Seed) {
  /**/ print([M,N,Rank,Seed]); 
  random(Seed);
  if (Rank > min(M,N)) Rank = min(M,N);
  A = newmat(M,N);
  S = newvect(N);

  /* Determine the support */
  for (I=0; I<Rank; I++) {
    while (1) {
      K = random()%N;
      print(K);
      if (I == 0) K = 0;
      if (S[K] == 0) { S[K] =1 ; break; }
    }
  }

  for (I=0,K=0; (K<N && I<M) ; I++) {
    while(1) {
      if (S[K] != 0) {A[I][K] = 1; K++; break;}
      else { K++; if (K >= N) break;}
    }
  }
  return A;
}

def should_zero(A,I0,J) {
  M = size(A)[0];
  for (I = I0+1; I<M; I++) {
    if (A[I][J]) return(1);
  }
  return(0);
}

def gen_1b(M,N,Rank,Seed) {
   /* static Dense; */
   A = gen_1(M,N,Rank,Seed);
   for (I=0; I<Rank; I++) {
     J=0;
     while (J < N ) {
       if ( A[I][J] ) {
         J++;
         while (J<N) {
           if (!should_zero(A,I,J)) {
             if (random() % 2 == 0 || Dense) {
               A[I][J] = (random()%MaxN +1)*(-1)^(random() % N);
             }
           }
           J++;
         }
       }
       J++;
     }
   }
   return A;
}

/*&usage begin: lasg.gen_rank_prob(M,N,Rank,P)
 It returns problems to evaluate ranks of matrices.
 description:
  It returns {P} 
  {M} X {N} matrix of the rank {Rank}.
  The symbol {Step} is used to control the difficulty
  and the global variable {seed0} is a seed for random numbers.
 example: lasg.gen_rank_prob(3,4,2,2);
end: */
def gen_rank_prob(M,N,Rank,P) {
  /* static Seed0;  */
  print(Seed0);
  Ans = [ ];
  for (K=0; K<P; K++) {
    A = gen_1b(M,N,Rank,Seed0);
    B = [A];
    A = make_dense(A);
    B = append(B,[A]);
    F = matrix_to_dp(A);
    for (R=0; R<Step; R++) {
      if (random()% (Step-1) == 0) {
         I = random()%M; J = random()%M;
         if (I != J) {
           F = lasg_1(F,I,J);
           B = append(B,[[I,J],[dp_to_matrix(F,N)]]);
         }
      }
      I = J = 0;
      while (I==J) {
        I = random()%M; J = random()%M; C = (random()%MaxN)*(-1)^(random()%3);
        if (C == 0) C = 1;
        if (I != J) {
           F = lasg_3(F,I,J,C);
           B = append(B,[[I,J,C],dp_to_matrix(F,N)]);
           break;
        }
      }
    }
    print_matrix_list(B);
    print("---------------------------------");
    Ans = append(Ans,[B]);
  }
  return Ans;
}

def print_matrix_list(B) {
  print("_____________________________________");
  N = length(B);
  for (I=0; I<N; I++) {
     print(B[I]);
     print("  ");
  }
  print("^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^");
}

/*&usage begin: lasg.gen_eq_prob(M,Rank,N)
 It returns problems to solve systems of linear equations.
 description:
  It returns {N} 
  {M} X {M} matrix of the rank {Rank}.
  The symbol {Step} is used to control the difficulty
  and the global variable {seed0} is a seed for random numbers.
 example: lasg.gen_eq_prob(4,3,2);
 ref: lasg.gen_lineq_quiz.
end: */
def gen_eq_prob(M,Rank,P) {
  Ans = [ ];
  N = M+1;
  for (K=0; K<P; K++) {
    A = gen_1b(M,M,Rank,Seed0);
    AA = newmat(M,N);
    for (I=0; I<M; I++) {
      for (J=0; J<N-1; J++) {
        AA[I][J] = A[I][J];
      }
      if (I < Rank) {
        AA[I][N-1] = random()%MaxN + 1;
      }
    }
    A = AA;
    B = [A];
    A = make_dense(A);
    B = append(B,[A]);
    F = matrix_to_dp(A);
    for (R=0; R<Step; R++) {
      if (random()% (Step-1) == 0) {
         I = random()%M; J = random()%M;
         if (I != J) {
           F = lasg_1(F,I,J);
           B = append(B,[[I,J],[dp_to_matrix(F,N)]]);
         }
      }
      I = J = 0;
      while (I==J) {
        I = random()%M; J = random()%M; C = (random()%MaxN)*(-1)^(random()%3);
        if (C == 0) C = 1;
        if (I != J) {
           F = lasg_3(F,I,J,C);
           B = append(B,[[I,J,C],dp_to_matrix(F,N)]);
           break;
        }
      }
    }
    print_matrix_list(B);
    print("---------------------------------");
    Ans = append(Ans,[B]);
  }
  return Ans;
}

def gen_eq_nosol_prob(M,Rank,P) {

  Ans = [ ];
  if (Rank >= M) error();
  N = M+1;
  for (K=0; K<P; K++) {
    A = gen_1b(M,M,Rank,Seed0);
    AA = newmat(M,N);
    for (I=0; I<M; I++) {
      for (J=0; J<N-1; J++) {
        AA[I][J] = A[I][J];
      }
      if (I <= Rank) {
        AA[I][N-1] = random()%MaxN + 1;
      }
    }
    A = AA;
    B = [A];
    A = make_dense(A);
    B = append(B,[A]);
    F = matrix_to_dp(A);
    for (R=0; R<Step; R++) {
      if (random()% (Step-1) == 0) {
         I = random()%M; J = random()%M;
         if (I != J) {
           F = lasg_1(F,I,J);
           B = append(B,[[I,J],[dp_to_matrix(F,N)]]);
         }
      }
      I = J = 0;
      while (I==J) {
        I = random()%M; J = random()%M; C = (random()% MaxC)*(-1)^(random()%3);
        if (C == 0) C = 1;
        if (I != J) {
           F = lasg_3(F,I,J,C);
           B = append(B,[[I,J,C],dp_to_matrix(F,N)]);
           break;
        }
      }
    }
    print_matrix_list(B);
    print("---------------------------------");
    Ans = append(Ans,[B]);
  }
  return Ans;
}

def make_dense(A) {
  M = size(A)[0];
  N = size(A)[1];
  AA = newmat(M,N);
  for (I=0; I<M; I++) {
    for (J=0; J<N; J++) {
      if (I != 0) {
        AA[I][J] = A[I][J] + A[0][J];
      }else{
        AA[I][J] = A[I][J];
      }
    }
  }
  return AA;
}

/* A = newmat(2,3,[[1,2,3],[0,1,2]])$ */

def copy_matrix(A) {
  M = size(A)[0];
  N = size(A)[1];
  AA = newmat(M,N);
  for (I=0; I<M; I++) {
    for (J=0; J<N; J++) {
      AA[I][J] = A[I][J];
    }
  }
  return AA;
}

/*&usage begin: lasg.reduced_form(A)
 It translates the matrix {A} into the reduced normal form
 by elementary transformations.
 The sequence of elementary transformations is also returned.
 example: lasg.reduced_form(newmat(2,3,[[2,3,8],[1,2,5]]));
 end:
*/
Lasg_test_data_1=newmat(3,5,[[0,0,0,1,1],[0,0,1,0,-2],[1,3,0,0,2]]) $
def reduced_form(A) {
  Ans = [ ];
  M = size(A)[0];
  N = size(A)[1];
  AA = A;
  Pivot = 0;
  J = 0;
  while (J < N) {
    I = Pivot;
    AllZero = 1;
    while (I < M) {
      if (AA[I][J] != 0) {
       AllZero = 0;
       if (AA[I][J] != 1) {
         Msg = "Multiplying the "+rtostr(I+1)+"th row by "+
               rtostr(1/AA[I][J]);
         B = copy_matrix(AA);
         for (JJ=0; JJ<N; JJ++) {
           B[I][JJ] = AA[I][JJ]/AA[I][J];
         }
         Ans = append(Ans,[[Msg,B]]);
         AA = B;
       }
       if (I != Pivot) {
         Msg = "Exchanging the "+rtostr(I+1)+"th row and "+rtostr(Pivot+1)+
               "th row";
         B = copy_matrix(AA);
         for (JJ=0; JJ<N; JJ++) {
           B[I][JJ] = AA[Pivot][JJ];
           B[Pivot][JJ] = AA[I][JJ];
         }
         Ans = append(Ans,[[Msg,B]]);
         AA = B;
       }
       Msg = "Eliminating the "+rtostr(J+1)+"th column by "+
               "("+rtostr(I+1)+","+rtostr(J+1)+")th entry" ;
       B = copy_matrix(AA);
       print(B); print("----------------");
       Changed = 0;
       for (II = 0; II<M; II++) {
         if (II != Pivot && B[II][J] != 0) {
           C = B[II][J];  Changed = 1;
           for (JJ=0; JJ<N; JJ++) {
             B[II][JJ] = B[II][JJ] - B[Pivot][JJ]*C;
           }
         }
       }
       if (Changed) {
         Ans = append(Ans,[[Msg,B]]);
         print(B); print("---------------");
       }
       AA = B;
       break; /* break J loop */
      }
      I++;
    }
    if (!AllZero) Pivot++;
    J++;
  }
  return(Ans);
}

def reduced_form_old(A) {
  Ans = [ ];
  M = size(A)[0];
  N = size(A)[1];
  AA = A;
  I = 0;
  while (I < M) {
    J = 0;
    while (J < N) {
      if (AA[I][J] != 0) {
       if (AA[I][J] != 1) {
         Msg = "Multiplying the "+rtostr(I+1)+"th row by "+
               rtostr(1/AA[I][J]);
         B = copy_matrix(AA);
         for (JJ=0; JJ<N; JJ++) {
           B[I][JJ] = AA[I][JJ]/AA[I][J];
         }
         Ans = append(Ans,[[Msg,B]]);
         AA = B;
       }
       Msg = "Eliminating the "+rtostr(J+1)+"th column by "+
               "("+rtostr(I+1)+","+rtostr(J+1)+")th entry" ;
       B = copy_matrix(AA);
       print(B); print("----------------");
       Changed = 0;
       for (II = 0; II<M; II++) {
         if (II != I && B[II][J] != 0) {
           C = B[II][J];  Changed = 1;
           for (JJ=0; JJ<N; JJ++) {
             B[II][JJ] = B[II][JJ] - B[I][JJ]*C;
           }
         }
       }
       if (Changed) {
         Ans = append(Ans,[[Msg,B]]);
         print(B); print("---------------");
       }
       AA = B;
       break; /* break J loop */
      }
      J++;
    }
    I++;
  }
  return(Ans);
}

/* Construct solutions from a matrix of the normal form. 
   [ x1 x2 ... xn b ]
*/
/* Test data for build_solution */
/* A = newmat(3,5,[[1,1,0,1,1],
                [0,0,1,1,2],
                [0,0,0,0,0]])$ */
def build_solution(A) {
  N =size(A);
  M = N[0]; N=N[1];
  B = newvect(M);
  for (I=0; I<M; I++) {
    B[I] = A[I][N-1];
  }
  /* Check if there is a solution or not. */
  for (I=M-1; I>=0; I--) {
    if (B[I] != 0 && zero_row(A,I)) {
      return([]); /* No solution */
    }
  }
  /* S is a solution vector for non-homogeneous problem. */
  S  = newvect(N);  S[N-1] = -1;
  for (I=M-1; I>=0; I--) {
    V = A*S;
    if (V[I] != 0) {
      for (J=0; J<N-1; J++) {
         if (A[I][J] != 0) {
           S[J] = -V[I]/A[I][J];
           break;
         }
      }
    }
  }
  AA = newmat(M,N-1);
  for (I=0; I<M; I++) {
    for (J=0; J<N-1;J++) {
      AA[I][J] = A[I][J];
    }
  }
  K = kernel(AA);
  SS = newvect(N-1);
  for (I=0; I<N-1; I++) {
    SS[I] = S[I];
  }
  return([SS,K]);
}

def zero_row(A,I) {
  N =size(A);
  M = N[0]; N=N[1];
  for (J=0; J<N-1; J++) {
    if (A[I][J] != 0) return 0;
  }
  return 1;
}

def kernel(A) {
  K = omatrix_kernel(A);
  N = K[0];
  if (N == 0) { return [ ]; }
  M = size(A)[1];
  Ans = [ ];
  for (I=0; I<N; I++) {
    Ans = append(Ans,[ newvect(M,K[1][I]) ]);
  }
  return Ans;
}

/*&usage begin: lasg.gen_lineq_quiz()
 It returns a set of problems and answers 
 to solve systems of linear equations
 in the LaTeX format.
 description:
  Change parameters in the program
    P = lasg.gen_eq_prob(M,R,N);
  where {M} X {M} is the size of the matrix, {R} is the rank, and 
  {N} is the number of problems.
  The symbol {Step} is used to control the difficulty
  and the global variable {seed0} is a seed for random numbers.
 Ref: lasg.gen_rank_prob, lasg.gen_eq_prob, lasg.build_solution, lasg.test.
end: */
def gen_lineq_quiz() {
   S = "\\documentclass{article} \\begin{document}\n";
   N = 2;  /* Number of questions */
   P = gen_eq_prob(5,3,N);  /* size of matrix and rank */
   for (I=0; I<N; I++) {
     PP = P[I];
     PP = PP[length(PP)-1];
     S += "\\noindent $\\bullet$ Make elementary transformations for \n"+
          "$$ (A|b) = "+taka_tex_form_old(PP) + "$$ ";
     S += "to solve a system of linear equations of the form $(A|b)$.\n \\medbreak \\noindent Answer:\n";
     A = reduced_form(PP);
     M = length(A);
     for (J=0; J<M; J++) {
       S += A[J][0]+", we get \\\\ \n";
       S += "$$ "+taka_tex_form_old(A[J][1])+" $$\n";
     }
     K = build_solution(A[M-1][1]);
     if (length(K) == 0) {
       S += "There is no solution.\n";
     }else{
       S += "The solutions of the system of linear equations are \n";
       S += "$$ "+taka_tex_form_old(K[0]);
       for (J=0; J < length(K[1]); J++) {
          S += "+ c_{"+rtostr(J+1)+"}" + taka_tex_form_old(K[1][J]);
       }
       S += " $$\n";
       if (length(K[1])>0) {
         S += "where $c_i$ are arbitrary constants. ";
       }
     }
     S += "\\bigbreak\n";
   }
   S += "\\end{document}\n";
   return(S);
}

def test() {
  S = gen_lineq_quiz();
  shell("rm hoge.tex");
  output("hoge.tex");
  print(S);
  output();
}


/*&uasge lasg.gen_ans(P)
 It generates an answer of the problem of solving linear equations
 given by {P} (extended matrix).
 The answer is returned as a string in LaTeX format.
 example:  lasg.gen_ans([[2,3,8],[1,2,5]]);
 end:
*/
def gen_ans(PP) {
     if (type(PP) == 4) {
       PP = matrix_list_to_matrix(PP);
     }
     S = "% problem. \n";
     S += "\\noindent $\\bullet$ Make elementary transformations for \n"+
          "$$ (A|b) = "+taka_tex_form_old(PP) + "$$\n";
     S += "to solve a system of linear equations of the form $(A|b)$.\n \\medbreak \\noindent Answer:\n";
     A = reduced_form(PP);
     M = length(A);
     for (J=0; J<M; J++) {
       S += A[J][0]+", we get \\\\ \n";
       S += "$$ "+taka_tex_form_old(A[J][1])+" $$\n";
     }
     K = build_solution(A[M-1][1]);
     if (length(K) == 0) {
       S += "There is no solution.\n";
     }else{
       S += "The solutions of the system of linear equations are \n";
       S += "$$ "+taka_tex_form_old(K[0]);
       for (J=0; J < length(K[1]); J++) {
          S += "+ c_{"+rtostr(J+1)+"}" + taka_tex_form_old(K[1][J]);
       }
       S += " $$\n";
       if (length(K[1])>0) {
         S += "where $c_i$ are arbitrary constants. ";
       }
     }
     S += "\n\n";
     return S;
}

/*&uasge lasg.gen_reduced_matrix(P)
 It generates reduced_matrix for a given matrix {P}.
 The answer is returned as a string in LaTeX format.
 example:  lasg.gen_reduced_matrix([[0,0,0,1,1],[0,0,1,0,-2],[1,3,0,0,2]]);
 end:
*/
def gen_reduced_matrix(PP) {
     if (type(PP) == 4) {
       PP = matrix_list_to_matrix(PP);
     }
     S = "% problem. \n";
     S += "\\noindent $\\bullet$ Make elementary transformations for \n"+
          "$$ A = "+taka_tex_form_old(PP) + "$$\n";
     S += "to generate the reduced expression.\n \\medbreak \\noindent Answer:\n";
     A = reduced_form(PP);
     M = length(A);
     for (J=0; J<M; J++) {
       S += A[J][0]+", we get \\\\ \n";
       S += "$$ "+taka_tex_form_old(A[J][1])+" $$\n";
     }
     S += "\n\n";
     return S;
}

/*&usage begin: lasg.gen_regmat(M)
 It returns a M x M regular (non-sigular) matrix
 description:
  It returns 
  {M} X {M} matrix A such that |A| <> 0
  The option {stop} is used to control the difficulty
  and the global variable {seed0} is a seed for random numbers.
 example: lasg.gen_regmat(4);
 ref: lasg.gen_lineq_quiz.
end: */
def gen_regmat(M) {
  Step0 = getopt(step);
  if (type(Step0) <= 0) Step0 = 2;
  SeedMat = getopt(seedmat);
  if (type(SeedMat)<=0) {
    Ans = newmat(M,M);
    for (I=0; I<M; I++) Ans[I][I] = 1+random()%M;
    Ans[M-1][0] = 1+random()%M;
    Ans2 = newmat(M,M);
    for (I=0; I<M; I++) Ans2[I][I] = 1;
    Ans2[0][M-1] = 1+random()%M;
    Ans=Ans*Ans2;
  }else{
    Ans = matrix_list_to_matrix(SeedMat);    
  }
  for (P=0; P<Step0; P++) {
    A = newmat(M,M);
    I0 = random()%M;
    J0 = I0+1; if (J0 >= M) J0=0;
    for (I=0; I<M; I++) A[I][I] = 1;
    A[I0][J0] = 1 + random()%M;
    Ans = Ans*A;
  }
  return(Ans);
}

/*&usage begin: lasg.print_det_prob(M |step=Step0, crypt=C)
 It returns [Problem in LaTeX format, Answer-string,Matrix]
 example: lasg.print_det_prob(4 | crypt=3)
 ***0xyz --> xyz-3 is the answer
end: */
def print_det_prob(M) {
  Step0 = getopt(step);
  if (type(Step0) <= 0) Step0 = 2;
  Crypt = getopt(crypt);
  if (type(Crypt) <= 0) Crypt=1;
  A=gen_regmat(M | step = Step0);
  Det = det(A)+Crypt;
  P=(1+random()%8)*10;
  Ans=rtostr(P)+rtostr(Det);
  return([print_tex_form(A),Ans,A]);
}
def random_unimod(N) {
  if (type(getopt(maxint)) > 0) Maxint = getopt(maxint);
  else Maxint = 5;
  if (type(getopt(iteration)) > 0) Iteration = getopt(iteration);
  else Iteration = 3;
  A = matrix_identity_matrix(N);
  for (I=0; I<Iteration; I++) {
    B = matrix_identity_matrix(N);
    Idx = random()%N;
    Idy = random()%N;
    if (Idx == Idy) Idy = (Idy+1)%N;
    B[Idx][Idy] = (random()%Maxint)+1;
    A=A*B;
  }
  B = matrix_identity_matrix(N);
  B[0][0]=B[1][1]=0;
  B[0][1]=1; B[1][0]=1;
  A=A*B;
  return(A);  
}
def is_diagonal(B) {
  N = size(B)[0];
  for (I=0; I<N; I++) {
    for (J=0; J<N; J++) {
      if (I != J) {
        if (B[I][J] != 0) return(0);
      }
    }
  }
  return(1);
}
def eigen_prob(N) {
  Maxint = 3;
  A = matrix_identity_matrix(N);
  for (I=0; I<N; I++) A[I][I] = random()%Maxint;
  Eigen=newvect(N);
  for (I=0; I<N; I++) Eigen[I] = A[I][I];
  P = random_unimod(N);
  B = P*A*matrix_inverse(P);
  if (is_diagonal(B)) return(eigen_prob(N));
  return([B,vtol(Eigen),matrix_matrix_to_list(matrix_transpose(P))]);
}

def print_eigen_prob(M) {
  Step0 = getopt(step);
  if (type(Step0) <= 0) Step0 = 2;
  Crypt = getopt(crypt);
  if (type(Crypt) > 0) Crypt=1; else Crypt=0;
  L=eigen_prob(M);
  A=L[0];
  E_crypt = newvect(M,L[1]);
  if (Crypt) {
    for (I=0; I<M; I++) E_crypt[I]++;
  }
  Ans=rtostr(matrix_matrix_to_list(E_crypt));
  return([print_tex_form(A),Ans,L]);
}
endmodule;


/*
 example: lasg.gen_rank_prob(3,4,2,2);
 example: lasg.gen_eq_prob(4,3,2);
 example: lasg.reduced_form(newmat(2,3,[[2,3,8],[1,2,5]]));
 example:  lasg.gen_ans([[2,3,8],[1,2,5]]);
 example:  lasg.gen_reduced_matrix([[0,0,0,1,1],[0,0,1,0,-2],[1,3,0,0,2]]);
*/


end$