Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  quarry.g   Sprache: unbekannt

 
#############################################################################
# Lazy grease:
#############################################################################

InstallMethod( LazyGreaser, "for a vector and a positive grease level",
  [IsObject, IsPosInt],
  function( vecs, lev )
    local lg;
    lg := rec( vecs := vecs, tab := vecs{[]}, ind := [], lev := lev, 
               fs := Size(BaseDomain(vecs)) );
    if lg.fs > 65536 then
        Error("Lazy grease only supported for fields with <= 65536 elements");
        return;
    fi;
    return Objectify( NewType(LazyGreaserFamily, IsLazyGreaser), lg );
  end );

InstallMethod( ViewObj, "for a lazy greaser",
  [IsLazyGreaser],
  function( lg )
    Print("<lazy greaser level ",lg!.lev," with ",Length(lg!.tab)," vectors>");
  end );

InstallMethod( GetLinearCombination, 
  "for a lazy greaser, a vector, an offset, and a list of integers",
  [IsLazyGreaser, IsVector, IsPosInt, IsList],
  function( lg, v, offset, pivs )
    # offset must be congruent 1 mod lev
    local group,i,pos,w;
    pos := NumberFFVector(v{Reversed(pivs)},lg!.fs)+1;
    if pos = 1 then return 0; fi;
    group := (offset-1) / lg!.lev + 1;
    #if not IsBound(lg!.ind[group]) then
    #    lg!.ind[group] := [];
    #fi;
    if not IsBound(lg!.ind[group][pos]) then
        # Cut away all trailing zeroes:
        i := Length(pivs);
        while i > 0 and IsZero(v[pivs[i]]) do i := i - 1; od;
        # i = 0 does not happen!
        if i = 1 then
            w := v[pivs[1]] * lg!.vecs[offset];
        else
            w := GetLinearCombination(lg,v,offset,pivs{[1..i-1]});
            if w = 0 then
                w := v[pivs[i]] * lg!.vecs[offset+i-1];
            else
                w := w + v[pivs[i]] * lg!.vecs[offset+i-1];
            fi;
        fi;
        Add(lg!.tab,w);
        lg!.ind[group][pos] := Length(lg!.tab);
    else
        w := lg!.tab[lg!.ind[group][pos]];
    fi;
    return w;
  end );

InstallMethod( GetLinearCombination, 
  "for a lazy greaser, a cvec, an offset, and a list of integers",
  [IsLazyGreaser, IsCVecRep, IsPosInt, IsList],
  function( lg, v, offset, pivs )
    # the vecs entry of the lazy greaser must be a cmat!
    # offset must be congruent 1 mod lev
    local group,i,pos,w;
    pos := CVEC_GREASEPOS(v,pivs);
    if pos = 1 then return 0; fi;
    group := (offset-1) / lg!.lev + 1;
    if not IsBound(lg!.ind[group]) then
        lg!.ind[group] := [];
    fi;
    if not IsBound(lg!.ind[group][pos]) then
        # Cut away all trailing zeroes:
        i := Length(pivs);
        while i > 0 and IsZero(v[pivs[i]]) do i := i - 1; od;
        # i = 0 does not happen!
        if i = 1 then
            w := v[pivs[1]] * lg!.vecs[offset];
        else
            w := GetLinearCombination(lg,v,offset,pivs{[1..i-1]});
            if w = 0 then
                w := v[pivs[i]] * lg!.vecs[offset+i-1];
            else
                w := w + v[pivs[i]] * lg!.vecs[offset+i-1];
            fi;
        fi;
        Add(lg!.tab,w);
        lg!.ind[group][pos] := Length(lg!.tab);
        return w;
    else
        return lg!.tab[lg!.ind[group][pos]];
    fi;
  end );

CVEC_TESTLAZY := function(m,lev)
  local erg,f,i,j,l,offset,newpos,poss,v,w;
  v := ShallowCopy(m[1]);
  l := LazyGreaser(m,lev);
  f := BaseDomain(m);
  offset := Random(1,Length(m)-lev+1);
  offset := QuoInt(offset-1,lev)*lev + 1;  # make it congruent 1 mod lev
  for i in [1..10000] do
      w := Zero(v);
      poss := [];
      for j in [1..lev] do
          repeat
              newpos := Random([1..Length(v)]);
          until not newpos in poss;
          Add(poss,newpos);
          v[poss[j]] := Random(f);
          w := w + v[poss[j]] * m[offset+j-1];
      od;
      erg := GetLinearCombination(l,v,offset,poss);
      if not((erg = 0 and IsZero(w)) or w = erg) then
          Error();
      fi;
      Print(i,"\r");
  od;
  Print("\n");
  return l;
