Quelle homology.gi
Sprache: unbekannt
|
|
################################################################################
##
## simpcomp / homology.gi
##
## Homology related functions
##
## $Id$
##
################################################################################
SCIntFunc.HomTransposeSparseMat:=function(A)
local res,yind,i,j;
res:=rec(n_row:=A.n_col, n_col:=A.n_row,M:=[]);
for i in [1..res.n_col]do
res.M[i]:=rec(n_entries:=0,inds:=[],vals:=[]);
od;
for i in [A.n_col,A.n_col-1..1] do
for j in [1..A.M[i].n_entries] do
yind:=A.M[i].inds[j];
res.M[yind].n_entries:=res.M[yind].n_entries+1;
Add(res.M[yind].inds,i);
Add(res.M[yind].vals,A.M[i].vals[j]);
od;
od;
return res;
end;;
SCIntFunc.HomSparseToDenseTMat:=function(A)
local i,j,res;
res:=NullMat(A.n_col,A.n_row);
for i in [1..A.n_col] do
for j in [1..A.M[i].n_entries] do
res[i][A.M[i].inds[j]]:=A.M[i].vals[j];
od;
od;
return res;
end;;
#=mult_a*a+mult_b*b
SCIntFunc.HomMult_add_mult_to_column:=function(mult_a, a, mult_b, b)
local i,j,res;
res:=rec(n_entries:=0,inds:=[],vals:=[]);
i:=1;
j:=1;
while(i<=a.n_entries and j <=b.n_entries)do
if(a.inds[i]>b.inds[j]) then
if ((mult_a*a.vals[i])<>0) then
res.n_entries:=res.n_entries+1;
Add(res.inds,a.inds[i]);
Add(res.vals,(mult_a*a.vals[i]));
fi;
i:=i+1;
elif (b.inds[j]>a.inds[i]) then
if((mult_b*b.vals[j])<>0) then
res.n_entries:=res.n_entries+1;
Add(res.inds,b.inds[j]);
Add(res.vals,(mult_b*b.vals[j]));
fi;
j:=j+1;
else #b.inds[j]==a.inds[i]
if ((mult_a*a.vals[i]+mult_b*b.vals[j])<>0) then
res.n_entries:=res.n_entries+1;
Add(res.inds,b.inds[j]);
Add(res.vals,(mult_a*a.vals[i]+mult_b*b.vals[j]));
fi;
i:=i+1;
j:=j+1;
fi;
od;
while(i<=a.n_entries) do
#copy rest of a
if ((mult_a*a.vals[i])<>0) then
res.n_entries:=res.n_entries+1;
Add(res.inds,a.inds[i]);
Add(res.vals,(mult_a*a.vals[i]));
fi;
i:=i+1;
od;
while(j <=b.n_entries) do
#copy rest of b
if((mult_b*b.vals[j])<>0) then
res.n_entries:=res.n_entries+1;
Add(res.inds,b.inds[j]);
Add(res.vals,(mult_b*b.vals[j]));
fi;
j:=j+1;
od;
return res;
end;;
SCIntFunc.HomInsert_col_to_sparse_mat:=function(matrix,vektor,col_ind)
local i;
matrix.M[col_ind].n_entries:=Length(vektor);
matrix.M[col_ind].inds:=[];
matrix.M[col_ind].vals:=[];
for i in [Length(vektor),Length(vektor)-1..1] do
Add(matrix.M[col_ind].inds,vektor[i][1]);
Add(matrix.M[col_ind].vals,vektor[i][2]);
od;
end;;
SCIntFunc.HomCopy_mat:=function(matrix)
local i, res;
res:=[];
for i in [1..matrix.n_col] do
res[i]:=rec(n_entries:=matrix.M[i].n_entries,inds:=ShallowCopy(matrix.M[i].inds),vals:=ShallowCopy(matrix.M[i].vals));
od;
return res;
end;;
SCIntFunc.HomIdentity_mat:=function(n_col)
local i, res;
res:=[];
for i in [1..n_col] do
res[i]:=rec(n_entries:=1,inds:=[i],vals:=[1]);
od;
return res;
end;;
SCIntFunc.HomGet_entry:=function(matrix,col_ind,row_ind)
local i;
i:=Position(matrix[col_ind].inds,row_ind);
return matrix[col_ind].vals[i];
end;;
SCIntFunc.HomBoundaryOperatorMatrix:=function(A,B,d)
local i,j,m,n, sign, help,dSimplex,pos,res, temp;
n:=Size(A);
m:=Size(B);
res:=rec(n_row:=m, n_col:=n, M:=[]);
for i in [1..res.n_col]do
res.M[i]:=rec(n_entries:=0,inds:=[],vals:=[]);
od;
if (m=0) then
return res;
elif (n=0) then
return res;
else
for j in [1..n] do
sign:=1;
temp:=[];
dSimplex:=ShallowCopy(A[j]);
for i in [1..d+1] do
sign:=sign * (-1);
help:=dSimplex[i];
RemoveSet(dSimplex,help);
pos:=Position(B,dSimplex);
AddSet(temp,[pos,sign]);
AddSet(dSimplex,help);
od;
SCIntFunc.HomInsert_col_to_sparse_mat(res,temp,j);
od;
return res;
fi;
end;;
SCIntFunc.HomComputeBasis:=function(matrix, im, rowinvvalues)
local i,j,k,m,n,done,N,res,Mtemp,gcd,rs,a,b,Nhelp,Mtemphelp,AntModi, AntModj,rowinv,Mtemp_j_k;
res:=rec( free:=[], torsion:=[]);
m:=matrix.n_row;
n:=matrix.n_col;
N:=SCIntFunc.HomIdentity_mat(n);
Mtemp:=matrix.M;
rowinv:=0*[1..m];
for i in [1..m] do
rowinvvalues[i]:=0;
od;
for i in [1..n] do
done:=false;
k:=m;
while (not done) do
if (Mtemp[i].n_entries>0) then
k:=Mtemp[i].inds[1];
j:=rowinv[k];
if (j<>0) then
Mtemp_j_k:=SCIntFunc.HomGet_entry(Mtemp,j,k);
AntModi:=Mtemp[i].vals[1];
AntModj:=Mtemp_j_k;
if (AntModi mod AntModj=0) then
#no torsion
b:=(Mtemp[i].vals[1])/AntModj;
N[i]:=SCIntFunc.HomMult_add_mult_to_column((Mtemp_j_k /AntModj),N[i],-b,N[j]);
Mtemp[i]:=SCIntFunc.HomMult_add_mult_to_column((Mtemp_j_k /AntModj),Mtemp[i],-b,Mtemp[j]);
else
#torsion
gcd:=Gcd(AntModj,AntModi);
a:=Mtemp_j_k/gcd;
b:=-Mtemp[i].vals[1]/gcd;
rs:=GcdRepresentation(AntModi,AntModj);
Nhelp:=ShallowCopy(N[j]);
Mtemphelp:=ShallowCopy(Mtemp[j]);
rs[1]:=rs[1]*(Mtemp_j_k/AntModj);
rs[2]:=rs[2]*(Mtemp[i].vals[1]/AntModi);
N[j]:=SCIntFunc.HomMult_add_mult_to_column(rs[2],N[j],rs[1],N[i] );
Mtemp[j]:=SCIntFunc.HomMult_add_mult_to_column(rs[2],Mtemp[j],rs[1],Mtemp[i] );
N[i]:=SCIntFunc.HomMult_add_mult_to_column(a,N[i],b,Nhelp );
Mtemp[i]:=SCIntFunc.HomMult_add_mult_to_column(a,Mtemp[i],b,Mtemphelp );
rowinvvalues[k]:=AbsoluteValue(SCIntFunc.HomGet_entry(Mtemp,j,k));
fi;
k:=k-1;
else
done:=true;
rowinv[k]:=i;
rowinvvalues[k]:=AbsoluteValue(SCIntFunc.HomGet_entry(Mtemp,i,k));
fi;
else
gcd:=AbsoluteValue(SCIntFunc.HomGet_entry(N,i,i)) ;
if (im[i] mod gcd<>0) then
Info(InfoSimpcomp,1,"SCIntFunc.HomComputeBasis: DANGERWILLROBINSON -- entry not annulated. Please contact the authors/maintainers of simpcomp.");
return fail;
fi;
if (im[i]=0) then
AddSet(res.free,N[i]);
elif (im[i] >gcd)then
AddSet(res.torsion,[im[i] /gcd,N[i]]);
fi;
done:=true;
fi;
od;
od;
matrix.M:=Mtemp;
return res;
end;;
SCIntFunc.HomCoHomologyD:=function(complex,d,mode)
local i,s,simplices,boundaries,matrix1, matrix2, row,row2,basis, res, temp,min,smith,smith_base,tors_ord, tors_ord_test,dim;
dim:=SCDim(complex);
if(dim=fail) then
return fail;
fi;
simplices:=[];
simplices[1]:=[];
for i in [d+1..d+3] do
simplices[i]:=[];
if(i-2>=0 and i-2<=dim) then
simplices[i]:=SCSkelEx(complex,i-2);
fi;
od;
#calculate boundary operator matrix
if (mode=1) then #cohomology
matrix1:=SCIntFunc.HomBoundaryOperatorMatrix(simplices[d+2],simplices[d+1],d );
matrix2:=SCIntFunc.HomBoundaryOperatorMatrix(simplices[d+3],simplices[d+2],d+1 );
matrix1:=SCIntFunc.HomTransposeSparseMat(matrix1);
matrix2:=SCIntFunc.HomTransposeSparseMat(matrix2);
else #homology
matrix2:=SCIntFunc.HomBoundaryOperatorMatrix(simplices[d+2],simplices[d+1],d );
matrix1:=SCIntFunc.HomBoundaryOperatorMatrix(simplices[d+3],simplices[d+2],d+1 );
fi;
row:=[];
SCIntFunc.HomComputeBasis(matrix1, 0*[1..matrix1.n_col], row); #calculate image
row2:=[];
basis:=SCIntFunc.HomComputeBasis(matrix2, row, row2); #calculate kernel and kernel/image
res:=[];
for s in basis.free do
temp:=[];
for i in [1..s.n_entries]do
#Add(temp,[s.vals[i],simplices[d+2][s.inds[i]]]);
Add(temp,[s.vals[i],s.inds[i]]);
od;
AddSet(res,[1,temp]);
od;
#check torsion with smith normal form
if(basis.torsion<>[]) then
tors_ord_test:=1;
tors_ord:=1;
for i in row do
if i<>0 then
tors_ord:=tors_ord*i;
fi;
od;
smith:=SmithNormalFormIntegerMatTransforms(SCIntFunc.HomSparseToDenseTMat(matrix1));
if (matrix1.n_col>matrix1.n_row) then
min:=matrix1.n_row;
else
min:=matrix1.n_col;
fi;
#evaluate smith-normal-form
for s in [1..min] do
if (AbsInt(smith.normal[s][s])>1) then
tors_ord_test:=tors_ord_test*smith.normal[s][s];
temp:=[];
smith_base:=SolutionIntMat(smith.coltrans,smith.normal[s]/smith.normal[s][s]);
for i in [1..matrix1.n_row] do
if (smith_base[i]<>0) then
Add(temp,[smith_base[i],i]);
fi;
od;
AddSet(res,[smith.normal[s][s],temp]);
fi;
od;
if (AbsInt(tors_ord)<>AbsInt(tors_ord_test)) then
Info(InfoSimpcomp,1,"SCIntFunc.HomCoHomologyD: inconsistent results, (co)homology computation failed. Please contact the authors/maintainers of simpcomp.");
return fail;
fi;
fi;
return res;
end;
SCIntFunc.HomHomologyBaseD:=function(complex,d)
return SCIntFunc.HomCoHomologyD(complex,d,0);
end;
SCIntFunc.HomCohomologyBaseD:=function(complex,d)
return SCIntFunc.HomCoHomologyD(complex,d,1);
end;
SCIntFunc.HomSmithN:=function( basis, matrix1,i)
local s, temp, smith, min;
if (basis[i].torsion<>[]) then
temp:=[];
smith:=SmithNormalFormIntegerMat(SCIntFunc.HomSparseToDenseTMat(matrix1));
if (matrix1.n_col>matrix1.n_row) then
min:=matrix1.n_row;
else
min:=matrix1.n_col;
fi;
for s in [1..min] do
if (AbsInt(smith[s][s])>1) then
AddSet(temp,[smith[s][s],[]]);
fi;
od;
basis[i].torsion:=temp;
fi;
end;
SCIntFunc.HomCoHomology:=function(complex,mode)
local i,j,d,s,simplices,boundaries,matrix1, matrix2, row,row2,basis, res, temp,min,smith,smith_base,tors_ord, tors_ord_test,dim,globres;
dim:=SCDim(complex);
if(dim=fail) then
return fail;
fi;
simplices:=[];
for i in [1..dim+3] do
simplices[i]:=[];
if(i-2>=0 and i-2<=dim) then
simplices[i]:=SCSkelEx(complex,i-2);
fi;
od;
globres:=[];
for d in [0..dim] do
#calculate boundary operator matrix
if (mode=1) then #cohomology
matrix1:=SCIntFunc.HomBoundaryOperatorMatrix(simplices[d+2],simplices[d+1],d);
matrix2:=SCIntFunc.HomBoundaryOperatorMatrix(simplices[d+3],simplices[d+2],d+1);
matrix1:=SCIntFunc.HomTransposeSparseMat(matrix1);
matrix2:=SCIntFunc.HomTransposeSparseMat(matrix2);
else #homology
matrix1:=SCIntFunc.HomBoundaryOperatorMatrix(simplices[d+3],simplices[d+2],d+1);
matrix2:=SCIntFunc.HomBoundaryOperatorMatrix(simplices[d+2],simplices[d+1],d);
fi;
row:=[];
SCIntFunc.HomComputeBasis(matrix1,ListWithIdenticalEntries(matrix1.n_col,0),row); #calculate image
row2:=[];
basis:=SCIntFunc.HomComputeBasis(matrix2, row, row2); #calculate kernel and kernel/image
res:=[];
for s in basis.free do
temp:=[];
for i in [1..s.n_entries]do
Add(temp,[s.vals[i],s.inds[i]]);
od;
AddSet(res,[1,temp]);
od;
#check torsion with smith normal form
if(basis.torsion<>[]) then
tors_ord_test:=1;
tors_ord:=1;
for i in row do
if i<>0 then
tors_ord:=tors_ord*i;
fi;
od;
smith:=SmithNormalFormIntegerMatTransforms(SCIntFunc.HomSparseToDenseTMat(matrix1));
if (matrix1.n_col>matrix1.n_row) then
min:=matrix1.n_row;
else
min:=matrix1.n_col;
fi;
#evaluate smith-normal-form
for s in [1..min] do
if (AbsInt(smith.normal[s][s])>1) then
tors_ord_test:=tors_ord_test*smith.normal[s][s];
temp:=[];
smith_base:=SolutionIntMat(smith.coltrans,smith.normal[s]/smith.normal[s][s]);
for i in [1..matrix1.n_row] do
if (smith_base[i]<>0) then
#Add(temp,[smith_base[i],simplices[d+2][i]]);
Add(temp,[smith_base[i],i]);
fi;
od;
AddSet(res,[smith.normal[s][s],temp]);
fi;
od;
if (AbsInt(tors_ord)<>AbsInt(tors_ord_test)) then
Info(InfoSimpcomp,1,"SCIntFunc.HomCoHomologyD: inconsistent results, (co)homology computation failed. Please contact the authors/maintainers of simpcomp.");
return fail;
fi;
fi;
Add(globres,res);
od;
res:=[];
for i in [1..Length(globres)] do
temp:=[];
temp[1]:=0;
temp[2]:=[];
for j in globres[i] do
if(j[1]=1) then
temp[1]:=temp[1]+1;
else
Add(temp[2],j[1]);
fi;
od;
if(i=1 and temp[1]>0 and mode=0) then
temp[1]:=temp[1]-1;
fi;
Add(res, temp);
od;
return res;
end;
#calculate boundary of one simplex
#-- orientation flag=true: save orientation, false discard
SCIntFunc.boundaryOperator := function(simplex,orientation)
local b,cur,i,j,pos;
b:=[];
#all positions, i=kill entry
for i in [1..Length(simplex)] do
cur:=[];
#reverse if i odd
if((i mod 2)=1) then
cur[1]:=-1;
#pos:=Length(simplex)-1;
else
cur[1]:=1;
#pos:=1;
fi;
pos:=1;
cur[2]:=[];
#extract one bounary face
for j in [1..Length(simplex)] do
if(i=j) then continue; fi;
cur[2][pos]:=simplex[j];
if((i mod 2)=1) then
#pos:=pos-1;
pos:=pos+1;
else
pos:=pos+1;
fi;
od;
#add to list of boundary faces
if(orientation=true) then
Add(b,[ShallowCopy(cur[1]),ShallowCopy(cur[2])]);
else
Add(b,ShallowCopy(cur[2]));
fi;
od;
return b;
end;
#calculate matrix of boundary operator mapping simplices to boundaries
#matrix: *-> d+1 simplices
# |
# V
# d simplices
SCIntFunc.boundaryOperatorMatrix:=function(simplices, boundaries)
local b,m,i,j,pos;
if(boundaries=[]) then
return [ListWithIdenticalEntries(Length(simplices),0)];
fi;
m:=[];
for i in [1..Length(boundaries)] do
m[i]:=[];
od;
for i in [1..Length(simplices)] do
#get boundary of current simplex
b:=SCIntFunc.boundaryOperator(simplices[i],true);
#calculate matrix column
for j in [1..Length(boundaries)] do
m[j][i]:=0;
od;
for j in [1..Length(b)] do
pos:=Position(boundaries,b[j][2]);
if(pos<>fail) then
m[pos][i]:=b[j][1];
else
Info(InfoSimpcomp,1,"SCIntFunc.boundaryOperatorMatrix: list of boundary simplices is not complete!");
return fail;
fi;
od;
od;
return m;
end;
################################################################################
##<#GAPDoc Label="SCBoundarySimplex">
## <ManSection>
## <Func Name="SCBoundarySimplex" Arg="simplex, orientation"/>
## <Returns> a list upon success, <K>fail</K> otherwise.</Returns>
## <Description>
## Calculates the boundary of a given <Arg>simplex</Arg>. If the flag <Arg>orientation</Arg> is set to <K>true</K>, the function returns the boundary as a list of oriented simplices of the form [ ORIENTATION, SIMPLEX ], where ORIENTATION is either +1 or -1 and a value of +1 means that SIMPLEX is positively oriented and a value of -1 that SIMPLEX is negatively oriented. If <Arg>orientation</Arg> is set to <K>false</K>, an unoriented list of simplices is returned.
## <Example><![CDATA[
## gap> SCBoundarySimplex([1..5],true);
## [ [ -1, [ 2, 3, 4, 5 ] ], [ 1, [ 1, 3, 4, 5 ] ], [ -1, [ 1, 2, 4, 5 ] ],
## [ 1, [ 1, 2, 3, 5 ] ], [ -1, [ 1, 2, 3, 4 ] ] ]
## gap> SCBoundarySimplex([1..5],false);
## [ [ 2, 3, 4, 5 ], [ 1, 3, 4, 5 ], [ 1, 2, 4, 5 ], [ 1, 2, 3, 5 ],
## [ 1, 2, 3, 4 ] ]
## ]]></Example>
## </Description>
## </ManSection>
##<#/GAPDoc>
################################################################################
InstallGlobalFunction(SCBoundarySimplex,
function(simplex,orientation)
if(not IsList(simplex) or not IsDuplicateFree(simplex) or not IsBool(orientation)) then
Info(InfoSimpcomp,1,"SCBoundaryOperator: first argument must be a simplex (given as vertex tuple), second a boolean.");
return fail;
fi;
return SCIntFunc.boundaryOperator(simplex,orientation);
end);
################################################################################
##<#GAPDoc Label="SCBoundaryOperatorMatrix">
## <ManSection>
## <Meth Name="SCBoundaryOperatorMatrix" Arg="complex,k"/>
## <Returns> a rectangular matrix upon success, <K>fail</K> otherwise.</Returns>
## <Description>
## Calculates the matrix of the boundary operator <M>\partial_{<Arg>k+1</Arg>}</M> of a simplicial complex <Arg>complex</Arg>. Note that each column contains the boundaries of a <Arg>k</Arg><M>+1</M>-simplex as a list of oriented <Arg>k</Arg>-simplices and that the matrix is stored as a list of row vectors (as usual in GAP).
## <Example><![CDATA[
## gap> c:=SCFromFacets([[1,2,3],[1,2,6],[1,3,5],[1,4,5],[1,4,6],\
## [2,3,4],[2,4,5],[2,5,6],[3,4,6],[3,5,6]]);;
## gap> mat:=SCBoundaryOperatorMatrix(c,1);
## [ [ 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
## [ -1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0 ],
## [ 0, -1, 0, 0, 0, -1, 0, 0, 0, 1, 1, 1, 0, 0, 0 ],
## [ 0, 0, -1, 0, 0, 0, -1, 0, 0, -1, 0, 0, 1, 1, 0 ],
## [ 0, 0, 0, -1, 0, 0, 0, -1, 0, 0, -1, 0, -1, 0, 1 ],
## [ 0, 0, 0, 0, -1, 0, 0, 0, -1, 0, 0, -1, 0, -1, -1 ] ]
## ]]></Example>
## </Description>
## </ManSection>
##<#/GAPDoc>
################################################################################
InstallMethod(SCBoundaryOperatorMatrixOp,
"for SCSimplicialComplex and Int",
[SCIsSimplicialComplex,IsInt],
function(complex,k)
local d,bdm,s1,s2;
if k < 0 then
Info(InfoSimpcomp,1,"SCBoundaryOperatorMatrix: second argument must be an integer >=0.");
return fail;
fi;
d:=SCDim(complex);
if(d=fail) then
return fail;
fi;
if(d < 0) then
return [];
fi;
if(k>d) then
return [[0]];
fi;
bdm:=[];
s1:=SCSkelEx(complex,k);
if(d>0) then
s2:=SCSkelEx(complex,k-1);
else
s2:=[];
fi;
bdm:=SCIntFunc.boundaryOperatorMatrix(s1,s2);
return bdm;
end);
################################################################################
##<#GAPDoc Label="SCCoboundaryOperatorMatrix">
## <ManSection>
## <Meth Name="SCCoboundaryOperatorMatrix" Arg="complex,k"/>
## <Returns> a rectangular matrix upon success, <K>fail</K> otherwise.</Returns>
## <Description>
## Calculates the matrix of the coboundary operator <M>d^{<Arg>k+1</Arg>}</M> as a list of row vectors.
## <Example><![CDATA[
## gap> c:=SCFromFacets([[1,2,3],[1,2,6],[1,3,5],[1,4,5],[1,4,6],\
## [2,3,4],[2,4,5],[2,5,6],[3,4,6],[3,5,6]]);
## gap> mat:=SCCoboundaryOperatorMatrix(c,1);
## [ [ -1, 1, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
## [ -1, 0, 0, 0, 1, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0 ],
## [ 0, -1, 0, 1, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0 ],
## [ 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0 ],
## [ 0, 0, -1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0 ],
## [ 0, 0, 0, 0, 0, -1, 1, 0, 0, -1, 0, 0, 0, 0, 0 ],
## [ 0, 0, 0, 0, 0, 0, -1, 1, 0, 0, 0, 0, -1, 0, 0 ],
## [ 0, 0, 0, 0, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, -1 ],
## [ 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 1, 0, -1, 0 ],
## [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 1, 0, 0, -1 ] ]
## ]]></Example>
## </Description>
## </ManSection>
##<#/GAPDoc>
################################################################################
InstallMethod(SCCoboundaryOperatorMatrixOp,
"for SCSimplicialComplex and Int",
[SCIsSimplicialComplex,IsInt],
function(complex,k)
local bd;
if k < 0 then
Info(InfoSimpcomp,1,"SCCoboundaryOperatorMatrix: second argument must be an integer >=0.");
return fail;
fi;
bd:=SCBoundaryOperatorMatrix(complex,k+1);
if(bd=fail) then
return fail;
fi;
return TransposedMat(bd);
end);
################################################################################
##<#GAPDoc Label="SCHomologyBasis">
## <ManSection>
## <Meth Name="SCHomologyBasis" Arg="complex,k"/>
## <Returns> a list of pairs of the form <C>[ integer, list of linear combinations of simplices ]</C> upon success, <K>fail</K> otherwise.</Returns>
## <Description>
## Calculates a set of basis elements for the <Arg>k</Arg>-dimensional homology group (with integer coefficients) of a simplicial complex <Arg>complex</Arg>. The entries of the returned list are of the form [ MODULUS, [ BASEELM1, BASEELM2, ...] ], where the value MODULUS is 1 for the basis elements of the free part of the <Arg>k</Arg>-th homology group and <M>q\geq 2</M> for the basis elements of the <M>q</M>-torsion part. In contrast to the function <Ref Meth="SCHomologyBasisAsSimplices" /> the basis elements are stored as lists of coefficient-index pairs referring to the simplices of the complex, i.e. a basis element of the form <M>[ [ \lambda_1, i], [\lambda_2, j], \dots ] \dots</M> encodes the linear combination of simplices of the form <M>\lambda_1*\Delta_1+\lambda_2*\Delta_2</M> with <M>\Delta_1</M>=<C>SCSkel(complex,k)[i]</C>, <M>\Delta_2</M>=<C>SCSkel(complex,k)[j]</C> and so on.
## <Example><![CDATA[
## gap> SCLib.SearchByName("(S^2xS^1)#RP^3");
## [ [ 237, "(S^2xS^1)#RP^3" ] ]
## gap> c:=SCLib.Load(last[1][1]);;
## gap> SCHomologyBasis(c,1);
## [ [ 1, [ [ 1, 12 ], [ -1, 7 ], [ 1, 1 ] ] ],
## [ 2, [ [ 1, 68 ], [ -1, 69 ], [ -1, 71 ], [ 2, 72 ], [ -2, 73 ] ] ] ]
## ]]></Example>
## </Description>
## </ManSection>
##<#/GAPDoc>
################################################################################
InstallMethod(SCHomologyBasisOp,
"for SCSimplicialComplex and Int",
[SCIsSimplicialComplex,IsInt],
function(complex,k)
local hom,dhom,row,t,tmp,tmp2,bd1,bd2,d;
if k < 0 then
Info(InfoSimpcomp,1,"SCHomologyBasis: second argument must be an integer >=0.");
return fail;
fi;
d:=SCDim(complex);
if(d=fail) then
return fail;
fi;
if(k>d) then
return [];
fi;
hom:=SCIntFunc.HomHomologyBaseD(complex,k);
return hom;
end);
################################################################################
##<#GAPDoc Label="SCCohomologyBasis">
## <ManSection>
## <Meth Name="SCCohomologyBasis" Arg="complex,k"/>
## <Returns> a list of pairs of the form <C>[ integer, list of linear combinations of simplices ]</C> upon success, <K>fail</K> otherwise.</Returns>
## <Description>
## Calculates a set of basis elements for the <Arg>k</Arg>-dimensional cohomology group (with integer coefficients) of a simplicial complex <Arg>complex</Arg>. The entries of the returned list are of the form [ MODULUS, [ BASEELM1, BASEELM2, ...] ], where the value MODULUS is 1 for the basis elements of the free part of the <Arg>k</Arg>-th homology group and <M>q\geq 2</M> for the basis elements of the <M>q</M>-torsion part. In contrast to the function <Ref Meth="SCCohomologyBasisAsSimplices" /> the basis elements are stored as lists of coefficient-index pairs referring to the linear forms dual to the simplices in the <M>k</M>-th cochain complex of <Arg>complex</Arg>, i.e. a basis element of the form <M>[ [ \lambda_1, i], [\lambda_2, j], \dots ] \dots</M> encodes the linear combination of simplices (or their dual linear forms in the corresponding cochain complex) of the form <M>\lambda_1*\Delta_1+\lambda_2*\Delta_2</M> with <M>\Delta_1</M>=<C>SCSkel(complex,k)[i]</C>, <M>\Delta_2</M>=<C>SCSkel(complex,k)[j]</C> and so on.
## <Example><![CDATA[
## gap> SCLib.SearchByName("SU(3)/SO(3)");
## [ [ 219, "SU(3)/SO(3) (VT)" ], [ 477, "SU(3)/SO(3) (VT)" ],
## [ 484, "SU(3)/SO(3) (VT)" ], [ 486, "SU(3)/SO(3) (VT)" ] ]
## gap> c:=SCLib.Load(last[1][1]);;
## gap> SCCohomologyBasis(c,3);
## [ [ 2, [ [ -9, 259 ], [ 9, 262 ], [ 9, 263 ], [ -9, 270 ], [ 9, 271 ],
## [ -9, 273 ], [ -9, 274 ], [ -18, 275 ], [ -9, 276 ], [ 9, 278 ],
## [ -9, 279 ], [ -9, 280 ], [ 3, 283 ], [ -3, 285 ], [ 3, 289 ],
## [ -3, 294 ], [ 3, 310 ], [ -3, 313 ], [ 3, 316 ], [ -1, 317 ],
## [ -6, 318 ], [ 3, 319 ], [ -6, 320 ], [ 6, 321 ], [ 1, 322 ],
## [ 3, 325 ], [ -1, 328 ], [ 6, 330 ], [ -2, 331 ], [ 12, 332 ],
## [ 7, 333 ], [ -5, 334 ], [ 1, 345 ], [ 3, 355 ], [ -9, 357 ],
## [ 9, 358 ], [ 1, 363 ], [ 12, 365 ], [ -9, 366 ], [ -3, 370 ],
## [ -1, 371 ], [ -3, 372 ], [ 8, 373 ], [ -1, 374 ], [ 6, 375 ],
## [ 9, 376 ], [ 3, 377 ], [ 1, 380 ], [ 3, 383 ], [ -8, 385 ],
## [ -9, 386 ], [ -9, 388 ], [ -18, 404 ], [ 9, 410 ], [ -9, 425 ],
## [ -18, 426 ], [ -9, 427 ], [ 9, 428 ], [ -9, 429 ], [ 3, 433 ],
## [ -3, 435 ], [ -9, 437 ], [ 10, 442 ], [ 12, 445 ], [ 1, 447 ],
## [ -19, 448 ], [ 2, 449 ], [ -1, 450 ], [ -9, 451 ], [ 3, 453 ],
## [ 1, 455 ], [ 1, 457 ], [ -11, 458 ], [ -9, 459 ], [ 9, 461 ],
## [ 9, 462 ], [ -9, 468 ], [ 9, 469 ], [ -18, 471 ], [ -9, 472 ],
## [ 9, 474 ], [ -9, 475 ], [ 9, 488 ], [ 9, 495 ], [ -9, 500 ],
## [ -3, 504 ], [ 9, 505 ], [ 9, 512 ], [ 9, 515 ], [ 6, 519 ],
## [ 18, 521 ], [ -15, 523 ], [ 9, 524 ], [ -3, 525 ], [ 18, 527 ],
## [ -18, 528 ], [ 6, 529 ], [ 6, 531 ], [ 12, 532 ] ] ] ]
## ]]></Example>
## </Description>
## </ManSection>
##<#/GAPDoc>
################################################################################
InstallMethod(SCCohomologyBasisOp,
"for SCSimplicialComplex and Int",
[SCIsSimplicialComplex,IsInt],
function(complex,k)
local hom,dhom,row,t,tmp,tmp2,bd1,bd2,d;
if k < 0 then
Info(InfoSimpcomp,1,"SCCohomologyBasis: second argument must be an integer >=0.");
return fail;
fi;
d:=SCDim(complex);
if(d=fail) then
return fail;
fi;
if(k>d) then
return [];
fi;
hom:=SCIntFunc.HomCohomologyBaseD(complex,k);
return hom;
end);
SCIntFunc.CoHomBasisToSimplexList:=
function(hom,faces)
if(hom=[]) then
return [];
fi;
return List(hom,
function(x)
if(x=[]) then
return [];
fi;
return [x[1],List(x[2],y->[y[1],faces[y[2]]])];
end);
end;
################################################################################
##<#GAPDoc Label="SCHomologyBasisAsSimplices">
## <ManSection>
## <Meth Name="SCHomologyBasisAsSimplices" Arg="complex, k"/>
## <Returns> a list of pairs of the form <C>[ integer, list of linear combinations of simplices ]</C> upon success, <K>fail</K> otherwise.</Returns>
## <Description>
## Calculates a set of basis elements for the <Arg>k</Arg>-dimensional homology group (with integer coefficients) of a simplicial complex <Arg>complex</Arg>. The entries of the returned list are of the form [ MODULUS, [ BASEELM1, BASEELM2, ...] ], where the value MODULUS is 1 for the basis elements of the free part of the <Arg>k</Arg>-th homology group and <M>q\geq 2</M> for the basis elements of the <M>q</M>-torsion part. In contrast to the function <Ref Meth="SCHomologyBasis" /> the basis elements are stored as lists of coefficient-simplex pairs, i.e. a basis element of the form <M>[ [ \lambda_1, \Delta_1], [\lambda_2, \Delta_2], \dots ]</M> encodes the linear combination of simplices of the form <M>\lambda_1*\Delta_1+\lambda_2*\Delta_2 + \dots</M>.
## <Example><![CDATA[
## gap> SCLib.SearchByName("(S^2xS^1)#RP^3");
## [ [ 237, "(S^2xS^1)#RP^3" ] ]
## gap> c:=SCLib.Load(last[1][1]);;
## gap> SCHomologyBasisAsSimplices(c,1);
## [ [ 1, [ [ 1, [ 2, 8 ] ], [ -1, [ 1, 8 ] ], [ 1, [ 1, 2 ] ] ] ],
## [ 2, [ [ 1, [ 11, 12 ] ], [ -1, [ 11, 13 ] ], [ -1, [ 12, 13 ] ],
## [ 2, [ 12, 14 ] ], [ -2, [ 13, 14 ] ] ] ] ]
## ]]></Example>
## </Description>
## </ManSection>
##<#/GAPDoc>
################################################################################
InstallMethod(SCHomologyBasisAsSimplicesOp,
"for SCSimplicialComplex and Int",
[SCIsSimplicialComplex,IsInt],
function(complex,k)
local homsimp,hom,faces;
if k < 0 then
Info(InfoSimpcomp,1,"SCHomologyBasisAsSimplices: second argument must be an integer >=0.");
return fail;
fi;
homsimp:=[];
hom:=SCHomologyBasis(complex,k);
faces:=SCSkelEx(complex,k);
if(hom=fail or faces=fail) then
return fail;
fi;
homsimp:=SCIntFunc.CoHomBasisToSimplexList(hom,faces);
return homsimp;
end);
################################################################################
##<#GAPDoc Label="SCCohomologyBasisAsSimplices">
## <ManSection>
## <Meth Name="SCCohomologyBasisAsSimplices" Arg="complex, k"/>
## <Returns> a list of pars of the form <C>[ integer, linear combination of simplices ]</C> upon success, <K>fail</K> otherwise.</Returns>
## <Description>
## Calculates a set of basis elements for the <Arg>k</Arg>-dimensional cohomology group (with integer coefficients) of a simplicial complex <Arg>complex</Arg>. The entries of the returned list are of the form [ MODULUS, [ BASEELM1, BASEELM2, ...] ], where the value MODULUS is 1 for the basis elements of the free part of the <Arg>k</Arg>-th homology group and <M>q\geq 2</M> for the basis elements of the <M>q</M>-torsion part. In contrast to the function <Ref Meth="SCCohomologyBasis" /> the basis elements are stored as lists of coefficient-simplex pairs referring to the linear forms dual to the simplices in the <M>k</M>-th cochain complex of <Arg>complex</Arg>, i.e. a basis element of the form <M>[ [ \lambda_1, \Delta_i], [\lambda_2, \Delta_j], \dots ] \dots</M> encodes the linear combination of simplices (or their dual linear forms in the corresponding cochain complex) of the form <M>\lambda_1*\Delta_1+\lambda_2*\Delta_2 + \dots</M>.
## <Example><![CDATA[
## gap> SCLib.SearchByName("SU(3)/SO(3)");
## [ [ 219, "SU(3)/SO(3) (VT)" ], [ 477, "SU(3)/SO(3) (VT)" ],
## [ 484, "SU(3)/SO(3) (VT)" ], [ 486, "SU(3)/SO(3) (VT)" ] ]
## gap> c:=SCLib.Load(last[1][1]);;
## gap> SCCohomologyBasisAsSimplices(c,3);
## [ [ 2, [ [ -9, [ 2, 7, 8, 9 ] ], [ 9, [ 2, 7, 8, 12 ] ], [ 9, [ 2, 7, 8, 13 ] ],
## [ -9, [ 2, 7, 11, 12 ] ], [ 9, [ 2, 7, 11, 13 ] ], [ -9, [ 2, 8, 9, 10 ] ],
## [ -9, [ 2, 8, 9, 11 ] ], [ -18, [ 2, 8, 9, 12 ] ], [ -9, [ 2, 8, 9, 13 ] ],
## [ 9, [ 2, 8, 10, 12 ] ], [ -9, [ 2, 8, 10, 13 ] ],
## [ -9, [ 2, 8, 11, 12 ] ], [ 3, [ 2, 9, 10, 12 ] ],
## [ -3, [ 2, 9, 11, 12 ] ], [ 3, [ 3, 4, 5, 7 ] ], [ -3, [ 3, 4, 5, 12 ] ],
## [ 3, [ 3, 4, 10, 12 ] ], [ -3, [ 3, 5, 6, 7 ] ], [ 3, [ 3, 5, 6, 11 ] ],
## [ -1, [ 3, 5, 6, 13 ] ], [ -6, [ 3, 5, 7, 8 ] ], [ 3, [ 3, 5, 7, 10 ] ],
## [ -6, [ 3, 5, 7, 11 ] ], [ 6, [ 3, 5, 7, 12 ] ], [ 1, [ 3, 5, 7, 13 ] ],
## [ 3, [ 3, 5, 8, 12 ] ], [ -1, [ 3, 5, 9, 13 ] ], [ 6, [ 3, 5, 10, 12 ] ],
## [ -2, [ 3, 5, 10, 13 ] ], [ 12, [ 3, 5, 11, 12 ] ],
## [ 7, [ 3, 5, 11, 13 ] ], [ -5, [ 3, 5, 12, 13 ] ], [ 1, [ 3, 6, 9, 13 ] ],
## [ 3, [ 3, 7, 10, 12 ] ], [ -9, [ 3, 7, 11, 12 ] ], [ 9, [ 3, 7, 11, 13 ] ],
## [ 1, [ 3, 8, 9, 13 ] ], [ 12, [ 3, 8, 10, 12 ] ], [ -9, [ 3, 8, 10, 13 ] ],
## [ -3, [ 3, 9, 10, 12 ] ], [ -1, [ 3, 9, 10, 13 ] ],
## [ -3, [ 3, 9, 11, 12 ] ], [ 8, [ 3, 9, 11, 13 ] ],
## [ -1, [ 3, 9, 12, 13 ] ], [ 6, [ 3, 10, 11, 12 ] ],
## [ 9, [ 3, 10, 11, 13 ] ], [ 3, [ 3, 10, 12, 13 ] ], [ 1, [ 4, 5, 6, 8 ] ],
## [ 3, [ 4, 5, 6, 11 ] ], [ -8, [ 4, 5, 6, 13 ] ], [ -9, [ 4, 5, 7, 8 ] ],
## [ -9, [ 4, 5, 7, 11 ] ], [ -18, [ 4, 6, 8, 9 ] ], [ 9, [ 4, 6, 9, 13 ] ],
## [ -9, [ 4, 8, 9, 10 ] ], [ -18, [ 4, 8, 9, 12 ] ], [ -9, [ 4, 8, 9, 13 ] ],
## [ 9, [ 4, 8, 10, 12 ] ], [ -9, [ 4, 8, 10, 13 ] ], [ 3, [ 4, 9, 10, 12 ] ],
## [ -3, [ 4, 9, 11, 12 ] ], [ -9, [ 4, 9, 12, 13 ] ], [ 10, [ 5, 6, 7, 8 ] ],
## [ 12, [ 5, 6, 7, 11 ] ], [ 1, [ 5, 6, 7, 13 ] ], [ -19, [ 5, 6, 8, 9 ] ],
## [ 2, [ 5, 6, 8, 11 ] ], [ -1, [ 5, 6, 8, 12 ] ], [ -9, [ 5, 6, 8, 13 ] ],
## [ 3, [ 5, 6, 9, 11 ] ], [ 1, [ 5, 6, 9, 13 ] ], [ 1, [ 5, 6, 10, 13 ] ],
## [ -11, [ 5, 6, 11, 13 ] ], [ -9, [ 5, 7, 8, 9 ] ], [ 9, [ 5, 7, 8, 12 ] ],
## [ 9, [ 5, 7, 8, 13 ] ], [ -9, [ 5, 7, 11, 12 ] ], [ 9, [ 5, 7, 11, 13 ] ],
## [ -18, [ 5, 8, 9, 12 ] ], [ -9, [ 5, 8, 9, 13 ] ], [ 9, [ 5, 8, 10, 12 ] ],
## [ -9, [ 5, 8, 11, 12 ] ], [ 9, [ 6, 7, 8, 13 ] ], [ 9, [ 6, 7, 11, 13 ] ],
## [ -9, [ 6, 8, 10, 13 ] ], [ -3, [ 6, 9, 11, 12 ] ],
## [ 9, [ 6, 9, 11, 13 ] ], [ 9, [ 7, 8, 9, 13 ] ], [ 9, [ 7, 8, 11, 12 ] ],
## [ 6, [ 7, 9, 11, 12 ] ], [ 18, [ 7, 11, 12, 13 ] ],
## [ -15, [ 8, 9, 10, 12 ] ], [ 9, [ 8, 9, 10, 13 ] ],
## [ -3, [ 8, 9, 11, 12 ] ], [ 18, [ 8, 10, 11, 12 ] ],
## [ -18, [ 8, 10, 12, 13 ] ], [ 6, [ 9, 10, 11, 12 ] ],
## [ 6, [ 9, 10, 12, 13 ] ], [ 12, [ 9, 11, 12, 13 ] ] ] ] ]
## ]]></Example>
## </Description>
## </ManSection>
##<#/GAPDoc>
################################################################################
InstallMethod(SCCohomologyBasisAsSimplicesOp,
"for SCSimplicialComplex and Int",
[SCIsSimplicialComplex,IsInt],
function(complex,k)
local cohomsimp,cohom,faces;
if k < 0 then
Info(InfoSimpcomp,1,"SCCohomologyBasisAsSimplices: second argument must be an integer >=0.");
return fail;
fi;
cohomsimp:=[];
cohom:=SCCohomologyBasis(complex,k);
faces:=SCSkelEx(complex,k);
if(cohom=fail or faces=fail) then
return fail;
fi;
cohomsimp:=SCIntFunc.CoHomBasisToSimplexList(cohom,faces);
return cohomsimp;
end);
################################################################################
##<#GAPDoc Label="SCHomologyInternal">
## <ManSection>
## <Func Name="SCHomologyInternal" Arg="complex"/>
## <Returns> a list of pairs of the form <C>[ integer, list ]</C> upon success, <K>fail</K> otherwise.</Returns>
## <Description>
## This function computes the reduced simplicial homology with integer coefficients of a given simplicial complex <Arg>complex</Arg> with integer coefficients. It uses the algorithm described in <Cite Key="Desbrun08DiscDiffFormCompModel"/>. <P/>
## The output is a list of homology groups of the form <M>[H_0,....,H_d]</M>, where <M>d</M> is the dimension of <Arg>complex</Arg>. The format of the homology groups <M>H_i</M> is given in terms of their maximal cyclic subgroups, i.e. a homology group <M>H_i\cong \mathbb{Z}^f + \mathbb{Z} / t_1 \mathbb{Z} \times \dots \times \mathbb{Z} / t_n \mathbb{Z}</M> is returned in form of a list <M>[ f, [t_1,...,t_n] ]</M>, where <M>f</M> is the (integer) free part of <M>H_i</M> and <M>t_i</M> denotes the torsion parts of <M>H_i</M> ordered in weakly incresing size. See also <Ref Meth="SCHomology"/> and
## <Ref Func="SCHomologyClassic" />.
## <Example><![CDATA[
## gap> c:=SCSurface(1,false);;
## gap> SCHomologyInternal(c);
## [ [ 0, [ ] ], [ 0, [ 2 ] ], [ 0, [ ] ] ]
## ]]></Example>
## </Description>
## </ManSection>
##<#/GAPDoc>
################################################################################
InstallGlobalFunction(SCHomologyInternal,
function(complex)
local d,hom;
if(not SCIsSimplicialComplex(complex)) then
Info(InfoSimpcomp,1,"SCHomologyInternal: argument must be a simplicial complex.");
return fail;
fi;
d:=SCDim(complex);
if(d=fail) then
return fail;
fi;
if HasSCHomology(complex) then
return SCHomology(complex);
fi;
hom:=SCIntFunc.HomCoHomology(complex,0);
if(hom=fail) then
return fail;
fi;
SetSCHomology(complex,hom);
return hom;
end);
################################################################################
##<#GAPDoc Label="SCCohomology">
## <ManSection>
## <Meth Name="SCCohomology" Arg="complex"/>
## <Returns> a list of pairs of the form <C>[ integer, list ]</C> upon success, <K>fail</K> otherwise.</Returns>
## <Description>
## This function computes the simplicial cohomology groups of a given simplicial complex <Arg>complex</Arg> with integer coefficients. It uses the algorithm described in <Cite Key="Desbrun08DiscDiffFormCompModel"/>.<P/>
## The output is a list of cohomology groups of the form <M>[H^0,....,H^d]</M>, where <M>d</M> is the dimension of <Arg>complex</Arg>. The format of the cohomology groups <M>H^i</M> is given in terms of their maximal cyclic subgroups, i.e. a cohomology group <M>H^i\cong \mathbb{Z}^f + \mathbb{Z} / t_1 \mathbb{Z} \times \dots \times \mathbb{Z} / t_n \mathbb{Z}</M> is returned in form of a list <M>[ f, [t_1,...,t_n] ]</M>, where <M>f</M> is the (integer) free part of <M>H^i</M> and <M>t_i</M> denotes the torsion parts of <M>H^i</M> ordered in weakly increasing size.
## <Example><![CDATA[
## gap> c:=SCFromFacets([[1,2,3],[1,2,6],[1,3,5],[1,4,5],[1,4,6],
## [2,3,4],[2,4,5],[2,5,6],[3,4,6],[3,5,6]]);
## gap> SCCohomology(c);
## [ [ 1, [ ] ], [ 0, [ ] ], [ 0, [ 2 ] ] ]
## ]]></Example>
## </Description>
## </ManSection>
##<#/GAPDoc>
################################################################################
InstallMethod(SCCohomology,
"for SCSimplicialComplex",
[SCIsSimplicialComplex],
function(complex)
local cohom;
cohom:=SCIntFunc.HomCoHomology(complex,1);
if(cohom=fail) then
return fail;
fi;
return cohom;
end);
################################################################################
##<#GAPDoc Label="SCCupProduct">
## <ManSection>
## <Func Name="SCCupProduct" Arg="complex,cocycle1,cocycle2"/>
## <Returns> a list of pairs of the form <C>[ ORIENTATION, SIMPLEX ]</C> upon success, <K>fail</K> otherwise. </Returns>
## <Description>
## The cup product is a method of adjoining two cocycles of degree <M>p</M> and <M>q</M> to form a composite cocycle of degree <M>p + q</M>. It endows the cohomology groups of a simplicial complex with the structure of a ring. <P/>
## The construction of the cup product starts with a product of cochains: if <Arg>cocycle1</Arg> is a p-cochain and <Arg>cocylce2</Arg> is a q-cochain of a simplicial complex <Arg>complex</Arg> (given as list of oriented p- (q-)simplices), then<P/>
## <Arg>cocycle1</Arg> <M>\smile</M> <Arg>cocycle2</Arg><M>(\sigma) = </M><Arg>cocycle1</Arg><M>(\sigma \circ \iota_{0,1, ... p}) \cdot</M> <Arg>cocycle2</Arg><M>(\sigma \circ \iota_{p, p+1 ,..., p + q})</M><P/>
## where <M>\sigma</M> is a <M>p + q</M>-simplex and <M>\iota_S</M>, <M>S \subset \{0,1,...,p+q \}</M> is the canonical embedding of the simplex spanned by <M>S</M> into the <M>(p + q)</M>-standard simplex.<P/>
## <M>\sigma \circ \iota_{0,1, ..., p}</M> is called the <M>p</M>-th front face and <M>\sigma \circ \iota_{p, p+1, ..., p + q}</M> is the <M>q</M>-th back face of <M>\sigma</M>, respectively.<P/>
## Note that this function only computes the cup product in the case that <Arg>complex</Arg> is an orientable weak pseudomanifold of dimension <M>2k</M> and <M>p = q = k</M>. Furthermore, <Arg>complex</Arg> must be given in standard labeling, with sorted facet list and <Arg>cocylce1</Arg> and <Arg>cocylce2</Arg> must be given in simplex notation and labeled accordingly. Note that the latter condition is usually fulfilled in case the cocycles were computed using <Ref Meth="SCCohomologyBasisAsSimplices"/>.
## <Example><![CDATA[
## gap> SCLib.SearchByName("K3");
## [ [ 520, "K3_16" ], [ 539, "K3_17" ] ]
## gap> c:=SCLib.Load(last[1][1]);;
## gap> basis:=SCCohomologyBasisAsSimplices(c,2);;
## gap> SCCupProduct(c,basis[1][2],basis[1][2]);
## [ [ 1, [ 1, 2, 4, 7, 11 ] ], [ 1, [ 2, 3, 4, 5, 9 ] ] ]
## gap> SCCupProduct(c,basis[1][2],basis[2][2]);
## [ [ -1, [ 1, 2, 4, 7, 11 ] ], [ -1, [ 1, 2, 4, 7, 15 ] ],
## [ -1, [ 2, 3, 4, 5, 9 ] ] ]
## ]]></Example>
## </Description>
## </ManSection>
##<#/GAPDoc>
################################################################################
InstallGlobalFunction(SCCupProduct,
function(complex,cocycle1,cocycle2)
local i, k, element, dim, cupProduct, product1, product2,
facets, facetsEx, frontface, backface, coeff, o;
dim := SCDim(complex)/2;
o := SCIsOrientable(complex);
if o = fail then
Info(InfoSimpcomp,1,"SCCupProduct: first argument must be an orientable simplicial complex.");
return fail;
fi;
if(not IsInt(dim) or not SCIsSimplicialComplex(complex) or cocycle1 = [] or cocycle2 = [] or Size(cocycle1[1][2]) <> dim+1 or Size(cocycle2[1][2]) <> dim+1 or not o) then
Info(InfoSimpcomp,1,"SCCupProduct: first argument must be an orientable 2k-dimensional simplicial complex, second and third argument must be non empty k-cochains.");
return fail;
fi;
facets:=SCFacets(complex);
facetsEx:=SCFacetsEx(complex);
if facets = fail or facetsEx = fail then
return fail;
fi;
if facets <> facetsEx or not IsSortedList(facets) or false in List(facets,x->IsSortedList(x)) then
Info(InfoSimpcomp,1,"SCCupProduct: first argument must be a simplicial complex in standard labeling and with sorted facet list.");
return fail;
fi;
cupProduct:=[];
for k in [1..Size(facets)] do
element:=ShallowCopy(facets[k]);
frontface:=element{[1..dim+1]};
backface:=element{[dim+1..2*dim+1]};
product1:=[];
for i in cocycle1 do
if frontface = i[2] then
product1:=i;
break;
fi;
od;
product2:=[];
for i in cocycle2 do
if backface = i[2] then
product2:=i;
break;
fi;
od;
if product1 <> [] and product2 <> [] then
coeff:=product1[1]*product2[1];
Add(cupProduct,[coeff,element]);
fi;
od;
return cupProduct;
end);
################################################################################
##<#GAPDoc Label="SCIntersectionForm">
## <ManSection>
## <Meth Name="SCIntersectionForm" Arg="complex"/>
## <Returns> a square matrix of integer values upon success, <K>fail</K> otherwise.</Returns>
## <Description>
## For <M>2k</M>-dimensional orientable manifolds <M>M</M> the cup product (see <Ref Meth="SCCupProduct"/>) defines a bilinear form <P/>
## H<M>^k ( M ) \times </M>H<M>^k ( M ) \to </M>H<M>^{2k} (M), (a,b) \mapsto a \cup b </M><P/>
## called the intersection form of <M>M</M>. This function returns the intersection form of an orientable combinatorial <M>2k</M>-manifold <Arg>complex</Arg> in form of a matrix <C>mat</C> with respect to the basis of H<M>^k ( </M><Arg>complex</Arg>M<M>)</M> computed by <Ref Meth="SCCohomologyBasisAsSimplices"/>. The matrix entry <C>mat[i][j]</C> equals the intersection number of the <C>i</C>-th base element with the <C>j</C>-th base element of H<M>^k ( </M><Arg>complex</Arg>M<M>)</M>.
## <Example><![CDATA[
## gap> SCLib.SearchByName("CP^2");
## [ [ 16, "CP^2 (VT)" ], [ 96, "CP^2#-CP^2" ],
## [ 97, "CP^2#CP^2" ], [ 185, "CP^2#(S^2xS^2)" ],
## [ 397, "Gaifullin CP^2" ],
## [ 457, "(S^3~S^1)#(CP^2)^{#5} (VT)" ] ]
## gap> c:=SCLib.Load(last[1][1]);;
## gap> c1:=SCConnectedSum(c,c);;
## gap> c2:=SCConnectedSumMinus(c,c);;
## gap> q1:=SCIntersectionForm(c1);;
## gap> q2:=SCIntersectionForm(c2);;
## gap> PrintArray(q1);
## [ [ 1, 0 ],
## [ 0, 1 ] ]
## gap> PrintArray(q2);
## [ [ 1, 0 ],
## [ 0, -1 ] ]
## ]]></Example>
## </Description>
## </ManSection>
##<#/GAPDoc>
################################################################################
InstallMethod(SCIntersectionForm,
"for SCSimplicialComplex",
[SCIsSimplicialComplex],
function(complex)
local i, j, idx1, idx2, idx, element, dim, cupProduct, product,
facets, frontface, backface, coeff, cocycles, orientation, sum, mat, labels,c;
dim := SCDim(complex);
if dim = fail then
return fail;
fi;
if(dim mod 2 <> 0 or SCIsPseudoManifold(complex) <> true) then
Info(InfoSimpcomp,1,"SCIntersectionForm: argument must be a orientable weak pseudomanifold of even dimension.");
return fail;
fi;
facets:=SCIntFunc.DeepCopy(SCFacetsEx(complex));
SCIntFunc.DeepSortList(facets);
c:=SCFromFacets(facets);
dim := dim/2;
orientation:=SCOrientation(c);
if orientation = fail then
return fail;
fi;
if(SCIsOrientable(c) <> true) then
Info(InfoSimpcomp,1,"SCIntersectionForm: argument must be orientable.");
return fail;
fi;
cocycles:=SCCohomologyBasisAsSimplices(c,dim);
if facets = fail or cocycles = fail then
return fail;
fi;
if cocycles = [] then
return [];
fi;
cupProduct:=[];
mat:=[];
for idx1 in [1..Size(cocycles)] do
mat[idx1]:=[];
for idx2 in [1..Size(cocycles)] do
product:= SCCupProduct(c,cocycles[idx1][2],cocycles[idx2][2]);
sum:=0;
for j in [1..Size(product)] do
idx:=Position(facets,product[j][2]);
sum:=sum+orientation[idx]*product[j][1];
od;
mat[idx1][idx2]:=sum;
od;
od;
return mat;
end);
################################################################################
##<#GAPDoc Label="SCIntersectionFormParity">
## <ManSection>
## <Meth Name="SCIntersectionFormParity" Arg="complex"/>
## <Returns> <C>0</C> or <C>1</C> upon success, <K>fail</K> otherwise.</Returns>
## <Description>
## Computes the parity of the intersection form of a combinatorial manifold <Arg>complex</Arg> (see <Ref Meth="SCIntersectionForm"/>). If the intersection for is even (i. e. all diagonal entries are even numbers) <C>0</C> is returned, otherwise <C>1</C> is returned.
## <Example><![CDATA[
## gap> SCLib.SearchByName("S^2xS^2");;
## gap> c:=SCLib.Load(last[1][1]);;
## gap> SCIntersectionFormParity(c);
## 0
## gap> SCLib.SearchByName("CP^2");;
## gap> c:=SCLib.Load(last[1][1]);;
## gap> SCIntersectionFormParity(c);
## 1
## ]]></Example>
## </Description>
## </ManSection>
##<#/GAPDoc>
################################################################################
InstallMethod(SCIntersectionFormParity,
"for SCSimplicialComplex",
[SCIsSimplicialComplex],
function(complex)
local parity, i, matrix, dim;
dim:=SCDim(complex);
if dim = fail then
return fail;
fi;
if(dim mod 2 <> 0 or SCIsPseudoManifold(complex) <> true) then
Info(InfoSimpcomp,1,"SCIntersectionFormParity: argument must be a pseudomanifold of even dimension.");
return fail;
fi;
matrix:=SCIntersectionForm(complex);
if matrix = fail then
return fail;
fi;
parity := 0;
for i in [1..Size(matrix)] do
if matrix[i][i] mod 2 <> 0 then
parity:=1;
break;
fi;
od;
return parity;
end);
################################################################################
##<#GAPDoc Label="SCIntersectionFormDimensionality">
## <ManSection>
## <Meth Name="SCIntersectionFormDimensionality" Arg="complex"/>
## <Returns> an integer upon success, <K>fail</K> otherwise.</Returns>
## <Description>
## Returns the dimensionality of the intersection form of a combinatorial manifold <Arg>complex</Arg>, i. e. the length of a minimal generating set of H<M>^k (M)</M> (where <M>2k</M> is the dimension of <Arg>complex</Arg>). See <Ref Meth="SCIntersectionForm"/> for further details.
## <Example><![CDATA[
## gap> SCLib.SearchByName("CP^2");;
## gap> c:=SCLib.Load(last[1][1]);;
## gap> SCIntersectionFormParity(c);
## 1
## gap> SCCohomology(c);
## [ [ 1, [ ] ], [ 0, [ ] ], [ 1, [ ] ], [ 0, [ ] ], [ 1, [ ] ] ]
## gap> SCIntersectionFormDimensionality(c);
## 1
## gap> d:=SCConnectedProduct(c,10);;
## gap> SCIntersectionFormDimensionality(d);
## 10
## ]]></Example>
## </Description>
## </ManSection>
##<#/GAPDoc>
################################################################################
InstallMethod(SCIntersectionFormDimensionality,
"for SCSimplicialComplex",
[SCIsSimplicialComplex],
function(complex)
local matrix, dim;
dim:=SCDim(complex);
if dim = fail then
return fail;
fi;
if(dim mod 2 <> 0 or SCIsPseudoManifold(complex) <> true) then
Info(InfoSimpcomp,1,"SCIntersectionFormDimensionality: argument must be a pseudomanifold of even dimension.");
return fail;
fi;
matrix:=SCIntersectionForm(complex);
if matrix = fail then
return fail;
fi;
return Size(matrix);
end);
################################################################################
##<#GAPDoc Label="SCIntersectionFormSignature">
## <ManSection>
## <Meth Name="SCIntersectionFormSignature" Arg="complex"/>
## <Returns> a triple of integers upon success, <K>fail</K> otherwise.</Returns>
## <Description>
## Computes the dimensionality (see <Ref Meth="SCIntersectionFormDimensionality"/>) and the signature of the intersection form of a combinatorial manifold <Arg>complex</Arg> as a <M>3</M>-tuple that contains the dimensionality in the first entry and the number of positive / negative eigenvalues in the second and third entry. See <Ref Meth="SCIntersectionForm"/> for further details.<P/>
## Internally calls the &GAP;-functions <C>Matrix_CharacteristicPolynomialSameField</C> and <C>CoefficientsOfLaurentPolynomial</C> to compute the number of positive / negative eigenvalues of the intersection form.
## <Example><![CDATA[
## gap> SCLib.SearchByName("CP^2");;
## gap> c:=SCLib.Load(last[1][1]);;
## gap> SCIntersectionFormParity(c);
## 1
## gap> SCCohomology(c);
## [ [ 1, [ ] ], [ 0, [ ] ], [ 1, [ ] ], [ 0, [ ] ], [ 1, [ ] ] ]
## gap> SCIntersectionFormSignature(c);
## [ 1, 0, 1 ]
## gap> d:=SCConnectedSum(c,c);
## gap> SCIntersectionFormSignature(d);
## [ 2, 1, 1 ]
## gap> d:=SCConnectedSumMinus(c,c);;
## gap> SCIntersectionFormSignature(d);
## [ 2, 0, 2 ]
## ]]></Example>
## </Description>
## </ManSection>
##<#/GAPDoc>
################################################################################
InstallMethod(SCIntersectionFormSignature,
"for SCSimplicialComplex",
[SCIsSimplicialComplex],
function(complex)
local sign,matrix,charpol,coeff,dim,prod,old,idx;
dim:=SCDim(complex);
if dim = fail then
return fail;
fi;
if(dim mod 2 <> 0 or SCIsPseudoManifold(complex) <> true) then
Info(InfoSimpcomp,1,"SCIntersectionFormSignature: argument must be a pseudomanifold of even dimension.");
return fail;
fi;
matrix:=SCIntersectionForm(complex);
if matrix = fail then
return fail;
fi;
dim:=Size(matrix);
charpol:= Matrix_CharacteristicPolynomialSameField(Integers,matrix,1);
coeff:=Reversed(CoefficientsOfLaurentPolynomial(charpol))[2];
sign:=0;
old:=0;
for idx in [1..Size(coeff)] do
if coeff[idx] = 0 then continue; fi;
if old = 0 then
old := coeff[idx];
continue;
fi;
prod:=old*coeff[idx];
if prod = 0 then
Info(InfoSimpcomp,1,"SCIntersectionFormSignature: Error, can not compute signature of intersection form.");
return fail;
fi;
if not IsPosInt(Int(prod)) then
sign := sign + 1;
fi;
old:=coeff[idx];
od;
return [dim,sign,dim-sign];
end);
[ Dauer der Verarbeitung: 0.41 Sekunden
(vorverarbeitet)
]
|
2026-04-02
|