Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/GAP/pkg/lpres/gap/   (Algebra von RWTH Aachen Version 4.15.1©)  Datei vom 12.6.2024 mit Größe 6 kB image not shown  

Quelle  hnf.gi   Sprache: unbekannt

 
############################################################################
##
#W hnf.gi   LPRES    René Hartung
##

############################################################################
##
#F  LPRES_PowerRelationsOfHNF ( <rec> )
##
## computes the power relations w.r.t. the Hermite normal form <rec>.
##
InstallGlobalFunction( LPRES_PowerRelationsOfHNF,
  function(HNF)
  local i,j, # loop variables
 A; # matrix of power relations w.r.t. HNF

  A:=ShallowCopy(HNF.mat);

  # determine the power relations a_i^m_i=w(a_{i+1}..a_n) from the 
  # Hermite normal form 
  for i in [1..Length(HNF.Heads)] do
    if A[i][HNF.Heads[i]]>1 then 
      for j in [1..i-1] do
        if A[j][HNF.Heads[i]]<>0 then
          if IsInt(A[j][HNF.Heads[i]]/A[i][HNF.Heads[i]]) then 
            A[j]:=A[j]-A[j][HNF.Heads[i]]/A[i][HNF.Heads[i]] * A[i];
          elif A[j][HNF.Heads[i]]>0 then    
            A[j]:=A[j]-(QuoInt(A[j][HNF.Heads[i]],A[i][HNF.Heads[i]])+1) * A[i];
          elif A[j][HNF.Heads[i]]<-A[i][HNF.Heads[i]] then 
            A[j]:=A[j]-(QuoInt(A[j][HNF.Heads[i]],A[i][HNF.Heads[i]])) * A[i];
          fi;
        fi;
  
        if LPRES_TEST_ALL then 
          if not A[j][HNF.Heads[i]]<=0 or 
             not A[j][HNF.Heads[i]]>-A[i][HNF.Heads[i]] then 
            Error("in LPRES_PowerRelationsOfHNF");
          fi;
        fi;
      od;
    fi;
  od;

  return(A);
  end);

############################################################################
##
#F  LPRES_ReduceHNF ( <mat> , <int> )
##
## if a new reduced row is added to the Hermite normal form, it has to be 
## reduced again.
##
InstallGlobalFunction( LPRES_ReduceHNF,
  function(HNF,n)
  local corner, # corner entries in HNF
 column, # corresponding column in HNF
   row, # corresponding row in HNF
 q; # quotient of 
 
  # after adding a row to the HNF we have to reduce the 
  # old HNF
  for corner in [n..Length(HNF.Heads)] do
    column:=HNF.Heads[corner];
    for row in [1..corner-1] do
      if IsInt(HNF.mat[row][column]/HNF.mat[corner][column]) then 
        q:=HNF.mat[row][column]/HNF.mat[corner][column];
        HNF.mat[row]:=HNF.mat[row]-q*HNF.mat[corner];
      elif HNF.mat[row][column]<0 then 
        q:=-QuoInt(HNF.mat[row][column],HNF.mat[corner][column])+1;
        HNF.mat[row]:=HNF.mat[row]+q*HNF.mat[corner];
      elif HNF.mat[row][column]>=HNF.mat[corner][column] then
        q:=QuoInt(HNF.mat[row][column],HNF.mat[corner][column]);
        HNF.mat[row]:=HNF.mat[row]-q*HNF.mat[corner];
      fi;
    od;
  od;

  end);