end;

  if IsBound(basis.lazygreaser) and basis.lazygreaser <> fail then
    # The grease case:
    lev := basis.lazygreaser!.lev;
    i := 1;
    mo := -One(vec[1]);
    while i+lev-1 <= len do
      pivs := basis.pivots{[i..i+lev-1]};
      j := lev;
      while j > 0 and pivs[j] < firstnz do j := j - 1; od;
      if j > 0 then    # Otherwise, there is nothing to do at all
        lc := GetLinearCombination(basis.lazygreaser,vec,i,pivs);
        #lc := glc(basis.lazygreaser,vec,i,pivs);
        if lc <> 0 then   # 0 indicates the zero linear combination
          if dec <> false and dec <> true then
            for j in [i..i+lev-1] do
              dec[j] := vec[basis.pivots[j]];
            od;
          fi;
          AddRowVector( vec, lc, mo );
        fi;
      fi;
      i := i + lev;
    od;
    # Now go to the standard case for the rest, starting at i
  else
    i := 1;
    # The non-grease case starts from the beginning
  fi;

  # we have to work without the lazy greaser:
  ...

InstallMethod( EmptySemiEchelonBasis, "GAP method", [IsObject],
  function( vec )
    return rec( vectors := MatrixNC([],vec), pivots := [], 
                lazygreaser := fail, helper := vec{[1]} );
    # The lazygreaser component must always be bound!
    # The helper is needed for the kernel cleaner for CVecs
  end );

InstallMethod( EmptySemiEchelonBasis, "GAP method", [IsObject, IsPosInt],
  function( vec, greaselev )
    local r;
    r := rec( vectors := MatrixNC([],vec), pivots := [], helper := vec{[1]} );
    # helper is needed for kernel cleaner
    r.lazygreaser := LazyGreaser( r.vectors, greaselev );
    return r;
  end );

      if IsBound(basis.lazygreaser) then
        # In the grease case, we do full-echelon form within the grease block:
        for j in [i..len] do
          c := basis.vectors[j][newpiv];
          if not IsZero(c) then
            AddRowVector( basis.vectors[j], basis.vectors[len+1], -c );
          fi;
        od;
      fi;

#############################################################################
# Lazy grease:
#############################################################################

BindGlobal( "LazyGreaserFamily", NewFamily("LazyGreaserFamily") );
DeclareCategory( "IsLazyGreaser", IsComponentObjectRep );
DeclareOperation( "LazyGreaser", [IsObject, IsPosInt] );
DeclareOperation( "GetLinearCombination", 
  [IsLazyGreaser, IsObject, IsPosInt, IsList] );


# From linalg.gi, early tries for minimal polynomial:
# The rest can probably go at some stage:

InstallGlobalFunction( CVEC_RelativeOrderPoly, function( m, v, subb, indetnr )
  # v must not lie in subb, a semi echelonised basis of a subspace W, m a matrix
  # v must already be cleaned with subb!
  # Returns a record:
  # Gives back a new semi echelonised basis of V/W (component b), together 
  # with the relative order polynomial of v+W in V/W (component ordpol),
  # v'=v*ordpol(m) in subb, and an invertible square matrix A with
  # A*[v,vm,vm^2,...,vm^{d-1}] = b (to write vectors in V/W in terms of
  # [v+W,vm+W,...]. Also a list vl containing [v,v*m,v*m^2,...,v*m^{d-1}]
  # is bound.
  # The original v is untouched!
  local A,B,b,closed,d,dec,f,fam,i,l,lambda,o,ordpol,vcopy,vl,vv;
  f := BaseDomain(m);
  o := One(f);
  fam := FamilyObj(o);
  b := EmptySemiEchelonBasis(v);
  dec := ZeroMutable(v);
  CleanRow(b,ShallowCopy(v),true,dec);  # this puts v into b as first vector
  lambda := [dec{[1]}];
  vl := [v];
  while true do
      v := v * m;
      Add(vl,v);
      vcopy := ShallowCopy(v);
      CleanRow(subb,vcopy,false,fail);
      closed := CleanRow(b,vcopy,true,dec);
      if closed then break; fi;
      # now dec{[1..Length(b.vectors)]} * b.vectors = v
      # however, we need to express vectors in terms of the v's, so we 
      # have to invert the matrix of the dec's, this we do later on:
      Add(lambda,dec{[1..Length(b.pivots)]});
  od;
  d := Length(b.pivots);
  Unbind(vl[d+1]);  # this is linear dependent from the first d vectors!
  # we have the lambdas, expressing v*m^(i-1) in terms of the semiechelon
  # basis, now we have to express v*m^d in terms of the v*m^(i-1), that
  # means inverting a matrix: 
  B := CVEC_ZeroMat(d,CVecClass(lambda[d]));
  for i in [1..d] do
      CopySubVector(lambda[i],B[i],[1..i],[1..i]);
  od;
  A := B^-1;
  l := - dec{[1..d]} * A;
  l := Unpack(l);
  Add(l,o);
  ConvertToVectorRep(l,Size(f));
  ordpol := UnivariatePolynomialByCoefficients(fam,l,indetnr);
  vv := l[1] * vl[1];
  for i in [2..Length(vl)] do
      AddRowVector(vv,vl[i],l[i]);
  od;
  return rec( b := b, A := A, ordpol := ordpol, v := vv, vl := vl );
end );

