Spracherkennung für: .gi vermutete Sprache: Unknown {[0] [0] [0]} [Methode: Schwerpunktbildung, einfache Gewichte, sechs Dimensionen]
#############################################################################
##
#W resclass.gi GAP4 Package `ResClasses' Stefan Kohl
##
## This file contains implementations of methods and functions for computing
## with unions of residue classes +/- finite sets ('residue class unions').
##
#############################################################################
#############################################################################
##
#S Implications between the categories of residue class unions /////////////
#S and shorthands for commonly used filters. ///////////////////////////////
##
#############################################################################
InstallTrueMethod( IsResidueClassUnion,
IsResidueClassUnionOfZorZ_pi );
InstallTrueMethod( IsResidueClassUnionOfZorZ_pi,
IsResidueClassUnionOfZ );
InstallTrueMethod( IsResidueClassUnionOfZorZ_pi,
IsResidueClassUnionOfZ_pi );
InstallTrueMethod( IsResidueClassUnion,
IsResidueClassUnionOfZxZ );
InstallTrueMethod( IsResidueClassUnion,
IsResidueClassUnionOfGFqx );
BindGlobal( "IsResidueClassOfZ",
IsResidueClassUnionOfZ and IsResidueClass );
BindGlobal( "IsResidueClassOfZxZ",
IsResidueClassUnionOfZxZ and IsResidueClass );
BindGlobal( "IsResidueClassOfZ_pi",
IsResidueClassUnionOfZ_pi and IsResidueClass );
BindGlobal( "IsResidueClassOfZorZ_pi",
IsResidueClassUnionOfZorZ_pi and IsResidueClass );
BindGlobal( "IsResidueClassOfGFqx",
IsResidueClassUnionOfGFqx and IsResidueClass );
BindGlobal( "IsResidueClassUnionInResidueListRep",
IsResidueClassUnion and IsResidueClassUnionResidueListRep );
BindGlobal( "IsResidueClassUnionInClassListRep",
IsResidueClassUnion and IsResidueClassUnionClassListRep );
BindGlobal( "IsResidueClassUnionOfZInClassListRep",
IsResidueClassUnionOfZ and IsResidueClassUnionClassListRep );
#############################################################################
##
#S The families of residue class unions. ///////////////////////////////////
##
#############################################################################
# Internal variables for caching the families of residue class unions
# used in the current GAP session.
BindGlobal( "Z_RESIDUE_CLASS_UNIONS_FAMILIES", [] );
BindGlobal( "Z_PI_RESIDUE_CLASS_UNIONS_FAMILIES", [] );
BindGlobal( "GF_Q_X_RESIDUE_CLASS_UNIONS_FAMILIES", [] );
#############################################################################
##
#F ZResidueClassUnionsFamily( <fixedreps> )
##
InstallGlobalFunction( ZResidueClassUnionsFamily,
function ( fixedreps )
local fam, pos;
if not fixedreps then pos := 1; else pos := 2; fi;
if IsBound( Z_RESIDUE_CLASS_UNIONS_FAMILIES[ pos ] )
then return Z_RESIDUE_CLASS_UNIONS_FAMILIES[ pos ]; fi;
if not fixedreps then
fam := NewFamily( "ResidueClassUnionsFamily( Integers )",
IsResidueClassUnionOfZ,
CanEasilySortElements, CanEasilySortElements );
SetUnderlyingRing( fam, Integers );
SetElementsFamily( fam, FamilyObj( 1 ) );
else
fam := NewFamily( "ResidueClassUnionsFamily( Integers, true )",
IsUnionOfResidueClassesWithFixedRepresentatives,
CanEasilySortElements, CanEasilySortElements );
SetUnderlyingRing( fam, Integers );
SetElementsFamily( fam, fam );
fi;
MakeReadWriteGlobal( "Z_RESIDUE_CLASS_UNIONS_FAMILIES" );
Z_RESIDUE_CLASS_UNIONS_FAMILIES[ pos ] := fam;
MakeReadOnlyGlobal( "Z_RESIDUE_CLASS_UNIONS_FAMILIES" );
return fam;
end );
#############################################################################
##
#V ZxZResidueClassUnionsFamily . . family of all residue class unions of Z^2
##
## GAP does not view Z^2 as a ring, but rather as a row module.
## Anyway it is viewed as the underlying ring of the family, since it
## mathematically is a ring and since this avoids a case distinction
## in many places in the code.
##
BindGlobal( "ZxZResidueClassUnionsFamily",
NewFamily( "ResidueClassUnionsFamily( Integers^2 )",
IsResidueClassUnionOfZxZ,
CanEasilySortElements, CanEasilySortElements ) );
SetUnderlyingRing( ZxZResidueClassUnionsFamily, Integers^2 );
SetElementsFamily( ZxZResidueClassUnionsFamily, FamilyObj( [ 0, 0 ] ) );
#############################################################################
##
#F Z_piResidueClassUnionsFamily( <R> , <fixedreps> )
##
InstallGlobalFunction( Z_piResidueClassUnionsFamily,
function ( R, fixedreps )
local fam, cat, name;
fam := First( Z_PI_RESIDUE_CLASS_UNIONS_FAMILIES,
fam -> UnderlyingRing( fam ) = R
and PositionSublist( fam!.NAME,
String(fixedreps) ) <> fail );
if fam <> fail then return fam; fi;
if not fixedreps
then cat := IsResidueClassUnionOfZ_pi;
else cat := IsUnionOfResidueClassesOfZ_piWithFixedRepresentatives; fi;
name := Concatenation( "ResidueClassUnionsFamily( ",
String( R ),", ",String(fixedreps)," )" );
fam := NewFamily( name, cat,
CanEasilySortElements, CanEasilySortElements );
SetUnderlyingRing( fam, R );
if not fixedreps then SetElementsFamily( fam, FamilyObj( 1 ) );
else SetElementsFamily( fam, fam ); fi;
MakeReadWriteGlobal( "Z_PI_RESIDUE_CLASS_UNIONS_FAMILIES" );
Add( Z_PI_RESIDUE_CLASS_UNIONS_FAMILIES, fam );
MakeReadOnlyGlobal( "Z_PI_RESIDUE_CLASS_UNIONS_FAMILIES" );
return fam;
end );
#############################################################################
##
#F GFqxResidueClassUnionsFamily( <R>, <fixedreps> )
##
InstallGlobalFunction( GFqxResidueClassUnionsFamily,
function ( R, fixedreps )
local fam, cat, name, x;
x := IndeterminatesOfPolynomialRing( R )[ 1 ];
fam := First( GF_Q_X_RESIDUE_CLASS_UNIONS_FAMILIES,
fam -> UnderlyingRing( fam ) = R
and PositionSublist( fam!.NAME,
String(fixedreps) ) <> fail );
if fam <> fail then return fam; fi;
if not fixedreps
then cat := IsResidueClassUnionOfGFqx;
else cat := IsUnionOfResidueClassesOfGFqxWithFixedRepresentatives; fi;
name := Concatenation( "ResidueClassUnionsFamily( ",
ViewString( R ),", ",String(fixedreps)," )" );
fam := NewFamily( name, cat,
CanEasilySortElements, CanEasilySortElements );
SetUnderlyingIndeterminate( fam, x );
SetUnderlyingRing( fam, R );
if not fixedreps then SetElementsFamily( fam, FamilyObj( x ) );
else SetElementsFamily( fam, fam ); fi;
MakeReadWriteGlobal( "GF_Q_X_RESIDUE_CLASS_UNIONS_FAMILIES" );
Add( GF_Q_X_RESIDUE_CLASS_UNIONS_FAMILIES, fam );
MakeReadOnlyGlobal( "GF_Q_X_RESIDUE_CLASS_UNIONS_FAMILIES" );
return fam;
end );
#############################################################################
##
#F ResidueClassUnionsFamily( <R> [ , <fixedreps> ] )
##
InstallGlobalFunction( ResidueClassUnionsFamily,
function ( arg )
local R, fixedreps;
if not Length(arg) in [1,2]
or Length(arg) = 2 and not arg[2] in [true,false]
then Error("Usage: ResidueClassUnionsFamily( <R> [ , <fixedreps> ] )\n");
fi;
R := arg[1];
if Length(arg) = 2 then fixedreps := arg[2]; else fixedreps := false; fi;
if IsIntegers( R )
then return ZResidueClassUnionsFamily( fixedreps );
elif IsZxZ( R ) then return ZxZResidueClassUnionsFamily;
elif IsZ_pi( R )
then return Z_piResidueClassUnionsFamily( R, fixedreps );
elif IsUnivariatePolynomialRing( R ) and IsFiniteFieldPolynomialRing( R )
then return GFqxResidueClassUnionsFamily( R, fixedreps );
else Error("Sorry, residue class unions of ",R,
" are not yet implemented.\n");
fi;
end );
#############################################################################
##
#M IsZxZ( <R> ) . . . . . . . . . . . . . . . . . . Z^2 = Z x Z = Integers^2
##
InstallMethod( IsZxZ, "general method (ResClasses)", true,
[ IsObject ], 0, R -> R = Integers^2 );
#############################################################################
##
#S Residues / residue classes (mod m). /////////////////////////////////////
##
#############################################################################
# Buffer for storing already computed polynomial residue systems.
BindGlobal( "POLYNOMIAL_RESIDUE_CACHE", [] );
BindGlobal( "AllGFqPolynomialsModDegree",
function ( q, d, x )
local erg, mon, gflist;
if d = 0
then return [ Zero( x ) ];
elif IsBound( POLYNOMIAL_RESIDUE_CACHE[ q ] )
and IsBound( POLYNOMIAL_RESIDUE_CACHE[ q ][ d ] )
then return ShallowCopy( POLYNOMIAL_RESIDUE_CACHE[ q ][ d ] );
else gflist := AsList( GF( q ) );
mon := List( gflist, el -> List( [ 0 .. d - 1 ], i -> el * x^i ) );
erg := List( Tuples( GF( q ), d ),
t -> Sum( List( [ 1 .. d ],
i -> mon[ Position( gflist, t[ i ] ) ]
[ d - i + 1 ] ) ) );
MakeReadWriteGlobal( "POLYNOMIAL_RESIDUE_CACHE" );
if not IsBound( POLYNOMIAL_RESIDUE_CACHE[ q ] )
then POLYNOMIAL_RESIDUE_CACHE[ q ] := [ ]; fi;
POLYNOMIAL_RESIDUE_CACHE[ q ][ d ] := Immutable( erg );
MakeReadOnlyGlobal( "POLYNOMIAL_RESIDUE_CACHE" );
return erg;
fi;
end );
# Difference r1(m1) \ r2(m2) of two residue classes;
# the residue classes r1(m1) and r2(m2) are to be given as pairs
# [r1,m1] and [r2,m2] of integers, and the output is a list of
# residue classes represented in the same way.
BindGlobal( "DIFFERENCE_OF_RESIDUE_CLASSES",
function ( cl1, cl2 )
local cls, r1, m1, r2, m2, r3, m3, divs, d, p, r, inc, i;
r1 := cl1[1]; m1 := cl1[2];
r2 := cl2[1]; m2 := cl2[2];
if (r1-r2) mod Gcd(m1,m2) <> 0 then return [cl1]; fi; # disjoint
m3 := Lcm(m1,m2);
if m3 = m1 then return []; fi; # second cl. is a superset of first cl.
r3 := ChineseRem([m1,m2],[r1,r2]);
divs := []; d := 1;
for p in Factors(m3/m1) do
d := d * p;
Add(divs,d);
od;
cls := [];
for i in [1..Length(divs)] do
d := divs[i];
if i > 1 then inc := divs[i-1]; else inc := 1; fi;
for r in [inc,2*inc..d-inc] do
Add(cls,[r,d]);
od;
od;
for i in [1..Length(cls)] do # get moduli and residues right
cls[i][2] := cls[i][2] * m1;
cls[i][1] := (cls[i][1] * m1 + r3) mod cls[i][2];
od;
SortParallel( List( cls, Reversed ), cls );
return cls;
end );
#############################################################################
##
#M AllResidues( <R>, <m> ) . . . . . . . . . . . . for Z, Z_pi and GF(q)[x]
##
InstallMethod( AllResidues,
"for Z, Z_pi and GF(q)[x] (ResClasses)", ReturnTrue,
[ IsRing, IsRingElement ], 0,
function ( R, m )
local q, d, x;
if IsIntegers(R) or IsZ_pi(R)
then return [0..StandardAssociate(R,m)-1]; fi;
if IsUnivariatePolynomialRing(R) and Characteristic(R) <> 0 then
q := Size(CoefficientsRing(R));
d := DegreeOfLaurentPolynomial(m);
x := IndeterminatesOfPolynomialRing(R)[1];
return AllGFqPolynomialsModDegree(q,d,x);
fi;
TryNextMethod();
end );
#############################################################################
##
#M AllResidues( Integers^2, <L> ) . . . . . . . . . . . . for lattice in Z^2
##
InstallOtherMethod( AllResidues,
"for lattice in Z^2 (ResClasses)", true,
[ IsRowModule, IsMatrix ], 0,
function ( ZxZ, L )
if not IsZxZ(ZxZ) or not IsSubset(ZxZ,L) then TryNextMethod(); fi;
L := HermiteNormalFormIntegerMat(L);
return Cartesian([0..L[1][1]-1],[0..L[2][2]-1]);
end );
#############################################################################
##
#M NumberOfResidues( <R>, <m> ) . . . . . . . . . . for Z, Z_pi and GF(q)[x]
##
InstallMethod( NumberOfResidues,
"for Z, Z_pi and GF(q)[x] (ResClasses)", ReturnTrue,
[ IsRing, IsRingElement ], 0,
function ( R, m )
local q, d, x;
if IsIntegers(R) or IsZ_pi(R) then return StandardAssociate(R,m); fi;
if IsUnivariatePolynomialRing(R) and Characteristic(R) <> 0 then
q := Size(CoefficientsRing(R));
d := DegreeOfLaurentPolynomial(m);
return q^d;
fi;
TryNextMethod();
end );
#############################################################################
##
#M NumberOfResidues( Integers^2, <L> ) . . . . . . . . . for lattice in Z^2
##
InstallOtherMethod( NumberOfResidues,
"for lattice in Z^2 (ResClasses)", ReturnTrue,
[ IsRowModule, IsMatrix ], 0,
function ( ZxZ, L )
if not IsZxZ(ZxZ) or not IsSubset(ZxZ,L) then TryNextMethod(); fi;
return AbsInt(DeterminantMat(L));
end );
#############################################################################
##
#F AllResidueClassesModulo( [ <R>, ] <m> ) . . the residue classes (mod <m>)
##
InstallGlobalFunction( AllResidueClassesModulo,
function ( arg )
local R, m;
if Length(arg) = 2
then R := arg[1]; m := arg[2];
else m := arg[1]; R := DefaultRing(m); fi;
if IsRing(R) and (IsZero(m) or not m in R) then return fail; fi;
return List(AllResidues(R,m),r->ResidueClass(R,m,r));
end );
#############################################################################
##
#F All2x2IntegerMatricesInHNFWithDeterminantUpTo( <maxdet> )
##
InstallGlobalFunction( All2x2IntegerMatricesInHNFWithDeterminantUpTo,
function ( maxdet )
local mods, det, diags, diag;
mods := [];
for det in [1..maxdet] do
diags := List(DivisorsInt(det),d->[d,det/d]);
for diag in diags do
Append(mods,List([0..diag[2]-1],k->[[diag[1],k],[0,diag[2]]]));
od;
od;
return mods;
end );
#############################################################################
##
#M SizeOfSmallestResidueClassRing( <R> ) . . . . . for Z, Z_pi and GF(q)[x]
##
InstallMethod( SizeOfSmallestResidueClassRing,
"for Z, Z_pi and GF(q)[x] (ResClasses)", true, [ IsRing ], 0,
function ( R )
if IsIntegers(R) then return 2;
elif IsZ_pi(R) then return Minimum(NoninvertiblePrimes(R));
elif IsFiniteFieldPolynomialRing(R) then return Characteristic(R);
else TryNextMethod(); fi;
end );
#############################################################################
##
#M SizeOfSmallestResidueClassRing( Integers^2 ) . . . . . . . . . . for Z^2
##
InstallOtherMethod( SizeOfSmallestResidueClassRing,
"for Z^2 (ResClasses)", true, [ IsRowModule ], 0,
function ( ZxZ )
if IsZxZ(ZxZ) then return 2; else TryNextMethod(); fi;
end );
#############################################################################
##
#S Basic functionality for lattices in Z^n. ////////////////////////////////
##
#############################################################################
#############################################################################
##
#M StandardAssociate( <R>, <mat> ) . . . . . . . HNF of n x n integer matrix
##
InstallOtherMethod( StandardAssociate,
"HNF of n x n integer matrix (ResClasses)", IsCollsElms,
[ IsRing and IsFullMatrixModule, IsMatrix ], 0,
function ( R, mat )
if not IsIntegers(LeftActingDomain(R))
or Length(Set(DimensionOfVectors(R))) <> 1 or not mat in R
then TryNextMethod(); fi;
return HermiteNormalFormIntegerMat(mat);
end );
#############################################################################
##
#M \mod . . . . . . . . . . . . . . . . . . . . . for a vector and a lattice
##
if not IsReadOnlyGlobal( "VectorModLattice" ) # not protected in polycyclic
then MakeReadOnlyGlobal( "VectorModLattice" ); fi;
InstallMethod( \mod, "for a vector and a lattice (ResClasses)", IsElmsColls,
[ IsRowVector, IsMatrix ], 0,
function ( v, L ) return VectorModLattice( v, L ); end );
#############################################################################
##
#M LcmOp( <R>, <mat1>, <mat2> ) . . . . . . . . lattice intersection in Z^n
##
InstallOtherMethod( LcmOp, "lattice intersection in Z^n (ResClasses)",
IsCollsElmsElms,
[ IsRing and IsFullMatrixModule, IsMatrix, IsMatrix ], 0,
function ( R, mat1, mat2 )
local n;
if not IsIntegers(LeftActingDomain(R))
or Length(Set(DimensionOfVectors(R))) <> 1
or not mat1 in R or not mat2 in R
then TryNextMethod(); fi;
n := DimensionOfVectors(R)[1];
if n = 2 then # Check whether matrices are already in HNF.
if mat1[2][1] <> 0 or ForAny(Flat(mat1),n->n<0)
or mat1[1][2] >= mat1[2][2]
then mat1 := HermiteNormalFormIntegerMat(mat1); fi;
if mat2[2][1] <> 0 or ForAny(Flat(mat2),n->n<0)
or mat2[1][2] >= mat2[2][2]
then mat2 := HermiteNormalFormIntegerMat(mat2); fi;
else
mat1 := HermiteNormalFormIntegerMat(mat1);
mat2 := HermiteNormalFormIntegerMat(mat2);
fi;
return LatticeIntersection( mat1, mat2 );
end );
#############################################################################
##
#M IsSublattice( <L1>, <L2> ) . . . . . . . . . . . . . for lattices in Z^n
##
InstallMethod( IsSublattice,
"for lattices in Z^n (ResClasses)", IsIdenticalObj,
[ IsMatrix, IsMatrix ], 0,
function ( L1, L2 )
return ForAll( Flat( L2 / L1 ), IsInt );
end );
#############################################################################
##
#M Superlattices( <L> ) . . . . . . . . . . . . . . . . for a lattice in Z^2
##
SetupCache( "RESCLASSES_SUPERLATTICES_CACHE", 100 );
InstallMethod( Superlattices,
"for a lattice in Z^2 (ResClasses)", true, [ IsMatrix ], 0,
function ( L )
local lattices, sup, divx, divy, x, y, dx;
if Set(DimensionsMat(L)) <> [2] or not ForAll(Flat(L),IsInt)
or DeterminantMat(L) = 0
then TryNextMethod(); fi;
if IsOne(L) then return [[[1,0],[0,1]]]; fi;
lattices := FetchFromCache( "RESCLASSES_SUPERLATTICES_CACHE", L );
if lattices <> fail then return lattices; fi;
divx := DivisorsInt(L[2][2]); divy := DivisorsInt(L[1][1]);
lattices := [];
for x in divx do for y in divy do for dx in [0..x-1] do
sup := [[y,dx],[0,x]];
if ForAll(Flat(L/sup),IsInt) then Add(lattices,sup); fi;
od; od; od;
lattices := Set(lattices,HermiteNormalFormIntegerMat);
SortParallel(List(lattices,Li->[DeterminantMat(Li),Li]),lattices);
PutIntoCache( "RESCLASSES_SUPERLATTICES_CACHE", L, lattices );
return lattices;
end );
#############################################################################
##
#F ModulusAsFormattedString( <m> ) . format lattice etc. for output purposes
##
BindGlobal( "ModulusAsFormattedString",
function ( m )
if not IsMatrix(m) then return ViewString(m); fi;
return Filtered(Concatenation(List(["(",m[1][1],",",m[1][2],")Z+(",
m[2][1],",",m[2][2],")Z"],
String)),ch->ch<>' ');
end );
#############################################################################
##
#S Construction of residue class unions. ///////////////////////////////////
##
#############################################################################
#############################################################################
##
#M ResidueClassUnionCons( <filter>, <R>, <m>, <r>, <included>, <excluded> )
##
InstallMethod( ResidueClassUnionCons,
"residue list rep., for Z, Z_pi and GF(q)[x] (ResClasses)",
ReturnTrue, [ IsResidueClassUnion, IsRing, IsRingElement,
IsList, IsList, IsList ], 0,
function ( filter, R, m, r, included, excluded )
local ReduceResidueClassUnion, result, both, fam, type, rep, pos;
ReduceResidueClassUnion := function ( U )
local R, m, r, mRed, mRedBuf, rRed, rRedBuf, valid, fact, p;
R := UnderlyingRing(FamilyObj(U));
m := StandardAssociate(R,U!.m); mRed := m;
r := Set( U!.r, n -> n mod m ); rRed := r;
fact := Set(Factors(R,m));
for p in fact do
repeat
mRedBuf := mRed; rRedBuf := ShallowCopy(rRed);
mRed := mRed/p;
rRed := Set(rRedBuf,n->n mod mRed);
if IsIntegers(R) or IsZ_pi(R)
then valid := Length(rRed) = Length(rRedBuf)/p;
else valid := Length(rRed) = Length(rRedBuf)/
Size(CoefficientsRing(R))^DegreeOfLaurentPolynomial(p);
fi;
until not valid or not IsZero(mRed mod p) or IsOne(mRed);
if not valid then mRed := mRedBuf; rRed := rRedBuf; fi;
od;
U!.m := mRed; U!.r := Immutable(rRed);
U!.included := Immutable(Set(Filtered(U!.included,
n -> not (n mod mRed in rRed))));
U!.excluded := Immutable(Set(Filtered(U!.excluded,
n -> n mod mRed in rRed)));
if rRed = [] then U := Difference(U!.included,U!.excluded); fi;
end;
if not ( IsIntegers( R ) or IsZ_pi( R )
or ( IsFiniteFieldPolynomialRing( R )
and IsUnivariatePolynomialRing( R ) ) )
then TryNextMethod( ); fi;
m := StandardAssociate( R, m );
r := Set( r, n -> n mod m );
both := Intersection( included, excluded );
included := Difference( included, both );
excluded := Difference( excluded, both );
if r = [] then return Difference(included,excluded); fi;
fam := ResidueClassUnionsFamily( R );
if IsIntegers( R ) then type := IsResidueClassUnionOfZ;
elif IsZ_pi( R ) then type := IsResidueClassUnionOfZ_pi;
elif IsPolynomialRing( R ) then type := IsResidueClassUnionOfGFqx;
fi;
result := Objectify( NewType( fam, type and
IsResidueClassUnionResidueListRep ),
rec( m := m, r := r,
included := included, excluded := excluded ) );
SetSize( result, infinity ); SetIsFinite( result, false );
SetIsEmpty( result, false );
rep := r[1]; pos := 1;
while rep in excluded do
pos := pos + 1;
rep := r[pos mod Length(r) + 1] + Int(pos/Length(r)) * m;
od;
if included <> [ ] and rep > Minimum( included )
then rep := Minimum( included ); fi;
SetRepresentative( result, rep );
ReduceResidueClassUnion( result );
if Length( result!.r ) = 1 then SetIsResidueClass( result, true ); fi;
if IsOne( result!.m ) and result!.r = [ Zero( R ) ]
and [ result!.included, result!.excluded ] = [ [ ], [ ] ]
then return R; else return result; fi;
end );
#############################################################################
##
#M ResidueClassUnionCons( <filter>, <R>, <cls>, <included>, <excluded> )
##
InstallMethod( ResidueClassUnionCons,
"class list rep., for Z (ResClasses)",
ReturnTrue, [ IsResidueClassUnionOfZInClassListRep,
IsIntegers, IsList, IsList, IsList ], 0,
function ( filter, R, cls, included, excluded )
local ReduceResidueClassUnion, result, m, both, rep, pos;
ReduceResidueClassUnion := function ( U )
local R, cls, clsRed, m, ndpair, d1, d2, density, divs, d, i,
partdens, cl, int, res, r, both;
cls := U!.cls;
cls := Set( cls, c -> [ c[1] mod c[2], AbsInt( c[2] ) ] );
SortParallel( List( cls, Reversed ), cls );
repeat
ndpair := First(Combinations(cls,2),
c->(c[1][1]-c[2][1]) mod Gcd(c[1][2],c[2][2]) = 0);
if ndpair <> fail then
cls := Difference(cls,ndpair);
d1 := DIFFERENCE_OF_RESIDUE_CLASSES(ndpair[1],ndpair[2]);
d2 := DIFFERENCE_OF_RESIDUE_CLASSES(ndpair[2],ndpair[1]);
if Length(d1) <= Length(d2) then
Append(cls,d1); Add(cls,ndpair[2]);
else
Append(cls,d2); Add(cls,ndpair[1]);
fi;
cls := Filtered(cls,cl->cl<>[]);
fi;
until ndpair = fail;
SortParallel( List( cls, Reversed ), cls );
clsRed := [];
m := U!.m;
divs := DivisorsInt(m);
density := Sum(List(cls,cl->1/cl[2]));
for d in divs do
if 1/d > density then continue; fi;
res := Set(cls,cl->cl[1] mod d);
for r in res do
partdens := 0;
for cl in cls do
if (r - cl[1]) mod Gcd(d,cl[2]) = 0
then partdens := partdens + 1/Lcm(d,cl[2]); fi;
od;
if partdens = 1/d then
Add(clsRed,[r,d]);
cls := List(cls,cl->DIFFERENCE_OF_RESIDUE_CLASSES(cl,[r,d]));
cls := Filtered(Concatenation(cls),cl->cl<>[]);
if cls = [] then break; fi;
SortParallel( List( cls, Reversed ), cls );
density := Sum(List(cls,cl->1/cl[2]));
elif partdens > 1/d then Error("internal error"); fi;
od;
if cls = [] then break; fi;
od;
m := Lcm(List(clsRed,c->c[2]));
SortParallel( List( clsRed, Reversed ), clsRed );
U!.cls := Immutable(clsRed); U!.m := m;
both := Intersection( U!.included, U!.excluded );
U!.included := Difference( U!.included, both );
U!.excluded := Difference( U!.excluded, both );
U!.included := Immutable(Set(Filtered(U!.included,
n -> not ForAny(clsRed,c -> n mod c[2] = c[1]))));
U!.excluded := Immutable(Set(Filtered(U!.excluded,
n -> ForAny(clsRed,c -> n mod c[2] = c[1]))));
if clsRed = [] then U := U!.included; fi;
end;
if not IsIntegers(R) then TryNextMethod(); fi;
if cls = [] then return Difference(included,excluded); fi;
result := Objectify( NewType( ResidueClassUnionsFamily( Integers ),
IsResidueClassUnionOfZ and
IsResidueClassUnionClassListRep ),
rec( cls := cls, m := Lcm(List(cls,c->c[2])),
included := included, excluded := excluded ) );
SetSize( result, infinity ); SetIsFinite( result, false );
SetIsEmpty( result, false );
if ValueOption("RCU_AlreadyReduced") <> true then
ReduceResidueClassUnion( result );
cls := result!.cls; m := result!.m;
included := result!.included; excluded := result!.excluded;
fi;
rep := cls[1][1]; pos := 1;
while rep in excluded do
pos := pos + 1;
rep := cls[pos mod Length(cls) + 1][1]
+ Int(pos/Length(cls)) * cls[pos mod Length(cls) + 1][2];
od;
if included <> [ ] and rep > Minimum( included )
then rep := Minimum( included ); fi;
SetRepresentative( result, rep );
if Length(result!.cls) = 1 then SetIsResidueClass(result,true); fi;
if result!.m = 1 and result!.cls = [[0,1]]
and [result!.included,result!.excluded] = [[],[]]
then return Integers; else return result; fi;
end );
#############################################################################
##
#M ResidueClassUnionCons( <filter>, Integers^2,
## <L>, <r>, <included>, <excluded> )
##
InstallMethod( ResidueClassUnionCons,
"residue list representation, for Z^2 (ResClasses)",
ReturnTrue, [ IsResidueClassUnion, IsRowModule,
IsMatrix, IsList, IsList, IsList ], 0,
function ( filter, ZxZ, L, r, included, excluded )
local ReduceResidueClassUnion, result, both, rep, pos;
ReduceResidueClassUnion := function ( U )
local L, r, LRed, rRed, divs, d;
L := HermiteNormalFormIntegerMat(U!.m); LRed := L;
r := List(U!.r,v->v mod L); rRed := r;
divs := Superlattices(L);
for d in divs do
if DeterminantMat(L)/DeterminantMat(d) > Length(r) then continue; fi;
rRed := Set(r,v->v mod d);
if Length(rRed) = Length(r)*DeterminantMat(d)/DeterminantMat(L)
then LRed := d; break; fi;
od;
U!.m := LRed; U!.r := Immutable(rRed);
U!.included := Immutable(Set(Filtered(U!.included,
v->not v mod LRed in rRed)));
U!.excluded := Immutable(Set(Filtered(U!.excluded,
v->v mod LRed in rRed)));
end;
if not IsZxZ( ZxZ ) then TryNextMethod( ); fi;
L := HermiteNormalFormIntegerMat( L );
r := Set( r, v -> v mod L );
both := Intersection( included, excluded );
included := Difference( included, both );
excluded := Difference( excluded, both );
if r = [] then L := [[1,0],[0,1]]; excluded := []; fi;
result := Objectify( NewType( ResidueClassUnionsFamily( ZxZ ),
IsResidueClassUnionOfZxZ and
IsResidueClassUnionResidueListRep ),
rec( m := L, r := r,
included := included, excluded := excluded ) );
if r <> [] then
SetSize( result, infinity ); SetIsFinite( result, false );
SetIsEmpty( result, false );
else
SetSize( result, Length( included ) );
SetIsEmpty( result, IsEmpty( included ) );
fi;
if not IsEmpty( result ) then
if included <> [ ] then rep := included[ 1 ]; else
rep := r[1]; pos := 1;
while rep in excluded do
pos := pos + 1;
rep := r[pos mod Length(r) + 1] + Int(pos/Length(r)) * L[1];
od;
fi;
SetRepresentative( result, rep );
fi;
if r <> [] then ReduceResidueClassUnion( result ); else
MakeImmutable( result!.included ); MakeImmutable( result!.excluded );
fi;
if Length( result!.r ) = 1 then SetIsResidueClass( result, true ); fi;
if AbsInt( DeterminantMat( result!.m ) ) = 1
and result!.r = [ [ 0, 0 ] ]
and [ result!.included, result!.excluded ] = [ [ ], [ ] ]
then return ZxZ; else return result; fi;
end );
#############################################################################
##
#M ResidueClassUnionCons( <filter>, Integers^2, ("modulus L as vector")
## <L>, <r>, <included>, <excluded> )
##
InstallOtherMethod( ResidueClassUnionCons,
"residue list rep, mod. as vector, for Z^2 (ResClasses)",
ReturnTrue, [ IsResidueClassUnion, IsRowModule,
IsRowVector, IsList, IsList, IsList ], 0,
function ( filter, ZxZ, L, r, included, excluded )
return ResidueClassUnionCons( filter, ZxZ,
DiagonalMat(L), r, included, excluded );
end );
#############################################################################
##
#F ResidueClassUnion( <R>, <m>, <r> ) . . . . . . . union of residue classes
#F ResidueClassUnion( <R>, <m>, <r>, <included>, <excluded> )
#F ResidueClassUnion( <R>, <cls> )
#F ResidueClassUnion( <R>, <cls>, <included>, <excluded> )
##
InstallGlobalFunction( ResidueClassUnion,
function ( arg )
if not ( Length(arg) in [3,5]
and ( IsRing(arg[1]) and arg[2] in arg[1]
or IsRowModule(arg[1]) and IsMatrix(arg[2])
and IsSubset(arg[1],arg[2])
and not IsZero(DeterminantMat(arg[2])) )
and IsList(arg[3]) and IsSubset(arg[1],arg[3])
and ( Length(arg) = 3 or IsList(arg[4]) and IsList(arg[5])
and IsSubset(arg[1],arg[4])
and IsSubset(arg[1],arg[5])) )
and not ( Length(arg) in [2,4]
and (IsRing(arg[1]) and IsList(arg[2])
and ForAll(arg[2],l->IsList(l) and Length(l) = 2
and IsSubset(arg[1],l) and not IsZero(l[2])))
and ( Length(arg) = 2 or IsList(arg[3]) and IsList(arg[4])
and IsSubset(arg[1],arg[3])
and IsSubset(arg[1],arg[4])) )
then Error("usage: ResidueClassUnion( <R>, <m>, <r> [, <included>",
", <excluded> ] )\nor ResidueClassUnion( <R>, <cls> ",
"[, <included>, <excluded> ] ), for details see manual.\n");
return fail;
fi;
return CallFuncList( ResidueClassUnionNC, arg );
end );
#############################################################################
##
#F ResidueClassUnionNC( <R>, <m>, <r> ) . . . . . . union of residue classes
#F ResidueClassUnionNC( <R>, <m>, <r>, <included>, <excluded> )
#F ResidueClassUnionNC( <R>, <cls> )
#F ResidueClassUnionNC( <R>, <cls>, <included>, <excluded> )
##
InstallGlobalFunction( ResidueClassUnionNC,
function ( arg )
local R, m, r, cls, included, excluded;
if Length(arg) in [2,4] then
R := arg[1]; cls := arg[2];
if Length(arg) = 4
then included := Set(arg[3]); excluded := Set(arg[4]);
else included := []; excluded := []; fi;
return ResidueClassUnionCons( IsResidueClassUnionOfZInClassListRep,
R, cls, included, excluded );
elif Length(arg) in [3,5] then
R := arg[1]; m := arg[2]; r := Set(arg[3]);
if Length(arg) = 5
then included := Set(arg[4]); excluded := Set(arg[5]);
else included := []; excluded := []; fi;
return ResidueClassUnionCons( IsResidueClassUnion, R, m, r,
included, excluded );
fi;
end );
#############################################################################
##
#F ResidueClass( <R>, <m>, <r> ) . . . . . . . . . . . residue class of <R>
#F ResidueClass( <m>, <r> ) . residue class of the default ring of <m>, <r>
#F ResidueClass( <r>, <m> ) . . . . . . . . . . . . . . . . . . . ( dito )
##
InstallGlobalFunction( ResidueClass,
function ( arg )
local R, m, r, d, cl, usage;
usage := "usage: see ?ResidueClass\n";
if Length( arg ) = 3 then
R := arg[1]; m := arg[2]; r := arg[3];
if not ( IsRing(R) and m in R and r in R and not IsZero(m)
or IsRowModule(R) and IsMatrix(m) and IsSubset(R,m)
and not IsZero(DeterminantMat(m)) )
then Error( usage ); return fail; fi;
elif Length( arg ) = 2 then
if ForAll( arg, IsRingElement ) then
if IsPolynomial(arg[1])
then R := DefaultRing(arg[1]); arg[2] := arg[2] * One(R);
elif IsPolynomial(arg[2])
then R := DefaultRing(arg[2]); arg[1] := arg[1] * One(R);
else R := DefaultRing(arg); fi;
m := Maximum( arg ); r := Minimum( arg );
if IsZero( m ) then Error( usage ); return fail; fi;
else
if IsMatrix( arg[1] ) then m := arg[1]; r := arg[2];
else m := arg[2]; r := arg[1]; fi;
if not ( IsMatrix(m) and IsVector(r) )
then Error( usage ); return fail; fi;
d := Length(r);
R := DefaultRing(r)^d;
if not ( DimensionsMat(m) = [d,d] and IsSubset(R,m)
and RankMat(m) = d and r in R )
then Error( usage ); return fail; fi;
fi;
elif Length( arg ) = 1 then
if IsList( arg[1] )
then return CallFuncList( ResidueClass, arg[1] );
elif IsResidueClass( arg[1] )
then return arg[1];
else Error( usage ); return fail; fi;
else
Error( usage ); return fail;
fi;
cl := ResidueClassUnionNC( R, m, [ r ] );
SetIsResidueClass( cl, true );
return cl;
end );
#############################################################################
##
#F ResidueClassNC( <R>, <m>, <r> ) . . . . . . . . . . residue class of <R>
#F ResidueClassNC( <m>, <r> ) residue class of the default ring of <m>, <r>
#F ResidueClassNC( <r>, <m> ) . . . . . . . . . . . . . . . . . . ( dito )
##
InstallGlobalFunction( ResidueClassNC,
function ( arg )
local R, m, r, d, cl;
if Length( arg ) = 3 then
R := arg[1]; m := arg[2]; r := arg[3];
elif Length( arg ) = 2 then
if ForAll(arg,IsRingElement) then
R := DefaultRing( arg );
m := Maximum( arg ); r := Minimum( arg );
else
if IsMatrix(arg[1]) then m := arg[1]; r := arg[2];
else m := arg[2]; r := arg[1]; fi;
d := Length(r);
R := DefaultRing(r)^d;
fi;
elif Length( arg ) = 1 then return CallFuncList(ResidueClassNC,arg[1]);
else return fail; fi;
cl := ResidueClassUnionNC( R, m, [ r ] );
SetIsResidueClass( cl, true );
return cl;
end );
#############################################################################
##
#M IsResidueClass( <obj> ) . . . . . . . . . . . . . . . . . general method
##
InstallMethod( IsResidueClass,
"general method (ResClasses)", true, [ IsObject ], 0,
function ( obj )
if IsRing(obj) then return true; fi;
if IsResidueClassUnionInResidueListRep(obj)
and Length(obj!.r) = 1 and obj!.included = [] and obj!.excluded = []
then return true; fi;
if IsResidueClassUnionInClassListRep(obj)
and Length(obj!.cls) = 1 and obj!.included = [] and obj!.excluded = []
then return true; fi;
return false;
end );
#############################################################################
##
#S ExtRepOfObj / ObjByExtRep for residue class unions. /////////////////////
##
#############################################################################
#############################################################################
##
#M ExtRepOfObj( <U> ) . . . . . . . . . . . . . . . for residue class unions
##
InstallMethod( ExtRepOfObj,
"for residue class unions (ResClasses)",
true, [ IsResidueClassUnion ], 0,
U -> [ Modulus( U ), ShallowCopy( Residues( U ) ),
ShallowCopy( IncludedElements( U ) ),
ShallowCopy( ExcludedElements( U ) ) ] );
#############################################################################
##
#M ExtRepOfObj( <U> ) . . . . . . . . . . . . . . . for residue class unions
##
InstallMethod( ExtRepOfObj,
"for residue class unions in standard rep. (ResClasses)",
true, [ IsResidueClassUnionInResidueListRep ], 0,
U -> [U!.m, ShallowCopy( U!.r ),
ShallowCopy(U!.included), ShallowCopy(U!.excluded)] );
#############################################################################
##
#M ObjByExtRep( <fam>, <l> ) . . . . . . . reconstruct a residue class union
##
InstallMethod( ObjByExtRep,
"reconstruct a residue class union (ResClasses)",
ReturnTrue, [ IsFamily, IsList ], 0,
function ( fam, l )
local R;
if not HasUnderlyingRing(fam) or Length(l) <> 4 then TryNextMethod(); fi;
R := UnderlyingRing(fam);
if fam <> ResidueClassUnionsFamily(R) then TryNextMethod(); fi;
return ResidueClassUnion(R,l[1],l[2],l[3],l[4]);
end );
#############################################################################
##
#S Accessing the components of a residue class union object. ///////////////
##
#############################################################################
#############################################################################
##
#M Modulus( <U> ) . . . . . . . . . . . . . . . . . for residue class unions
#M Modulus( <R> ) . . . . . . . . . . . . . . . for the base ring / -module
#M Modulus( <l> ) . . . . . . . . . . . . . . . . . . . . . for finite sets
##
## Since the empty list carries no information about the objects it does
## not contain, the method for that case silently assumes that these are
## supposed to be integers, and returns 0.
##
InstallMethod( Modulus,
"for residue class unions, standard rep. (ResClasses)", true,
[ IsResidueClassUnionInResidueListRep ], 0, U -> U!.m );
InstallMethod( Modulus,
"for residue class unions, sparse rep. (ResClasses)", true,
[ IsResidueClassUnionInClassListRep ], 0, U -> U!.m );
InstallOtherMethod( Modulus, "for the base ring (ResClasses)", true,
[ IsRing ], 0, One );
InstallOtherMethod( Modulus, "for the base module (ResClasses)", true,
[ IsRowModule ], 0, R -> AsList( Basis( R ) ) );
InstallOtherMethod( Modulus, "for finite sets (ResClasses)", true,
[ IsList ], 0, l -> Zero( l[ 1 ] ) );
InstallOtherMethod( Modulus, "for the empty set (ResClasses)", true,
[ IsList and IsEmpty ], 0, empty -> 0 );
#############################################################################
##
#M Residue( <cl> ) . . . . . . . . . . . . . . . . . . . for residue classes
#M Residue( <R> ) . . . . . . . . . . . . . . . for the base ring / -module
##
InstallMethod( Residue, "for residue classes (ResClasses)", true,
[ IsResidueClass ], 0, cl -> Residues(cl)[1] );
InstallOtherMethod( Residue, "for the base ring (ResClasses)", true,
[ IsRing ], 0, Zero );
InstallOtherMethod( Residue, "for the base module (ResClasses)", true,
[ IsRowModule ], 0, Zero );
#############################################################################
##
#M Residues( <U> ) . . . . . . . . . . . . . . . . for residue class unions
#M Residues( <R> ) . . . . . . . . . . . . . . . for the base ring / -module
#M Residues( <l> ) . . . . . . . . . . . . . . . . . . . . . for finite sets
##
InstallMethod( Residues,
"for residue class unions of Z in sparse rep (ResClasses)",
true, [ IsResidueClassUnionOfZInClassListRep ], 0,
function ( U )
local res, cls, m, cl, i;
cls := U!.cls; m := U!.m; res := [];
for cl in cls do
for i in [0..m/cl[2]-1] do
Add(res,i*cl[2]+cl[1]);
od;
od;
res := Set(res);
return res;
end );
InstallMethod( Residues, "for residue class unions (ResClasses)", true,
[ IsResidueClassUnionInResidueListRep ], 0, U -> U!.r );
InstallOtherMethod( Residues, "for the base ring (ResClasses)", true,
[ IsRing ], 0, R -> [ Zero( R ) ] );
InstallOtherMethod( Residues, "for the base module (ResClasses)", true,
[ IsRowModule ], 0, R -> [ Zero( R ) ] );
InstallOtherMethod( Residues, "for finite sets (ResClasses)", true,
[ IsList ], 0, l -> [ ] );
#############################################################################
##
#M Classes( <U> ) . . . . . . . . . . . . . . . . . for residue class unions
##
InstallMethod( Classes, "for residue class unions, sparse rep. (ResClasses)",
true, [ IsResidueClassUnionInClassListRep ], 0, U -> U!.cls );
InstallMethod( Classes, "for residue class unions, std. rep. (ResClasses)",
true, [ IsResidueClassUnionInResidueListRep ], 0,
U -> List(AsUnionOfFewClasses(U),
cl->[Residue(cl),Modulus(cl)]) );
InstallOtherMethod( Classes, "for the base ring (ResClasses)",
true, [ IsRing ], 0, R -> [ [ Zero(R), One(R) ] ] );
InstallOtherMethod( Classes, "for finite sets (ResClasses)",
true, [ IsList ], 0, R -> [ ] );
#############################################################################
##
#M IncludedElements( <U> ) . . . . . . . . . . . . for residue class unions
#M IncludedElements( <R> ) . . . . . . . . . . . for the base ring / -module
#M IncludedElements( <l> ) . . . . . . . . . . . . . . . . . for finite sets
##
InstallMethod( IncludedElements, "for residue class unions (ResClasses)",
true, [ IsResidueClassUnionInResidueListRep ], 0,
U -> U!.included );
InstallMethod( IncludedElements, "for residue class unions (ResClasses)",
true, [ IsResidueClassUnionInClassListRep ], 0,
U -> U!.included );
InstallOtherMethod( IncludedElements, "for the base ring (ResClasses)",
true, [ IsRing ], 0, R -> [ ] );
InstallOtherMethod( IncludedElements, "for the base module (ResClasses)",
true, [ IsRowModule ], 0, R -> [ ] );
InstallOtherMethod( IncludedElements, "for finite sets (ResClasses)",
true, [ IsList ], 0, l -> l );
#############################################################################
##
#M ExcludedElements( <U> ) . . . . . . . . . . . . for residue class unions
#M ExcludedElements( <R> ) . . . . . . . . . . . for the base ring / -module
#M ExcludedElements( <l> ) . . . . . . . . . . . . . . . . . for finite sets
##
InstallMethod( ExcludedElements, "for residue class unions (ResClasses)",
true, [ IsResidueClassUnionInResidueListRep ], 0,
U -> U!.excluded );
InstallMethod( ExcludedElements, "for residue class unions (ResClasses)",
true, [ IsResidueClassUnionInClassListRep ], 0,
U -> U!.excluded );
InstallOtherMethod( ExcludedElements, "for the base ring (ResClasses)",
true, [ IsRing ], 0, R -> [ ] );
InstallOtherMethod( ExcludedElements, "for the base module (ResClasses)",
true, [ IsRowModule ], 0, R -> [ ] );
InstallOtherMethod( ExcludedElements, "for finite sets (ResClasses)",
true, [ IsList ], 0, l -> [ ] );
#############################################################################
##
#M SparseRep( <U> ) . . . conversion to class list ("sparse") representation
##
InstallMethod( SparseRep,
"for residue class unions in standard rep. (ResClasses)",
true, [ IsResidueClassUnionInResidueListRep ], 0,
U -> ResidueClassUnionNC(UnderlyingRing(FamilyObj(U)),
List(AsUnionOfFewClasses(U),
cl->[Residue(cl),Modulus(cl)]),
U!.included,U!.excluded) );
InstallMethod( SparseRep,
"for residue class unions in sparse rep (ResClasses)",
true, [ IsResidueClassUnionInClassListRep ], 0, U -> U );
InstallMethod( SparseRep,
"for finite sets (ResClasses)",
true, [ IsList ], 0, l -> l );
InstallMethod( SparseRep,
"for the base ring (ResClasses)",
true, [ IsRing ], 0, R -> R );
InstallMethod( SparseRep,
"for the base module (ResClasses)",
true, [ IsRowModule ], 0, R -> R );
#############################################################################
##
#M StandardRep( <U> ) . . . . . conversion to residue list ("standard") rep.
##
InstallMethod( StandardRep,
"for residue class unions in sparse rep. (ResClasses)",
true, [ IsResidueClassUnionInClassListRep ], 0,
U -> ResidueClassUnionNC(UnderlyingRing(FamilyObj(U)),
Modulus(U),Residues(U),
U!.included,U!.excluded) );
InstallMethod( StandardRep,
"for residue class unions in standard rep. (ResClasses)",
true, [ IsResidueClassUnionInResidueListRep ], 0, U -> U );
InstallMethod( StandardRep,
"for finite sets (ResClasses)",
true, [ IsList ], 0, l -> l );
InstallMethod( StandardRep,
"for the base ring (ResClasses)",
true, [ IsRing ], 0, R -> R );
InstallMethod( StandardRep,
"for the base module (ResClasses)",
true, [ IsRowModule ], 0, R -> R );
#############################################################################
##
#S Testing residue class unions for equality. //////////////////////////////
##
#############################################################################
#############################################################################
##
#M \=( <U1>, <U2> ) . . . . . . . . . . . . . . . . for residue class unions
##
InstallMethod( \=,
"for two residue class unions in standard rep. (ResClasses)",
IsIdenticalObj,
[ IsResidueClassUnionInResidueListRep,
IsResidueClassUnionInResidueListRep ], 0,
function ( U1, U2 )
return U1!.m = U2!.m and U1!.r = U2!.r
and U1!.included = U2!.included and U1!.excluded = U2!.excluded;
end );
InstallMethod( \=,
"for two residue class unions in sparse rep. (ResClasses)",
IsIdenticalObj,
[ IsResidueClassUnionInClassListRep,
IsResidueClassUnionInClassListRep ], 0,
function ( U1, U2 )
return U1!.m = U2!.m and U1!.cls = U2!.cls
and U1!.included = U2!.included and U1!.excluded = U2!.excluded;
end );
InstallMethod( \=,
"for two residue class unions in different rep. (ResClasses)",
IsIdenticalObj,
[ IsResidueClassUnionInResidueListRep,
IsResidueClassUnionInClassListRep ], 0,
function ( U1, U2 ) return SparseRep(U1) = U2; end );
InstallMethod( \=,
"for two residue class unions in different rep. (ResClasses)",
IsIdenticalObj,
[ IsResidueClassUnionInClassListRep,
IsResidueClassUnionInResidueListRep ], 0,
function ( U1, U2 ) return U1 = SparseRep(U2); end );
#############################################################################
##
#M \=( <U>, <l> ) . . . . . . . . . . . for a residue class union and a list
#M \=( <l>, <U> ) . . . . . . . . . . . for a list and a residue class union
##
InstallMethod( \=, "for a residue class union and a list (ResClasses)",
ReturnTrue, [ IsResidueClassUnionInResidueListRep, IsList ],
SUM_FLAGS,
function ( U, l )
return IsOne(U!.m) and U!.r = [] and U!.included = l;
end );
InstallMethod( \=, "for a list and a residue class union (ResClasses)",
ReturnTrue, [ IsList, IsResidueClassUnionInResidueListRep ],
SUM_FLAGS, function ( l, U ) return U = l; end );
#############################################################################
##
#M \=( <D>, <l> ) . . . . . . for an infinite domain and a list of elements
#M \=( <l>, <D> ) . . . . . . for a list of elements and an infinite domain
##
InstallMethod( \=,
"for an infinite domain and a list of elements (ResClasses)",
IsIdenticalObj, [ IsDomain, IsList and IsFinite ], 0,
function ( D, l )
if not IsFinite( D ) then return false;
else TryNextMethod( ); fi;
end );
InstallMethod( \=,
"for a list of elements and an infinite domain (ResClasses)",
IsIdenticalObj, [ IsList and IsFinite, IsDomain ], 0,
function ( l, D ) return D = l; end );
#############################################################################
##
#M \<( <U1>, <U2> ) . . . . . . . . . . . . . . . . for residue class unions
##
## A total ordering of residue class unions - we want to be able to form
## sorted lists and sets of these objects.
##
InstallMethod( \<,
"for two residue class unions in standard rep. (ResClasses)",
IsIdenticalObj,
[ IsResidueClassUnionInResidueListRep,
IsResidueClassUnionInResidueListRep ], 0,
function ( U1, U2 )
if U1!.r = [] and U2!.r <> [] then return false;
elif U1!.r <> [] and U2!.r = [] then return true;
elif U1!.m <> U2!.m then return U1!.m < U2!.m;
elif U1!.r <> U2!.r then return U1!.r < U2!.r;
elif U1!.included <> U2!.included
then return U1!.included < U2!.included;
else return U1!.excluded < U2!.excluded; fi;
end );
InstallMethod( \<,
"for two residue class unions in sparse rep. (ResClasses)",
IsIdenticalObj,
[ IsResidueClassUnionInClassListRep,
IsResidueClassUnionInClassListRep ], 0,
function ( U1, U2 )
if U1!.m <> U2!.m then return U1!.m < U2!.m;
elif List(U1!.cls,cl->cl[2]) <> List(U2!.cls,cl->cl[2])
then return List(U1!.cls,cl->cl[2]) < List(U2!.cls,cl->cl[2]);
elif U1!.cls <> U2!.cls then return U1!.cls < U2!.cls;
elif U1!.included <> U2!.included
then return U1!.included < U2!.included;
else return U1!.excluded < U2!.excluded; fi;
end );
InstallMethod( \<,
"for two residue class unions, mixed rep. (ResClasses)",
IsIdenticalObj,
[ IsResidueClassUnionInResidueListRep,
IsResidueClassUnionInClassListRep ], 0,
function ( U1, U2 )
Error("residue class unions in different representations ",
"cannot be sorted\n-- convert to same representation first");
return fail;
end );
InstallMethod( \<,
"for two residue class unions, mixed rep. (ResClasses)",
IsIdenticalObj,
[ IsResidueClassUnionInClassListRep,
IsResidueClassUnionInResidueListRep ], 0,
function ( U1, U2 )
Error("residue class unions in different representations ",
"cannot be sorted\n-- convert to same representation first");
return fail;
end );
#############################################################################
##
#M \<( <U>, <R> ) . . . . . . for a residue class union and a ring / module
#M \<( <R>, <U> ) . . . . . . for a ring / module and a residue class union
#M \<( <l>, <R> ) . . . . for a finite list of elements and a ring / module
#M \<( <R>, <l> ) . . . . for a ring / module and a finite list of elements
#M \<( <l>, <U> ) . for a finite list of elements and a residue class union
#M \<( <U>, <l> ) . for a residue class union and a finite list of elements
##
InstallMethod( \<, "for a residue class union and a ring (ResClasses)",
ReturnTrue, [ IsResidueClassUnion, IsRing ], 0, ReturnFalse );
InstallMethod( \<, "for a residue class union and a module (ResClasses)",
ReturnTrue, [ IsResidueClassUnion, IsRowModule ], 0,
ReturnFalse );
InstallMethod( \<, "for a ring and a residue class union (ResClasses)",
ReturnTrue, [ IsRing, IsResidueClassUnion ], 0, ReturnTrue );
InstallMethod( \<, "for a module and a residue class union (ResClasses)",
ReturnTrue, [ IsRowModule, IsResidueClassUnion ], 0,
ReturnTrue );
InstallMethod( \<, "for a list of elements and a ring (ResClasses)",
IsIdenticalObj, [ IsList, IsRing ], 0,
function ( list, R )
if not IsIntegers(R) and not IsZ_pi(R)
and not ( IsUnivariatePolynomialRing(R)
and IsFiniteFieldPolynomialRing(R))
then TryNextMethod(); fi;
return false;
end );
InstallMethod( \<, "for a list of elements and a module (ResClasses)",
IsIdenticalObj, [ IsList, IsRowModule ], 0, ReturnFalse );
InstallMethod( \<, "for a ring and a list of elements (ResClasses)",
IsIdenticalObj, [ IsRing, IsList ], 0,
function ( R, list )
if not IsIntegers(R) and not IsZ_pi(R)
and not ( IsUnivariatePolynomialRing(R)
and IsFiniteFieldPolynomialRing(R))
then TryNextMethod(); fi;
return true;
end );
InstallMethod( \<, "for a module and a list of elements (ResClasses)",
IsIdenticalObj, [ IsRowModule, IsList ], 0, ReturnTrue );
InstallMethod( \<, "for a list and a residue class union (ResClasses)",
ReturnTrue, [ IsList, IsResidueClassUnion ], 0, ReturnFalse );
InstallMethod( \<, "for a residue class union and a list (ResClasses)",
ReturnTrue, [ IsResidueClassUnion, IsList ], 0,
function ( U, l )
if IsFinite(U) then return AsList(U) < l;
else return true; fi;
end );
#############################################################################
##
#S Testing for membership in a residue class union. ////////////////////////
##
#############################################################################
#############################################################################
##
#M \in( <n>, <U> ) . . . . . . for a ring element and a residue class union
##
InstallMethod( \in,
Concatenation("for a ring element and a residue class union ",
"in standard rep. (ResClasses)"),
ReturnTrue,
[ IsObject, IsResidueClassUnionInResidueListRep ], 0,
function ( n, U )
if not n in UnderlyingRing(FamilyObj(U)) then return false; fi;
if n in U!.included then return true;
elif n in U!.excluded then return false;
else return n mod U!.m in U!.r; fi;
end );
InstallMethod( \in,
Concatenation("for a ring element and a residue class union ",
"in sparse rep. (ResClasses)"),
ReturnTrue,
[ IsObject, IsResidueClassUnionInClassListRep ], 0,
function ( n, U )
if not n in UnderlyingRing(FamilyObj(U)) then return false; fi;
if n in U!.included then return true;
elif n in U!.excluded then return false;
else return ForAny(U!.cls,cl->n mod cl[2] = cl[1]); fi;
end );
#############################################################################
##
#S Density and subset relations. ///////////////////////////////////////////
##
#############################################################################
#############################################################################
##
#M Density( <U> ) . . . . . . . . . . . . . . . . . for residue class unions
#M Density( <R> ) . . . . . . . . . . . . for the whole base ring / -module
#M Density( <l> ) . . . . . . . . . . . . . . . . . . . . . for finite sets
##
InstallMethod( Density,
"for residue class unions in standard rep. (ResClasses)",
true, [ IsResidueClassUnionInResidueListRep ], 0,
U -> Length(Residues(U))/
NumberOfResidues(UnderlyingRing(FamilyObj(U)),
Modulus(U)) );
InstallMethod( Density,
"for residue class unions in sparse rep. (ResClasses)",
true, [ IsResidueClassUnionOfZInClassListRep ], 0,
U -> Sum(List(U!.cls,cl->1/cl[2])) );
InstallOtherMethod( Density, "for the whole base ring (ResClasses)", true,
[ IsRing ], 0, R -> 1 );
InstallOtherMethod( Density, "for the whole base module (ResClasses)", true,
[ IsRowModule ], 0, R -> 1 );
InstallOtherMethod( Density, "for finite sets (ResClasses)", true,
[ IsList and IsCollection ], 0,
function ( l )
if not IsFinite(DefaultRing(l[1]))
then return 0; else TryNextMethod(); fi;
end );
InstallOtherMethod( Density, "for the empty set (ResClasses)", true,
[ IsList and IsEmpty ], 0, l -> 0 );
#############################################################################
##
#M IsSubset( <U>, <l> ) . . . for a residue class union and an element list
##
InstallMethod( IsSubset,
"for residue class union and element list (ResClasses)",
ReturnTrue, [ IsResidueClassUnion, IsList ], 0,
function ( U, l )
return ForAll( Set( l ), n -> n in U );
end );
#############################################################################
##
#M IsSubset( <U1>, <U2> ) . . for two residue class unions in standard rep.
##
InstallMethod( IsSubset,
"for two residue class unions in standard rep. (ResClasses)",
IsIdenticalObj,
[ IsResidueClassUnionInResidueListRep,
IsResidueClassUnionInResidueListRep ], 0,
function ( U1, U2 )
local R, m1, m2, m, r1, r2, r, allres1, allres2, allres;
R := UnderlyingRing(FamilyObj(U1));
m1 := U1!.m; m2 := U2!.m;
r1 := U1!.r; r2 := U2!.r;
if not IsSubset(U1,U2!.included) or Intersection(U1!.excluded,U2) <> []
then return false; fi;
if IsRing(R) then m := Lcm(R,m1,m2);
elif IsRowModule(R) then m := LatticeIntersection(m1,m2); fi;
allres := AllResidues(R,m);
allres1 := Filtered(allres,n->n mod m1 in r1);
allres2 := Filtered(allres,n->n mod m2 in r2);
return IsSubset(allres1,allres2);
end );
#############################################################################
##
#M IsSubset( <U1>, <U2> ) . . . for two residue class unions in sparse rep.
##
InstallMethod( IsSubset,
"for two residue class unions in sparse rep. (ResClasses)",
IsIdenticalObj,
[ IsResidueClassUnionInClassListRep,
IsResidueClassUnionInClassListRep ], 0,
function ( U1, U2 )
if Density(U2) > Density(U1) then return false; fi;
if not IsSubset(U1,U2!.included) or Intersection(U1!.excluded,U2) <> []
then return false; fi;
return Difference(U2,U1) = [];
end );
#############################################################################
##
#M IsSubset( <U1>, <U2> ) . . for two residue class unions in different rep.
##
InstallMethod( IsSubset,
"for two residue class unions in different rep. (ResClasses)",
IsIdenticalObj,
[ IsResidueClassUnionInResidueListRep,
IsResidueClassUnionInClassListRep ], 0,
function ( U1, U2 ) return IsSubset(SparseRep(U1),U2); end );
InstallMethod( IsSubset,
"for two residue class unions in different rep. (ResClasses)",
IsIdenticalObj,
[ IsResidueClassUnionInClassListRep,
IsResidueClassUnionInResidueListRep ], 0,
function ( U1, U2 ) return IsSubset(U1,SparseRep(U2)); end );
#############################################################################
##
#M IsSubset( <R>, <U> ) . . . . for the base ring and a residue class union
#M IsSubset( <U>, <R> ) . . . . for a residue class union and the base ring
##
InstallMethod( IsSubset,
"for the base ring and a residue class union (ResClasses)",
ReturnTrue, [ IsDomain, IsResidueClassUnion ], 0,
function ( R, U )
if R = UnderlyingRing(FamilyObj(U))
then return true; else TryNextMethod(); fi;
end );
InstallMethod( IsSubset,
"for a residue class union and the base ring (ResClasses)",
ReturnTrue, [ IsResidueClassUnion, IsDomain ], 0,
function ( U, R )
if R = UnderlyingRing(FamilyObj(U))
then return U = R; else TryNextMethod(); fi;
end );
#############################################################################
##
#M IsSubset( Z_pi( <pi> ), Rationals ) . . . . . . . . . . . for Z_pi and Q
##
InstallMethod( IsSubset, "for Z_pi and Rationals (ResClasses)",
ReturnTrue, [ IsZ_pi, IsRationals ], 0, ReturnFalse );
#############################################################################
##
#S Computing unions, intersections and differences. ////////////////////////
##
#############################################################################
#############################################################################
##
#M Union2( <U1>, <U2> ) . . . . . for residue class unions in standard rep.
##
InstallMethod( Union2,
"for two residue class unions in standard rep. (ResClasses)",
IsIdenticalObj,
[ IsResidueClassUnionInResidueListRep,
IsResidueClassUnionInResidueListRep ], 0,
function ( U1, U2 )
local R, m1, m2, m, r1, r2, r, included, excluded,
r1exp, r2exp, allres;
R := UnderlyingRing(FamilyObj(U1));
m1 := U1!.m; m2 := U2!.m;
r1 := U1!.r; r2 := U2!.r;
if IsRing(R) then m := Lcm(R,m1,m2);
elif IsRowModule(R) then m := LatticeIntersection(m1,m2); fi;
included := Union(U1!.included,U2!.included);
excluded := Difference(Union(Difference(U1!.excluded,U2),
Difference(U2!.excluded,U1)),included);
if IsIntegers(R) then
r1exp := Concatenation(List([0..m/m1-1],i->i*m1+r1));
r2exp := Concatenation(List([0..m/m2-1],i->i*m2+r2));
r := Union(r1exp,r2exp);
else
allres := AllResidues(R,m);
r := Filtered(allres,n->n mod m1 in r1 or n mod m2 in r2);
fi;
return ResidueClassUnionNC(R,m,r,included,excluded);
end );
#############################################################################
##
#M Union2( <U1>, <U2> ) . . . . . . for residue class unions in sparse rep.
##
InstallMethod( Union2,
"for two residue class unions in sparse rep. (ResClasses)",
IsIdenticalObj,
[ IsResidueClassUnionInClassListRep,
IsResidueClassUnionInClassListRep ], 0,
function ( U1, U2 )
local R, m1, m2, m, r1, r2, r, included, excluded,
r1exp, r2exp, allres;
R := UnderlyingRing(FamilyObj(U1));
included := Union(U1!.included,U2!.included);
excluded := Difference(Union(Difference(U1!.excluded,U2),
Difference(U2!.excluded,U1)),included);
return ResidueClassUnionNC(R,Union(U1!.cls,U2!.cls),included,excluded);
end );
#############################################################################
##
#M Union2( <U1>, <U2> ) . . . . . for residue class unions in different rep.
##
InstallMethod( Union2,
"for two residue class unions in different rep. (ResClasses)",
IsIdenticalObj,
[ IsResidueClassUnionInResidueListRep,
IsResidueClassUnionInClassListRep ], 0,
function ( U1, U2 ) return Union2(SparseRep(U1),U2); end );
InstallMethod( Union2,
"for two residue class unions in different rep. (ResClasses)",
IsIdenticalObj,
[ IsResidueClassUnionInClassListRep,
IsResidueClassUnionInResidueListRep ], 0,
function ( U1, U2 ) return Union2(U1,SparseRep(U2)); end );
#############################################################################
##
#M Union2( <U>, <S> ) . . . . . . for a residue class union and a finite set
##
InstallMethod( Union2,
"for a residue class union and a finite set (ResClasses)",
ReturnTrue, [ IsResidueClassUnionInResidueListRep, IsList ],
0,
function ( U, S )
if not IsSubset(UnderlyingRing(FamilyObj(U)),S) then TryNextMethod(); fi;
return ResidueClassUnionNC(UnderlyingRing(FamilyObj(U)),U!.m,U!.r,
Union(U!.included,S),
Difference(U!.excluded,S));
end );
InstallMethod( Union2,
"for a residue class union and a finite set (ResClasses)",
ReturnTrue, [ IsResidueClassUnionInClassListRep, IsList ], 0,
function ( U, S )
if not IsSubset(UnderlyingRing(FamilyObj(U)),S) then TryNextMethod(); fi;
return ResidueClassUnionNC(UnderlyingRing(FamilyObj(U)),U!.cls,
Union(U!.included,S),
Difference(U!.excluded,S));
end );
#############################################################################
##
#M Union2( <S>, <U> ) . . . . . . for a finite set and a residue class union
##
InstallMethod( Union2,
"for a finite set and a residue class union (ResClasses)",
ReturnTrue, [ IsList, IsResidueClassUnion ], 0,
function ( S, U ) return Union2( U, S ); end );
#############################################################################
##
#M Union2( <U>, <R> ) . . . . . for a residue class union and the base ring
##
InstallMethod( Union2,
"for a residue class union and the base ring (ResClasses)",
ReturnTrue, [ IsResidueClassUnion, IsDomain ], 0,
function ( U, R )
if not UnderlyingRing(FamilyObj(U)) = R then TryNextMethod(); fi;
return R;
end );
#############################################################################
##
#M Union2( <R>, <U> ) . . . . . for the base ring and a residue class union
##
InstallMethod( Union2,
"for the base ring and a residue class union (ResClasses)",
ReturnTrue, [ IsDomain, IsResidueClassUnion ], 0,
function ( R, U ) return Union2( U, R ); end );
#############################################################################
##
#M Union2( <S>, <R> ) . . . . . . . . . . for a finite set and the base ring
##
InstallMethod( Union2,
"for a finite set and the base ring (ResClasses)",
ReturnTrue, [ IsList, IsDomain ], 0,
function ( S, R )
if not IsSubset(R,S) then TryNextMethod(); fi;
return R;
end );
#############################################################################
##
#M Union2( <R>, <S> ) . . . . . . . . . . for the base ring and a finite set
##
InstallMethod( Union2,
"for the base ring and a finite set (ResClasses)",
ReturnTrue, [ IsDomain, IsList ], 0,
function ( R, S ) return Union2( S, R ); end );
#############################################################################
##
#M Union2( <R>, <R_> ) . . . . . . . . . . . . . for two times the same ring
##
InstallMethod( Union2,
"for two times the same ring (ResClasses)",
IsIdenticalObj, [ IsRing, IsRing ], 0,
function ( R, R_ )
if IsIdenticalObj(R,R_) or R = R_
then return R; else TryNextMethod(); fi;
end );
#############################################################################
##
#M Union2( <M>, <M_> ) . . . . . . . . . . for two times the same row module
##
InstallMethod( Union2,
"for two times the same row module (ResClasses)",
IsIdenticalObj, [ IsRowModule, IsRowModule ], 0,
function ( M, M_ )
if IsIdenticalObj(M,M_) or M = M_
then return M; else TryNextMethod(); fi;
end );
#############################################################################
##
#M Intersection2( <U1>, <U2> ) . . for residue class unions in standard rep.
##
InstallMethod( Intersection2,
"for two residue class unions in standard rep. (ResClasses)",
IsIdenticalObj,
[ IsResidueClassUnionInResidueListRep,
IsResidueClassUnionInResidueListRep ], 0,
function ( U1, U2 )
local R, m1, m2, m, r1, r2, r, included, excluded,
gcd, rescsd, res, res1, res2, pairs, pair, allres,
crt, bruteforce;
R := UnderlyingRing(FamilyObj(U1));
m1 := U1!.m; m2 := U2!.m;
r1 := U1!.r; r2 := U2!.r;
if IsRing(R) then m := Lcm(R,m1,m2);
elif IsRowModule(R) then m := LatticeIntersection(m1,m2); fi;
included := Union(U1!.included,U2!.included);
included := Filtered(included,n -> n in U1!.included and n mod m2 in r2
or n in U2!.included and n mod m1 in r1);
included := Union(included,Intersection(U1!.included,U2!.included));
excluded := Union(U1!.excluded,U2!.excluded);
crt := ValueOption("CRTIntersection") = true;
bruteforce := ValueOption("BruteForceIntersection") = true;
if IsIntegers(R)
and (crt or m > 10^6 or m1 * m2 > 100 * Length(r1) * Length(r2))
and not bruteforce
then
gcd := Gcd(m1,m2);
rescsd := Intersection(Set(r1 mod gcd),Set(r2 mod gcd));
r1 := Filtered(r1,res->res mod gcd in rescsd);
r2 := Filtered(r2,res->res mod gcd in rescsd);
pairs := Concatenation(List(r1,res1->List(Filtered(r2,
res->(res1-res) mod gcd = 0),res2->[res1,res2])));
r := Set(List(pairs,pair->ChineseRem([m1,m2],pair)));
else
allres := AllResidues(R,m);
r := Filtered(allres,n->n mod m1 in r1 and n mod m2 in r2);
fi;
return ResidueClassUnionNC(R,m,r,included,excluded);
end );
#############################################################################
##
#M Intersection2( <U1>, <U2> ) for residue class unions of Z in sparse rep.
##
InstallMethod( Intersection2,
"for residue class unions of Z in sparse rep. (ResClasses)",
IsIdenticalObj,
[ IsResidueClassUnionOfZInClassListRep,
IsResidueClassUnionOfZInClassListRep ], 0,
function ( U1, U2 )
local cls1, cls2, cls, cl1, cl2, cl, included, excluded;
cls1 := U1!.cls; cls2 := U2!.cls; cls := [];
for cl1 in cls1 do
for cl2 in cls2 do
if (cl1[1]-cl2[1]) mod Gcd(cl1[2],cl2[2]) = 0 then
cl := [ChineseRem([cl1[2],cl2[2]],[cl1[1],cl2[1]]),
Lcm(cl1[2],cl2[2])];
Add(cls,cl);
fi;
od;
od;
included := Union(U1!.included,U2!.included);
included := Filtered(included,n -> n in U1!.included and n in U2
or n in U2!.included and n in U1);
included := Union(included,Intersection(U1!.included,U2!.included));
excluded := Union(U1!.excluded,U2!.excluded);
return ResidueClassUnionNC(Integers,cls,included,excluded);
end );
#############################################################################
##
#M Intersection2( <U1>, <U2> ) . for residue class unions in different rep.
##
InstallMethod( Intersection2,
"for two residue class unions in different rep. (ResClasses)",
IsIdenticalObj,
[ IsResidueClassUnionInResidueListRep,
IsResidueClassUnionInClassListRep ], 0,
function ( U1, U2 )
return Intersection2(SparseRep(U1),U2);
end );
InstallMethod( Intersection2,
"for two residue class unions in different rep. (ResClasses)",
IsIdenticalObj,
[ IsResidueClassUnionInClassListRep,
IsResidueClassUnionInResidueListRep ], 0,
function ( U1, U2 )
return Intersection2(U1,SparseRep(U2));
end );
#############################################################################
##
#M Intersection2( <U>, <S> ) . . for a residue class union and a finite set
##
InstallMethod( Intersection2,
"for a residue class union and a finite set (ResClasses)",
ReturnTrue, [ IsResidueClassUnionInResidueListRep, IsList ],
0,
function ( U, S )
if not IsSubset(UnderlyingRing(FamilyObj(U)),S) then TryNextMethod(); fi;
return Filtered( Set(S), n -> n in U!.included
or ( n mod U!.m in U!.r and not n in U!.excluded ) );
end );
InstallMethod( Intersection2,
"for a residue class union and a finite set (ResClasses)",
ReturnTrue, [ IsResidueClassUnionInClassListRep, IsList ],
0,
function ( U, S )
if not IsSubset(UnderlyingRing(FamilyObj(U)),S) then TryNextMethod(); fi;
return Filtered( Set(S), n -> n in U!.included
or ( ForAny(U!.cls,cl->n mod cl[2] = cl[1])
and not n in U!.excluded ) );
end );
#############################################################################
##
#M Intersection2( <S>, <U> ) . . for a finite set and a residue class union
##
InstallMethod( Intersection2,
"for a finite set and a residue class union (ResClasses)",
ReturnTrue, [ IsList, IsResidueClassUnion ], 0,
function ( S, U ) return Intersection2( U, S ); end );
#############################################################################
##
#M Intersection2( <U>, <R> ) . . for a residue class union and the base ring
##
InstallMethod( Intersection2,
"for a residue class union and the base ring (ResClasses)",
ReturnTrue, [ IsResidueClassUnion, IsDomain ], 0,
function ( U, R )
local S;
S := UnderlyingRing(FamilyObj(U));
if S = R or IsSubset(R,S) then return U; fi;
if IsResidueClassUnion(R) then TryNextMethod(); fi;
if Intersection(S,R) <> [] then
Error("sorry, this case is not yet implemented");
return fail;
else return []; fi;
end );
#############################################################################
##
#M Intersection2( <R>, <U> ) . . for the base ring and a residue class union
##
InstallMethod( Intersection2,
"for the base ring and a residue class union (ResClasses)",
ReturnTrue, [ IsDomain, IsResidueClassUnion ], 0,
function ( R, U ) return Intersection2( U, R ); end );
#############################################################################
##
#M Intersection2( <R>, <R_> ) . . . . . . . . . for two times the same ring
##
InstallMethod( Intersection2,
"for two times the same ring (ResClasses)", ReturnTrue,
[ IsListOrCollection, IsListOrCollection ], SUM_FLAGS,
function ( R, R_ )
if IsIdenticalObj(R,R_) then return R; else
if ForAll([R,R_],IsZ_pi) or ForAll([R,R_],IsRowModule)
then if R = R_ then return R; fi; fi;
TryNextMethod();
fi;
end );
#############################################################################
##
#M Difference( <U1>, <U2> ) . . . for residue class unions in standard rep.
##
InstallMethod( Difference,
"for two residue class unions in standard rep. (ResClasses)",
IsIdenticalObj,
[ IsResidueClassUnionInResidueListRep,
IsResidueClassUnionInResidueListRep ], 0,
function ( U1, U2 )
local R, m1, m2, m, r1, r2, r, included, excluded, allres, expres;
R := UnderlyingRing(FamilyObj(U1));
m1 := U1!.m; m2 := U2!.m;
r1 := U1!.r; r2 := U2!.r;
if IsRing(R) then m := Lcm(R,m1,m2);
elif IsRowModule(R) then m := LatticeIntersection(m1,m2); fi;
included := Union(U1!.included,U2!.excluded);
included := Filtered(included,
n -> n in U1!.included and not n mod m2 in r2
or n in U2!.excluded and n mod m1 in r1);
excluded := Union(U1!.excluded,U2!.included);
if IsIntegers(R) then
expres := Concatenation(List([0..m/m1-1],i->i*m1+r1));
r := Filtered(expres,n -> not n mod m2 in r2);
else
allres := AllResidues(R,m);
r := Filtered(allres,n -> n mod m1 in r1 and not n mod m2 in r2);
fi;
return ResidueClassUnionNC(R,m,r,included,excluded);
end );
#############################################################################
##
#M Difference( <U1>, <U2> ) . . for residue class unions of Z in sparse rep.
##
InstallMethod( Difference,
"for residue class unions of Z in sparse rep. (ResClasses)",
IsIdenticalObj,
[ IsResidueClassUnionOfZInClassListRep,
IsResidueClassUnionOfZInClassListRep ], 0,
function ( U1, U2 )
local cls1, cls2, cl, cls, included, excluded, i;
cls1 := U1!.cls; cls2 := U2!.cls; cls := [];
cls := ShallowCopy(cls1);
for cl in cls2 do
for i in [1..Length(cls)] do
cls[i] := DIFFERENCE_OF_RESIDUE_CLASSES(cls[i],cl);
od;
cls := Union(cls);
od;
included := Union(U1!.included,U2!.excluded);
included := Filtered(included,
n -> n in U1!.included
and not ForAny(cls2,cl->n mod cl[2] = cl[1])
or n in U2!.excluded
and ForAny(cls1,cl->n mod cl[2] = cl[1]));
excluded := Union(U1!.excluded,U2!.included);
return ResidueClassUnionNC(Integers,cls,included,excluded);
end );
#############################################################################
##
#M Difference( <U1>, <U2> ) . . . for residue class unions in different rep.
##
InstallMethod( Difference,
"for two residue class unions in different rep. (ResClasses)",
IsIdenticalObj,
[ IsResidueClassUnionInResidueListRep,
IsResidueClassUnionInClassListRep ], 0,
function ( U1, U2 )
return Difference(SparseRep(U1),U2);
end );
InstallMethod( Difference,
"for two residue class unions in different rep. (ResClasses)",
IsIdenticalObj,
[ IsResidueClassUnionInClassListRep,
IsResidueClassUnionInResidueListRep ], 0,
function ( U1, U2 )
return Difference(U1,SparseRep(U2));
end );
#############################################################################
##
#M Difference( <U>, <S> ) . . . . for a residue class union and a finite set
##
InstallMethod( Difference,
"for a residue class union and a finite set (ResClasses)",
ReturnTrue, [ IsResidueClassUnionInResidueListRep, IsList ],
100,
function ( U, S )
if not IsSubset(UnderlyingRing(FamilyObj(U)),S) then TryNextMethod(); fi;
return ResidueClassUnionNC(UnderlyingRing(FamilyObj(U)),U!.m,U!.r,
Difference(U!.included,S),
Union(U!.excluded,S));
end );
InstallMethod( Difference,
"for a residue class union and a finite set (ResClasses)",
ReturnTrue, [ IsResidueClassUnionInClassListRep, IsList ],
100,
function ( U, S )
if not IsSubset(UnderlyingRing(FamilyObj(U)),S) then TryNextMethod(); fi;
return ResidueClassUnionNC(UnderlyingRing(FamilyObj(U)),U!.cls,
Difference(U!.included,S),
Union(U!.excluded,S));
end );
#############################################################################
##
#M Difference( <S>, <U> ) . . . . for a finite set and a residue class union
##
InstallMethod( Difference,
"for a finite set and a residue class union (ResClasses)",
ReturnTrue, [ IsList, IsResidueClassUnion ], 0,
function ( S, U )
return Filtered( Set( S ), n -> not n in U );
end );
#############################################################################
##
#M Difference( <R>, <U> ) . . . for the base ring and a residue class union
##
InstallMethod( Difference,
"for the base ring and a residue class union (ResClasses)",
ReturnTrue,
[ IsDomain, IsResidueClassUnionInResidueListRep ], 0,
function ( R, U )
if not UnderlyingRing(FamilyObj(U)) = R then TryNextMethod(); fi;
return ResidueClassUnion(R,U!.m,Difference(AllResidues(R,U!.m),U!.r),
U!.excluded,U!.included);
end );
InstallMethod( Difference,
"for Z and a residue class union in sparse rep. (ResClasses)",
ReturnTrue,
[ IsIntegers, IsResidueClassUnionOfZInClassListRep ], 0,
function ( R, U )
local cls1, cls, cl, i;
cls1 := U!.cls; cls := [];
cls := [[0,1]];
for cl in cls1 do
for i in [1..Length(cls)] do
cls[i] := DIFFERENCE_OF_RESIDUE_CLASSES(cls[i],cl);
od;
cls := Filtered(Union(cls),cl->cl<>[]);
od;
return ResidueClassUnionNC(Integers,cls,U!.excluded,U!.included);
end );
#############################################################################
##
#M Difference( <U>, <R> ) . . . for a residue class union and the base ring
##
InstallMethod( Difference,
"for a residue class union and the base ring (ResClasses)",
ReturnTrue, [ IsResidueClassUnion, IsDomain ], 0,
function ( U, R )
if not UnderlyingRing(FamilyObj(U)) = R then TryNextMethod(); fi;
return [];
end );
#############################################################################
##
#M Difference( <R>, <S> ) . . . . . . . . . . . for a ring and a finite set
##
InstallMethod( Difference,
"for a ring and a finite set (ResClasses)", ReturnTrue,
[ IsRing, IsList ], 0,
function ( R, S )
if IsFinite(R) or not IsSubset(R,S) then TryNextMethod(); fi;
return ResidueClassUnionNC(R,One(R),[Zero(R)],[],Set(S));
end );
#############################################################################
##
#M Difference( <ZxZ>, <S> ) . . . . . . . . . . . . for Z^2 and a finite set
##
InstallOtherMethod( Difference,
"for Z^2 and a finite set (ResClasses)", ReturnTrue,
[ IsRowModule, IsList ], 0,
function ( ZxZ, S )
if not IsZxZ(ZxZ) or not IsSubset(ZxZ,S) then TryNextMethod(); fi;
return ResidueClassUnionNC(ZxZ,[[1,0],[0,1]],[[0,0]],[],Set(S));
end );
#############################################################################
##
#M Difference( <D>, <S> ) . . . . . . . . . . . for a ring and the empty set
##
InstallMethod( Difference, "for a domain and the empty set (ResClasses)",
ReturnTrue, [ IsDomain, IsList and IsEmpty ], SUM_FLAGS,
function ( D, S ) return D; end );
#############################################################################
##
#M Difference( <R>, <R_> ) . . . . . . . . . . . for two times the same ring
##
InstallMethod( Difference,
"for two times the same ring (ResClasses)", IsIdenticalObj,
[ IsDomain, IsDomain ], SUM_FLAGS,
function ( R, R_ )
if IsIdenticalObj(R,R_) then
if IsRing(R) then return [];
elif IsZxZ(R) then return ResidueClassUnion(R,[[1,0],[0,1]],[],[],[]);
else TryNextMethod(); fi;
else TryNextMethod(); fi;
end );
#############################################################################
##
#S Applying arithmetic operations to the elements of a residue class union.
##
#############################################################################
#############################################################################
##
#M \+( <U>, <x> ) for residue class union in standard rep. and ring element
##
InstallOtherMethod( \+,
Concatenation("for residue class union in standard rep.",
" and ring element (ResClasses)"),
ReturnTrue,
[ IsResidueClassUnionInResidueListRep, IsObject ], 0,
function ( U, x )
local R;
R := UnderlyingRing(FamilyObj(U));
if IsRing(R) and not x in R then
if IsInt(x) or Characteristic(x) = Characteristic(R)
then x := x * One(R); else TryNextMethod(); fi;
fi;
if not x in R then TryNextMethod(); fi;
return ResidueClassUnion(R,U!.m,List(U!.r,r->(r+x) mod U!.m),
List(U!.included,el->el+x),
List(U!.excluded,el->el+x));
end );
#############################################################################
##
#M \+( <U>, <x> ) . for residue class union in sparse rep. and ring element
##
InstallOtherMethod( \+,
Concatenation("for residue class union in sparse rep.",
" and ring element (ResClasses)"),
ReturnTrue,
[ IsResidueClassUnionInClassListRep, IsObject ], 0,
function ( U, x )
local R;
R := UnderlyingRing(FamilyObj(U));
if IsRing(R) and not x in R then
if IsInt(x) or Characteristic(x) = Characteristic(R)
then x := x * One(R); else TryNextMethod(); fi;
fi;
if not x in R then TryNextMethod(); fi;
return ResidueClassUnion(R,List(U!.cls,cl->[(cl[1]+x) mod cl[2],cl[2]]),
List(U!.included,el->el+x),
List(U!.excluded,el->el+x));
end );
#############################################################################
##
#M \+( <x>, <U> ) . . . . . . . for a ring element and a residue class union
##
InstallOtherMethod( \+,
"for ring element and residue class union (ResClasses)",
ReturnTrue, [ IsObject, IsResidueClassUnion ], 0,
function ( x, U ) return U + x; end );
#############################################################################
##
#M \+( <R>, <x> ) . . . . . . . . . . . for the base ring and a ring element
##
InstallOtherMethod( \+,
"for the base ring and a ring element (ResClasses)",
IsCollsElms, [ IsDomain, IsObject ], SUM_FLAGS,
function ( R, x )
if not IsRing(R) and not IsRowModule(R) then TryNextMethod(); fi;
if IsRing(R) and not x in R then
if IsInt(x) or Characteristic(x) = Characteristic(R)
then x := x * One(R); fi;
fi;
if not x in R then TryNextMethod(); fi;
return R;
end );
#############################################################################
##
#M \+( <x>, <R> ) . . . . . . . . . . . for a ring element and the base ring
#M \+( <x>, <R> ) . . . . . . . . . . . . . for a scalar and the base module
##
InstallOtherMethod( \+,
"for a ring element and the base ring (ResClasses)",
IsElmsColls, [ IsObject, IsRing ], SUM_FLAGS,
function ( x, R ) return R + x; end );
InstallOtherMethod( \+,
"for a scalar and the base module (ResClasses)",
IsElmsColls, [ IsObject, IsRowModule ], SUM_FLAGS,
function ( x, R ) return R + x; end );
#############################################################################
##
#M AdditiveInverseOp( <U> ) . . . . . . . . . . . . for residue class unions
##
InstallOtherMethod( AdditiveInverseOp,
"for residue class unions in standard rep. (ResClasses)",
true, [ IsResidueClassUnionInResidueListRep ], 0,
U -> ResidueClassUnion(UnderlyingRing(FamilyObj(U)),U!.m,
List(U!.r,r->(-r) mod U!.m),
List(U!.included,el->-el),
List(U!.excluded,el->-el)) );
InstallOtherMethod( AdditiveInverseOp,
"for residue class unions in sparse rep. (ResClasses)",
true, [ IsResidueClassUnionInClassListRep ], 0,
U -> ResidueClassUnion(UnderlyingRing(FamilyObj(U)),
List(U!.cls,cl->[(-cl[1]) mod cl[2],cl[2]]),
List(U!.included,el->-el),
List(U!.excluded,el->-el)) );
#############################################################################
##
#M \-( <U>, <x> ) . . . . . . . for a residue class union and a ring element
##
InstallOtherMethod( \-,
"for residue class union and ring element (ResClasses)",
ReturnTrue, [ IsResidueClassUnion, IsObject ], 0,
function ( U, x ) return U + (-x); end );
#############################################################################
##
#M \-( <x>, <U> ) . . . . . . . for a ring element and a residue class union
##
InstallOtherMethod( \-,
"for ring element and residue class union (ResClasses)",
ReturnTrue, [ IsObject, IsResidueClassUnion ], 0,
function ( x, U ) return (-U) + x; end );
#############################################################################
##
#M \-( <x>, <U> ) . . . . . . . . . . . . . . for a ring element and a ring
##
InstallOtherMethod( \-,
"for a ring element and a ring (ResClasses)",
IsElmsColls, [ IsRingElement, IsRing ], 0,
function ( x, U ) return (-U) + x; end );
#############################################################################
##
#M AdditiveInverseOp( <R> ) . . . . . . . . . . . . . . . for the base ring
##
InstallOtherMethod( AdditiveInverseOp,
"for base ring (ResClasses)", true,
[ IsRing ], 0, R -> R );
InstallOtherMethod( AdditiveInverseOp,
"for base module (ResClasses)", true,
[ IsRowModule ], 0, R -> R );
#############################################################################
##
#M \*( <U>, <x> ) for residue class union in standard rep. and ring element
##
InstallOtherMethod( \*,
Concatenation("for residue class union in standard rep.",
" and ring element (ResClasses)"),
ReturnTrue, [ IsResidueClassUnionInResidueListRep,
IsRingElement ], 0,
function ( U, x )
local R;
R := UnderlyingRing(FamilyObj(U));
if IsRing(R) and not x in R then
if IsInt(x) or Characteristic(x) = Characteristic(R)
then x := x * One(R); else TryNextMethod(); fi;
elif IsRowModule(R) and not x in LeftActingDomain(R)
then TryNextMethod(); fi;
if IsZero(x) then return [Zero(R)]; fi;
return ResidueClassUnionNC(R,U!.m*x,U!.r*x,U!.included*x,U!.excluded*x);
end );
#############################################################################
##
#M \*( <U>, <x> ) . for residue class union in sparse rep. and ring element
##
InstallOtherMethod( \*,
Concatenation("for residue class union in sparse rep.",
" and ring element (ResClasses)"),
ReturnTrue, [ IsResidueClassUnionInClassListRep,
IsRingElement ], 0,
function ( U, x )
local R;
R := UnderlyingRing(FamilyObj(U));
if IsRing(R) and not x in R then
if IsInt(x) or Characteristic(x) = Characteristic(R)
then x := x * One(R); else TryNextMethod(); fi;
elif IsRowModule(R) and not x in LeftActingDomain(R)
then TryNextMethod(); fi;
if IsZero(x) then return [Zero(R)]; fi;
return ResidueClassUnionNC(R,U!.cls*x,U!.included*x,U!.excluded*x);
end );
#############################################################################
##
#M \*( <x>, <U> ) . . . . . . . for a ring element and a residue class union
##
InstallOtherMethod( \*,
"for ring element and residue class union (ResClasses)",
ReturnTrue, [ IsRingElement, IsResidueClassUnion ], 0,
function ( x, U )
if IsRing(UnderlyingRing(FamilyObj(U)))
and IsCommutative(UnderlyingRing(FamilyObj(U)))
then return U * x;
else TryNextMethod(); fi;
end );
#############################################################################
##
#M \*( <U>, <M> ) . . . . . . for a residue class union of Z^2 and a matrix
##
InstallOtherMethod( \*,
"for residue class union of Z^2 and matrix (ResClasses)",
ReturnTrue, [ IsResidueClassUnionOfZxZ, IsMatrix ], 0,
function ( U, M )
local R, m, r, inc, exc;
if not ForAll(Flat(M),IsRat) or DeterminantMat(M) = 0
then TryNextMethod(); fi;
R := UnderlyingRing(FamilyObj(U));
m := Modulus(U) * M;
if Residues(U) <> []
then r := Residues(U) * M; else r := []; fi;
if IncludedElements(U) <> []
then inc := IncludedElements(U) * M; else inc := []; fi;
if ExcludedElements(U) <> []
then exc := ExcludedElements(U) * M; else exc := []; fi;
if not ForAll([m,r,inc,exc],S->IsSubset(R,S)) then TryNextMethod(); fi;
return ResidueClassUnionNC(R,m,r,inc,exc);
end );
#############################################################################
##
#M \*( <n>, <U> ) . . . . . for an integer and a residue class union of Z^2
##
InstallOtherMethod( \*,
"for an integer and a residue class union of Z^2 (ResClasses)",
ReturnTrue, [ IsInt, IsResidueClassUnionOfZxZ ], 0,
function ( n, U ) return U * n; end );
#############################################################################
##
#M \*( <R>, <x> ) . . . . . . . . . . . for the base ring and a ring element
##
InstallOtherMethod( \*,
"for the base ring and a ring element (ResClasses)",
ReturnTrue, [ IsRing, IsRingElement ], 0,
function ( R, x )
if not IsIntegers(R) and not IsZ_pi(R)
and not ( IsUnivariatePolynomialRing(R)
and IsFiniteFieldPolynomialRing(R))
then TryNextMethod(); fi;
if not x in R then
if IsInt(x) or Characteristic(x) = Characteristic(R)
then x := x * One(R); else TryNextMethod(); fi;
fi;
if IsZero(x) then return [Zero(R)];
else return ResidueClass(R,x,Zero(x)); fi;
end );
#############################################################################
##
#M \*( <R>, <x> ) . . . . . . . . for the base module and a scalar / matrix
##
InstallOtherMethod( \*,
"for the base module and a scalar / matrix (ResClasses)",
ReturnTrue, [ IsRowModule, IsRingElement ], 0,
function ( R, x )
if x in LeftActingDomain(R)
then return ResidueClassNC(R,x*One(GL(Dimension(R),
LeftActingDomain(R))),[0,0]);
elif x in FullMatrixAlgebra(LeftActingDomain(R),Dimension(R))
then return ResidueClassNC(R,x,Zero(R));
else TryNextMethod(); fi;
end );
#############################################################################
##
#M \*( <x>, <R> ) . . . . . . . . . . . for a ring element and the base ring
#M \*( <x>, <R> ) . . . . . . . . . . . . . . . . . . for an integer and Z^2
##
InstallOtherMethod( \*,
"for a ring element and the base ring (ResClasses)",
ReturnTrue, [ IsRingElement,
IsRing and IsCommutative ], 0,
function ( x, R ) return R * x; end );
InstallOtherMethod( \*,
"for a scalar and Z^2 (ResClasses)",
ReturnTrue, [ IsInt, IsRowModule ], 0,
function ( n, ZxZ )
if IsZxZ(ZxZ) then return ZxZ * n;
else TryNextMethod(); fi;
end );
#############################################################################
##
#M \/( <U>, <x> ) for residue class union in standard rep. and ring element
##
InstallOtherMethod( \/,
Concatenation("for residue class union in standard rep.",
" and ring element (ResClasses)"),
ReturnTrue, [ IsResidueClassUnionInResidueListRep,
IsRingElement ], 0,
function ( U, x )
local R, S1, S2, m, quot;
R := UnderlyingRing(FamilyObj(U)); m := U!.m;
if IsRing(R)
then S1 := R; S2 := R;
elif IsRowModule(R)
then if U!.r = [] then
quot := U!.included/x;
if IsSubset(R,quot)
then return ResidueClassUnion(R,m,[],quot,[]);
else TryNextMethod(); fi;
fi;
S1 := LeftActingDomain(R);
S2 := FullMatrixModule(S1,Dimension(R),Dimension(R));
fi;
if not x in S1 or not m/x in S2
or not ForAll(U!.r,r->r/x in R)
or not ForAll(U!.included,el->el/x in R)
then TryNextMethod(); fi;
return ResidueClassUnion(R,m/x,U!.r/x,U!.included/x,U!.excluded/x);
end );
#############################################################################
##
#M \/( <U>, <x> ) . for residue class union of Z in sparse rep. and integer
##
InstallOtherMethod( \/,
Concatenation("for residue class union of Z in sparse ",
"rep. and integer (ResClasses)"),
ReturnTrue, [ IsResidueClassUnionOfZInClassListRep,
IsInt ], 0,
function ( U, x )
local cls;
if x = 0 then Error("cannot divide by 0"); return fail; fi;
if not ForAll(U!.included/x,IsInt) then TryNextMethod(); fi;
cls := List(U!.cls,cl->cl/x);
if not ForAll(cls,cl->ForAll(cl,IsInt)) then TryNextMethod(); fi;
return ResidueClassUnion(Integers,cls,U!.included/x,U!.excluded/x);
end );
#############################################################################
##
#M \/( <U>, <x> ) . . . . . . . . . . . for a residue class union and a unit
##
InstallOtherMethod( \/,
"for residue class union and unit (ResClasses)",
ReturnTrue, [ IsResidueClassUnion, IsRingElement ], 5,
function ( U, x )
if IsUnit(x) then return U * Inverse(x); else TryNextMethod(); fi;
end );
#############################################################################
##
#M \/( [ ], <x> ) . . . . . . . . . . . for the empty set and a ring element
##
InstallOtherMethod( \/,
"for the empty set and a ring element (ResClasses)",
ReturnTrue, [ IsList and IsEmpty, IsRingElement ], 0,
function ( empty, x )
if not IsZero(x) then return [ ]; else TryNextMethod( ); fi;
end );
#############################################################################
##
#S Some methods for residue class unions of Z^2 ////////////////////////////
#S which are degenerated to finite sets. ///////////////////////////////////
##
#############################################################################
#############################################################################
##
#M Enumerator( <U> ) . . . . . . for degenerated residue class unions of Z^2
##
InstallMethod( Enumerator,
"for degenerated residue class unions of Z^2 (ResClasses)",
true, [ IsResidueClassUnionOfZxZ and IsFinite ], 0,
IncludedElements );
#############################################################################
##
#M \[\]( <U>, <pos> ) . . . . . for degenerated residue class unions of Z^2
##
InstallOtherMethod( \[\],
"for degenerated residue class unions of Z^2 (ResClasses)",
ReturnTrue,
[ IsResidueClassUnionOfZxZ and IsFinite, IsPosInt ], 0,
function ( U, pos ) return IncludedElements(U)[pos]; end );
#############################################################################
##
#M ListOp( <U>, <f> ) . . . . . for degenerated residue class unions of Z^2
##
InstallMethod( ListOp,
"for degenerated residue class unions of Z^2 (ResClasses)",
ReturnTrue, [ IsResidueClassUnionOfZxZ and IsFinite,
IsFunction ], 0,
function ( U, f ) return List(IncludedElements(U),f); end );
#############################################################################
##
#M FilteredOp( <U>, <f> ) . . . for degenerated residue class unions of Z^2
##
InstallMethod( FilteredOp,
"for degenerated residue class unions of Z^2 (ResClasses)",
ReturnTrue, [ IsResidueClassUnionOfZxZ and IsFinite,
IsFunction ], 0,
function ( U, f )
return ResidueClassUnion(UnderlyingRing(FamilyObj(U)),[[1,0],[0,1]],[],
Filtered(IncludedElements(U),f),[]);
end );
#############################################################################
##
#M ForAllOp( <U>, <f> ) . . . . for degenerated residue class unions of Z^2
#M ForAnyOp( <U>, <f> ) . . . . for degenerated residue class unions of Z^2
##
InstallMethod( ForAllOp,
"for degenerated residue class unions of Z^2 (ResClasses)",
ReturnTrue, [ IsResidueClassUnionOfZxZ and IsFinite,
IsFunction ], 0,
function ( U, f ) return ForAll(IncludedElements(U),f); end );
InstallMethod( ForAnyOp,
"for degenerated residue class unions of Z^2 (ResClasses)",
ReturnTrue, [ IsResidueClassUnionOfZxZ and IsFinite,
IsFunction ], 0,
function ( U, f ) return ForAny(IncludedElements(U),f); end );
#############################################################################
##
#M Length( <U> ) . . . . . . . . for degenerated residue class unions of Z^2
##
InstallOtherMethod( Length,
"for degenerated residue class unions of Z^2 (ResClasses)",
true, [ IsResidueClassUnionOfZxZ and IsFinite ], 0, Size );
#############################################################################
##
#S Splitting residue classes. //////////////////////////////////////////////
##
#############################################################################
#############################################################################
##
#M SplittedClass( <cl>, <t> ) . . . . . . . for residue classes of Z or Z_pi
##
InstallMethod( SplittedClass,
"for residue classes of Z or Z_pi (ResClasses)", ReturnTrue,
[ IsResidueClassOfZorZ_pi, IsPosInt ], 0,
function ( cl, t )
local R, r, m;
R := UnderlyingRing(FamilyObj(cl));
if IsZ_pi(R) and not IsSubset(Union(NoninvertiblePrimes(R),[1]),
Set(Factors(t)))
then return fail; fi;
r := Residue(cl); m := Modulus(cl);
return List([0..t-1],k->ResidueClass(R,t*m,k*m+r));
end );
#############################################################################
##
#M SplittedClass( <cl>, <t> ) . . . . . . . for residue classes of GF(q)[x]
##
InstallMethod( SplittedClass,
"for residue classes of GF(q)[x] (ResClasses)", ReturnTrue,
[ IsResidueClassOfGFqx, IsPosInt ], 0,
function ( cl, t )
local R, r, m1, m2, m;
if t = 1 then return [cl]; fi;
R := UnderlyingRing(FamilyObj(cl));
if SmallestRootInt(t) <> Characteristic(R) then return fail; fi;
r := Residue(cl);
m1 := Modulus(cl);
m2 := IndeterminatesOfPolynomialRing(R)[1]^LogInt(t,Characteristic(R));
m := m1 * m2;
return List(AllResidues(R,m2),k->ResidueClass(R,m,k*m1+r));
end );
#############################################################################
##
#M SplittedClass( <R>, <t> ) . . . . . . . . . . . . for Z, Z_pi or GF(q)[x]
##
InstallOtherMethod( SplittedClass,
"for Z, Z_pi or GF(q)[x] (ResClasses)", ReturnTrue,
[ IsRing, IsPosInt ], 0,
function ( R, t )
local m;
if IsOne(t) then return [R]; fi;
if not IsIntegers(R) and not IsZ_pi(R)
and not IsFiniteFieldPolynomialRing(R)
then TryNextMethod(); fi;
if IsZ_pi(R)
and not IsSubset(Union(NoninvertiblePrimes(R),[1]),Set(Factors(t)))
then return fail; fi;
if IsFiniteFieldPolynomialRing(R)
and SmallestRootInt(t) <> Characteristic(R)
then return fail; fi;
if IsIntegers(R) or IsZ_pi(R) then m := t; else
m := IndeterminatesOfPolynomialRing(R)[1]^LogInt(t,Characteristic(R));
fi;
return AllResidueClassesModulo(R,m);
end );
#############################################################################
##
#M SplittedClass( <cl>, <m2> ) . for a residue class of GF(q)[x] and a pol.
##
InstallMethod( SplittedClass,
"for a res.-class of GF(q)[x] and a polynomial (ResClasses)",
IsCollsElms, [ IsResidueClassOfGFqx, IsPolynomial ], 0,
function ( cl, m2 )
local R, r, m1, m;
R := UnderlyingRing(FamilyObj(cl));
if not m2 in R then return fail; fi;
if IsOne(m2) then return [cl]; fi;
r := Residue(cl);
m1 := Modulus(cl);
m := m1 * m2;
return List(AllResidues(R,m2),k->ResidueClass(R,m,k*m1+r));
end );
#############################################################################
##
#M SplittedClass( <R>, <m> ) . . . . . . . . . for GF(q)[x] and a polynomial
##
InstallOtherMethod( SplittedClass,
"for GF(q)[x] and a polynomial (ResClasses)",
IsCollsElms,
[ IsFiniteFieldPolynomialRing, IsPolynomial ], 0,
function ( R, m )
if not m in R then return fail; fi;
return AllResidueClassesModulo(R,m);
end );
#############################################################################
##
#M SplittedClass( <cl>, <t> ) . . . . . . . . . . for residue classes of Z^2
##
InstallMethod( SplittedClass,
"for residue classes of Z^2 (ResClasses)", ReturnTrue,
[ IsResidueClassOfZxZ, IsRowVector ], 0,
function ( cl, t )
local R, r, m;
R := UnderlyingRing(FamilyObj(cl));
if not t in R then TryNextMethod(); fi;
if not ForAll(t,IsPosInt) then return fail; fi;
r := Residue(cl); m := Modulus(cl);
return Union(List([0..t[1]-1],
i->List([0..t[2]-1],
j->ResidueClass(R,[t[1]*m[1],t[2]*m[2]],
r+i*m[1]+j*m[2]))));
end );
#############################################################################
##
#M SplittedClass( <R>, <t> ) . . . . . . . . . . . . . . . . . . . . for Z^2
##
InstallOtherMethod( SplittedClass,
"for Z^2 (ResClasses)", IsCollsElms,
[ IsRowModule, IsRowVector ], 0,
function ( R, t )
if not t in R then TryNextMethod(); fi;
if not ForAll(t,IsPosInt) then return fail; fi;
return AllResidueClassesModulo(R,DiagonalMat(t));
end );
#############################################################################
##
#S Computing partitions into residue classes. //////////////////////////////
##
#############################################################################
#############################################################################
##
#M AsUnionOfFewClasses( <U> ) . . . . . . . . for pure residue class unions
##
InstallMethod( AsUnionOfFewClasses,
"for pure residue class unions (ResClasses)", true,
[ IsResidueClassUnion ], 0,
function ( U )
local R, cls, cl, remaining, m, res, res_d, div, d, r;
R := UnderlyingRing(FamilyObj(U));
m := Modulus(U); res := Residues(U);
if Length(res) = 1 then return [ ResidueClass(R,m,res[1]) ]; fi;
cls := []; remaining := U;
div := List(Combinations(Factors(R,m)),Product);
div[1] := One(R); div := Set(div);
for d in div do
if not IsZero(m mod d) or NumberOfResidues(R,m/d) > Length(res)
then continue; fi;
res_d := Set(res mod d);
for r in res_d do
if IsSubset(res,List(AllResidues(R,m/d),s->r+s*d)) then
cl := ResidueClass(R,d,r);
Add(cls,cl); remaining := Difference(remaining,cl);
if IsList(remaining) then break; fi;
m := Modulus(remaining); res := Residues(remaining);
if not IsZero(m mod d) or Length(res) < NumberOfResidues(R,m/d)
then break; fi;
fi;
od;
if IsList(remaining) then break; fi;
od;
return cls;
end );
#############################################################################
##
#M AsUnionOfFewClasses( <U> ) . . . . . . for pure residue class unions of Z
##
InstallMethod( AsUnionOfFewClasses,
"for pure residue class unions of Z, 2 (ResClasses)", true,
[ IsResidueClassUnionOfZ ], 20,
function ( U )
local cls, cl, remaining, m, res, res_d, div, d, r;
m := Modulus(U); res := Residues(U);
if Length(res) = 1 then return [ ResidueClass(Integers,m,res[1]) ]; fi;
cls := []; remaining := U;
div := DivisorsInt(m);
for d in div do
if m mod d <> 0 or m/d > Length(res) then continue; fi;
res_d := Set(res mod d);
for r in res_d do
if ForAll([0..m/d-1],k->r+k*d in res) then
cl := ResidueClass(Integers,d,r);
Add(cls,cl); remaining := Difference(remaining,cl);
if IsList(remaining) then break; fi;
m := Modulus(remaining); res := Residues(remaining);
if m mod d <> 0 or Length(res) < m/d then break; fi;
fi;
od;
if IsList(remaining) then break; fi;
od;
return cls;
end );
#############################################################################
##
#M AsUnionOfFewClasses( <U> ) . for residue class unions of Z in sparse rep.
##
InstallMethod( AsUnionOfFewClasses,
"for residue class unions of Z in sparse rep. (ResClasses)",
true, [ IsResidueClassUnionOfZInClassListRep ], 20,
U -> List(U!.cls,ResidueClass) );
#############################################################################
##
#M AsUnionOfFewClasses( <U> ) . . . . . for pure residue class unions of Z^2
##
InstallMethod( AsUnionOfFewClasses,
"for pure residue class unions of Z^2 (ResClasses)", true,
[ IsResidueClassUnionOfZxZ ], 0,
function ( U )
local ZxZ, cls, cl, remaining, L, res, res_d, div, d, r;
ZxZ := UnderlyingRing(FamilyObj(U));
L := Modulus(U);
res := Residues(U);
if res = [] then return []; fi;
if Length(res) = 1 then return [ ResidueClass(ZxZ,L,res[1]) ]; fi;
div := Superlattices(L); # sorted by increasing determinant
cls := []; remaining := U;
for d in div do
if not IsSublattice(d,L)
or DeterminantMat(L)/DeterminantMat(d) > Length(res)
then continue; fi;
res_d := Set(res,r->r mod d);
for r in res_d do
if IsSubset(res,Filtered(AllResidues(ZxZ,L),s->s mod d = r)) then
cl := ResidueClass(ZxZ,d,r);
Add(cls,cl); remaining := Difference(remaining,cl);
if IsList(remaining) then break; fi;
L := Modulus(remaining); res := Residues(remaining);
if not IsSublattice(d,L)
or DeterminantMat(L)/DeterminantMat(d) > Length(res)
then break; fi;
fi;
od;
if IsList(remaining) then break; fi;
od;
return Set(cls);
end );
#############################################################################
##
#M AsUnionOfFewClasses( <l> ) . . . . . . . . . for finite sets of elements
##
InstallOtherMethod( AsUnionOfFewClasses,
"for finite sets of elements (ResClasses)", true,
[ IsList ], 0, l -> [ ] );
#############################################################################
##
#M AsUnionOfFewClasses( <R> ) . . . . . . . . . . . . . . . . . . . for ring
##
InstallOtherMethod( AsUnionOfFewClasses, "for a ring (ResClasses)",
true, [ IsRing ], 0, R -> [ R ] );
InstallOtherMethod( AsUnionOfFewClasses, "for a row module (ResClasses)",
true, [ IsRowModule ], 0, R -> [ R ] );
#############################################################################
##
#M PartitionsIntoResidueClasses( <R>, <length> ) . . . . . . general method
##
InstallMethod( PartitionsIntoResidueClasses,
"general method (ResClasses)",
ReturnTrue, [ IsRing, IsPosInt ], 0,
function ( R, length )
local Recurse, partitions, primes, desiredprimes, distinct, eqcls,
p, q, x, i, j;
Recurse := function ( P, pos, p )
local remaining_primes;
P[pos] := SplittedClass(P[pos],p);
if P[pos] = fail then return; fi;
P := Flat(P);
if Length(P) = length then Add(partitions,Set(P)); return; fi;
if IsIntegers(R) or IsZ_pi(P)
then remaining_primes := Intersection(primes,[2..length-Length(P)+1]);
else remaining_primes := Filtered(primes,p->NumberOfResidues(R,p)
<= length-Length(P)+1);
fi;
for p in remaining_primes do
for pos in [1..Length(P)] do
if not distinct or pos = Length(P)
or Mod(P[pos+1]) <> Mod(P[pos])
then Recurse(ShallowCopy(P),pos,p); fi;
od;
od;
end;
if length = 1 then return [[R]]; fi;
distinct := ValueOption("distinct") = true;
partitions := [];
if IsIntegers(R)
then primes := Filtered([2..length],IsPrime);
desiredprimes := ValueOption("Primes");
if desiredprimes <> fail and IsList(desiredprimes)
then primes := Intersection(primes,desiredprimes); fi;
elif IsZ_pi(R)
then primes := Intersection([2..length],NoninvertiblePrimes(R));
elif IsUnivariatePolynomialRing(R) and IsFiniteFieldPolynomialRing(R)
then x := IndeterminatesOfPolynomialRing(R)[1];
q := Size(CoefficientsRing(R));
primes := Filtered(AllResidues(R,x^(LogInt(length,q)+1)),
p -> IsIrreducibleRingElement(R,p));
else TryNextMethod(); fi;
for p in primes do Recurse([R],1,p); od;
partitions := Set(partitions);
if distinct then
eqcls := EquivalenceClasses(partitions,P->List(P,Density));
partitions := Set(eqcls,cl->cl[1]);
fi;
return partitions;
end );
#############################################################################
##
#M PartitionsIntoResidueClasses( <R>, <length>, <primes> ) . . . . . . for Z
##
InstallMethod( PartitionsIntoResidueClasses,
"method for Z (ResClasses)",
ReturnTrue, [ IsIntegers, IsPosInt, IsList ], 0,
function ( R, length, primes )
if primes = [] or not ForAll(primes,IsPrimeInt) then TryNextMethod(); fi;
return PartitionsIntoResidueClasses(R,length:Primes:=primes);
end );
#############################################################################
##
#M RandomPartitionIntoResidueClasses( <R>, <length>, <primes> ) for Z, Z_pi
##
InstallMethod( RandomPartitionIntoResidueClasses,
"for Z or Z_pi (ResClasses)", ReturnTrue,
[ IsRing, IsPosInt, IsList ], 0,
function ( R, length, primes )
local P, diff, p, parts, part, i, j;
if not (IsIntegers(R) or IsZ_pi(R))
or not ForAll(primes,IsInt) or not ForAll(primes,IsPrime)
then TryNextMethod(); fi;
if IsZ_pi(R)
then primes := Intersection(primes,NoninvertiblePrimes(R)); fi;
parts := Filtered(Partitions(length-1),
part->IsSubset(primes-1,part));
if IsEmpty(parts) then return fail; fi;
part := Random(parts);
P := [ R ];
for i in [1..Length(part)] do
p := part[i] + 1;
j := Random([1..Length(P)]);
P[j] := SplittedClass(P[j],p);
P := Flat(P);
od;
return Set(P);
end );
#############################################################################
##
#M RandomPartitionIntoResidueClasses( <R>, <length>, <primes> ) for GF(q)[x]
##
InstallMethod( RandomPartitionIntoResidueClasses,
"for GF(q)[x] (ResClasses)", ReturnTrue,
[ IsFiniteFieldPolynomialRing, IsPosInt, IsList ], 0,
function ( R, length, primes )
local P, splitparts, parts, part, p, i, j;
if not IsSubset(R,primes) then TryNextMethod(); fi;
splitparts := List(primes,p->NumberOfResidues(R,p)-1);
parts := Filtered(Partitions(length-1),part->IsSubset(splitparts,part));
if IsEmpty(parts) then return fail; fi;
part := Random(parts);
P := [ R ];
for i in [1..Length(part)] do
p := Random(Filtered(primes, q->NumberOfResidues(R,q) = part[i]+1));
j := Random([1..Length(P)]);
P[j] := SplittedClass(P[j],p);
P := Flat(P);
od;
return Set(P);
end );
#############################################################################
##
#S Covers by residue classes. //////////////////////////////////////////////
##
#############################################################################
#############################################################################
##
#M CoverByResidueClasses( Integers, <moduli> ) . for Z and list of integers
##
InstallMethod( CoverByResidueClasses,
"for Z and list of positive integers (ResClasses)",
IsIdenticalObj, [ IsIntegers, IsList ], 0,
function ( R, moduli )
local covers;
covers := CoversByResidueClasses(R,moduli:onlyone);
if covers <> [] then return covers[1]; else return fail; fi;
end );
#############################################################################
##
#M CoversByResidueClasses( Integers, <moduli> ) . for Z and list of integers
##
InstallMethod( CoversByResidueClasses,
"for Z and list of positive integers (ResClasses)",
IsIdenticalObj, [ IsIntegers, IsList ], 0,
function ( R, moduli )
local construct, covers, m, onlyone;
construct := function ( residues, remaining )
local cover, i, residue, r;
if onlyone and Length(covers) >= 1 then return; fi;
if remaining = [] then
cover := Set([1..Length(residues)],
i->ResidueClass(residues[i],moduli[i]));
Add(covers,cover);
return;
elif Length(residues) = Length(moduli) then
return;
fi;
i := Length(residues) + 1;
for residue in [0..moduli[i]-1] do
if ForAny(remaining,r->r mod moduli[i] = residue) then
construct(Concatenation(residues,[residue]),
Filtered(remaining,r->r mod moduli[i] <> residue));
fi;
od;
end;
if not ForAll(moduli,IsPosInt) then TryNextMethod(); fi;
if Sum(moduli,m->1/m) < 1 then return []; fi;
onlyone := ValueOption("onlyone") = true;
moduli := AsSortedList(moduli);
covers := [];
m := Lcm(moduli);
construct([],[0..m-1]);
return Set(covers);
end );
#############################################################################
##
#S The invariants Delta and Rho. ///////////////////////////////////////////
##
#############################################################################
#############################################################################
##
#M Delta( <U> ) . . . . . . . . . . . . . . . for residue class unions of Z
##
InstallMethod( Delta,
"for residue class unions of Z (ResClasses)",
true, [ IsResidueClassUnionOfZ ], 0,
function ( U )
local delta;
if IsEmpty(U) then return 0;
elif IsIntegers(U) then return 1/2; else
delta := Sum(Residues(U))/Modulus(U)
- Length(Residues(U))/2 + Modulus(U);
return delta - Int(delta);
fi;
end );
#############################################################################
##
#M Rho( <U> ) . . . . . . . . . . . . . . . . for residue class unions of Z
##
InstallMethod( Rho,
"for residue class unions of Z (ResClasses)",
true, [ IsResidueClassUnionOfZ ], 0,
function ( U )
local delta;
if IsEmpty(U) or IsIntegers(U) then return 1; else
delta := Delta(U)/2;
delta := delta - Int(delta);
if delta >= 1/2 then delta := delta - 1/2; fi;
return E(DenominatorRat(delta))^NumeratorRat(delta);
fi;
end );
#############################################################################
##
#S Iterators for residue class unions. /////////////////////////////////////
##
#############################################################################
#############################################################################
##
#M Iterator( <U> ) . . . . . . . . . . . . . . . . for residue class unions
##
InstallMethod( Iterator,
"for residue class unions (ResClasses)", true,
[ IsResidueClassUnionInResidueListRep ], 0,
function ( U )
return Objectify( NewType( IteratorsFamily,
IsIterator
and IsMutable
and IsResidueClassUnionsIteratorRep ),
rec( U := U,
counter := 0,
classpos := 1,
m_count := 0,
element := fail,
rem_included := ShallowCopy( U!.included ) ) );
end );
#############################################################################
##
#M NextIterator( <iter> ) . . . . . . for iterators of residue class unions
##
InstallMethod( NextIterator,
"for iterators of residue class unions (ResClasses)", true,
[ IsIterator and IsMutable
and IsResidueClassUnionsIteratorRep ], 0,
function ( iter )
local U, next, R, m, r, excluded;
U := iter!.U;
if IsResidueClassUnionOfZ(U) then
if iter!.rem_included <> [] then
next := iter!.rem_included[1];
RemoveSet(iter!.rem_included,next);
iter!.counter := iter!.counter + 1;
return next;
else
m := Modulus(U); r := Residues(U);
excluded := ExcludedElements(U);
repeat
if iter!.classpos > Length(r) then
iter!.classpos := 1;
iter!.m_count := iter!.m_count + 1;
fi;
if iter!.element <> fail and iter!.element >= 0 then
next := (-iter!.m_count-1) * m + r[iter!.classpos];
iter!.classpos := iter!.classpos + 1;
else
next := iter!.m_count * m + r[iter!.classpos];
fi;
iter!.element := next;
iter!.counter := iter!.counter + 1;
until not next in excluded;
return next;
fi;
else TryNextMethod(); fi;
end );
#############################################################################
##
#M IsDoneIterator( <iter> ) . . . . . for iterators of residue class unions
##
InstallMethod( IsDoneIterator,
"for iterators of residue class unions (ResClasses)", true,
[ IsIterator and IsResidueClassUnionsIteratorRep ], 0,
ReturnFalse );
#############################################################################
##
#M ShallowCopy( <iter> ) . . . . . . . for iterators of residue class unions
##
InstallMethod( ShallowCopy,
"for iterators of residue class unions (ResClasses)", true,
[ IsIterator and IsResidueClassUnionsIteratorRep ], 0,
iter -> Objectify( Subtype( TypeObj( iter ), IsMutable ),
rec( U := iter!.U,
counter := iter!.counter,
classpos := iter!.classpos,
m_count := iter!.m_count,
element := iter!.element,
rem_included := iter!.rem_included ) ) );
#############################################################################
##
#M ViewObj( <iter> ) . . . . . . . . . for iterators of residue class unions
##
InstallMethod( ViewObj,
"for iterators of residue class unions (ResClasses)", true,
[ IsIterator and IsResidueClassUnionsIteratorRep ], 0,
function ( iter )
local R;
R := UnderlyingRing(FamilyObj(iter!.U));
Print("<iterator of a residue class union of ",RingToString(R),">");
end );
#############################################################################
##
#S Viewing, printing and displaying residue class unions. //////////////////
##
#############################################################################
#############################################################################
##
#V RESCLASSES_VIEWINGFORMAT . . . current viewing format ("short" or "long")
#F ResidueClassUnionViewingFormat( format ) . short <--> long viewing format
##
BindGlobal( "RESCLASSES_VIEWINGFORMAT", "long" );
InstallGlobalFunction( ResidueClassUnionViewingFormat,
function ( format )
if not format in [ "short", "long" ]
then Error( "viewing formats other than \"short\" and \"long\" ",
"are not supported.\n");
fi;
MakeReadWriteGlobal( "RESCLASSES_VIEWINGFORMAT" );
RESCLASSES_VIEWINGFORMAT := format;
MakeReadOnlyGlobal( "RESCLASSES_VIEWINGFORMAT" );
end );
#############################################################################
##
#F RingToString( <R> ) . . . how the ring <R> is printed by `View'/`Display'
##
InstallGlobalFunction( RingToString,
function ( R )
if IsIntegers(R) then return "Z";
elif IsZxZ(R) then return "Z^2";
else return ViewString(R); fi;
end );
#############################################################################
##
#M ViewString( <cl> ) . . . . . . . . . . . . . . . . . for residue classes
##
InstallMethod( ViewString,
"for residue classes (ResClasses)", true,
[ IsResidueClass ], 0,
cl -> Concatenation(ViewString(Residue(cl)),"(",
ViewString(Modulus(cl)),")") );
#############################################################################
##
#M ViewString( <cl> ) . . . . . . . . . . . . . . for residue classes of Z^2
##
InstallMethod( ViewString,
"for residue classes of Z^2 (ResClasses)", true,
[ IsResidueClassUnionOfZxZ and IsResidueClass ], 0,
function ( cl )
local str;
str := Filtered(Concatenation(String(Residue(cl)),"+",
ModulusAsFormattedString(Modulus(cl))),
ch->ch<>' ');
str := ReplacedString(str,"[","(");
str := ReplacedString(str,"]",")");
return str;
end );
#############################################################################
##
#M ViewObj( <U> ) . . . . . . . . . . . . . . . . . for residue class unions
##
InstallMethod( ViewObj,
"for residue class unions (ResClasses)", true,
[ IsResidueClassUnion ], 0,
function ( U )
local PrintFiniteSet, RCString, str, pos, linelng,
R, m, r, cls, included, excluded, numres, n,
endval, short, bound, display;
PrintFiniteSet := function ( S )
local i;
if Length(String(S)) <= 32 or display then
if not IsPolynomialRing(R) then Print(S); else
Print("[ ");
for i in [1..Length(S)] do
Print(ViewString(S[i]));
if i < Length(S) then Print(", "); fi;
od;
Print(" ]");
fi;
else Print("<set of cardinality ",Length(S),">"); fi;
end;
RCString := function ( cl )
local s, r, m;
if IsRing(R) then
m := Modulus(cl); r := Residue(cl);
if IsIntegers(R) or IsZ_pi(R)
then s := String(r); else s := ViewString(r); fi;
if IsIntegers(R) or IsZ_pi(R)
then s := Concatenation(s,"(",String(m),")");
elif short then s := Concatenation(s,"(",ViewString(m),")");
else s := Concatenation(s," ( mod ",ViewString(m)," )"); fi;
elif IsZxZ(R) then s := ViewString(cl);
else return fail; fi;
return s;
end;
short := RESCLASSES_VIEWINGFORMAT = "short";
display := ValueOption("RC_DISPLAY") = true;
R := UnderlyingRing(FamilyObj(U)); m := Modulus(U);
if IsResidueClassUnionInResidueListRep(U)
then r := Residues(U); numres := Length(r);
else cls := AsUnionOfFewClasses(U); numres := m * Density(U); fi;
included := IncludedElements(U); excluded := ExcludedElements(U);
if numres = 0 then View(included); return; fi;
if (display or numres <= 20) and not IsBound(cls)
then cls := AsUnionOfFewClasses(U); fi;
if (display or numres > NumberOfResidues(R,m) - 20)
and numres > NumberOfResidues(R,m)/2
and included = [] and excluded = []
and Length(AsUnionOfFewClasses(Difference(R,U))) <= 3
then
Print(RingToString(R)," \\ "); View(Difference(R,U));
return;
fi;
if IsIntegers(R) or IsZ_pi(R)
then bound := 5; elif short then bound := 3; else bound := 1; fi;
if display or (IsBound(cls) and Length(cls) <= bound) then
if IsOne(m) then
Print(RingToString(R)," \\ "); PrintFiniteSet(excluded);
else
if not short and (included <> [] or excluded <> [])
then Print("("); pos := 1; else pos := 0; fi;
linelng := SizeScreen()[1];
if numres > 1 then
if not short
then Print("Union of the residue classes "); pos := pos + 29; fi;
endval := Length(cls) - 1;
for n in [1..endval] do
str := RCString(cls[n]);
Print(str); pos := pos + Length(str);
if n < endval then
if short then Print(" U "); pos := pos + 3;
else Print(", "); pos := pos + 2; fi;
fi;
if pos >= linelng - Length(str) - 4
then Print("\n"); pos := 0; fi;
od;
if short then Print(" U "); else Print(" and "); fi;
elif not short then Print("The residue class "); fi;
Print(RCString(Last(cls)));
if not short then Print(" of ",RingToString(R)); fi;
if included <> [] then
if short then Print(" U "); else Print(") U "); fi;
PrintFiniteSet(included);
fi;
if excluded <> [] then
if short or included <> [] then Print(" \\ ");
else Print(") \\ "); fi;
PrintFiniteSet(excluded);
fi;
fi;
else
Print("<union of ",numres," residue classes (mod ",
ModulusAsFormattedString(m),")");
if not short then Print(" of ",RingToString(R)); fi;
if IsBound(cls) and Length(cls) < numres
then Print(" (",Length(cls)," classes)"); fi;
Print(">");
if included <> [] then Print(" U "); PrintFiniteSet(included); fi;
if excluded <> [] then Print(" \\ "); PrintFiniteSet(excluded); fi;
fi;
end );
#############################################################################
##
#M String( <U> ) . . . . . . . . . for residue class unions in standard rep.
##
InstallMethod( String,
"for residue class unions in standard rep. (ResClasses)",
true, [ IsResidueClassUnionInResidueListRep ], 0,
function ( U )
local s, R;
R := UnderlyingRing(FamilyObj(U));
s := Concatenation("ResidueClassUnion( ",String(R),", ",
String(U!.m),", ",String(U!.r));
if U!.included <> [] or U!.excluded <> []
then s := Concatenation(s,", ",String(U!.included),
", ",String(U!.excluded));
fi;
s := Concatenation(s," )");
return s;
end );
#############################################################################
##
#M String( <U> ) . . . . . . . . . . for residue class unions in sparse rep.
##
InstallMethod( String,
"for residue class unions in standard rep. (ResClasses)",
true, [ IsResidueClassUnionInClassListRep ], 0,
function ( U )
local s, R;
R := UnderlyingRing(FamilyObj(U));
s := Concatenation("ResidueClassUnion( ",String(R),", ",String(U!.cls));
if U!.included <> [] or U!.excluded <> []
then s := Concatenation(s,", ",String(U!.included),
", ",String(U!.excluded));
fi;
s := Concatenation(s," )");
return s;
end );
#############################################################################
##
#M PrintObj( <U> ) . . . . . . . . for residue class unions in standard rep.
##
InstallMethod( PrintObj,
"for residue class unions in standard rep. (ResClasses)",
true, [ IsResidueClassUnionInResidueListRep ], 0,
function ( U )
local R;
R := UnderlyingRing(FamilyObj(U));
Print("ResidueClassUnion( ",R,", ",U!.m,", ",U!.r);
if U!.included <> [] or U!.excluded <> []
then Print(", ",U!.included,", ",U!.excluded); fi;
Print(" )");
end );
#############################################################################
##
#M PrintObj( <U> ) . . . . . . . . . for residue class unions in sparse rep.
##
InstallMethod( PrintObj,
"for residue class unions in sparse rep. (ResClasses)",
true, [ IsResidueClassUnionInClassListRep ], 0,
function ( U )
local R;
R := UnderlyingRing(FamilyObj(U));
Print("ResidueClassUnion( ",R,", ",U!.cls);
if U!.included <> [] or U!.excluded <> []
then Print(", ",U!.included,", ",U!.excluded); fi;
Print(" )");
end );
#############################################################################
##
#F DisplayAsGrid( <U> ) . display the residue class union <U> as ASCII grid
##
InstallGlobalFunction( DisplayAsGrid,
function ( U )
local lines, cols, i, j;
if not IsSubset(Integers^2,U) then return fail; fi;
lines := SizeScreen()[2]; cols := SizeScreen()[1]-2;
for i in [lines-1,lines-2..0] do
for j in [0..cols-1] do
if [i,j] in U then Print("*"); else Print(" "); fi;
od;
Print("\n");
od;
end );
#############################################################################
##
#M DisplayString( <U> ) . . . . . . . . . . . . . . for residue class unions
##
InstallMethod( DisplayString,
"for residue class unions (ResClasses)", true,
[ IsResidueClassUnion ], 0,
function ( U )
local str, R, m, r, inc, exc, m_red, r_red, cl, cls, cls_complement, i,
StringFiniteSet;
StringFiniteSet := function ( S )
local str, i;
if not IsPolynomialRing(R) then return String(S); else
str := "[ ";
for i in [1..Length(S)] do
Append(str,ViewString(S[i]));
if i < Length(S) then Append(str,", "); fi;
od;
Append(str," ]");
fi;
end;
R := UnderlyingRing(FamilyObj(U));
m := Mod(U); r := Residues(U);
inc := IncludedElements(U); exc := ExcludedElements(U);
cls := AsUnionOfFewClasses(U);
if not IsZxZ(R) and not IsResidueClass(U) then
m_red := Gcd(R,m,Gcd(R,DifferencesList(r)));
r_red := r[1] mod m_red;
cl := ResidueClass(R,m_red,r_red);
cls_complement := AsUnionOfFewClasses(Difference(cl,U));
fi;
if IsZxZ(R) or IsResidueClass(U)
or Length(cls) <= Length(cls_complement) + 1
then
str := ShallowCopy(ViewString(cls[1]));
for i in [2..Length(cls)] do
Append(str," U ");
Append(str,ViewString(cls[i]));
od;
if inc <> [] then
Append(str," U ");
Append(str,StringFiniteSet(inc));
fi;
if exc <> [] then
Append(str," \\ ");
Append(str,StringFiniteSet(exc));
fi;
else
if inc <> [] then str := "("; else str := ""; fi;
if IsRing(cl) then Append(str,RingToString(R));
else Append(str,ViewString(cl)); fi;
if U <> cl then
Append(str," \\ ");
for i in [1..Length(cls_complement)] do
Append(str,ViewString(cls_complement[i]));
if i < Length(cls_complement) then Append(str," U "); fi;
od;
fi;
if exc <> [] then
Append(str," U ");
Append(str,StringFiniteSet(exc));
fi;
if inc <> [] then
Append(str,") U ");
Append(str,StringFiniteSet(inc));
fi;
fi;
return str;
end );
#############################################################################
##
#M Display( <U> ) . . . . . . . . . . . . . . . . . for residue class unions
##
InstallMethod( Display,
"for residue class unions (ResClasses)", true,
[ IsResidueClassUnion ], 0,
function ( U )
local str, R, m, r, inc, exc, m_red, r_red, cl, cls, cls_complement, i,
PrintFiniteSet;
PrintFiniteSet := function ( S )
local i;
if not IsPolynomialRing(R) then Print(S); else
Print("[ ");
for i in [1..Length(S)] do
Print(ViewString(S[i]));
if i < Length(S) then Print(", "); fi;
od;
Print(" ]");
fi;
end;
if IsResidueClassUnionOfZxZ(U) and ValueOption("AsGrid") <> fail
then DisplayAsGrid(U); return; fi;
if RESCLASSES_VIEWINGFORMAT = "long" or IsResidueClassUnionOfZxZ(U)
then View(U:RC_DISPLAY); Print("\n"); return; fi;
R := UnderlyingRing(FamilyObj(U));
m := Mod(U); r := Residues(U);
inc := IncludedElements(U); exc := ExcludedElements(U);
cls := AsUnionOfFewClasses(U);
if not IsZxZ(R) and not IsResidueClass(U) then
m_red := Gcd(R,m,Gcd(R,DifferencesList(r)));
r_red := r[1] mod m_red;
cl := ResidueClass(R,m_red,r_red);
cls_complement := AsUnionOfFewClasses(Difference(cl,U));
fi;
if IsZxZ(R) or IsResidueClass(U)
or Length(cls) <= Length(cls_complement) + 1
then
Print(ViewString(cls[1]));
for i in [2..Length(cls)] do
Print(" U ",ViewString(cls[i]));
od;
if inc <> [] then Print(" U "); PrintFiniteSet(inc); fi;
if exc <> [] then Print(" \\ "); PrintFiniteSet(exc); fi;
else
if inc <> [] then Print("("); fi;
if IsRing(cl) then Print(RingToString(R));
else Print(ViewString(cl)); fi;
if U <> cl then
Print(" \\ ");
for i in [1..Length(cls_complement)] do
Print(ViewString(cls_complement[i]));
if i < Length(cls_complement) then Print(" U "); fi;
od;
fi;
if exc <> [] then Print(" U "); PrintFiniteSet(exc); fi;
if inc <> [] then Print(") U "); PrintFiniteSet(inc); fi;
fi;
Print("\n");
end );
#############################################################################
##
#M Display( <U> ) . . . . . . . for residue class unions of Z in sparse rep.
##
InstallMethod( Display,
"for residue class unions of Z in sparse rep. (ResClasses)",
true, [ IsResidueClassUnionOfZInClassListRep ], 0,
function ( U )
local str, m, cls, clsraw, cls_complement, cl, inc, exc,
m_red, r_red, i;
if RESCLASSES_VIEWINGFORMAT = "long"
then View(U:RC_DISPLAY); Print("\n"); return; fi;
m := U!.m; inc := U!.included; exc := U!.excluded;
clsraw := U!.cls;
cls := AsUnionOfFewClasses(U);
if not IsResidueClass(U) then
m_red := Gcd(m,Gcd(List(clsraw,cl->cl[1])));
r_red := clsraw[1][1] mod m_red;
cl := ResidueClass(r_red,m_red);
cls_complement := AsUnionOfFewClasses(Difference(cl,U));
fi;
if IsResidueClass(U) or Length(cls) <= Length(cls_complement) + 1 then
Print(ViewString(cls[1]));
for i in [2..Length(cls)] do
Print(" U ",ViewString(cls[i]));
od;
if inc <> [] then Print(" U "); Print(inc); fi;
if exc <> [] then Print(" \\ "); Print(exc); fi;
else
if inc <> [] then Print("("); fi;
if IsIntegers(cl) then Print("Z"); else Print(ViewString(cl)); fi;
if U <> cl then
Print(" \\ ");
for i in [1..Length(cls_complement)] do
Print(ViewString(cls_complement[i]));
if i < Length(cls_complement) then Print(" U "); fi;
od;
fi;
if exc <> [] then Print(" U "); Print(exc); fi;
if inc <> [] then Print(") U "); Print(inc); fi;
fi;
Print("\n");
end );
#############################################################################
##
#M Display( <U> ) . . . . . for partitions of Z^2 into residue class unions
##
InstallMethod( Display,
Concatenation("for partitions of Z^2 into ",
"residue class unions (ResClasses)"),
true, [ IsList ], SUM_FLAGS,
function ( P )
local lines, cols, i, j, l, pos, color, colors;
if IsEmpty(P) or not ForAll(P,IsResidueClassUnionOfZxZ)
or ValueOption("AsGrid") = fail
then TryNextMethod(); fi;
colors := ["*","+","-","#",".","&","/","~","%","<","$",":","!","^","'"];
l := Length(P);
lines := SizeScreen()[2]; cols := SizeScreen()[1]-2;
for i in [lines-1,lines-2..0] do
for j in [0..cols-1] do
pos := First([1..Length(P)],k->[i,j] in P[k]);
if pos = fail then color := " ";
elif pos > Length(colors) then color := "?";
else color := colors[pos]; fi;
Print(color);
od;
Print("\n");
od;
end );
#############################################################################
##
#E resclass.gi . . . . . . . . . . . . . . . . . . . . . . . . . . ends here