Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
| Download
GAP 4.8.9 installation with standard packages -- copy to your CoCalc project to get it
Project: cocalc-sagemath-dev-slelievre
Views: 418346############################################################################# ## #W FundamentalDomainStandardSP.gi HAPcryst package Marc Roeder ## ## ## #H @(#)$Id: FundamentalDomainStandardSP.gi, v 0.1.11 2013/10/27 18:31:09 gap Exp $ ## #Y Copyright (C) 2006 Marc Roeder #Y #Y This program is free software; you can redistribute it and/or #Y modify it under the terms of the GNU General Public License #Y as published by the Free Software Foundation; either version 2 #Y of the License, or (at your option) any later version. #Y #Y This program is distributed in the hope that it will be useful, #Y but WITHOUT ANY WARRANTY; without even the implied warranty of #Y MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #Y GNU General Public License for more details. #Y #Y You should have received a copy of the GNU General Public License #Y along with this program; if not, write to the Free Software #Y Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA ## Revision.("FundamentalDomainStandardSP_gi"):= "@(#)$Id: FundamentalDomainStandardSP.gi, v 0.1.11 2013/10/27 18:31:09 gap Exp $"; ######################################################################## ######################################################################## #### #### #### ALL THIS DOES ONLY WORK FOR THE STANDARD SCALAR PRODUCT! #### #### #### ######################################################################## ######################################################################## InstallMethod(FundamentalDomainFromGeneralPointAndOrbitPartGeometric, [IsVector,IsMatrix], function(center,orbitpart) local smallestPointOfOneCubeAroundCenter, NextLargerInteger, inequalitiesFromVertices, needsConsideration, reducePolytope, initialPolytope, radiussquareMaxentryMaxsum, dim, centersquare, partialFD, radmax, orbitpartAroundCenter, polyChanged, sums, currentsum, nrNon0, signs, signvectors, non0entries, offsetvector, non0part, issmall, offset, non0indices, index; # for a point <center> find the edge of the cube <center>+{-1/2,1/2}^n # with minimal euclidian norm. # smallestPointOfOneCubeAroundCenter:=function(center) local edge, i, entry, sign, minusentry, plusentry; # middle:=List(center,i->0); edge:=List(center); for i in [1..Size(center)] do entry:=edge[i]; sign:=SignRat(entry); if sign=0 then sign:=1; fi; minusentry:=-sign/2+entry; plusentry:=sign/2+entry; if AbsoluteValue(minusentry)<AbsoluteValue(plusentry) then edge[i]:=minusentry; elif AbsoluteValue(minusentry)=AbsoluteValue(plusentry) then edge[i]:=(minusentry+plusentry)/2; # middle[i]:=(minusentry+plusentry)/2; # edge[i]:=plusentry; else edge[i]:=plusentry; # middle[i]:=plusentry; fi; od; return edge; # return rec(edge:=edge,middle:=middle); end; NextLargerInteger:=function(rat) if IsInt(rat) then return rat; else return Int(rat+1); fi; end; #given a point <center> and an offset vector <offset> as well as the part of # the orbit around <center>, the interesting inequalities induced by # <orbitpart>+offset are calculated, assuming that only points nearer # than <radius> can induce something interesting. # inequalitiesFromVertices:=function(center,offset,signvectors,orbitpart,vertices,radiussquare) local ineqs, inequalities, sign, off; ineqs:=function(center,points,vertices,rsquare) local returnlist, point, ineq; returnlist:=[]; for point in points do if (point-center)^2<=rsquare then ineq:=BisectorInequalityFromPointPair(center,point); if ineq<>fail and ForAny(vertices,thiscorner->WhichSideOfHyperplane(thiscorner,ineq)=-1) # if ForAny(vertices,thiscorner->WhichSideOfHyperplane(thiscorner,ineq)=-1) then Add(returnlist,ineq); fi; fi; od; return returnlist; end; inequalities:=[]; for sign in signvectors do off:=List([1..Size(sign)],i->sign[i]*offset[i])+orbitpart; Append(inequalities,ineqs(center,off,vertices,radiussquare)); od; return Set(inequalities); end; needsConsideration:=function(offset,radiussquare) # edgeAndMiddle:=smallestPointOfOneCubeAroundCenter(offset); # if edgeAndMiddle.edge^2<radiussquare or # edgeAndMiddle.middle^2<=radiussquare if smallestPointOfOneCubeAroundCenter(offset)^2<=radiussquare then return true; else return false; fi; end; reducePolytope:=function(poly,center,offset,signvectors,radiussquare,orbitpart) local vertices, inequalities; vertices:=Polymake(poly,"VERTICES"); inequalities:=inequalitiesFromVertices(center,offset,signvectors,orbitpart,vertices,radiussquare); if inequalities <> [] then UniteSet(inequalities,Polymake(poly,"FACETS")); ClearPolymakeObject(poly,["polytope","2.3","RationalPolytope"]); AppendInequalitiesToPolymakeObject(poly,inequalities); Polymake(poly,"VERTICES FACETS"); if InfoLevel(InfoHAPcryst)>1 then Print("|",Size(Polymake(poly,"VERTICES")),":",Size(Polymake(poly,"FACETS")),">\c"); fi; return true; else return false; fi; end; initialPolytope:=function(center) local dim, poly, signvectors, cubevertices; dim:=Size(center); poly:=CreatePolymakeObject("partialFD", POLYMAKE_DATA_DIR, ["polytope","2.3","RationalPolytope"] ); signvectors:=Tuples([-1,1],dim); cubevertices:=(1/2*signvectors)+center; AppendVertexlistToPolymakeObject(poly,cubevertices); AppendToPolymakeObject(poly, ConvertMatrixToPolymakeString("FACETS", List(Union(IdentityMat(dim),-IdentityMat(dim)), i->BisectorInequalityFromPointPair(center,center+i)))); Polymake(poly,"VERTICES FACETS"); return poly; end; # this calculates the radius of the ball to be covered and the maximal # entry (and the maximal entry sum) in the offset vectors needed to cover # the ball. The maximum distance for offset vectors is 3*radius. radiussquareMaxentryMaxsum:=function(poly,center,dim) local x, vertices, radiussquare, outerradiussquare, maxentry, maxsum, offsetradiussquare; x:=Indeterminate(Rationals); vertices:=Polymake(poly,"VERTICES"); # this is the radius of the smallest circle around the polygon: radiussquare:=Maximum(List(vertices-center,v->v^2)); #now, we look at the offset vectors. #radius of the ball we want to cover (twice the radius of the polygon): outerradiussquare:=4*radiussquare; #maximal entry of an offset vector (\infty - norm): # 1/2+2*radius(poly) (1/2=half the side length of the offset cube): maxentry:=NextLargerInteger(1/2+ContinuedFractionApproximationOfRoot( DenominatorRat(outerradiussquare)*x^2 -NumeratorRat(outerradiussquare), 10) ); #maximum sum of entries of offset vectors (1-norm): #=dim*((2*radius(poly))^2/dim+1/2) maxsum:=NextLargerInteger(dim*(outerradiussquare/dim+1/2)); return rec(radiussquare:=outerradiussquare,maxsum:=maxsum,maxentry:=maxentry); end; ###################################################################### ###################################################################### ## Los gehts! ###################################################################### ###################################################################### dim:=Size(center); # First, generate the initial (translation) cube. partialFD:=initialPolytope(center); radmax:=radiussquareMaxentryMaxsum(partialFD,center,dim); orbitpartAroundCenter:=Set(ShiftedOrbitPart(center,orbitpart)); polyChanged:=reducePolytope(partialFD, center, List([1..dim],i->0), [List([1..dim],i->1)], radmax.radiussquare, orbitpartAroundCenter); radmax:=radiussquareMaxentryMaxsum(partialFD,center,dim); sums:=Iterator([1..radmax.maxsum]); currentsum:=1; if InfoLevel(InfoHAPcryst)>1 then Print(radmax,"\n"); fi; while currentsum<radmax.maxsum do currentsum:=NextIterator(sums); if InfoLevel(InfoHAPcryst)>1 then Print("\n",currentsum,"(",Int(radmax.radiussquare),"-",radmax.maxsum,"-",radmax.maxentry,")\n"); fi; for nrNon0 in [1..Minimum(currentsum,dim)] do signs:=Tuples([1,-1],nrNon0); signvectors:=NullMat(Size(signs),dim); non0entries:=Iterator(RestrictedPartitions(currentsum,[1..radmax.maxentry],nrNon0)); offsetvector:=List(center,i->0); for non0part in non0entries do offsetvector{[1..nrNon0]}:=non0part; issmall:=(non0part^2<=radmax.radiussquare); for offset in PermutationsList(offsetvector) do if issmall or needsConsideration(offset,radmax.radiussquare) then non0indices:=Positions(List(offset,i->i<>0),true); Apply(signvectors,i->List(i,j->1)); for index in [1..Size(signs)] do signvectors[index]{non0indices}:=signs[index]; od; polyChanged:=reducePolytope(partialFD, center, offset, signvectors, radmax.radiussquare, orbitpartAroundCenter); if polyChanged then radmax:=radiussquareMaxentryMaxsum(partialFD,center,dim); fi; if radmax.maxsum<currentsum then return partialFD; ## We found it! fi; fi; od; od; od; od; return partialFD; end);