InstallGlobalFunction( CVEC_CalcOrderPoly, 
function( opi, v, i, indetnr )
  local coeffs,g,h,j,ordpol,w;
  ordpol := [];  # comes factorised
  while i >= 1 do
      coeffs := v{opi.ranges[i]};
      if IsZero(coeffs) then
          i := i - 1;
          continue;
      fi;
      coeffs := Unpack(coeffs);
      h := UnivariatePolynomialByCoefficients(opi.fam,coeffs,indetnr);
      g := opi.rordpols[i]/Gcd(opi.rordpols[i],h);
      Add(ordpol,g);
      # This is the part coming from the ith cyclic space, now go down:
      coeffs := CoefficientsOfUnivariatePolynomial(g);
      w := coeffs[1]*v;
      for j in [2..Length(coeffs)] do
          v := v * opi.mm;
          AddRowVector(w,v,coeffs[j]);
      od;
      # Now w is one subspace lower
      v := w;
      i := i - 1;
      if IsZero(v) then break; fi;
      #Print("i=",i," new vector: ");
      #Display(v);
  od;
  return Product(ordpol);
end );
    
BindGlobal( "CVEC_CalcOrderPolyEstimate", 
function( est, opi, v, i, indetnr )
  local c,coeffs,g,h,j,k,op,ordpol,w;
  ordpol := [];  # comes factorised
  op := UnivariatePolynomialByCoefficients(opi.fam,[opi.o],indetnr);
  k := i;
  while true do   # break is used near the end
      coeffs := Unpack(v{opi.ranges[k]});
      h := UnivariatePolynomialByCoefficients(opi.fam,coeffs,indetnr);
      c := Gcd(opi.rordpols[k],h);
      g := opi.rordpols[k]/c;
      Add(ordpol,g);
      op := op * g;
      #Print("Relative order pol: ",g,"\n");
      # This is the part coming from the ith cyclic space, now go down:
      coeffs := CoefficientsOfUnivariatePolynomial(g);
      w := coeffs[1]*v;
      for j in [2..Length(coeffs)] do
          v := v * opi.mm;
          AddRowVector(w,v,coeffs[j]);
      od;
      # Now w is one subspace lower
      v := w;
      k := k - 1;
      if IsZero(v) then break; fi;
      if k = 0 then break; fi;
      #Print("Check:",Degree(est[i-1])," ", Degree(est[k]*op),"\n");
      if IsZero(est[i-1] mod (est[k] * op)) then
          Print("|\c");
          return est[i-1];
      fi;
      #Print("i=",i," new vector: ");
      #Display(v);
  od;
  return op;
end );
    