############################################################################
##
#F  LPRES_AddRow ( <mat> , <evec> )
##
## adds the row <evec> to the Hermite normal form <mat> and returns
## whether <mat> has changed.
##
InstallGlobalFunction( LPRES_AddRow,
  function(HNF,ev)
  local evn,  # reduced <ev>
 lcm,  # least common multiple
 i,j,k,l,q, # loop variables
 Changed, # did <ev> changed the HNF?
 B,b;  # check variables

  if LPRES_TEST_ALL then 
    B:=ShallowCopy(HNF.mat);
    b:=ShallowCopy(ev);
  fi;
  
  Changed:=false;
  
  if IsZero(ev) then 
    return(false);
  fi;
  
  # the HNF does not contain any row
  if HNF.mat=[] then 
    if ev[PositionNonZero(ev)]>0 then 
      Add(HNF.mat,ev);
    else
      Add(HNF.mat,-ev);
    fi;
    Add(HNF.Heads,PositionNonZero(ev));
    return(true);
  fi;
  
  # reduce <ev> and the HNF
  i:=1;
  while i<=Length(ev) do 
    if ev[i]<>0 then 
      if not i in HNF.Heads then 
        # new corner-entry
  
        # Determine the entry in which <ev> will be added
        j:=Length(HNF.Heads)+1;
        for k in [1..Length(HNF.Heads)] do 
          if i<HNF.Heads[k] then 
            j:=k; 
            break;
          fi; 
        od;   
  
        if j>Length(HNF.Heads) then 
          # new position at the end
          Append(HNF.Heads,[i]);
          if ev[i]>0 then 
            Append(HNF.mat,[ev]);
          else 
            Append(HNF.mat,[-ev]);
          fi;  
        else 
          # at before the j-th element
  
          # move the element behind the j-th position
          for k in [Length(HNF.Heads),Length(HNF.Heads)-1..j] do
            HNF.mat[k+1]:=HNF.mat[k];
            HNF.Heads[k+1]:=HNF.Heads[k];
          od;
           
          # add the row in the j-th position
          if ev[i]>0 then 
            HNF.mat[j]:=ev;
          else
            HNF.mat[j]:=-ev;
          fi;
          HNF.Heads[j]:=i;
        fi;
        
        # since we have changed the HNF we have to reduce the remaining part
        LPRES_ReduceHNF(HNF,j);  
  
        Changed:=true;
        break;
      else
        # there is a row with the same first non-zero entry
        l:=Position(HNF.Heads,i);
  
        # reduce the given vector or the HNF
        if IsInt(ev[i]/HNF.mat[l][i]) then 
          # reduce the given vector
          ev:=ev-ev[i]/HNF.mat[l][i] * HNF.mat[l];
        elif IsInt(HNF.mat[l][i]/ev[i]) then 
          # reduce the HNF
          evn:=ShallowCopy(HNF.mat[l]);
          if ev[i]>0 then 
            HNF.mat[l]:=ev;
          else
            HNF.mat[l]:=-ev;
          fi;
          ev:=evn;
         
          LPRES_ReduceHNF(HNF,l);
       
          Changed:=true;
        else
          # both can be reduce
          q:=GcdRepresentation(HNF.mat[l][i],ev[i]);
          lcm:=Lcm(HNF.mat[l][i],ev[i]);
          if q[1]=0 then
            Error("strange GcdRepresentation in hnf.gi\n");
          fi;
          evn:=lcm/HNF.mat[l][i] *  HNF.mat[l]-lcm/ev[i] * ev;
  
          HNF.mat[l]:=q[1]*HNF.mat[l]+q[2]*ev;
  
          LPRES_ReduceHNF(HNF,l);
  
          k:=PositionNonZero(evn);
          if IsBound(evn[k]) and evn[k]<0 then 
            ev:=-evn;
          else 
            ev:=evn;
          fi;
  
          Changed:=true;
        fi;
      fi;
    else
      i:=i+1;
    fi;
  od;
  
  if LPRES_TEST_ALL then 
    if not Filtered(HermiteNormalFormIntegerMat(Concatenation(B,[b])),
                    x->not IsZero(x))=HNF.mat then 
      Error("in LPRES_AddRow: wrong Hermite normal form!");
    fi;
    if not List(HNF.mat,x->PositionNonZero(x))=HNF.Heads then 
      Error("in LPRES_AddRow: wrong heads");
    fi;
  fi;
  
  return(Changed);
  end);

############################################################################
##
#F  LPRES_RowReduce( <ev>, <HNF> )
##
## reduces the exponent vector <ev> via the Hermite normal form <HNF>.
##
InstallGlobalFunction( LPRES_RowReduce,
  function(ev,HNF)
  local i,l; # loop variables
  
  if HNF.mat=[] then 
    return(ev);
  fi;
  
  # reduce a vector with the HNF
  for i in [1..Length(ev)] do
   if ev[i]<>0 then 
     l:=Position(HNF.Heads,i);
     if l<>fail then 
       if IsInt(ev[i]/HNF.mat[l][i]) then 
         ev:=ev-ev[i]/HNF.mat[l][i]*HNF.mat[l];
       elif ev[i]>0 then
         ev:=ev-(QuoInt(ev[i],HNF.mat[l][i]))*HNF.mat[l];
       elif ev[i]<0 then
         ev:=ev-(QuoInt(ev[i],HNF.mat[l][i])-1)*HNF.mat[l];
       fi;
     fi;
   fi;
  od;

  return(ev);
  end);

[ Dauer der Verarbeitung: 0.29 Sekunden  (vorverarbeitet)  ]