InstallGlobalFunction( CVEC_NewMinimalPolynomialMC, 
function( m, eps, verify, indetnr )
  # a new try using Cheryl's ideas for cyclic matrices generalised to 
  # an arbitrary matrix m
  # eps is a cyclotomic which is an upper bound for the error probability
  # verify is a boolean indicating, whether the result should be verified,
  # thereby proving correctness
  # indetnr is the number of an indeterminate
  local A,b,col,d,g,i,irreds,j,l,lowbounds,mm,mult,multmin,nrunclear,ns,opi,
        ordpol,p,pivs,prob,proof,re,v,vl,vli,w,zero;
  zero := ZeroMutable(m[1]);
  pivs := [1..Length(m)];
  b := EmptySemiEchelonBasis(zero);
  v := Matrix([],m[1]);   # start vectors for the spinning
  vl := Matrix([],m[1]);  # start vectors together with their images under m
  A := [];   # base changes within each subquotient
  l := [];   # a list of semi echelon bases for the subquotients
  # order polynomial infrastructure (grows over time):
  opi := rec( f := BaseDomain(m),
              d := [],
              ranges := [],
              rordpols := [],   # list of relative order polynomials
              ordpols := [],    # list of real order polynomials
              mm := fail,       # will be base-changed m later on
            );  
  opi.o := One(opi.f);
  opi.fam := FamilyObj(opi.o);
  Print(Length(m),":\c");
  while Length(pivs) > 0 do
      p := pivs[1];
      w := ShallowCopy(zero);
      w[p] := opi.o;
      Add(v,w);   # FIXME: needed?
      re := CVEC_RelativeOrderPoly(m,w,b,indetnr);
      d := Degree(re.ordpol);
      Print(d," \c");
      Add(opi.rordpols,re.ordpol);
      Add(opi.d,d);
      Add(opi.ranges,[Length(b.vectors)+1..Length(b.vectors)+d]);
      Add(l,re.b);  # FIXME: needed?
      Add(A,re.A);  # FIXME: needed?
      Append(vl,re.vl);
      pivs := Difference(pivs,re.b.pivots);
      # Add re.b to b:
      Append(b.vectors,re.b.vectors);
      Append(b.pivots,re.b.pivots);
      # Note that the latter does not cost too much memory as the vectors
      # are not copied.
  od;
  Print("\n");
  if Degree(opi.rordpols[1]) = Length(m) then
      return rec( minpoly := opi.rordpols[1],
                  charpoly := opi.rordpols[1],
                  opi := opi );
      # FIXME: Return a consistent result!
  fi;
  Info(InfoCVec,2,"Doing basechange...");
  # Now we have spun up the whole space, that is, vl is a basis of the full
  # row space
  # Now we do the base change:
  vli := vl^-1;
  opi.mm := vl*m*vli;
  Unbind(vl);  # no longer needed
  Unbind(vli); # dito

  Info(InfoCVec,2,"Factoring relative order polynomials...");
  # Factor all parts:
  col := List(opi.rordpols,f->Collected(Factors(f)));
  # Collect all irreducible factors:
  irreds := [];
  mult := [];
  lowbounds := [];
  multmin := [];
  for l in col do
      for i in l do
          p := Position(irreds,i[1]);
          if p = fail then
              Add(irreds,i[1]);
              Add(mult,i[2]);
              Add(lowbounds,i[2]);
              Add(multmin,0);
              p := Sortex(irreds);
              mult := Permuted(mult,p);
              lowbounds := Permuted(lowbounds,p);
          else
              mult[p] := mult[p] + i[2];
              if i[2] > lowbounds[p] then
                  lowbounds[p] := i[2];
              fi;
          fi;
      od;
  od;
  nrunclear := 0;   # number of irreducible factors the multiplicity of which
                    # are not yet known
  for i in [1..Length(irreds)] do
      if mult[i] > lowbounds[i] then
          nrunclear := nrunclear + 1;
      fi;
  od;
  Info(InfoCVec,2,"Number of irreducible factors in charpoly: ",Length(irreds),
                  " mult. in minpoly unknown: ",nrunclear);

  ordpol := Lcm(opi.rordpols); # this is a lower bound for the minpoly
                               # in particular, it is a multiple of rordpols[1]
  i := 2;
  p := 1/Size(opi.f);
  proof := false;
  repeat   # until verification said "OK"
      # This is an upper estimate of the probability not to find a generator
      # of a cyclic space:
      prob := p;   # we already have for one vector the order polynomial
      Info(InfoCVec,2,"Calculating order polynomials...");
      while i <= Length(opi.rordpols) do
          v := ShallowCopy(zero);
          v[opi.ranges[i][1]] := opi.o;
          g := CVEC_CalcOrderPoly(opi,v,i,indetnr);
          if not(IsZero(ordpol mod g)) then
              ordpol := Lcm(ordpol,g);
          fi;
          if Degree(ordpol) = Length(m) then   # a cyclic matrix!
              break;
          fi;
          prob := prob * p;  # probability to have missed one Jordan block
          Print( "Probability to have them all (%%): ",
                 Int((1-prob)^nrunclear*1000),"\n");
          if 1-(1-prob)^nrunclear < eps then
              break;   # this is the probability to have missed one
          fi;
          i := i + 1;
      od;

      Info(InfoCVec,2,"Checking multiplicities...");
      nrunclear := 0;
      for j in [1..Length(irreds)] do
          multmin[j] := CVEC_FactorMultiplicity(ordpol,irreds[j]);
          if multmin[j] < mult[j] then
              nrunclear := nrunclear + 1;
          fi;
      od;
      if nrunclear = 0 then proof := true; break; fi;   # result is correct!

      if verify then
          Info(InfoCVec,2,"Verifying result (",nrunclear,
               " unclear multiplicities) ...");
          proof := true;  # will be set to false once we discover something
          for j in [1..Length(irreds)] do
              if multmin[j] < mult[j] then
                  Info(InfoCVec,2,"Working on factor: ",irreds[j],
                                  " multiplicity: ",multmin[j]);
                  mm := Value(irreds[j],opi.mm)^multmin[j];
                  ns := NullspaceMatMutableX(mm);
                  if Length(ns) < mult[j] then
                      proof := false;
                      break;
                  fi;
              fi;
          od;
      fi;
  until not(verify) or proof;

  return rec(minpoly := ordpol,
             charpoly := Product( opi.rordpols ),
             opi := opi,
             irreds := irreds,
             mult := mult,
             multmin := multmin);
end );

InstallGlobalFunction( CVEC_NewMinimalPolynomial, function( m, indetnr )
  # a new try using Cheryl's ideas for cyclic matrices generalised to 
  # an arbitrary matrix m
  local A,b,d,est,g,i,l,opi,ordpol,p,pivs,re,v,vl,vli,w,zero;
  zero := ZeroMutable(m[1]);
  pivs := [1..Length(m)];
  b := EmptySemiEchelonBasis(zero);
  v := Matrix([],m[1]);   # start vectors for the spinning
  vl := Matrix([],m[1]);  # start vectors together with their images under m
  A := [];   # base changes within each subquotient
  l := [];   # a list of semi echelon bases for the subquotients
  # order polynomial infrastructure (grows over time):
  opi := rec( f := BaseDomain(m),
              d := [],
              ranges := [],
              rordpols := [],   # list of relative order polynomials
              ordpols := [],    # list of real order polynomials
              mm := fail,       # will be base-changed m later on
            );  
  opi.o := One(opi.f);
  opi.fam := FamilyObj(opi.o);
  Print(Length(m),":\c");
  while Length(pivs) > 0 do
      p := pivs[1];
      w := ShallowCopy(zero);
      w[p] := opi.o;
      Add(v,w);   # FIXME: needed?
      re := CVEC_RelativeOrderPoly(m,w,b,indetnr);
      d := Degree(re.ordpol);
      Print(d," \c");
      Add(opi.rordpols,re.ordpol);
      Add(opi.d,d);
      Add(opi.ranges,[Length(b.vectors)+1..Length(b.vectors)+d]);
      Add(l,re.b);  # FIXME: needed?
      Add(A,re.A);  # FIXME: needed?
      Append(vl,re.vl);
      pivs := Difference(pivs,re.b.pivots);
      # Add re.b to b:
      Append(b.vectors,re.b.vectors);
      Append(b.pivots,re.b.pivots);
      # Note that the latter does not cost too much memory as the vectors
      # are not copied.
  od;
  Print("\nDoing basechange...\c");
  # Now we have spun up the whole space, that is, vl is a basis of the full
  # row space
  # Now we do the base change:
  vli := vl^-1;
  opi.mm := vl*m*vli;
  Unbind(vl);  # no longer needed
  Unbind(vli); # dito
  ordpol := opi.rordpols[1];
  Print("done\nCalculating order polynomials...\c");
  est := [opi.rordpols[1]];
  for i in [2..Length(opi.rordpols)] do
      v := ShallowCopy(zero);
      v[opi.ranges[i][1]] := opi.o;
      g := CVEC_CalcOrderPolyEstimate(est,opi,v,i,indetnr);
      if g <> ordpol then
          ordpol := Lcm(ordpol,g);
      fi;
      est[i] := ordpol;
      Print(i,"(",Length(opi.rordpols),"):",Degree(ordpol)," \c");
      if Degree(ordpol) = Length(m) then   # a cyclic matrix!
          break;
      fi;
  od;
  return rec(minpoly := ordpol,charpoly := Product( opi.rordpols ),opi := opi);
end );

# From linalg.gd, early tries for the minimal polynomial:
# The rest can probably be deleted later on:
DeclareGlobalFunction( "CVEC_RelativeOrderPoly" );
DeclareGlobalFunction( "CVEC_CalcOrderPoly" );
DeclareGlobalFunction( "CVEC_NewMinimalPolynomial" );
DeclareGlobalFunction( "CVEC_NewMinimalPolynomialMC" );


[ Dauer der Verarbeitung: 0.39 Sekunden  (vorverarbeitet)  ]

                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge